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