3 #Usage: pnd_run.sh -p your.pnd -e executeable [-a "(arguments)"] [ -s "cd to folder inside pnd"] [-b UID (name of mountpoint/pandora/appdata)] [-x close x before launching(script needs to be started with nohup for this to work]
5 # arguments can be inside -e, -a is optional
7 #/etc/sudoers needs to be adjusted if you touch any of the sudo lines
9 # look at the comments in the nox part, adjust
10 #use "lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq > whitelist" with nothing running to generate the whitelist
12 #todo - no proper order
13 #validate params better
14 #make uid/pnd_name mandatory (and rename var, its confusing!)
15 #find a clean way of shutting down x without a fixed dm, mabye avoid nohup usage somehow
16 #add options to just mount iso without union and to mount the union later
18 #Rewrite! - this sucks
21 for p in $(fuser -m $1 2>/dev/null);do ps hf $p;done
26 if ! [ -f "${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed" ]; then
27 if [ ${cpuspeed:-$(cat /proc/pandora/cpu_mhz_max)} -gt $(cat /proc/pandora/cpu_mhz_max) ]; then
28 cpuselection=$(zenity --title="set cpu speed" --height=350 --list --column "id" --column "Please select" --hide-column=1 --text="$PND_NAME suggests to set the cpu speed to $cpuspeed MHz to make it run properly.\n\n Do you want to change the cpu speed? (current speed: $(cat /proc/pandora/cpu_mhz_max) MHz)\n\nWarning: Setting the clock speed above 600MHz can be unstable and it NOT recommended!" "yes" "Yes, set it to $cpuspeed MHz" "custom" "Yes, select custom value" "yessave" "Yes, set it to $cpuspeed MHz and don't ask again" "customsave" "Yes, set it to custom speed and don't ask again" "no" "No, don't change the speed" "nosave" "No, don't chage the speed and don't ask again")
29 if [ ${cpuselection} = "yes" ]; then
30 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
31 sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
32 elif [ ${cpuselection} = "custom" ]; then
33 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
34 sudo /usr/pandora/scripts/op_cpuspeed.sh
35 elif [ ${cpuselection} = "customsave" ]; then
36 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
37 sudo /usr/pandora/scripts/op_cpuspeed.sh
38 zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed"
39 cat /proc/pandora/cpu_mhz_max > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
40 elif [ ${cpuselection} = "yessave" ]; then
41 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
42 cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed
43 zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed"
44 sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
45 cat /proc/pandora/cpu_mhz_max > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
46 elif [ ${cpuselection} = "nosave" ]; then
47 zenity --info --title="Note" --text="Speed will not be changed.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed"
48 echo 9999 > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
52 cpuspeed=$(cat "${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed")
53 if [ "$cpuspeed" -lt "1500" ]; then
54 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
55 echo Setting to CPU-Speed $cpuspeed MHz
56 sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
60 cd "/mnt/utmp/$PND_NAME" # cd to union mount
61 if [ "$STARTDIR" ] && [ -d "$STARTDIR" ]; then
62 cd "$STARTDIR"; # cd to folder specified by the optional arg -s
64 echo "[------------------------------]{ App start }[---------------------------------]"
65 if [ -d /mnt/utmp/$PND_NAME/lib ];then
66 export LD_LIBRARY_PATH="/mnt/utmp/$PND_NAME/lib:${LD_LIBRARY_PATH:-"/usr/lib:/lib"}"
68 export LD_LIBRARY_PATH="/mnt/utmp/$PND_NAME:${LD_LIBRARY_PATH:-"/usr/lib:/lib"}"
70 if [ -d /mnt/utmp/$PND_NAME/bin ];then
71 export PATH="/mnt/utmp/$PND_NAME/bin:${PATH:-"/usr/bin:/bin:/usr/local/bin"}"
73 if [ -d /mnt/utmp/$PND_NAME/share ];then
74 export XDG_DATA_DIRS="/mnt/utmp/$PND_NAME/share:$XDG_DATA_DIRS:/usr/share"
76 export XDG_CONFIG_HOME="/mnt/utmp/$PND_NAME"
77 "./$EXENAME" $ARGUMENTS
78 # execute app with ld_lib_path set to the union mount, a bit evil but i think its a good solution
80 #the app could have exited now, OR it went into bg, we still need to wait in that case till it really quits!
81 PID=$(pidof -o %PPID -x \"$EXENAME\") # get pid of app
82 while [ "$PID" ];do # wait till we get no pid back for tha app, again a bit ugly, but it works
84 PID=`pidof -o %PPID -x \"$EXENAME\"`
86 echo "[-------------------------------]{ App end }[----------------------------------]"
88 if [ ! -z "$CURRENTSPEED" ]; then
89 sudo /usr/pandora/scripts/op_cpuspeed.sh $CURRENTSPEED
94 if [ $(id -u) -ne 0 ];then
95 echo "sudo /usr/pandora/scripts/pnd_run.sh -m $PNDARGS"
96 sudo /usr/pandora/scripts/pnd_run.sh -m $PNDARGS
97 mount | grep "on /mnt/utmp/${PND_NAME} type"
99 echo "The Union File-system is not mounted !"
104 #create mountpoints, check if they exist already first to avoid annoying error messages
105 if ! [ -d "/mnt/pnd/${PND_NAME}" ]; then
106 mkdir -p "/mnt/pnd/${PND_NAME}" #mountpoint for iso, ro
108 #writeable dir for union
109 if ! [ -d "${APPDATADIR}" ]; then
110 mkdir -p "${APPDATADIR}"
111 chmod -R a+xrw "${APPDATADIR}" 2>/dev/null
113 # create the union mountpoint
114 if ! [ -d "/mnt/utmp/${PND_NAME}" ]; then
115 mkdir -p "/mnt/utmp/${PND_NAME}" # union over the two
117 #is the union already mounted? if not mount evrything, else launch the stuff
118 mount | grep "on /mnt/utmp/${PND_NAME} type"
120 mount | grep "on /mnt/pnd/${PND_NAME} type"
122 echo not mounted on loop yet, doing so
123 #check if pnd is already attached to loop
124 LOOP=$(losetup -a | grep "$PND" | tail -n1 | awk -F: '{print $1}')
125 #check if the loop device is already mounted
126 if ! [ -z "$LOOP" ];then
127 echo "Found a loop ($LOOP), using it"
128 loopmountedon=$( mount | grep "$(mount | grep "$LOOP" | awk '{print $3}')" | grep utmp | awk '{print $3}' )
132 echo "LoopMountedon: $loopmountedon"
133 if [ ! "$loopmountedon" ]; then #check if the pnd is already attached to some loop device but not used
136 if [ ! "$LOOP" ]; then
137 FREELOOP=$(/sbin/losetup -f) #get first free loop device
139 if [ ! "$FREELOOP" ]; then # no free loop device, create a new one
140 #find a free loop device and use it
141 usedminor=$(/sbin/losetup -a | tail -n1)
142 usedminor=${usedminor:9:1}
143 echo usedminor $usedminor
144 freeminor=$(($usedminor+1))
145 echo freeminor $freeminor
146 mknod -m777 /dev/loop$freeminor b 7 $freeminor
147 FREELOOP=/dev/loop$freeminor
154 /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
155 mntline="mount" #setup the mountline for later
157 #mntline="mount -o loop,mode=777 $PND /mnt/pnd/$PND_NAME"
158 echo "Filetype is $PND_FSTYPE";;
160 #we bind the folder, now it can be treated in a unified way
161 #ATENTION: -o ro doesnt work for --bind at least on 25, on 26 its possible using remount, may have changed on 27
162 mntline="mount --bind -o ro"
164 echo "Filetype is $PND_FSTYPE";;
166 /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
167 mntline="mount -t squashfs"
169 echo "Filetype is $PND_FSTYPE";;
171 echo "error determining fs, output was $PND_FSTYPE"
174 echo "Mounting PND ($mntline) :"
175 $mntline "$mntdev" "/mnt/pnd/${PND_NAME}" #mount the pnd/folder
177 else #the pnd is already mounted but a mount was requested with a different basename/uid, just link it there
178 echo $LOOP already mounted on $loopmountedon skipping losetup - putting link to old mount
180 rmdir "/mnt/utmp/$PND_NAME"
181 ln -s $loopmountedon "/mnt/utmp/$PND_NAME"
184 mount | grep "on /mnt/pnd/${PND_NAME} type"
186 echo "The PND File-system is not mounted ! - Union wont work anyway"
191 echo "the PND is already mounted"
193 FILESYSTEM=$(mount | grep "on $MOUNTPOINT " | grep -v rootfs | awk '{print $5}' | tail -n1) #get filesystem appdata is on to determine aufs options
194 RO=0;for o in $(mount|grep "on $MOUNTPOINT "|sed 's/.*(//;s/)$//;s/,/ /g');do [[ $o = "ro" ]]&& RO=1;done
195 if [ $RO -eq 1 ];then
196 echo "SD-Card is mounted Read-only !! Trying to remount RW"
197 mount -oremount,rw $MOUNTPOINT
199 echo "Filesystem is $FILESYSTEM"
200 echo "Mounting the Union FS using ${APPDATADIR} as Write directory:"
201 if [[ "$FILESYSTEM" = "vfat" ]]; then # use noplink on fat, dont on other fs's
202 #append is fucking dirty, need to clean that up
203 echo mount -t aufs -o exec,noplink,dirs="${APPDATADIR}=rw+nolwh":"/mnt/pnd/$PND_NAME=rr$append" none "/mnt/utmp/$PND_NAME"
204 mount -t aufs -o exec,noplink,dirs="${APPDATADIR}=rw+nolwh":"/mnt/pnd/$PND_NAME=rr$append" none "/mnt/utmp/$PND_NAME"
207 mount -t aufs -o exec,dirs="${APPDATADIR}=rw+nolwh":"/mnt/pnd/$PND_NAME=rr$append" none "/mnt/utmp/$PND_NAME"
211 mount | grep "on /mnt/utmp/${PND_NAME} type"
213 echo "The Union File-system is not mounted !"
218 echo "Union already mounted"
223 #delete folders created by aufs if empty
224 rmdir -rf "${APPDATADIR}/.wh..wh.plnk" 2>/dev/null
225 rmdir -rf "${APPDATADIR}/.wh..wh..tmp" 2>/dev/null
227 #delete appdata folder and ancestors if _empty_
228 rmdir -p "${APPDATADIR}" 2>/dev/null
230 # Clean the loopback device
231 if [ $PND_FSTYPE = ISO ] || [ $PND_FSTYPE = Squashfs ]; then # check if we where running an iso, clean up loop device if we did
232 LOOP=$(losetup -a | grep "$(basename $PND)" | tail -n1 | awk -F: '{print $1}')
233 /sbin/losetup -d $LOOP
241 if mount | grep -q "on /mnt/pnd/${PND_NAME} type";then
242 umount "/mnt/pnd/$PND_NAME"
244 if ! [ -z "$(mount |grep pnd/$PND_NAME|cut -f3 -d' ')" ]; then
245 echo umount PND failed, didnt clean up. Process still using this FS :
246 list_using_fs "/mnt/pnd/$PND_NAME"
248 # removing the now useless mountpoint
249 if [ -d /mnt/pnd/$PND_NAME ];then
250 rmdir "/mnt/pnd/$PND_NAME"
253 # All went well, cleaning
260 if [ $(id -u) -ne 0 ];then
261 sudo /usr/pandora/scripts/pnd_run.sh -u $PNDARGS
265 # Make sure the Union FS is unmounted
266 if mount | grep -q "on /mnt/utmp/${PND_NAME} type";then
267 umount "/mnt/utmp/$PND_NAME" #umount union
269 if ! [ -z "$(mount |grep utmp/$PND_NAME|cut -f3 -d' ')" ]; then
270 echo umount UNION failed, didnt clean up. Process still using this FS :
271 list_using_fs "/mnt/utmp/$PND_NAME"
273 # the Union is umounted, removing the now empty mountpoint
274 if [ -d "/mnt/utmp/$PND_NAME" ];then
275 rmdir "/mnt/utmp/$PND_NAME"
276 elif [ -e "/mnt/utmp/$PND_NAME" ];then
277 rm "/mnt/utmp/$PND_NAME" >/dev/null 2>&1 # as it might be a symlink
279 # Try umounting the PND
285 if [ $nox ]; then #the app doesnt want x to run, so we kill it and restart it once the app quits
286 if [ ! $(pidof X) ]; then
289 applist=$(lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq)
290 whitelist=$(cat ~/pndtest/whitelist) #adjust this to a fixed whitelist, maybe in the config dir
291 filteredlist=$(echo -e "$applist\n\n$whitelist\n\n$whitelist" | sort | uniq -u) #whitelist appended two times so those items are always removed
292 if [ ${#filteredlist} -ge 1 ]; then
293 message=$(echo -e "The following applications are still running, are you sure you want to close x? \n$filteredlist")
294 echo -e "?ae[34me[30m?"
295 xmessage -center "$message", -buttons yes,no
296 if [ $? = 102 ]; then
299 sudo /etc/init.d/slim-init stop
302 echo -e "?ae[34me[30m?"
303 xmessage -center "killing x, nothing of value will be lost", -buttons ok,cancel
304 if [ $? = 102 ]; then
307 # close x now, do we want to use slim stop or just kill x?
308 sudo /etc/init.d/slim-init stop
316 umount) umountUnion;;
320 zenity --warning --title="Mounting the PND failed" --text="Mounting the PND failed. The application wont start. Please have a look at $LOGFILE"
330 if [ $nox ]; then #restart x if it was killed
331 echo "starting x in 5s"
333 sudo /etc/init.d/slim-init start
339 Usage: pnd_run.sh -p your.pnd -e executeable [-a "(arguments)"] [ -s "cd to folder inside pnd"] [-b UID (name of mountpoint/pandora/appdata)] [-x close x before launching(script needs to be started with nohup for this to work]
340 Usage for mounting/umounting pnd_run.sh -p your.pnd -b uid -m or -u
344 function parseArgs() {
346 TEMP=`getopt -o d:p:e:a:b:s:m::u::n::x::j:c: -- "$@"`
347 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
348 # Note the quotes around `$TEMP': they are essential!
352 -p) PND="$2";shift 2;;
353 -e) EXENAME="$2";shift 2 ;;
354 -b) PND_NAME="$2";shift 2;;
355 -s) STARTDIR="$2";shift 2;;
356 -m) ACTION=mount;shift 2;;
357 -u) ACTION=umount;shift 2;;
359 -j) append="$2";shift 2;;
360 -c) cpuspeed="$2";shift 2;;
361 -d) APPDATASET=1;APPDATADIR="$2";shift 2;;
364 "") echo "no arguments"; shift 2 ;;
365 *) ARGUMENTS="$2";shift 2 ;;
368 *) echo "Error while parsing arguments!"; showHelp; exit 1 ;;
372 ######################################################################################
378 if [ ! -e "$PND" ]; then #check if theres a pnd suplied, need to clean that up a bit more
379 echo "ERROR: selected PND($PND) file does not exist!"
384 if [ ! "$EXENAME" ] && [[ "$ACTION" = "run" ]]; then
385 echo "ERROR: no executable name provided!"
390 PND_FSTYPE=$(file -b "$PND" | awk '{ print $1 }') # is -p a zip/iso or folder?
391 MOUNTPOINT=$(df "$PND" | tail -1|awk '{print $6}') # find out on which mountpoint the pnd is
392 if [ ! -d "$MOUNTPOINT" ] || [ $MOUNTPOINT = "/" ]; then
396 [ ! -z $APPDATASET ] || [ -z ${MOUNTPOINT} ] && APPDATADIR=${APPDATADIR:-$(dirname $PND)/$PND_NAME}
397 APPDATADIR=${APPDATADIR:-${MOUNTPOINT}/pandora/appdata/${PND_NAME}}
399 LOGFILE="/tmp/pndrun_${PND_NAME}.out"
401 #PND_NAME really should be something sensible and somewhat unique
402 #if -b is set use that as pnd_name, else generate it from PND
403 #get basename (strip extension if file) for union mountpoints etc, maybe this should be changed to something specified inside the xml
404 #this should probably be changed to .... something more sensible
405 #currently only everything up to the first '.' inside the filenames is used.
406 PND_NAME=${PND_NAME:-"$(basename $PND | cut -d'.' -f1)"}
408 if [[ $ACTION != "run" ]];then #not logging mount and umount as these are from command-line
411 main > $LOGFILE 2>&1 &