abf1b1ef4a9ae9b5d3a536f9770ab258684eb81b
[pandora-libraries.git] / testdata / scripts / pnd_run.sh
1 #!/bin/bash
2  
3 #/etc/sudoers needs to be adjusted if you touch any of the sudo lines
4  
5 # look at the comments in the CLOSE_X part, adjust 
6 #use "lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq > whitelist" with nothing running to generate the whitelist
7  
8 #todo - no proper order
9 #validate params better
10 #make uid/pnd_name mandatory (and rename var, its confusing!)
11 #find a clean way of shutting down x without a fixed dm, mabye avoid nohup usage somehow
12 #add options to just mount iso without union and to mount the union later
13
14 #SCRIPT_DIR=$(echo $(dirname $(which $0))|sed 's#^\.#'"$(pwd)"'#')
15 #. $SCRIPT_DIR/pnd_loging
16 #PND_LogDateFormat=PND_Time
17
18 PND_MOUNT_DIR="/mnt/pnd"
19 UNION_MOUNT_DIR="/mnt/utmp"
20 CPUSPEEDSCRIPT=/usr/pandora/scripts/op_cpuspeed.sh
21
22 #=============================================================================
23 # Log functions
24
25 PND_isInteractive=0
26 PND_Start() {
27         if [ $(ps -o tty,pid 2>/dev/null|grep $$|awk 'BEGIN{R=0}/pts/{R=1}END{print R}') -eq 1 ];then
28                 PND_isInteractive=1
29                 exec 3>&1       # duplicate stdout so we can still write to screen after the log redirect
30         fi
31         {
32         echo "======================================================================================="
33         for v in $PND_HEADER;do
34                 printf "%-15s : %s\n" "$v"  "$(eval "echo \${$v:-'<unset>'}")"
35         done
36         echo "======================================================================================="
37         }>"$PND_LOG"
38 }
39
40 PND_checkLog() {
41 awk 'BEGIN{R=0}END{exit R}
42 /cannot open display/||/unary operator expected/||/No such file or directory/||/command not found/{R=R+1}
43 {IGNORECASE=1}
44 !/gpg-error/&&/ERROR/||/FAILED/{R=R+1}
45 {IGNORECASE=0}' < "$PND_LOG"
46 }
47
48 PND_Stop() {
49         local RC=$?
50         PND_checkLog
51         RC=$(( $RC + $? ))      # trying to find error in the logs
52         {
53         echo "======================================================================================="
54         echo "Return code is : $RC"
55         }>>"$PND_LOG"
56         return $RC
57 }
58
59 PND_BeginTask() {
60         export PND_TASK_NAME="$*"
61         echo "[ START ]--- $PND_TASK_NAME ----------"
62         if [ $PND_isInteractive -eq 1 ];then
63                 printf "$PND_TASK_NAME"  >&3
64         fi
65 }
66
67 PND_EndTask() {
68         local RC="$?"
69         local STATUS=""
70         local COLOR=""
71         local X=""
72         if [ $RC -eq 0 ];then 
73                 STATUS=SUCCESS
74                 COLOR="\\033[32m"
75         else
76                 STATUS=FAILED
77                 COLOR="\\033[31m"
78         fi
79         
80         printf "[%7s]--- $PND_TASK_NAME ----------\n" "$STATUS"
81         if [ $PND_isInteractive -eq 1 ];then
82                 printf "\r%s\033[70G[$COLOR%7s\033[m]\n" "$PND_TASK_NAME" "$STATUS" >&3
83         fi
84         unset PND_TASK_NAME
85         return $RC
86 }
87
88 PND_WaitFor() {
89         [ $# -gt 0 ]||return 1
90         local l_test="$1"
91         local l_name=${2:-"Wait succes of $1"}
92         local l_cnt=${3:-12}
93         local l_sleep=${4:-10}
94         local C=0
95         PND_BeginTask $l_name
96         while [ $C -lt $l_cnt ] && ! eval $l_test;do
97                 sleep $l_sleep;C=$(($C + 1));
98         done
99         [ $C -lt $l_cnt ]
100         PND_EndTask
101 }
102
103 PND_WaitForExit() {
104         local l_sleep=1
105         PID=$(pidof -o %PPID -x "$1")   # get pid of app
106         while [ -n "$PID" ]; do
107                 sleep $l_sleep
108                 test $l_sleep -lt 10 && l_sleep=$(($l_sleep + 1))
109                 PID=$(pidof -o %PPID -x "$1")
110         done
111 }
112
113 PND_Exec() {
114         local CMD="$*"
115         {
116         if [ $PND_ISEXEC -eq 0 ];then
117                 PND_ISEXEC=1
118                 exec 3>&1               # 
119         fi
120         export PND_INTERACTIVE=2
121         $* 2>&1
122         RES=$(( $? + $PND_ERRORS ))
123         echo "<result>$RES</result>"
124         PND_ISEXEC=0
125         exec 3>&-
126         }|{
127         while read line;do
128                 if echo "$line"|grep -q "<result>.*</result>";then
129                         return $(( $(echo $line|sed 's/<[^>]*>//g') + $PND_ERRORS ))
130                 elif ! echo "$line"| $(eval $PND_OUT_CHECK); then
131                         PND_Error "$line";
132                 else
133                         PND_Print "$line";
134                 fi
135         done
136         return $PND_ERRORS
137         }
138 }
139
140
141
142 #=============================================================================
143 # Utility functions
144
145 showHelp() {
146         cat <<endHELP
147 Usage:
148   pnd_run.sh -p file.pnd -e cmd [-a args] [-b pndid] [-s path] [-c speed] [-d [path]] [-x] [-m] [-u] [-- more_args]
149     -p file.pnd : Specify the pnd file to execute
150     -e cmd      : Command to run
151     -a args     : Arguments to the command
152     -b pndid    : name of the directory mount-point ($UNION_MOUNT_DIR/pndid) (Default: name of the pnd file)
153     -s path     : Directory in the union to start the command from
154     -o speed    : Set the CPU speed
155     -d [path]   : Use path as source of the overlay. (Default: pandora/appdata/pndid)
156     -x          : Stop X before starting the apps
157     -m          : Only mount the pnd, dont run it (-e become optional)
158     -u          : Only umount the pnd, dont run it (-e become optional)
159
160   If '--' is specified, all subsequent arguments are passed through to the command
161   (useful if you want to pass quotes and weird chars to the command)
162 endHELP
163 }
164
165 list_using_fs() {
166         for p in $(fuser -m $1 2>/dev/null);do ps hf $p;done
167 }
168
169
170 #=============================================================================
171 # CPU speed functions
172 PND_getCPUSpeed() {
173         cat /proc/pandora/cpu_mhz_max
174 }
175
176 PND_setCPUSpeed() {
177         unset CURRENTSPEED
178         if ! [ -f "$CPUSPEED_FILE" ] && [ ! -z "$PND_CPUSPEED" ]; then
179                 if [ ${PND_CPUSPEED} -gt $(PND_getCPUSpeed) ]; then 
180                    CURRENTSPEED=$(PND_getCPUSpeed)
181                    case "$(zenity --title="set cpu speed" --height=350 --list --column "id" --column "Please select" --hide-column=1 \
182                                   --text="$PND_NAME suggests to set the cpu speed to $PND_CPUSPEED MHz to make it run properly.\n\n Do you want to change the cpu speed? (current speed: $(PND_getCPUSpeed) MHz)\n\nWarning: Setting the clock speed above 600MHz can be unstable and it NOT recommended!" \
183                                   "yes" "Yes, set it to $PND_CPUSPEED MHz" \
184                                   "custom" "Yes, select custom value" \
185                                   "yessave" "Yes, set it to $PND_CPUSPEED MHz and don't ask again" \
186                                   "customsave" "Yes, set it to custom speed and don't ask again" \
187                                   "no" "No, don't change the speed" \
188                                   "nosave" "No, don't chage the speed and don't ask again")" in
189                         "yes")
190                                 sudo $CPUSPEEDSCRIPT $PND_CPUSPEED
191                                 ;;
192                         "custom")
193                                 sudo $CPUSPEEDSCRIPT
194                                 ;;
195                         "customsave")
196                                 sudo $CPUSPEEDSCRIPT
197                                 zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n$CPUSPEED_FILE"
198                                 PND_getCPUSpeed > $CPUSPEED_FILE
199                                 ;;
200                         "yessave")
201                                 zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n$CPUSPEED_FILE"
202                                 sudo $CPUSPEEDSCRIPT $PND_CPUSPEED
203                                 PND_getCPUSpeed > $CPUSPEED_FILE
204                                 ;;
205                         "nosave")
206                                 unset CURRENTSPEED
207                                 zenity --info --title="Note" --text="Speed will not be changed.\n\nTo re-enable this dialogue, please delete the file\n$CPUSPEED_FILE"
208                                 echo 9999 > $CPUSPEED_FILE
209                                 ;;
210                         *)      unset CURRENTSPEED;;
211                   esac
212                fi
213         elif [ "$PND_CPUSPEED" -lt "1500" ]; then
214                 CURRENTSPEED=$(PND_getCPUSpeed)
215                 echo Setting to CPU-Speed $PND_CPUSPEED MHz
216                 sudo $CPUSPEEDSCRIPT $PND_CPUSPEED
217         fi
218 }
219
220 PND_resetCPUSpeed() {
221         if [ ! -z "$CURRENTSPEED" ]; then
222                 sudo $CPUSPEEDSCRIPT $CURRENTSPEED
223         fi
224 }
225
226 #=============================================================================
227 # X management functions
228
229 PND_CloseX(){
230         if [ $CLOSE_X ]; then #the app doesnt want x to run, so we kill it and restart it once the app quits
231                 if [ ! $(pidof X) ]; then 
232                         unset $CLOSE_X
233                 else
234                         applist=$(lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq)
235                         whitelist=$(cat ~/pndtest/whitelist) #adjust this to a fixed whitelist, maybe in the config dir
236                         filteredlist=$(echo -e "$applist\n\n$whitelist\n\n$whitelist" | sort | uniq -u) #whitelist appended two times so those items are always removed
237                         if [ ${#filteredlist} -ge 1 ]; then
238                                 message=$(echo -e "The following applications are still running, are you sure you want to close x? \n$filteredlist")
239                                 echo -e "?ae[34me[30m?"
240                                 xmessage -center "$message", -buttons yes,no
241                                 if [ $? = 102 ]; then
242                                         exit 1
243                                 fi
244                                 sudo /etc/init.d/slim-init stop
245                                 sleep 5s
246                         else
247                                 echo -e "?ae[34me[30m?"
248                                 xmessage -center "killing x, nothing of value will be lost", -buttons ok,cancel
249                                 if [ $? = 102 ]; then
250                                         exit 1
251                                 fi
252                                 # close x now, do we want to use slim stop or just kill x?
253                                 sudo /etc/init.d/slim-init stop
254                                 sleep 5s
255                         fi
256                 fi
257         fi
258 }
259
260 PND_RestartX(){
261         if [ $CLOSE_X ]; then #restart x if it was killed
262                 # We need to wait a bit, doing it nicely ;)
263                 sleep 5
264                 sudo /etc/init.d/slim-init start
265         fi
266 }
267
268
269 #=============================================================================
270 # (u)Mounting functions
271
272 show_mounted_info(){
273         echo "+++++++"
274         echo "Loopback devices :"
275         sudo /sbin/losetup -a
276         echo "Are mounted on :"
277         mount|grep loop
278         echo "For these Union :"
279         mount|grep aufs
280 }
281
282 is_union_mounted() {
283         mount | grep -q "on $UNION_MOUNT_DIR/${PND_NAME} type aufs"
284 }
285
286 is_pnd_mounted() {
287         mount |grep -v aufs | grep -q "on $PND_MOUNT_DIR/${PND_NAME} type" || \
288         mount |grep -v aufs | grep -q "on $UNION_MOUNT_DIR/${PND_NAME} type"
289 }
290
291 noMoreProcessPnd() {
292         [ -z "$(list_using_fs "$PND_MOUNT_DIR/$PND_NAME")" ]
293 }
294
295 noMoreProcessUnion() {
296         [ -z "$(list_using_fs "$UNION_MOUNT_DIR/$PND_NAME")" ]
297 }
298
299 mountPnd() {
300         MOUNT_TARGET="${1:-$PND_MOUNT_DIR}"
301         if ! is_pnd_mounted;then
302                 #check if pnd is already attached to loop 
303                 LOOP=$(/sbin/losetup -a | grep "$PND" | tail -n1 | awk -F: '{print $1}')
304                 #check if the loop device is already mounted
305                 if ! [ -z "$LOOP" ];then
306                         echo "Found a loop ($LOOP), using it"
307                         loopmountedon=$( mount | grep "$(mount | grep "$LOOP" | awk '{print $3}')" | grep utmp | awk '{print $3}' )
308                 else
309                         loopmountedon=""
310                 fi
311                 if [ ! "$loopmountedon" ]; then #check if the pnd is already attached to some loop device but not used
312                         FREELOOP=$LOOP 
313                         #reuse existing loop
314                         if [ ! "$LOOP" ]; then
315                                 FREELOOP=$(/sbin/losetup -f) #get first free loop device
316                                 if [ ! "$FREELOOP" ]; then  # no free loop device, create a new one
317                                         #find a free loop device and use it 
318                                         usedminor=$(/sbin/losetup -a | tail -n1|sed 's/.*loop\(.*\)\: .*/\1/')
319                                         #usedminor=${usedminor:9:1}
320                                         freeminor=$(($usedminor+1))
321                                         echo "Creating a new device : mknod -m777 /dev/loop$freeminor b 7 $freeminor"
322                                         mknod -m777 /dev/loop$freeminor b 7 $freeminor
323                                         FREELOOP=/dev/loop$freeminor
324                                 fi
325                         fi
326
327                         #detect fs
328                         case $PND_FSTYPE in
329                         ISO)
330                                 /sbin/losetup -r $FREELOOP "$PND" #attach the pnd to the loop device
331                                 mntline="mount -o ro" #setup the mountline for later
332                                 mntdev="${FREELOOP}"
333                                 ;;
334                         directory)
335                                 #we bind the folder, now it can be treated in a unified way 
336                                 #ATENTION: -o ro doesnt work for --bind at least on 25, on 26 its possible using remount, may have changed on 27
337                                 mntline="mount --bind -o ro"
338                                 mntdev="${PND}"
339                                 ;;
340                         Squashfs)
341                                 /sbin/losetup -r $FREELOOP "$PND" #attach the pnd to the loop device
342                                 mntline="mount -t squashfs -o ro"
343                                 mntdev="${FREELOOP}"
344                                 ;;
345                         *)
346                                 echo "ERROR Unknown filesystem type : $PND_FSTYPE"
347                                 exit 1;;
348                         esac
349                         echo "Mounting : $mntline \"$mntdev\" \"$MOUNT_TARGET/${PND_NAME}\""
350                         $mntline "$mntdev" "$MOUNT_TARGET/${PND_NAME}" #mount the pnd/folder
351
352                         if ! is_pnd_mounted ;then
353                                 sleep 1
354                                 echo "WARNING : mount faild, re-tring"
355                                 sleep 1
356                                 $mntline "$mntdev" "$MOUNT_TARGET/${PND_NAME}" #mount the pnd/folder
357                                 if ! is_pnd_mounted ;then
358                                         echo "ERROR The PND File-system is not mounted !"
359                                         show_mounted_info
360                                         return 2
361                                 fi
362                         fi
363                 else #the pnd is already mounted but a mount was requested with a different basename/uid, just link it there
364                       echo WARNING $LOOP already mounted on $loopmountedon skipping losetup - putting link to old mount
365                       #this is bullshit
366                       rmdir "$UNION_MOUNT_DIR/$PND_NAME"
367                       ln -s $loopmountedon "$UNION_MOUNT_DIR/$PND_NAME" 
368                 fi
369         fi
370
371         # For backward compatibility
372         if [[ "$MOUNT_TARGET" != "$PND_MOUNT_DIR" ]];then
373                 if [ -h "$PND_MOUNT_DIR/$PND_NAME" ];then
374                         rm "$PND_MOUNT_DIR/$PND_NAME"
375                 else
376                         rmdir "$PND_MOUNT_DIR/$PND_NAME"
377                 fi
378                 if [ ! -e "$PND_MOUNT_DIR/$PND_NAME" ];then
379                         ln -s "$MOUNT_TARGET/$PND_NAME" "$PND_MOUNT_DIR/$PND_NAME"
380                 fi
381         fi
382 }
383
384 mountUnion() {
385         if [ $(id -u) -ne 0 ];then
386                 sudo /usr/pandora/scripts/pnd_run.sh -m -p "$PND" -b "$PND_NAME"
387                 if ! is_union_mounted;then
388                         echo "ERROR: The Union File-system is not mounted !"
389                         show_mounted_info
390                         return 1
391                 fi
392                 return $RC
393         fi
394         #create mountpoints, check if they exist already first to avoid annoying error messages
395         if ! [ -d "$PND_MOUNT_DIR/${PND_NAME}" ]; then 
396                 mkdir -p "$PND_MOUNT_DIR/${PND_NAME}"           #mountpoint for iso, ro
397         fi 
398         #writeable dir for union
399         if ! [ -d "${APPDATADIR}" ]; then 
400                 mkdir -p "${APPDATADIR}"
401                 chmod -R a+xrw "${APPDATADIR}" 2>/dev/null
402         fi
403         # create the union mountpoint
404         if ! [ -d "$UNION_MOUNT_DIR/${PND_NAME}" ]; then
405                 mkdir -p "$UNION_MOUNT_DIR/${PND_NAME}"         # union over the two
406         fi
407         #is the union already mounted? if not mount evrything, else launch the stuff
408         if ! is_union_mounted;then
409                 if ! is_pnd_mounted;then
410                         mountPnd "$UNION_MOUNT_DIR"|| return 2; # quit mounting the union if the PND first didnt mount
411                 else
412                         echo "WARNING The PND is already mounted, using it"
413                         show_mounted_info
414                 fi
415                 RO=0;for o in $(mount|awk '$3=="'$MOUNTPOINT'"{print $6}'|sed 's/.*(//;s/)$//;s/,/ /g');do [[ $o = "ro" ]]&& RO=1;done
416                 if [ $RO -eq 1 ];then
417                         echo "WARNING SD-Card is mounted Read-only !! Trying to remount RW"
418                         mount -oremount,rw $MOUNTPOINT
419                 fi
420
421                 if [[ "$APPDD_FSTYPE" = "vfat" ]]; then # use noplink on fat, dont on other fs's 
422                         #append is fucking dirty, need to clean that up
423                         MOUNT_CMD="mount -t aufs -o exec,noplink,dirs=\"${APPDATADIR}=rw+nolwh\":\"$PND_MOUNT_DIR/$PND_NAME=rr$append\" none \"$UNION_MOUNT_DIR/$PND_NAME\""
424                 else
425                         MOUNT_CMD="mount -t aufs -o exec,dirs=\"${APPDATADIR}=rw+nolwh\":\"$PND_MOUNT_DIR/$PND_NAME=rr$append\" none \"$UNION_MOUNT_DIR/$PND_NAME\""
426                 fi
427                 echo "Mounting the Union FS : $MOUNT_CMD"
428                 eval $MOUNT_CMD
429
430                 if ! is_union_mounted;then
431                         sleep 1
432                         echo "WARNING : mount faild, re-tring"
433                         sleep 1
434                         eval $MOUNT_CMD
435                         if ! is_union_mounted;then
436                                 echo "ERROR: The Union File-system is not mounted !"
437                                 show_mounted_info
438                                 return 1
439                         fi
440                 fi
441         else
442                 echo "WARNING Union already mounted, using it"
443                 show_mounted_info
444         fi
445 }
446
447 cleanups() {
448         #delete folders created by aufs if empty
449         rmdir -rf "${APPDATADIR}/.wh..wh.plnk" 2>/dev/null
450         rmdir -rf "${APPDATADIR}/.wh..wh..tmp" 2>/dev/null
451         rmdir "${APPDATADIR}/.wh..wh.orph" 2>/dev/null
452         rm "${APPDATADIR}/.aufs.xino" 2>/dev/null
453
454         #delete appdata folder and ancestors if _empty_
455         rmdir -p "${APPDATADIR}" 2>/dev/null
456
457         # Clean the loopback device
458         if [ $PND_FSTYPE = ISO ] || [ $PND_FSTYPE = Squashfs ]; then # check if we where running an iso, clean up loop device if we did
459                 LOOP=$(/sbin/losetup -a | grep "$(basename $PND)" | tail -n1 | awk -F: '{print $1}')
460                 /sbin/losetup -d $LOOP
461                 #rm $LOOP
462         fi
463         /sbin/losetup -a|cut -d':' -f 1|while read l;do
464                 if ! mount|grep -q $l;then
465                         echo "WARNING Found $l loop as unused. flushing"
466                         /sbin/losetup -d $l
467                 fi
468         done
469
470         echo cleanup done
471 }
472
473 umountPnd() {
474         MOUNT_TARGET="${1:-$PND_MOUNT_DIR}"
475         if is_pnd_mounted;then
476                 PND_WaitFor noMoreProcessPnd "Waiting the PND mount dir to be free"
477                 umount "$MOUNT_TARGET/$PND_NAME"
478         fi
479         if is_pnd_mounted; then
480                 echo WARNING umount PND failed, didnt clean up. Process still using this FS :
481                 list_using_fs "$MOUNT_TARGET/$PND_NAME"
482                 show_mounted_info
483         else
484                 # removing the now useless mountpoint
485                 if [ -d "$MOUNT_TARGET/$PND_NAME" ];then
486                         rmdir "$MOUNT_TARGET/$PND_NAME"
487                 fi
488                 if [ -h "$PND_MOUNT_DIR/$PND_NAME" ];then
489                         rm "$PND_MOUNT_DIR/$PND_NAME"
490                 fi
491
492                 # All went well, cleaning
493                 cleanups
494         fi
495 }
496
497 umountUnion() {
498         # Are we root yet ?
499         if [ $(id -u) -ne 0 ];then
500                 sudo /usr/pandora/scripts/pnd_run.sh -u -p "$PND" -b "$PND_NAME"
501                 return $?
502         fi
503
504         # Make sure the Union FS is unmounted
505         #PND_INTERACTIVE=2
506         if is_union_mounted;then
507                 PND_WaitFor noMoreProcessUnion "Waiting the Union to be available"
508                 umount "$UNION_MOUNT_DIR/$PND_NAME" #umount union
509         fi
510         if is_union_mounted; then
511                 echo "WARNING umount UNION failed, didnt clean up. Process still using this FS :"
512                 list_using_fs "$UNION_MOUNT_DIR/$PND_NAME"
513                 show_mounted_info
514         else
515                 # the Union is umounted, removing the now empty mountpoint
516                 if [[ "$PND_MOUNT_DIR" != "$UNION_MOUNT_DIR" ]];then
517                         if [ -d "$UNION_MOUNT_DIR/$PND_NAME" ];then
518                                 rmdir "$UNION_MOUNT_DIR/$PND_NAME"
519                         elif [ -e "$UNION_MOUNT_DIR/$PND_NAME" ];then
520                                 rm "$UNION_MOUNT_DIR/$PND_NAME" >/dev/null 2>&1 # as it might be a symlink
521                         fi
522                 fi
523                 # Try umounting the PND
524                 umountPnd $UNION_MOUNT_DIR
525         fi
526 }
527
528
529
530 #=============================================================================
531 # Create the condition to run an app, run it and wait for it's end
532 runApp() {
533         cd "$UNION_MOUNT_DIR/$PND_NAME"         # cd to union mount
534         if [ "$STARTDIR" ] && [ -d "$STARTDIR" ]; then
535                 cd "$STARTDIR";                 # cd to folder specified by the optional arg -s
536         fi
537
538         echo "$EXENAME" | grep -q "^\.\/" && DOTSLASH="true"
539
540         # now set up the env for the PND, don't run any tools after this point
541         # because PATH and LD_LIBRARY_PATH may be different and incompatible
542
543         if [ -d "$UNION_MOUNT_DIR/$PND_NAME/lib" ];then
544                 export LD_LIBRARY_PATH="$UNION_MOUNT_DIR/$PND_NAME/lib:${LD_LIBRARY_PATH:-"/usr/lib:/lib"}"
545         else
546                 export LD_LIBRARY_PATH="$UNION_MOUNT_DIR/$PND_NAME:${LD_LIBRARY_PATH:-"/usr/lib:/lib"}"
547         fi
548
549         REAL_PATH="$PATH"
550         if [ -d "$UNION_MOUNT_DIR/$PND_NAME/bin" ];then
551                 export PATH="$UNION_MOUNT_DIR/$PND_NAME/bin:${PATH:-"/usr/bin:/bin:/usr/local/bin"}"
552         fi
553
554         if [ -d "$UNION_MOUNT_DIR/$PND_NAME/share" ];then
555                 export XDG_DATA_DIRS="$UNION_MOUNT_DIR/$PND_NAME/share:$XDG_DATA_DIRS:/usr/share"
556         fi
557
558         export REAL_HOME="$HOME"
559         export HOME="$UNION_MOUNT_DIR/$PND_NAME"
560         export XDG_CONFIG_HOME="$HOME"
561         export XDG_DATA_HOME="$HOME"
562         export XDG_CACHE_HOME="$HOME"
563
564         if [ "$DOTSLASH" = "true" ]; then
565                 "$EXENAME" $ARGUMENTS "$@"
566         else
567                 "./$EXENAME" $ARGUMENTS "$@"
568         fi
569         RC=$?
570
571         #the app could have exited now, OR it went into bg, we still need to wait in that case till it really quits!
572         LD_LIBRARY_PATH= PATH="$REAL_PATH" PND_WaitForExit "$EXENAME"
573
574         # clean up to avoid any effects of the .pnd on the remaining parts of this script
575         unset LD_LIBRARY_PATH
576         export HOME="$REAL_HOME"
577         unset REAL_HOME
578         export PATH="$REAL_PATH"
579         unset REAL_PATH
580         # ... the rest should not matter
581
582         return $RC
583 }
584
585
586 main() {
587         case $ACTION in
588         mount)  
589                 mountUnion
590                 ;;
591         umount)
592                 umountUnion
593                 ;;
594         run)
595                 PND_BeginTask "Mount the PND"
596                 mountUnion
597                 PND_EndTask
598                 if [ $? -ne 0 ];then
599                         zenity --warning --title="Mounting the PND failed" --text="Mounting the PND failed. The application wont start. Please have a look at $PND_LOG"
600                         return 3
601                 fi
602                 if [ -e /proc/pandora/cpu_mhz_max ] && [ ! -z "$PND_CPUSPEED" ];then
603                         PND_BeginTask "Set CPU speed"
604                         PND_setCPUSpeed
605                         PND_EndTask
606                 fi
607                 if [ $CLOSE_X ]; then
608                         PND_BeginTask "Closing X"
609                         PND_CloseX
610                         PND_EndTask
611                 fi
612                 oPWD=$(pwd)
613                 old_fb0_geometry=$(fbset -fb /dev/fb0 -s | grep geometry | awk '{print $2, $3, $4, $5, $6}')
614                 if [ -e "${APPDATADIR}/PND_pre_script.sh" ]; then
615                         PND_BeginTask "Starting user configured pre-script"
616                         . ${APPDATADIR}/PND_pre_script.sh # Sourcing so it can shared vars with post-script ;)
617                         PND_EndTask
618                 fi
619
620                 PND_BeginTask "Starting the application ( $EXENAME $ARGUMENTS "$@")"
621                 runApp "$@"
622                 PND_EndTask
623
624                 if [ -e "${APPDATADIR}/PND_post_script.sh" ]; then
625                         PND_BeginTask "Starting user configured post-script"
626                         . ${APPDATADIR}/PND_post_script.sh
627                         PND_EndTask
628                 fi
629                 cd $oPWD
630                 if [ $CLOSE_X ]; then
631                         PND_BeginTask "Restarting X"
632                         PND_RestartX
633                         PND_EndTask
634                 fi
635                 if [ ! -z "$CURRENTSPEED" ]; then
636                         PND_BeginTask "Reset CPU speed to $CURRENTSPEED"
637                         PND_resetCPUSpeed
638                         PND_EndTask
639                 fi
640                 PND_BeginTask "Restoring the frame buffer status"
641                 ofbset -fb /dev/fb0 -pos 0 0
642                 fbset -fb /dev/fb0 -g $old_fb0_geometry
643                 old_res=$(echo $old_fb0_geometry | awk '{print $1, $2}')
644                 ofbset -fb /dev/fb0 -size $old_res -en 1
645                 if ! lsof /dev/fb1 > /dev/null; then
646                         ofbset -fb /dev/fb1 -mem 0 -size 0 0 -en 0
647                 fi
648                 PND_EndTask
649
650                 running_pnd_count=$(ps ax | grep "pnd_run.s[h]" | wc -l)
651                 # restore settings if we are the last exiting pnd
652                 # compare with 2 because one is used by subshell where "ps ax | ..." runs
653                 if [ "$running_pnd_count" -eq "2" ]; then
654                         PND_BeginTask "Restoring nub mode"
655                         sed -n '1p' /etc/pandora/conf/nubs.state > /proc/pandora/nub0/mode
656                         sed -n '7p' /etc/pandora/conf/nubs.state > /proc/pandora/nub1/mode
657                         PND_EndTask
658                 fi
659
660                 PND_BeginTask "uMount the PND"
661                 umountUnion
662                 PND_EndTask
663                 ;;
664         esac
665 }
666
667 ######################################################################################
668 ####    Parsing the arguments :
669 ##
670 if [ "$#" -lt 1 ]; then
671         showHelp
672         exit 1
673 fi
674
675 ACTION=run
676 while [ "$#" -gt 0 ];do
677         if [ "$1" == "--" ]; then
678                 shift
679                 break
680         fi
681
682         if [ "$#" -gt 1 ] && ( [[ "$(echo $2|cut -c 1)" != "-" ]] || [[ "$1" = "-a" ]] );then
683                 case "$1" in
684                 -p) PND="$2";;
685                 -e) EXENAME="$2";;
686                 -b) PND_NAME="$2";;
687                 -s) STARTDIR="$2";;
688                 -j) append="$2";;
689                 -c) PND_CPUSPEED="$2";;
690                 -d) APPDATASET=1;APPDATADIR="$2";;
691                 -a) ARGUMENTS="$2";;
692                 *)      echo "ERROR while parsing arguments: \"$1 $2\" is not a valid argument"; 
693                         showHelp;
694                         exit 1 ;;
695                 esac
696                 shift 2
697         else # there's no $2 or it's an argument
698                 case "$1" in
699                 -m) ACTION=mount;;
700                 -u) ACTION=umount;;
701                 -x) CLOSE_X=1;;
702                 -d) APPDATASET=1;;
703                 *)      echo "ERROR while parsing arguments: \"$1\" is not a valid argument"; 
704                         showHelp;
705                         exit 1 ;;
706                 esac
707                 shift
708
709         fi
710 done
711
712 if test -z "$PND"; then
713         echo "ERROR: pnd file provided (-p)"
714         showHelp
715         exit 1
716 fi
717
718 # getting the real full path to the file
719 PND="$(readlink -f $PND)"
720
721 #PND_NAME really should be something sensible and somewhat unique
722 #if -b is set use that as pnd_name, else generate it from PND
723 #get basename (strip extension if file) for union mountpoints etc, maybe  this should be changed to something specified inside the xml
724 #this should probably be changed to .... something more sensible
725 #currently only everything up to the first '.' inside the filenames is used.
726 PND_NAME="${PND_NAME:-"$(basename $PND | cut -d'.' -f1)"}"
727
728 PND_LOG="/tmp/pndrun_${PND_NAME}.out"
729 PND_HEADER="PND PND_FSTYPE APPDATADIR APPDD_FSTYPE PND_CPUSPEED EXENAME ARGUMENTS"
730
731 if [ ! -e "$PND" ]; then #check if theres a pnd suplied, need to clean that up a bit more
732         echo "ERROR: selected PND($PND) file does not exist!"
733         showHelp
734         exit 1
735 fi
736
737 if [ ! "$EXENAME" ] && [[ "$ACTION" = "run" ]]; then
738         echo "ERROR: no executable name provided! (-e)"
739         showHelp
740         exit 1
741 fi
742
743 PND_FSTYPE=$(file -b "$PND" | awk '{ print $1 }')       # is -p a zip/iso or folder?
744 MOUNTPOINT=$(df "$PND" | tail -1|awk '{print $6}')      # find out on which mountpoint the pnd is
745 if [ $(df "$PND"|wc -l) -eq 1 ];then                    # this is actually a bug in busybox
746         MOUNTPOINT="/";
747 elif [ ! -d "$MOUNTPOINT" ]; then 
748         MOUNTPOINT="";
749 fi
750 [ ! -z $APPDATASET ] || [ -z ${MOUNTPOINT} ] && APPDATADIR=${APPDATADIR:-$(dirname $PND)/$PND_NAME}
751 APPDATADIR=${APPDATADIR:-${MOUNTPOINT}/pandora/appdata/${PND_NAME}}
752 APPDD_FSTYPE=$(cat /proc/mounts | awk '$2=="'${MOUNTPOINT}'"{print $3}' | head -1)
753 CPUSPEED_FILE=${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
754 if [ -f "$CPUSPEED_FILE" ]; then
755         PND_CPUSPEED=$(cat "$CPUSPEED_FILE")
756 fi
757 export APPDATADIR PND PND_NAME
758
759 #Only logging when running
760 if [[ "$ACTION" == "run" ]];then
761         PND_Start
762         {
763         if [ $CLOSE_X ]; then
764                 main "$@" 2>&1 & 
765                 disown
766         else
767                 main "$@" 2>&1
768         fi
769         }>>"$PND_LOG"
770         PND_Stop
771 else
772         main
773 fi