pnd_run.sh: More tidy-ups, added some null string protection and a warning at the...
[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/basename 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 # parse arguments
21 TEMP=`getopt -o p:e:a:b:s:m::u::n::x::j:c: -- "$@"`
22  
23 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
24  
25 # Note the quotes around `$TEMP': they are essential!
26 eval set -- "$TEMP"
27  
28 while true ; do
29         case "$1" in
30                 -p) echo "pnd set to \`$2'" ;PND=$2;shift 2;;
31                 -e) echo "exec set to \`$2'" ;EXENAME=$2;shift 2 ;;
32 #               -n) echo "n set, no union pls!";NOUNION=1;shift 2;; # we will reuse -n soon,stop using it if you still did!
33                 -b) echo "BASENAME set to $2";BASENAME=$2;shift 2;;
34                 -s) echo "startdir set to $2";STARTDIR=$2;shift 2;;
35                 -m) echo "mount";mount=1;shift 2;;
36                 -u) echo "umount";umount=1;shift 2;;
37                 -x) echo "no x";nox=1;shift 2;;
38                 -j) echo "join/ also mount those folders";append=$2;shift 2;;
39                 -c) echo "set cpu speed to";cpuspeed=$2;shift 2;;
40                 -a) 
41                         case "$2" in
42                                 "") echo "no arguments"; shift 2 ;;
43                                 *)  echo "args set to \`$2'" ;ARGUMENTS=$2;shift 2 ;;
44                         esac ;;
45                 --) shift ; break ;;
46                 *) echo "Error while parsing arguments!" ; exit 1 ;;
47         esac
48 done
49
50 if [ ! -e "$PND" ]; then #check if theres a pnd suplied, need to clean that up a bit more
51         echo "ERROR: selected PND file does not exist!"
52         echo "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]"
53         exit 1
54 fi
55 if [ ! "$EXENAME" ]; then
56         if [ ! $mount ] && [ ! $umount ]; then
57                 echo "ERROR: no executable name provided!"
58                 echo "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]"
59                 echo "Usage for mounting/umounting pnd_run.sh -p your.pnd -b uid -m or -u"
60                 exit 1
61         fi
62 fi
63
64 fork () {
65 echo in fork!
66 if [ $nox ]; then #the app doesnt want x to run, so we kill it and restart it once the app quits
67         if [ ! $(pidof X) ]; then 
68                 unset $nox
69         else
70                 applist=$(lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq)
71                 whitelist=$(cat ~/pndtest/whitelist) #adjust this to a fixed whitelist, maybe in the config dir
72                 filteredlist=$(echo -e "$applist\n\n$whitelist\n\n$whitelist" | sort | uniq -u) #whitelist appended two times so those items are always removed
73                 if [ ${#filteredlist} -ge 1 ]; then
74                         message=$(echo -e "The following applications are still running, are you sure you want to close x? \n$filteredlist")
75                         echo -e ?ae[34me[30m?
76                         xmessage -center "$message", -buttons yes,no
77                         if [ $? = 102 ]; then
78                         exit 1
79                         fi
80                         sudo /etc/init.d/slim-init stop
81                         sleep 5s
82                 else
83                         echo -e ?ae[34me[30m?
84                         xmessage -center "killing x, nothing of value will be lost", -buttons ok,cancel
85                         if [ $? = 102 ]; then
86                         exit 1
87                         fi
88                         # close x now, do we want to use slim stop or just kill x?
89                         sudo /etc/init.d/slim-init stop
90                         sleep 5s
91                 fi
92         fi
93 fi
94  
95 #vars
96 echo "PND ++ $PND"
97 DFS=$(file -b "$PND" | awk '{ print $1 }') #is -p a zip/iso or folder?
98 MOUNTPOINT=$(df "$PND" | sed -ne 's/.*\% \(\S*\)/\1/p' | tail -n1) #find out on which mountpoint the pnd is
99 if [ ! -d "/.$MOUNTPOINT" ]; then MOUNTPOINT="/"; fi #make sure folder exists, if it doesnt assume rootfs
100
101 #if the pnd is on / set mountpoint to "" so we dont and up with // at the start,
102 #this is to make sure sudo doesnt get confused
103 if [ "$MOUNTPOINT" = "/" ]; then MOUNTPOINT=""; fi
104 echo "mountpoint :${MOUNTPOINT}:"
105  
106 #BASENAME really should be something sensible and somewhat unique
107 #if -b is set use that as basename, else generate it from PND
108 #get basename (strip extension if file) for union mountpoints etc, maybe  this should be changed to something specified inside the xml
109 #this should probably be changed to .... something more sensible
110 #currently only everything up to the first '.' inside the filenames is used.
111 if [ ! "$BASENAME" ]; then BASENAME=$(basename $PND | cut -d'.' -f1) ; fi
112  
113 echo "Basename: $BASENAME"
114  
115 if [ ! $umount ]; then 
116
117         oCWD=$(pwd)
118         #create mountpoints, check if they exist already first to avoid annoying error messages
119         if [ ! -d "/mnt/pnd/${BASENAME}" ]; then sudo mkdir -p "/mnt/pnd/${BASENAME}" ; echo "mkdir -p /mnt/pnd/${BASENAME}"; fi #mountpoint for iso, ro
120         #writeable dir for union
121         if [ ! -d "${MOUNTPOINT}/pandora/appdata/${BASENAME}" ]; then sudo mkdir -p "${MOUNTPOINT}/pandora/appdata/${BASENAME}"; echo "mkdir -p ${MOUNTPOINT}/pandora/appdata/${BASENAME}"; sudo chmod -R a+xrw "${MOUNTPOINT}/pandora/appdata/${BASENAME}"; fi
122         if [ ! -d "/mnt/utmp/${BASENAME}" ]; then sudo mkdir -p "/mnt/utmp/${BASENAME}"; echo "/mnt/utmp/${BASENAME}"; fi #union over the two
123
124         if [ $cpuspeed ]; then
125                 if [ ! $cpuspeed -eq $(cat /proc/pandora/cpu_mhz_max) ]; then 
126                   gksu --message "$BASENAME wants to set the cpu speed to $cpuspeed, enter root password to allow" echo $cpuspeed > /proc/pandora/cpu_mhz_max
127                 fi
128         fi
129         #is the union already mounted? if not mount evrything, else launch the stuff
130         mount | grep "on /mnt/utmp/${BASENAME} type" # > /dev/null
131         if [ ! $? -eq 0 ]; then 
132
133                 echo not mounted on loop yet, doing so
134                 #check if pnd is already attached to loop 
135                 LOOP=$(sudo losetup -a | grep "$PND" | tail -n1 | awk -F: '{print $1}')
136                 if [ $LOOP ]; then
137                         #check if the loop device is already mounted
138                         loopmountedon=$( mount | grep $(mount | grep $LOOP | awk '{print $3}') | grep utmp | awk '{print $3}' )
139                 fi
140                 echo "LoopMountedon: $loopmountedon"
141                 if [ ! "$loopmountedon" ]; then #check if the pnd is already attached to some loop device but not used
142                         FREELOOP=$LOOP 
143                         #reuse existing loop
144                         if [ ! "$LOOP" ]; then
145                                 FREELOOP=$(sudo /sbin/losetup -f) #get first free loop device
146                                 echo $FREELOOP
147                                 if [ ! "$FREELOOP" ]; then  # no free loop device, create a new one
148                                             #find a free loop device and use it 
149                                             usedminor=$(sudo /sbin/losetup -a | tail -n1)
150                                             usedminor=${usedminor:9:1}
151                                             echo usedminor $usedminor
152                                             freeminor=$(($usedminor+1))
153                                             echo freeminor $freeminor
154                                             sudo mknod -m777 /dev/loop$freeminor b 7 $freeminor
155                                             FREELOOP=/dev/loop$freeminor
156                                 fi
157                         fi
158                           #detect fs
159                         
160                         if [ $DFS = ISO ]; then
161                                 sudo /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
162                                 mntline="sudo mount ${FREELOOP}" #setup the mountline for later
163                                 #mntline="sudo mount -o loop,mode=777 $PND /mnt/pnd/$BASENAME"
164                                 echo "Filetype is $DFS"
165                         elif [ $DFS = directory ]; then
166                                   mntline="sudo mount --bind -o ro \"${PND}\" "
167                           #we bind the folder, now it can be treated in a unified way ATENTION: -o ro doesnt work for --bind at least on 25, on 26 its possible using remount, may have changed on 27
168                                   echo "Filetype is $DFS"
169                         elif [ $DFS = Squashfs ]; then
170                                   sudo /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
171                                   mntline="sudo mount -t squashfs  ${FREELOOP}"
172                                   echo "Filetype is $DFS"
173                         else
174                                   echo "error determining fs, output was $DFS"
175                                   exit 1;
176                         fi
177
178                         echo "$mntline"
179                         $mntline "/mnt/pnd/${BASENAME}" #mount the pnd/folder
180                         echo "mounting union!"
181                         FILESYSTEM=$(mount | grep "on $MOUNTPOINT " | grep -v rootfs | awk '{print $5}' | tail -n1) #get filesystem appdata is on to determine aufs options
182                         echo "Filesystem is $FILESYSTEM"
183                         if [ x$FILESYSTEM = xvfat ]; then # use noplink on fat, dont on other fs's 
184                                 #append is fucking dirty, need to clean that up
185                                 sudo mount -t aufs -o exec,noplink,dirs="$MOUNTPOINT/pandora/appdata/$BASENAME=rw+nolwh":"/mnt/pnd/$BASENAME=rr$append" none "/mnt/utmp/$BASENAME" # put union on top
186                                 else
187                                 sudo mount -t aufs -o exec,dirs="$MOUNTPOINT/pandora/appdata/$BASENAME=rw+nolwh":"/mnt/pnd/$BASENAME=rr$append" none "/mnt/utmp/$BASENAME" # put union on top
188                         fi
189                 else #the pnd is already mounted but a mount was requested with a different basename/uid, just link it there
190                               echo $LOOP already mounted on $loopmountedon skipping losetup - putting link to old mount
191                               #this is bullshit
192                               sudo rmdir "/mnt/utmp/$BASENAME"
193                               sudo ln -s $loopmountedon "/mnt/utmp/$BASENAME" 
194                 fi
195         
196         else
197                 echo "Union already mounted"
198         fi
199  
200         if [ $mount ]; then echo "mounted /mnt/utmp/$BASENAME"; exit 1; fi; #mount only, die here
201         
202         cd "/mnt/utmp/$BASENAME" # cd to union mount
203         if [ "$STARTDIR" ]; then cd "$STARTDIR"; fi #cd to folder specified by the optional arg -s
204         LD_LIBRARY_PATH="/mnt/utmp/$BASENAME" "./$EXENAME" $ARGUMENTS # execute app with ld_lib_path set to the union mount, a bit evil but i think its a good solution
205         #the app could have exited now, OR it went into bg, we still need to wait in that case till it really quits!
206         PID=`pidof -o %PPID -x \"$EXENAME\"` #get pid of app
207         while [ "$PID" ] #wait till we get no pid back for tha app, again a bit ugly, but it works
208         do
209                 sleep 10s
210                 PID=`pidof -o %PPID -x \"$EXENAME\"`
211         done
212         echo app exited
213         #app exited
214         cd $oCWD #cd out of the mountpoint so we can umount, doesnt really matter to where...
215 else
216 echo "-u set, nothing to do here"
217 fi
218  
219 #clean up
220 echo Un-Mounting, expect some warnings
221 sudo rmdir "/mnt/utmp/$BASENAME"
222 sudo rm "/mnt/utmp/$BASENAME"
223 sudo umount "/mnt/utmp/$BASENAME" #umount union
224 if [ $? -eq 0 ]; then # check if the umount was successfull, if it wasnt it would mean that theres still something running so we skip this stuff, this WILL lead to clutter if it happens, so we should make damn sure it never happens
225         #umount the actual pnd
226         sudo umount "/mnt/pnd/$BASENAME"
227         #delete folders created by aufs if empty
228         sudo rmdir "$MOUNTPOINT/pandora/appdata/$BASENAME/.wh..wh.plnk"
229         sudo rmdir "$MOUNTPOINT/pandora/appdata/$BASENAME/.wh..wh..tmp"
230         #delete appdata folder and ancestors if empty
231         sudo rmdir -p "$MOUNTPOINT/pandora/appdata/$BASENAME/"
232         #delete tmp mountpoint
233         sudo rmdir "/mnt/utmp/$BASENAME"
234         if [ $DFS = ISO ] || [ $DFS = Squashfs ]; then # check if we where running an iso, clean up loop device if we did
235                 LOOP=$(sudo losetup -a | grep $(basename $PND) | tail -n1 | awk -F: '{print $1}')
236                 sudo /sbin/losetup -d $LOOP
237                 sudo rm $LOOP
238         fi
239         sudo rmdir "/mnt/pnd/$BASENAME" #delete pnd mountpoint
240         echo cleanup done
241 else
242         echo umount failed, didnt clean up
243 fi
244
245 if [ $nox ]; then #restart x if it was killed
246         echo "starting x in 5s"
247         sleep 5
248         sudo /etc/init.d/slim-init start
249 fi
250
251 } #function end!
252
253 if [ $nox ]; then
254         echo forking now!
255         fork &> "/tmp/pndrun$BASENAME$mount.out" & 
256         disown
257 else
258         echo Running with x, not disowning!
259         fork &> "/tmp/pndrun$BASENAME$mount.out"
260 fi