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
22 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]
23 Usage for mounting/umounting pnd_run.sh -p your.pnd -b uid -m or -u
28 for p in $(fuser -m $1 2>/dev/null);do ps hf $p;done
33 if ! [ -f "${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed" ]; then
34 if [ ${cpuspeed:-$(cat /proc/pandora/cpu_mhz_max)} -gt $(cat /proc/pandora/cpu_mhz_max) ]; then
35 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")
36 if [ ${cpuselection} = "yes" ]; then
37 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
38 sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
39 elif [ ${cpuselection} = "custom" ]; then
40 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
41 sudo /usr/pandora/scripts/op_cpuspeed.sh
42 elif [ ${cpuselection} = "customsave" ]; then
43 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
44 sudo /usr/pandora/scripts/op_cpuspeed.sh
45 zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed"
46 cat /proc/pandora/cpu_mhz_max > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
47 elif [ ${cpuselection} = "yessave" ]; then
48 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
49 cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed
50 zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed"
51 sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
52 cat /proc/pandora/cpu_mhz_max > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
53 elif [ ${cpuselection} = "nosave" ]; then
54 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"
55 echo 9999 > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
59 cpuspeed=$(cat "${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed")
60 if [ "$cpuspeed" -lt "1500" ]; then
61 CURRENTSPEED=$(cat /proc/pandora/cpu_mhz_max)
62 echo Setting to CPU-Speed $cpuspeed MHz
63 sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
67 cd "/mnt/utmp/$PND_NAME" # cd to union mount
68 if [ "$STARTDIR" ] && [ -d "$STARTDIR" ]; then
69 cd "$STARTDIR"; # cd to folder specified by the optional arg -s
71 echo "[------------------------------]{ App start }[---------------------------------]"
72 if [ -d /mnt/utmp/$PND_NAME/lib ];then
73 export LD_LIBRARY_PATH="/mnt/utmp/$PND_NAME/lib:${LD_LIBRARY_PATH:-"/usr/lib:/lib"}"
75 export LD_LIBRARY_PATH="/mnt/utmp/$PND_NAME:${LD_LIBRARY_PATH:-"/usr/lib:/lib"}"
77 if [ -d /mnt/utmp/$PND_NAME/bin ];then
78 export PATH="/mnt/utmp/$PND_NAME/bin:${PATH:-"/usr/bin:/bin:/usr/local/bin"}"
80 if [ -d /mnt/utmp/$PND_NAME/share ];then
81 export XDG_DATA_DIRS="/mnt/utmp/$PND_NAME/share:$XDG_DATA_DIRS:/usr/share"
83 export XDG_CONFIG_HOME="/mnt/utmp/$PND_NAME"
84 "./$EXENAME" $ARGUMENTS
85 # execute app with ld_lib_path set to the union mount, a bit evil but i think its a good solution
87 #the app could have exited now, OR it went into bg, we still need to wait in that case till it really quits!
88 PID=$(pidof -o %PPID -x \"$EXENAME\") # get pid of app
89 while [ "$PID" ];do # wait till we get no pid back for tha app, again a bit ugly, but it works
91 PID=`pidof -o %PPID -x \"$EXENAME\"`
93 echo "[-------------------------------]{ App end }[----------------------------------]"
95 if [ ! -z "$CURRENTSPEED" ]; then
96 sudo /usr/pandora/scripts/op_cpuspeed.sh $CURRENTSPEED
101 if [ $(id -u) -ne 0 ];then
102 echo "sudo /usr/pandora/scripts/pnd_run.sh -m $PNDARGS"
103 sudo /usr/pandora/scripts/pnd_run.sh -m $PNDARGS
104 mount | grep "on /mnt/utmp/${PND_NAME} type"
106 echo "The Union File-system is not mounted !"
111 #create mountpoints, check if they exist already first to avoid annoying error messages
112 if ! [ -d "/mnt/pnd/${PND_NAME}" ]; then
113 mkdir -p "/mnt/pnd/${PND_NAME}" #mountpoint for iso, ro
115 #writeable dir for union
116 if ! [ -d "${APPDATADIR}" ]; then
117 mkdir -p "${APPDATADIR}"
118 chmod -R a+xrw "${APPDATADIR}" 2>/dev/null
120 # create the union mountpoint
121 if ! [ -d "/mnt/utmp/${PND_NAME}" ]; then
122 mkdir -p "/mnt/utmp/${PND_NAME}" # union over the two
124 #is the union already mounted? if not mount evrything, else launch the stuff
125 mount | grep "on /mnt/utmp/${PND_NAME} type"
127 mount | grep "on /mnt/pnd/${PND_NAME} type"
129 echo not mounted on loop yet, doing so
130 #check if pnd is already attached to loop
131 LOOP=$(losetup -a | grep "$PND" | tail -n1 | awk -F: '{print $1}')
132 #check if the loop device is already mounted
133 if ! [ -z "$LOOP" ];then
134 echo "Found a loop ($LOOP), using it"
135 loopmountedon=$( mount | grep "$(mount | grep "$LOOP" | awk '{print $3}')" | grep utmp | awk '{print $3}' )
139 echo "LoopMountedon: $loopmountedon"
140 if [ ! "$loopmountedon" ]; then #check if the pnd is already attached to some loop device but not used
143 if [ ! "$LOOP" ]; then
144 FREELOOP=$(/sbin/losetup -f) #get first free loop device
146 if [ ! "$FREELOOP" ]; then # no free loop device, create a new one
147 #find a free loop device and use it
148 usedminor=$(/sbin/losetup -a | tail -n1)
149 usedminor=${usedminor:9:1}
150 echo usedminor $usedminor
151 freeminor=$(($usedminor+1))
152 echo freeminor $freeminor
153 mknod -m777 /dev/loop$freeminor b 7 $freeminor
154 FREELOOP=/dev/loop$freeminor
161 /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
162 mntline="mount" #setup the mountline for later
164 #mntline="mount -o loop,mode=777 $PND /mnt/pnd/$PND_NAME"
165 echo "Filetype is $PND_FSTYPE";;
167 #we bind the folder, now it can be treated in a unified way
168 #ATENTION: -o ro doesnt work for --bind at least on 25, on 26 its possible using remount, may have changed on 27
169 mntline="mount --bind -o ro"
171 echo "Filetype is $PND_FSTYPE";;
173 /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
174 mntline="mount -t squashfs"
176 echo "Filetype is $PND_FSTYPE";;
178 echo "error determining fs, output was $PND_FSTYPE"
181 echo "Mounting PND ($mntline) :"
182 $mntline "$mntdev" "/mnt/pnd/${PND_NAME}" #mount the pnd/folder
184 else #the pnd is already mounted but a mount was requested with a different basename/uid, just link it there
185 echo $LOOP already mounted on $loopmountedon skipping losetup - putting link to old mount
187 rmdir "/mnt/utmp/$PND_NAME"
188 ln -s $loopmountedon "/mnt/utmp/$PND_NAME"
191 mount | grep "on /mnt/pnd/${PND_NAME} type"
193 echo "The PND File-system is not mounted ! - Union wont work anyway"
198 echo "the PND is already mounted"
200 FILESYSTEM=$(mount | grep "on $MOUNTPOINT " | grep -v rootfs | awk '{print $5}' | tail -n1) #get filesystem appdata is on to determine aufs options
201 RO=0;for o in $(mount|grep "on $MOUNTPOINT "|sed 's/.*(//;s/)$//;s/,/ /g');do [[ $o = "ro" ]]&& RO=1;done
202 if [ $RO -eq 1 ];then
203 echo "SD-Card is mounted Read-only !! Trying to remount RW"
204 mount -oremount,rw $MOUNTPOINT
206 echo "Filesystem is $FILESYSTEM"
207 echo "Mounting the Union FS using ${APPDATADIR} as Write directory:"
208 if [[ "$FILESYSTEM" = "vfat" ]]; then # use noplink on fat, dont on other fs's
209 #append is fucking dirty, need to clean that up
210 echo mount -t aufs -o exec,noplink,dirs="${APPDATADIR}=rw+nolwh":"/mnt/pnd/$PND_NAME=rr$append" none "/mnt/utmp/$PND_NAME"
211 mount -t aufs -o exec,noplink,dirs="${APPDATADIR}=rw+nolwh":"/mnt/pnd/$PND_NAME=rr$append" none "/mnt/utmp/$PND_NAME"
214 mount -t aufs -o exec,dirs="${APPDATADIR}=rw+nolwh":"/mnt/pnd/$PND_NAME=rr$append" none "/mnt/utmp/$PND_NAME"
218 mount | grep "on /mnt/utmp/${PND_NAME} type"
220 echo "The Union File-system is not mounted !"
225 echo "Union already mounted"
230 #delete folders created by aufs if empty
231 rmdir -rf "${APPDATADIR}/.wh..wh.plnk" 2>/dev/null
232 rmdir -rf "${APPDATADIR}/.wh..wh..tmp" 2>/dev/null
234 #delete appdata folder and ancestors if _empty_
235 rmdir -p "${APPDATADIR}" 2>/dev/null
237 # Clean the loopback device
238 if [ $PND_FSTYPE = ISO ] || [ $PND_FSTYPE = Squashfs ]; then # check if we where running an iso, clean up loop device if we did
239 LOOP=$(losetup -a | grep "$(basename $PND)" | tail -n1 | awk -F: '{print $1}')
240 /sbin/losetup -d $LOOP
248 if mount | grep -q "on /mnt/pnd/${PND_NAME} type";then
249 umount "/mnt/pnd/$PND_NAME"
251 if ! [ -z "$(mount |grep pnd/$PND_NAME|cut -f3 -d' ')" ]; then
252 echo umount PND failed, didnt clean up. Process still using this FS :
253 list_using_fs "/mnt/pnd/$PND_NAME"
255 # removing the now useless mountpoint
256 if [ -d /mnt/pnd/$PND_NAME ];then
257 rmdir "/mnt/pnd/$PND_NAME"
260 # All went well, cleaning
267 if [ $(id -u) -ne 0 ];then
268 sudo /usr/pandora/scripts/pnd_run.sh -u $PNDARGS
272 # Make sure the Union FS is unmounted
273 if mount | grep -q "on /mnt/utmp/${PND_NAME} type";then
274 umount "/mnt/utmp/$PND_NAME" #umount union
276 if ! [ -z "$(mount |grep utmp/$PND_NAME|cut -f3 -d' ')" ]; then
277 echo umount UNION failed, didnt clean up. Process still using this FS :
278 list_using_fs "/mnt/utmp/$PND_NAME"
280 # the Union is umounted, removing the now empty mountpoint
281 if [ -d "/mnt/utmp/$PND_NAME" ];then
282 rmdir "/mnt/utmp/$PND_NAME"
283 elif [ -e "/mnt/utmp/$PND_NAME" ];then
284 rm "/mnt/utmp/$PND_NAME" >/dev/null 2>&1 # as it might be a symlink
286 # Try umounting the PND
292 if [ $nox ]; then #the app doesnt want x to run, so we kill it and restart it once the app quits
293 if [ ! $(pidof X) ]; then
296 applist=$(lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq)
297 whitelist=$(cat ~/pndtest/whitelist) #adjust this to a fixed whitelist, maybe in the config dir
298 filteredlist=$(echo -e "$applist\n\n$whitelist\n\n$whitelist" | sort | uniq -u) #whitelist appended two times so those items are always removed
299 if [ ${#filteredlist} -ge 1 ]; then
300 message=$(echo -e "The following applications are still running, are you sure you want to close x? \n$filteredlist")
301 echo -e "?ae[34me[30m?"
302 xmessage -center "$message", -buttons yes,no
303 if [ $? = 102 ]; then
306 sudo /etc/init.d/slim-init stop
309 echo -e "?ae[34me[30m?"
310 xmessage -center "killing x, nothing of value will be lost", -buttons ok,cancel
311 if [ $? = 102 ]; then
314 # close x now, do we want to use slim stop or just kill x?
315 sudo /etc/init.d/slim-init stop
323 umount) umountUnion;;
327 zenity --warning --title="Mounting the PND failed" --text="Mounting the PND failed. The application wont start. Please have a look at $LOGFILE"
337 if [ $nox ]; then #restart x if it was killed
338 echo "starting x in 5s"
340 sudo /etc/init.d/slim-init start
344 ######################################################################################
350 TEMP=`getopt -o d:p:e:a:b:s:m::u::n::x::j:c: -- $PNDARGS`
351 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
352 eval set -- "$TEMP" # Note the quotes around `$TEMP': they are essential!
358 -e) EXENAME=$2;shift 2 ;;
359 -b) PND_NAME=$2;shift 2;;
360 -s) STARTDIR=$2;shift 2;;
361 -m) ACTION=mount;shift 2;;
362 -u) ACTION=umount;shift 2;;
364 -j) append=$2;shift 2;;
365 -c) cpuspeed=$2;shift 2;;
366 -d) APPDATASET=1;APPDATADIR=$2;shift 2;;
369 "") echo "no arguments"; shift 2 ;;
370 *) echo "args set to \`$2'" ;ARGUMENTS=$2;shift 2 ;;
373 *) echo "Error while parsing arguments!" ; exit 1 ;;
377 if [ ! -e "$PND" ]; then #check if theres a pnd suplied, need to clean that up a bit more
378 echo "ERROR: selected PND($PND) file does not exist!"
383 if [ ! "$EXENAME" ] && [[ "$ACTION" = "run" ]]; then
384 echo "ERROR: no executable name provided!"
389 PND_FSTYPE=$(file -b "$PND" | awk '{ print $1 }') # is -p a zip/iso or folder?
390 MOUNTPOINT=$(df "$PND" | tail -1|awk '{print $6}') # find out on which mountpoint the pnd is
391 if [ ! -d "$MOUNTPOINT" ] || [ $MOUNTPOINT = "/" ]; then
395 [ ! -z $APPDATASET ] || [ -z ${MOUNTPOINT} ] && APPDATADIR=${APPDATADIR:-$(dirname $PND)/$PND_NAME}
396 APPDATADIR=${APPDATADIR:-${MOUNTPOINT}/pandora/appdata/${PND_NAME}}
398 LOGFILE="/tmp/pndrun_${PND_NAME}.out"
400 #PND_NAME really should be something sensible and somewhat unique
401 #if -b is set use that as pnd_name, else generate it from PND
402 #get basename (strip extension if file) for union mountpoints etc, maybe this should be changed to something specified inside the xml
403 #this should probably be changed to .... something more sensible
404 #currently only everything up to the first '.' inside the filenames is used.
405 PND_NAME=${PND_NAME:-"$(basename $PND | cut -d'.' -f1)"}
407 if [[ $ACTION != "run" ]];then #not logging mount and umount as these are from command-line
410 main > $LOGFILE 2>&1 &