pnd_run.sh: Added "Do not change speed and don't ask again".
[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 ${FREELOOP}" #setup the mountline for later
131                                 #mntline="sudo mount -o loop,mode=777 $PND /mnt/pnd/$PND_NAME"
132                                 echo "Filetype is $PND_FSTYPE";;
133                         directory)
134                                 #we bind the folder, now it can be treated in a unified way 
135                                 #ATENTION: -o ro doesnt work for --bind at least on 25, on 26 its possible using remount, may have changed on 27
136                                 mntline="sudo mount --bind -o ro \"${PND}\" "
137                                 echo "Filetype is $PND_FSTYPE";;
138                         Squashfs)
139                                 sudo /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
140                                 mntline="sudo mount -t squashfs  ${FREELOOP}"
141                                 echo "Filetype is $PND_FSTYPE";;
142                         *)
143                                 echo "error determining fs, output was $PND_FSTYPE"
144                                 exit 1;;
145                         esac
146
147                         echo "$mntline"
148                         $mntline "/mnt/pnd/${PND_NAME}" #mount the pnd/folder
149                         echo "mounting union!"
150                         FILESYSTEM=$(mount | grep "on $MOUNTPOINT " | grep -v rootfs | awk '{print $5}' | tail -n1) #get filesystem appdata is on to determine aufs options
151                         echo "Filesystem is $FILESYSTEM"
152                         if [[ "$FILESYSTEM" = "vfat" ]]; then # use noplink on fat, dont on other fs's 
153                                 #append is fucking dirty, need to clean that up
154                                 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"
155                                 # put union on top
156                         else
157                                 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" 
158                                 # put union on top
159                         fi
160                 else #the pnd is already mounted but a mount was requested with a different basename/uid, just link it there
161                               echo $LOOP already mounted on $loopmountedon skipping losetup - putting link to old mount
162                               #this is bullshit
163                               sudo rmdir "/mnt/utmp/$PND_NAME"
164                               sudo ln -s $loopmountedon "/mnt/utmp/$PND_NAME" 
165                 fi
166         
167         else
168                 echo "Union already mounted"
169         fi
170 }
171
172 unmountPnd() {
173         sudo umount "/mnt/utmp/$PND_NAME" #umount union
174         if [ -f /tmp/cpuspeed ]; then
175                 cpuspeed=$(cat /tmp/cpuspeed)
176                 sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed
177                 rm /tmp/cpuspeed
178         fi
179         if [ -z "$(mount |grep utmp/$PND_NAME|cut -f3 -d' ')" ]; then
180                 # check if the umount was successfull, if it wasnt it would mean that theres still something running so we skip this stuff, 
181                 # this WILL lead to clutter if it happens, so we should make damn sure it never happens
182                 # umount the actual pnd
183                 sudo umount "/mnt/pnd/$PND_NAME"
184                 if [ -z "$(mount |grep pnd/$PND_NAME|cut -f3 -d' ')" ]; then
185                         #delete folders created by aufs if empty
186                         sudo rmdir "$MOUNTPOINT/pandora/appdata/$PND_NAME/.wh..wh.plnk" 2>/dev/null
187                         sudo rmdir "$MOUNTPOINT/pandora/appdata/$PND_NAME/.wh..wh..tmp" 2>/dev/null
188                         #delete appdata folder and ancestors if empty
189                         sudo rmdir -p "$MOUNTPOINT/pandora/appdata/$PND_NAME/" 2>/dev/null
190                         #delete tmp mountpoint
191                         if [ -d "/mnt/utmp/$PND_NAME" ];then
192                                 sudo rmdir "/mnt/utmp/$PND_NAME"
193                         else
194                                 sudo rm "/mnt/utmp/$PND_NAME" >/dev/null 2>&1
195                         fi
196                         if [ $PND_FSTYPE = ISO ] || [ $PND_FSTYPE = Squashfs ]; then # check if we where running an iso, clean up loop device if we did
197                                 LOOP=$(sudo losetup -a | grep "$(basename $PND)" | tail -n1 | awk -F: '{print $1}')
198                                 sudo /sbin/losetup -d $LOOP
199                                 sudo rm $LOOP
200                         fi
201                         if [ -d /mnt/pnd/$PND_NAME ];then
202                                 sudo rmdir "/mnt/pnd/$PND_NAME" #delete pnd mountpoint
203                         fi
204
205                         echo cleanup done
206                 else
207                         echo umount failed, didnt clean up. Process still using this FS :
208                         list_using_fs "/mnt/pnd/$PND_NAME"
209                 fi
210         else
211                 echo umount failed, didnt clean up. Process still using this FS :
212                 list_using_fs "/mnt/utmp/$PND_NAME"
213         fi
214 }
215
216 main() {
217         if [ $nox ]; then #the app doesnt want x to run, so we kill it and restart it once the app quits
218                 if [ ! $(pidof X) ]; then 
219                         unset $nox
220                 else
221                         applist=$(lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq)
222                         whitelist=$(cat ~/pndtest/whitelist) #adjust this to a fixed whitelist, maybe in the config dir
223                         filteredlist=$(echo -e "$applist\n\n$whitelist\n\n$whitelist" | sort | uniq -u) #whitelist appended two times so those items are always removed
224                         if [ ${#filteredlist} -ge 1 ]; then
225                                 message=$(echo -e "The following applications are still running, are you sure you want to close x? \n$filteredlist")
226                                 echo -e "?ae[34me[30m?"
227                                 xmessage -center "$message", -buttons yes,no
228                                 if [ $? = 102 ]; then
229                                         exit 1
230                                 fi
231                                 sudo /etc/init.d/slim-init stop
232                                 sleep 5s
233                         else
234                                 echo -e "?ae[34me[30m?"
235                                 xmessage -center "killing x, nothing of value will be lost", -buttons ok,cancel
236                                 if [ $? = 102 ]; then
237                                         exit 1
238                                 fi
239                                 # close x now, do we want to use slim stop or just kill x?
240                                 sudo /etc/init.d/slim-init stop
241                                 sleep 5s
242                         fi
243                 fi
244         fi
245
246         case $ACTION in
247         mount)  mountPnd;;
248         umount) unmountPnd;;
249         run)
250                 mountPnd
251                 oPWD=$(pwd)
252                 runApp
253                 cd $oPWD
254                 unmountPnd;;
255         esac
256
257
258         if [ $nox ]; then #restart x if it was killed
259                 echo "starting x in 5s"
260                 sleep 5
261                 sudo /etc/init.d/slim-init start
262         fi
263 }
264
265 ######################################################################################
266 ####    Parse arguments
267 ##
268
269 TEMP=`getopt -o p:e:a:b:s:m::u::n::x::j:c: -- "$@"`
270  
271 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
272  
273 # Note the quotes around `$TEMP': they are essential!
274 eval set -- "$TEMP"
275  
276 ACTION=run
277 while true ; do
278         case "$1" in
279                 -p) PND=$2;shift 2;;
280                 -e) EXENAME=$2;shift 2 ;;
281                 -b) PND_NAME=$2;shift 2;;
282                 -s) STARTDIR=$2;shift 2;;
283                 -m) ACTION=mount;shift 2;;
284                 -u) ACTION=umount;shift 2;;
285                 -x) nox=1;shift 2;;
286                 -j) append=$2;shift 2;;
287                 -c) cpuspeed=$2;shift 2;;
288                 -a) 
289                         case "$2" in
290                                 "") echo "no arguments"; shift 2 ;;
291                                 *)  echo "args set to \`$2'" ;ARGUMENTS=$2;shift 2 ;;
292                         esac ;;
293                 --) shift ; break ;;
294                 *) echo "Error while parsing arguments!" ; exit 1 ;;
295         esac
296 done
297 if [ ! -e "$PND" ]; then #check if theres a pnd suplied, need to clean that up a bit more
298         echo "ERROR: selected PND file does not exist!"
299         showHelp
300         exit 1
301 fi
302 if [ ! "$EXENAME" ] && [[ "$ACTION" = "run" ]]; then
303         echo "ERROR: no executable name provided!"
304         showHelp
305         exit 1
306 fi
307
308
309 PND_FSTYPE=$(file -b "$PND" | awk '{ print $1 }')       # is -p a zip/iso or folder?
310 MOUNTPOINT=$(df "$PND" | tail -1|awk '{print $6}')      # find out on which mountpoint the pnd is
311 if [ ! -d "$MOUNTPOINT" ] || [ $MOUNTPOINT = "/" ]; then 
312         MOUNTPOINT="";
313 fi
314  
315 #PND_NAME really should be something sensible and somewhat unique
316 #if -b is set use that as pnd_name, else generate it from PND
317 #get basename (strip extension if file) for union mountpoints etc, maybe  this should be changed to something specified inside the xml
318 #this should probably be changed to .... something more sensible
319 #currently only everything up to the first '.' inside the filenames is used.
320 PND_NAME=${PND_NAME:-"$(basename $PND | cut -d'.' -f1)"}
321
322 if [ $nox ]; then
323         main > "/tmp/pndrun${PND_NAME}_$ACTION.out" 2>&1 & 
324         disown
325 else
326         main > "/tmp/pndrun${PND_NAME}_$ACTION.out" 2>&1
327 fi
328
329