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