pnd_run.sh: Applied patch by Paul Brook (pbrook) to fix the broken
[pandora-libraries.git] / testdata / scripts / pnd_run.sh
1 #!/bin/bash
2  
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]
4 # -s startdir
5 # arguments can be inside -e, -a is optional
6  
7 #/etc/sudoers needs to be adjusted if you touch any of the sudo lines
8  
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
11  
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
17 #cleanup
18 #Rewrite! - this sucks
19
20 showHelp() {
21         cat <<endHELP
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
24 endHELP
25 }
26
27 list_using_fs() {
28         for p in $(fuser -m $1 2>/dev/null);do ps hf $p;done
29 }
30
31 runApp() {
32         cd "/mnt/utmp/$PND_NAME"                # cd to union mount
33         if [ "$STARTDIR" ] && [ -d "$STARTDIR" ]; then
34                 cd "$STARTDIR";                 # cd to folder specified by the optional arg -s
35         fi
36         echo "[------------------------------]{ App start }[---------------------------------]"
37         LD_LIBRARY_PATH="/mnt/utmp/$PND_NAME" "./$EXENAME" $ARGUMENTS 
38                                                 # execute app with ld_lib_path set to the union mount, a bit evil but i think its a good solution
39
40         #the app could have exited now, OR it went into bg, we still need to wait in that case till it really quits!
41         PID=$(pidof -o %PPID -x \"$EXENAME\")   # get pid of app
42         while [ "$PID" ];do                     # wait till we get no pid back for tha app, again a bit ugly, but it works
43                 sleep 10s
44                 PID=`pidof -o %PPID -x \"$EXENAME\"`
45         done
46         echo "[-------------------------------]{ App end }[----------------------------------]"
47 }
48
49 mountPnd() {
50         #create mountpoints, check if they exist already first to avoid annoying error messages
51         if ! [ -d "/mnt/pnd/${PND_NAME}" ]; then 
52                 sudo mkdir -p "/mnt/pnd/${PND_NAME}"            #mountpoint for iso, ro
53         fi 
54         #writeable dir for union
55         if ! [ -d "${MOUNTPOINT}/pandora/appdata/${PND_NAME}" ]; then 
56                 sudo mkdir -p "${MOUNTPOINT}/pandora/appdata/${PND_NAME}"
57                 sudo chmod -R a+xrw "${MOUNTPOINT}/pandora/appdata/${PND_NAME}" 2>/dev/null
58         fi
59         if ! [ -d "/mnt/utmp/${PND_NAME}" ]; then
60                 sudo mkdir -p "/mnt/utmp/${PND_NAME}"           # union over the two
61         fi
62         rm  /tmp/cpuspeed
63         if ! [ -f "${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed" ]; then
64                 if [ ${cpuspeed:-$(cat /proc/pandora/cpu_mhz_max)} -gt $(cat /proc/pandora/cpu_mhz_max) ]; then 
65                    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")
66                   if [ ${cpuselection} = "yes" ]; then  
67                         cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed   
68                         sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
69                   elif [ ${cpuselection} = "custom" ]; then     
70                         cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed           
71                         sudo /usr/pandora/scripts/op_cpuspeed.sh
72                   elif [ ${cpuselection} = "customsave" ]; then 
73                         cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed           
74                         sudo /usr/pandora/scripts/op_cpuspeed.sh
75                         zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed"
76                         cat /proc/pandora/cpu_mhz_max > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
77                  elif [ ${cpuselection} = "yessave" ]; then     
78                         cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed           
79                         zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed"
80                         sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
81                         cat /proc/pandora/cpu_mhz_max > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
82                  elif [ ${cpuselection} = "nosave" ]; then                      
83                         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"
84                         echo 9999 > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
85                 fi
86                fi
87         else
88                 cpuspeed=$(cat "${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed")
89                 if [ "$cpuspeed" -lt "1500" ]; then
90                   cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed
91                   echo Setting to CPU-Speed $cpuspeed MHz
92                   sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
93                 fi
94         fi
95         #is the union already mounted? if not mount evrything, else launch the stuff
96         mount | grep "on /mnt/utmp/${PND_NAME} type"
97         if [ $? -ne 0 ];then
98                 echo not mounted on loop yet, doing so
99                 #check if pnd is already attached to loop 
100                 LOOP=$(sudo losetup -a | grep "$PND" | tail -n1 | awk -F: '{print $1}')
101                 #check if the loop device is already mounted
102                 if ! [ -z "$LOOP" ];then
103                         loopmountedon=$( mount | grep "$(mount | grep "$LOOP" | awk '{print $3}')" | grep utmp | awk '{print $3}' )
104                 else
105                         loopmountedon=""
106                 fi
107                 echo "LoopMountedon: $loopmountedon"
108                 if [ ! "$loopmountedon" ]; then #check if the pnd is already attached to some loop device but not used
109                         FREELOOP=$LOOP 
110                         #reuse existing loop
111                         if [ ! "$LOOP" ]; then
112                                 FREELOOP=$(sudo /sbin/losetup -f) #get first free loop device
113                                 echo $FREELOOP
114                                 if [ ! "$FREELOOP" ]; then  # no free loop device, create a new one
115                                             #find a free loop device and use it 
116                                             usedminor=$(sudo /sbin/losetup -a | tail -n1)
117                                             usedminor=${usedminor:9:1}
118                                             echo usedminor $usedminor
119                                             freeminor=$(($usedminor+1))
120                                             echo freeminor $freeminor
121                                             sudo mknod -m777 /dev/loop$freeminor b 7 $freeminor
122                                             FREELOOP=/dev/loop$freeminor
123                                 fi
124                         fi
125                         #detect fs
126
127                         case $PND_FSTYPE in
128                         ISO)
129                                 sudo /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
130                                 mntline="sudo mount" #setup the mountline for later
131                                 mntdev="${FREELOOP}"
132                                 #mntline="sudo mount -o loop,mode=777 $PND /mnt/pnd/$PND_NAME"
133                                 echo "Filetype is $PND_FSTYPE";;
134                         directory)
135                                 #we bind the folder, now it can be treated in a unified way 
136                                 #ATENTION: -o ro doesnt work for --bind at least on 25, on 26 its possible using remount, may have changed on 27
137                                 mntline="sudo mount --bind -o ro"
138                                 mntdev="${PND}"
139                                 echo "Filetype is $PND_FSTYPE";;
140                         Squashfs)
141                                 sudo /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
142                                 mntline="sudo mount -t squashfs"
143                                 mntdev="${FREELOOP}"
144                                 echo "Filetype is $PND_FSTYPE";;
145                         *)
146                                 echo "error determining fs, output was $PND_FSTYPE"
147                                 exit 1;;
148                         esac
149
150                         echo "$mntline"
151                         $mntline "$mntdev" "/mnt/pnd/${PND_NAME}" #mount the pnd/folder
152                         echo "mounting union!"
153                         FILESYSTEM=$(mount | grep "on $MOUNTPOINT " | grep -v rootfs | awk '{print $5}' | tail -n1) #get filesystem appdata is on to determine aufs options
154                         echo "Filesystem is $FILESYSTEM"
155                         if [[ "$FILESYSTEM" = "vfat" ]]; then # use noplink on fat, dont on other fs's 
156                                 #append is fucking dirty, need to clean that up
157                                 sudo mount -t aufs -o exec,noplink,dirs="$MOUNTPOINT/pandora/appdata/$PND_NAME=rw+nolwh":"/mnt/pnd/$PND_NAME=rr$append" none "/mnt/utmp/$PND_NAME"
158                                 # put union on top
159                         else
160                                 sudo mount -t aufs -o exec,dirs="$MOUNTPOINT/pandora/appdata/$PND_NAME=rw+nolwh":"/mnt/pnd/$PND_NAME=rr$append" none "/mnt/utmp/$PND_NAME" 
161                                 # put union on top
162                         fi
163                 else #the pnd is already mounted but a mount was requested with a different basename/uid, just link it there
164                               echo $LOOP already mounted on $loopmountedon skipping losetup - putting link to old mount
165                               #this is bullshit
166                               sudo rmdir "/mnt/utmp/$PND_NAME"
167                               sudo ln -s $loopmountedon "/mnt/utmp/$PND_NAME" 
168                 fi
169         
170         else
171                 echo "Union already mounted"
172         fi
173 }
174
175 unmountPnd() {
176         sudo umount "/mnt/utmp/$PND_NAME" #umount union
177         if [ -f /tmp/cpuspeed ]; then
178                 cpuspeed=$(cat /tmp/cpuspeed)
179                 sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
180                 rm /tmp/cpuspeed
181         fi
182         if [ -z "$(mount |grep utmp/$PND_NAME|cut -f3 -d' ')" ]; then
183                 # check if the umount was successfull, if it wasnt it would mean that theres still something running so we skip this stuff, 
184                 # this WILL lead to clutter if it happens, so we should make damn sure it never happens
185                 # umount the actual pnd
186                 sudo umount "/mnt/pnd/$PND_NAME"
187                 if [ -z "$(mount |grep pnd/$PND_NAME|cut -f3 -d' ')" ]; then
188                         #delete folders created by aufs if empty
189                         sudo rmdir "$MOUNTPOINT/pandora/appdata/$PND_NAME/.wh..wh.plnk" 2>/dev/null
190                         sudo rmdir "$MOUNTPOINT/pandora/appdata/$PND_NAME/.wh..wh..tmp" 2>/dev/null
191                         #delete appdata folder and ancestors if empty
192                         sudo rmdir -p "$MOUNTPOINT/pandora/appdata/$PND_NAME/" 2>/dev/null
193                         #delete tmp mountpoint
194                         if [ -d "/mnt/utmp/$PND_NAME" ];then
195                                 sudo rmdir "/mnt/utmp/$PND_NAME"
196                         else
197                                 sudo rm "/mnt/utmp/$PND_NAME" >/dev/null 2>&1
198                         fi
199                         if [ $PND_FSTYPE = ISO ] || [ $PND_FSTYPE = Squashfs ]; then # check if we where running an iso, clean up loop device if we did
200                                 LOOP=$(sudo losetup -a | grep "$(basename $PND)" | tail -n1 | awk -F: '{print $1}')
201                                 sudo /sbin/losetup -d $LOOP
202                                 sudo rm $LOOP
203                         fi
204                         if [ -d /mnt/pnd/$PND_NAME ];then
205                                 sudo rmdir "/mnt/pnd/$PND_NAME" #delete pnd mountpoint
206                         fi
207
208                         echo cleanup done
209                 else
210                         echo umount failed, didnt clean up. Process still using this FS :
211                         list_using_fs "/mnt/pnd/$PND_NAME"
212                 fi
213         else
214                 echo umount failed, didnt clean up. Process still using this FS :
215                 list_using_fs "/mnt/utmp/$PND_NAME"
216         fi
217 }
218
219 main() {
220         if [ $nox ]; then #the app doesnt want x to run, so we kill it and restart it once the app quits
221                 if [ ! $(pidof X) ]; then 
222                         unset $nox
223                 else
224                         applist=$(lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq)
225                         whitelist=$(cat ~/pndtest/whitelist) #adjust this to a fixed whitelist, maybe in the config dir
226                         filteredlist=$(echo -e "$applist\n\n$whitelist\n\n$whitelist" | sort | uniq -u) #whitelist appended two times so those items are always removed
227                         if [ ${#filteredlist} -ge 1 ]; then
228                                 message=$(echo -e "The following applications are still running, are you sure you want to close x? \n$filteredlist")
229                                 echo -e "?ae[34me[30m?"
230                                 xmessage -center "$message", -buttons yes,no
231                                 if [ $? = 102 ]; then
232                                         exit 1
233                                 fi
234                                 sudo /etc/init.d/slim-init stop
235                                 sleep 5s
236                         else
237                                 echo -e "?ae[34me[30m?"
238                                 xmessage -center "killing x, nothing of value will be lost", -buttons ok,cancel
239                                 if [ $? = 102 ]; then
240                                         exit 1
241                                 fi
242                                 # close x now, do we want to use slim stop or just kill x?
243                                 sudo /etc/init.d/slim-init stop
244                                 sleep 5s
245                         fi
246                 fi
247         fi
248
249         case $ACTION in
250         mount)  mountPnd;;
251         umount) unmountPnd;;
252         run)
253                 mountPnd
254                 oPWD=$(pwd)
255                 runApp
256                 cd $oPWD
257                 unmountPnd;;
258         esac
259
260
261         if [ $nox ]; then #restart x if it was killed
262                 echo "starting x in 5s"
263                 sleep 5
264                 sudo /etc/init.d/slim-init start
265         fi
266 }
267
268 ######################################################################################
269 ####    Parse arguments
270 ##
271
272 TEMP=`getopt -o p:e:a:b:s:m::u::n::x::j:c: -- "$@"`
273  
274 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
275  
276 # Note the quotes around `$TEMP': they are essential!
277 eval set -- "$TEMP"
278  
279 ACTION=run
280 while true ; do
281         case "$1" in
282                 -p) PND=$2;shift 2;;
283                 -e) EXENAME=$2;shift 2 ;;
284                 -b) PND_NAME=$2;shift 2;;
285                 -s) STARTDIR=$2;shift 2;;
286                 -m) ACTION=mount;shift 2;;
287                 -u) ACTION=umount;shift 2;;
288                 -x) nox=1;shift 2;;
289                 -j) append=$2;shift 2;;
290                 -c) cpuspeed=$2;shift 2;;
291                 -a) 
292                         case "$2" in
293                                 "") echo "no arguments"; shift 2 ;;
294                                 *)  echo "args set to \`$2'" ;ARGUMENTS=$2;shift 2 ;;
295                         esac ;;
296                 --) shift ; break ;;
297                 *) echo "Error while parsing arguments!" ; exit 1 ;;
298         esac
299 done
300 if [ ! -e "$PND" ]; then #check if theres a pnd suplied, need to clean that up a bit more
301         echo "ERROR: selected PND file does not exist!"
302         showHelp
303         exit 1
304 fi
305 if [ ! "$EXENAME" ] && [[ "$ACTION" = "run" ]]; then
306         echo "ERROR: no executable name provided!"
307         showHelp
308         exit 1
309 fi
310
311
312 PND_FSTYPE=$(file -b "$PND" | awk '{ print $1 }')       # is -p a zip/iso or folder?
313 MOUNTPOINT=$(df "$PND" | tail -1|awk '{print $6}')      # find out on which mountpoint the pnd is
314 if [ ! -d "$MOUNTPOINT" ] || [ $MOUNTPOINT = "/" ]; then 
315         MOUNTPOINT="";
316 fi
317  
318 #PND_NAME really should be something sensible and somewhat unique
319 #if -b is set use that as pnd_name, else generate it from PND
320 #get basename (strip extension if file) for union mountpoints etc, maybe  this should be changed to something specified inside the xml
321 #this should probably be changed to .... something more sensible
322 #currently only everything up to the first '.' inside the filenames is used.
323 PND_NAME=${PND_NAME:-"$(basename $PND | cut -d'.' -f1)"}
324
325 if [ $nox ]; then
326         main > "/tmp/pndrun${PND_NAME}_$ACTION.out" 2>&1 & 
327         disown
328 else
329         main > "/tmp/pndrun${PND_NAME}_$ACTION.out" 2>&1
330 fi
331
332