pnd_run.sh: restore nub settings on last pnd exit
[pandora-libraries.git] / testdata / scripts / pnd_run.sh
old mode 100644 (file)
new mode 100755 (executable)
index bda21f4..c6cdc9b
@@ -1,12 +1,8 @@
 #!/bin/bash
  
-#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]
-# -s startdir
-# arguments can be inside -e, -a is optional
 #/etc/sudoers needs to be adjusted if you touch any of the sudo lines
  
-# look at the comments in the nox part, adjust 
+# look at the comments in the CLOSE_X part, adjust 
 #use "lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq > whitelist" with nothing running to generate the whitelist
  
 #todo - no proper order
 #make uid/pnd_name mandatory (and rename var, its confusing!)
 #find a clean way of shutting down x without a fixed dm, mabye avoid nohup usage somehow
 #add options to just mount iso without union and to mount the union later
-#cleanup
-#Rewrite! - this sucks
+
+#SCRIPT_DIR=$(echo $(dirname $(which $0))|sed 's#^\.#'"$(pwd)"'#')
+#. $SCRIPT_DIR/pnd_loging
+#PND_LogDateFormat=PND_Time
+
+PND_MOUNT_DIR="/mnt/pnd"
+UNION_MOUNT_DIR="/mnt/utmp"
+CPUSPEEDSCRIPT=/usr/pandora/scripts/op_cpuspeed.sh
+
+#=============================================================================
+# Log functions
+
+PND_isInteractive=0
+PND_Start() {
+       if [ $(ps -o tty,pid 2>/dev/null|grep $$|awk 'BEGIN{R=0}/pts/{R=1}END{print R}') -eq 1 ];then
+               PND_isInteractive=1
+               exec 3>&1       # duplicate stdout so we can still write to screen after the log redirect
+       fi
+       {
+       echo "======================================================================================="
+       for v in $PND_HEADER;do
+               printf "%-15s : %s\n" "$v"  "$(eval "echo \${$v:-'<unset>'}")"
+       done
+       echo "======================================================================================="
+       }>"$PND_LOG"
+}
+
+PND_checkLog() {
+awk 'BEGIN{R=0}END{exit R}
+/cannot open display/||/unary operator expected/||/No such file or directory/||/command not found/{R=R+1}
+{IGNORECASE=1}
+!/gpg-error/&&/ERROR/||/FAILED/{R=R+1}
+{IGNORECASE=0}' < "$PND_LOG"
+}
+
+PND_Stop() {
+       local RC=$?
+       PND_checkLog
+       RC=$(( $RC + $? ))      # trying to find error in the logs
+       {
+       echo "======================================================================================="
+       echo "Return code is : $RC"
+       }>>"$PND_LOG"
+       return $RC
+}
+
+PND_BeginTask() {
+       export PND_TASK_NAME="$*"
+       echo "[ START ]--- $PND_TASK_NAME ----------"
+       if [ $PND_isInteractive -eq 1 ];then
+               printf "$PND_TASK_NAME"  >&3
+       fi
+}
+
+PND_EndTask() {
+       local RC="$?"
+       local STATUS=""
+       local COLOR=""
+       local X=""
+       if [ $RC -eq 0 ];then 
+               STATUS=SUCCESS
+               COLOR="\\033[32m"
+       else
+               STATUS=FAILED
+               COLOR="\\033[31m"
+       fi
+       
+       printf "[%7s]--- $PND_TASK_NAME ----------\n" "$STATUS"
+       if [ $PND_isInteractive -eq 1 ];then
+               printf "\r%s\033[70G[$COLOR%7s\033[m]\n" "$PND_TASK_NAME" "$STATUS" >&3
+       fi
+       unset PND_TASK_NAME
+       return $RC
+}
+
+PND_WaitFor() {
+       [ $# -gt 0 ]||return 1
+       local l_test="$1"
+       local l_name=${2:-"Wait succes of $1"}
+       local l_cnt=${3:-12}
+       local l_sleep=${4:-10}
+       local C=0
+       PND_BeginTask $l_name
+       while [ $C -lt $l_cnt ] && ! eval $l_test;do
+               sleep $l_sleep;C=$(($C + 1));
+       done
+       [ $C -lt $l_cnt ]
+       PND_EndTask
+}
+
+PND_Exec() {
+       local CMD="$*"
+       {
+       if [ $PND_ISEXEC -eq 0 ];then
+               PND_ISEXEC=1
+               exec 3>&1               # 
+       fi
+       export PND_INTERACTIVE=2
+       $* 2>&1
+       RES=$(( $? + $PND_ERRORS ))
+       echo "<result>$RES</result>"
+       PND_ISEXEC=0
+       exec 3>&-
+       }|{
+       while read line;do
+               if echo "$line"|grep -q "<result>.*</result>";then
+                       return $(( $(echo $line|sed 's/<[^>]*>//g') + $PND_ERRORS ))
+               elif ! echo "$line"| $(eval $PND_OUT_CHECK); then
+                       PND_Error "$line";
+               else
+                       PND_Print "$line";
+               fi
+       done
+       return $PND_ERRORS
+       }
+}
+
+
+
+#=============================================================================
+# Utility functions
 
 showHelp() {
        cat <<endHELP
-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]
-Usage for mounting/umounting pnd_run.sh -p your.pnd -b uid -m or -u
+Usage:
+  pnd_run.sh -p file.pnd -e cmd [-a args] [-b pndid] [-s path] [-c speed] [-d [path]] [-x] [-m] [-u] [-- more_args]
+    -p file.pnd        : Specify the pnd file to execute
+    -e cmd     : Command to run
+    -a args    : Arguments to the command
+    -b pndid   : name of the directory mount-point ($UNION_MOUNT_DIR/pndid) (Default: name of the pnd file)
+    -s path    : Directory in the union to start the command from
+    -o speed   : Set the CPU speed
+    -d [path]  : Use path as source of the overlay. (Default: pandora/appdata/pndid)
+    -x         : Stop X before starting the apps
+    -m         : Only mount the pnd, dont run it (-e become optional)
+    -u         : Only umount the pnd, dont run it (-e become optional)
+
+  If '--' is specified, all subsequent arguments are passed through to the command
+  (useful if you want to pass quotes and weird chars to the command)
 endHELP
 }
 
 list_using_fs() {
        for p in $(fuser -m $1 2>/dev/null);do ps hf $p;done
 }
-runApp() {
-       cd "/mnt/utmp/$PND_NAME"                # cd to union mount
-       if [ "$STARTDIR" ] && [ -d "$STARTDIR" ]; then
-               cd "$STARTDIR";                 # cd to folder specified by the optional arg -s
-       fi
-       echo "[------------------------------]{ App start }[---------------------------------]"
-       LD_LIBRARY_PATH="/mnt/utmp/$PND_NAME" "./$EXENAME" $ARGUMENTS 
-                                               # execute app with ld_lib_path set to the union mount, a bit evil but i think its a good solution
 
-       #the app could have exited now, OR it went into bg, we still need to wait in that case till it really quits!
-       PID=$(pidof -o %PPID -x \"$EXENAME\")   # get pid of app
-       while [ "$PID" ];do                     # wait till we get no pid back for tha app, again a bit ugly, but it works
-               sleep 10s
-               PID=`pidof -o %PPID -x \"$EXENAME\"`
-       done
-       echo "[-------------------------------]{ App end }[----------------------------------]"
+
+#=============================================================================
+# CPU speed functions
+PND_getCPUSpeed() {
+       cat /proc/pandora/cpu_mhz_max
 }
 
-mountPnd() {
-       #create mountpoints, check if they exist already first to avoid annoying error messages
-       if ! [ -d "/mnt/pnd/${PND_NAME}" ]; then 
-               sudo mkdir -p "/mnt/pnd/${PND_NAME}"            #mountpoint for iso, ro
-       fi 
-       #writeable dir for union
-       if ! [ -d "${MOUNTPOINT}/pandora/appdata/${PND_NAME}" ]; then 
-               sudo mkdir -p "${MOUNTPOINT}/pandora/appdata/${PND_NAME}"
-               sudo chmod -R a+xrw "${MOUNTPOINT}/pandora/appdata/${PND_NAME}" 2>/dev/null
+PND_setCPUSpeed() {
+       unset CURRENTSPEED
+       if ! [ -f "$CPUSPEED_FILE" ] && [ ! -z "$PND_CPUSPEED" ]; then
+               if [ ${PND_CPUSPEED} -gt $(PND_getCPUSpeed) ]; then 
+                  CURRENTSPEED=$(PND_getCPUSpeed)
+                  case "$(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 $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!" \
+                                 "yes" "Yes, set it to $PND_CPUSPEED MHz" \
+                                 "custom" "Yes, select custom value" \
+                                 "yessave" "Yes, set it to $PND_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")" in
+                       "yes")
+                               sudo $CPUSPEEDSCRIPT $PND_CPUSPEED
+                               ;;
+                       "custom")
+                               sudo $CPUSPEEDSCRIPT
+                               ;;
+                       "customsave")
+                               sudo $CPUSPEEDSCRIPT
+                               zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n$CPUSPEED_FILE"
+                               PND_getCPUSpeed > $CPUSPEED_FILE
+                               ;;
+                       "yessave")
+                               zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n$CPUSPEED_FILE"
+                               sudo $CPUSPEEDSCRIPT $PND_CPUSPEED
+                               PND_getCPUSpeed > $CPUSPEED_FILE
+                               ;;
+                       "nosave")
+                               unset CURRENTSPEED
+                               zenity --info --title="Note" --text="Speed will not be changed.\n\nTo re-enable this dialogue, please delete the file\n$CPUSPEED_FILE"
+                               echo 9999 > $CPUSPEED_FILE
+                               ;;
+                       *)      unset CURRENTSPEED;;
+                 esac
+              fi
+       elif [ "$PND_CPUSPEED" -lt "1500" ]; then
+               CURRENTSPEED=$(PND_getCPUSpeed)
+               echo Setting to CPU-Speed $PND_CPUSPEED MHz
+               sudo $CPUSPEEDSCRIPT $PND_CPUSPEED
+       fi
+}
+
+PND_resetCPUSpeed() {
+       if [ ! -z "$CURRENTSPEED" ]; then
+               sudo $CPUSPEEDSCRIPT $CURRENTSPEED
        fi
-       if ! [ -d "/mnt/utmp/${PND_NAME}" ]; then
-               sudo mkdir -p "/mnt/utmp/${PND_NAME}"           # union over the two
+}
+
+#=============================================================================
+# X management functions
+
+PND_CloseX(){
+       if [ $CLOSE_X ]; then #the app doesnt want x to run, so we kill it and restart it once the app quits
+               if [ ! $(pidof X) ]; then 
+                       unset $CLOSE_X
+               else
+                       applist=$(lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq)
+                       whitelist=$(cat ~/pndtest/whitelist) #adjust this to a fixed whitelist, maybe in the config dir
+                       filteredlist=$(echo -e "$applist\n\n$whitelist\n\n$whitelist" | sort | uniq -u) #whitelist appended two times so those items are always removed
+                       if [ ${#filteredlist} -ge 1 ]; then
+                               message=$(echo -e "The following applications are still running, are you sure you want to close x? \n$filteredlist")
+                               echo -e "?ae[34me[30m?"
+                               xmessage -center "$message", -buttons yes,no
+                               if [ $? = 102 ]; then
+                                       exit 1
+                               fi
+                               sudo /etc/init.d/slim-init stop
+                               sleep 5s
+                       else
+                               echo -e "?ae[34me[30m?"
+                               xmessage -center "killing x, nothing of value will be lost", -buttons ok,cancel
+                               if [ $? = 102 ]; then
+                                       exit 1
+                               fi
+                               # close x now, do we want to use slim stop or just kill x?
+                               sudo /etc/init.d/slim-init stop
+                               sleep 5s
+                       fi
+               fi
        fi
+}
 
-       if [ ${cpuspeed:-$(cat /proc/pandora/cpu_mhz_max)} -ne $(cat /proc/pandora/cpu_mhz_max) ]; then 
-               gksudo --message "$PND_NAME wants to set the cpu speed to $cpuspeed, enter your password to allow" "echo $cpuspeed>/proc/pandora/cpu_mhz_max"
+PND_RestartX(){
+       if [ $CLOSE_X ]; then #restart x if it was killed
+               # We need to wait a bit, doing it nicely ;)
+               sleep 5
+               sudo /etc/init.d/slim-init start
        fi
+}
 
-       #is the union already mounted? if not mount evrything, else launch the stuff
-       mount | grep "on /mnt/utmp/${PND_NAME} type"
-       if [ $? -ne 0 ];then
-               echo not mounted on loop yet, doing so
+
+#=============================================================================
+# (u)Mounting functions
+
+show_mounted_info(){
+       echo "+++++++"
+       echo "Loopback devices :"
+       sudo /sbin/losetup -a
+       echo "Are mounted on :"
+       mount|grep loop
+       echo "For these Union :"
+       mount|grep aufs
+}
+
+is_union_mounted() {
+       mount | grep -q "on $UNION_MOUNT_DIR/${PND_NAME} type aufs"
+}
+
+is_pnd_mounted() {
+       mount |grep -v aufs | grep -q "on $PND_MOUNT_DIR/${PND_NAME} type" || \
+       mount |grep -v aufs | grep -q "on $UNION_MOUNT_DIR/${PND_NAME} type"
+}
+
+noMoreProcessPnd() {
+       [ -z "$(list_using_fs "$PND_MOUNT_DIR/$PND_NAME")" ]
+}
+
+noMoreProcessUnion() {
+       [ -z "$(list_using_fs "$UNION_MOUNT_DIR/$PND_NAME")" ]
+}
+
+mountPnd() {
+       MOUNT_TARGET="${1:-$PND_MOUNT_DIR}"
+       if ! is_pnd_mounted;then
                #check if pnd is already attached to loop 
-               LOOP=$(sudo losetup -a | grep "$PND" | tail -n1 | awk -F: '{print $1}')
+               LOOP=$(/sbin/losetup -a | grep "$PND" | tail -n1 | awk -F: '{print $1}')
                #check if the loop device is already mounted
                if ! [ -z "$LOOP" ];then
+                       echo "Found a loop ($LOOP), using it"
                        loopmountedon=$( mount | grep "$(mount | grep "$LOOP" | awk '{print $3}')" | grep utmp | awk '{print $3}' )
                else
                        loopmountedon=""
                fi
-               echo "LoopMountedon: $loopmountedon"
                if [ ! "$loopmountedon" ]; then #check if the pnd is already attached to some loop device but not used
                        FREELOOP=$LOOP 
                        #reuse existing loop
                        if [ ! "$LOOP" ]; then
-                               FREELOOP=$(sudo /sbin/losetup -f) #get first free loop device
-                               echo $FREELOOP
+                               FREELOOP=$(/sbin/losetup -f) #get first free loop device
                                if [ ! "$FREELOOP" ]; then  # no free loop device, create a new one
-                                           #find a free loop device and use it 
-                                           usedminor=$(sudo /sbin/losetup -a | tail -n1)
-                                           usedminor=${usedminor:9:1}
-                                           echo usedminor $usedminor
-                                           freeminor=$(($usedminor+1))
-                                           echo freeminor $freeminor
-                                           sudo mknod -m777 /dev/loop$freeminor b 7 $freeminor
-                                           FREELOOP=/dev/loop$freeminor
+                                       #find a free loop device and use it 
+                                       usedminor=$(/sbin/losetup -a | tail -n1|sed 's/.*loop\(.*\)\: .*/\1/')
+                                       #usedminor=${usedminor:9:1}
+                                       freeminor=$(($usedminor+1))
+                                       echo "Creating a new device : mknod -m777 /dev/loop$freeminor b 7 $freeminor"
+                                       mknod -m777 /dev/loop$freeminor b 7 $freeminor
+                                       FREELOOP=/dev/loop$freeminor
                                fi
                        fi
-                       #detect fs
 
+                       #detect fs
                        case $PND_FSTYPE in
                        ISO)
-                               sudo /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
-                               mntline="sudo mount ${FREELOOP}" #setup the mountline for later
-                               #mntline="sudo mount -o loop,mode=777 $PND /mnt/pnd/$PND_NAME"
-                               echo "Filetype is $PND_FSTYPE";;
+                               /sbin/losetup -r $FREELOOP "$PND" #attach the pnd to the loop device
+                               mntline="mount -o ro" #setup the mountline for later
+                               mntdev="${FREELOOP}"
+                               ;;
                        directory)
                                #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
-                               mntline="sudo mount --bind -o ro \"${PND}\" "
-                               echo "Filetype is $PND_FSTYPE";;
+                               mntline="mount --bind -o ro"
+                               mntdev="${PND}"
+                               ;;
                        Squashfs)
-                               sudo /sbin/losetup $FREELOOP "$PND" #attach the pnd to the loop device
-                               mntline="sudo mount -t squashfs  ${FREELOOP}"
-                               echo "Filetype is $PND_FSTYPE";;
+                               /sbin/losetup -r $FREELOOP "$PND" #attach the pnd to the loop device
+                               mntline="mount -t squashfs -o ro"
+                               mntdev="${FREELOOP}"
+                               ;;
                        *)
-                               echo "error determining fs, output was $PND_FSTYPE"
+                               echo "ERROR Unknown filesystem type : $PND_FSTYPE"
                                exit 1;;
                        esac
+                       echo "Mounting : $mntline \"$mntdev\" \"$MOUNT_TARGET/${PND_NAME}\""
+                       $mntline "$mntdev" "$MOUNT_TARGET/${PND_NAME}" #mount the pnd/folder
 
-                       echo "$mntline"
-                       $mntline "/mnt/pnd/${PND_NAME}" #mount the pnd/folder
-                       echo "mounting union!"
-                       FILESYSTEM=$(mount | grep "on $MOUNTPOINT " | grep -v rootfs | awk '{print $5}' | tail -n1) #get filesystem appdata is on to determine aufs options
-                       echo "Filesystem is $FILESYSTEM"
-                       if [[ "$FILESYSTEM" = "vfat" ]]; then # use noplink on fat, dont on other fs's 
-                               #append is fucking dirty, need to clean that up
-                               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"
-                               # put union on top
-                       else
-                               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" 
-                               # put union on top
+                       if ! is_pnd_mounted ;then
+                               sleep 1
+                               echo "WARNING : mount faild, re-tring"
+                               sleep 1
+                               $mntline "$mntdev" "$MOUNT_TARGET/${PND_NAME}" #mount the pnd/folder
+                               if ! is_pnd_mounted ;then
+                                       echo "ERROR The PND File-system is not mounted !"
+                                       show_mounted_info
+                                       return 2
+                               fi
                        fi
                else #the pnd is already mounted but a mount was requested with a different basename/uid, just link it there
-                             echo $LOOP already mounted on $loopmountedon skipping losetup - putting link to old mount
-                             #this is bullshit
-                             sudo rmdir "/mnt/utmp/$PND_NAME"
-                             sudo ln -s $loopmountedon "/mnt/utmp/$PND_NAME" 
+                     echo WARNING $LOOP already mounted on $loopmountedon skipping losetup - putting link to old mount
+                     #this is bullshit
+                     rmdir "$UNION_MOUNT_DIR/$PND_NAME"
+                     ln -s $loopmountedon "$UNION_MOUNT_DIR/$PND_NAME" 
+               fi
+       fi
+
+       # For backward compatibility
+       if [[ "$MOUNT_TARGET" != "$PND_MOUNT_DIR" ]];then
+               if [ -d "$PND_MOUNT_DIR/$PND_NAME" ];then
+                       rmdir "$PND_MOUNT_DIR/$PND_NAME"
+               else
+                       rm "$PND_MOUNT_DIR/$PND_NAME"
+               fi
+               if [ ! -e "$PND_MOUNT_DIR/$PND_NAME" ];then
+                       ln -s "$MOUNT_TARGET/$PND_NAME" "$PND_MOUNT_DIR/$PND_NAME"
                fi
-       
-       else
-               echo "Union already mounted"
        fi
 }
 
-unmountPnd() {
-       sudo umount "/mnt/utmp/$PND_NAME" #umount union
-       if [ -z "$(mount |grep utmp/$PND_NAME|cut -f3 -d' ')" ]; 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
-               # umount the actual pnd
-               sudo umount "/mnt/pnd/$PND_NAME"
-               if [ -z "$(mount |grep pnd/$PND_NAME|cut -f3 -d' ')" ]; then
-                       #delete folders created by aufs if empty
-                       sudo rmdir "$MOUNTPOINT/pandora/appdata/$PND_NAME/.wh..wh.plnk" 2>/dev/null
-                       sudo rmdir "$MOUNTPOINT/pandora/appdata/$PND_NAME/.wh..wh..tmp" 2>/dev/null
-                       #delete appdata folder and ancestors if empty
-                       sudo rmdir -p "$MOUNTPOINT/pandora/appdata/$PND_NAME/" 2>/dev/null
-                       #delete tmp mountpoint
-                       if [ -d "/mnt/utmp/$PND_NAME" ];then
-                               sudo rmdir "/mnt/utmp/$PND_NAME"
-                       else
-                               sudo rm "/mnt/utmp/$PND_NAME" >/dev/null 2>&1
-                       fi
-                       if [ $PND_FSTYPE = ISO ] || [ $PND_FSTYPE = Squashfs ]; then # check if we where running an iso, clean up loop device if we did
-                               LOOP=$(sudo losetup -a | grep "$(basename $PND)" | tail -n1 | awk -F: '{print $1}')
-                               sudo /sbin/losetup -d $LOOP
-                               sudo rm $LOOP
-                       fi
-                       if [ -d /mnt/pnd/$PND_NAME ];then
-                               sudo rmdir "/mnt/pnd/$PND_NAME" #delete pnd mountpoint
-                       fi
+mountUnion() {
+       if [ $(id -u) -ne 0 ];then
+               sudo /usr/pandora/scripts/pnd_run.sh -m -p "$PND" -b "$PND_NAME"
+               if ! is_union_mounted;then
+                       echo "ERROR: The Union File-system is not mounted !"
+                       show_mounted_info
+                       return 1
+               fi
+               return $RC
+       fi
+       #create mountpoints, check if they exist already first to avoid annoying error messages
+       if ! [ -d "$PND_MOUNT_DIR/${PND_NAME}" ]; then 
+               mkdir -p "$PND_MOUNT_DIR/${PND_NAME}"           #mountpoint for iso, ro
+       fi 
+       #writeable dir for union
+       if ! [ -d "${APPDATADIR}" ]; then 
+               mkdir -p "${APPDATADIR}"
+               chmod -R a+xrw "${APPDATADIR}" 2>/dev/null
+       fi
+       # create the union mountpoint
+       if ! [ -d "$UNION_MOUNT_DIR/${PND_NAME}" ]; then
+               mkdir -p "$UNION_MOUNT_DIR/${PND_NAME}"         # union over the two
+       fi
+       #is the union already mounted? if not mount evrything, else launch the stuff
+       if ! is_union_mounted;then
+               if ! is_pnd_mounted;then
+                       mountPnd "$UNION_MOUNT_DIR"|| return 2; # quit mounting the union if the PND first didnt mount
+               else
+                       echo "WARNING The PND is already mounted, using it"
+                       show_mounted_info
+               fi
+               RO=0;for o in $(mount|awk '$3=="'$MOUNTPOINT'"{print $6}'|sed 's/.*(//;s/)$//;s/,/ /g');do [[ $o = "ro" ]]&& RO=1;done
+               if [ $RO -eq 1 ];then
+                       echo "WARNING SD-Card is mounted Read-only !! Trying to remount RW"
+                       mount -oremount,rw $MOUNTPOINT
+               fi
 
-                       echo cleanup done
+               if [[ "$APPDD_FSTYPE" = "vfat" ]]; then # use noplink on fat, dont on other fs's 
+                       #append is fucking dirty, need to clean that up
+                       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\""
                else
-                       echo umount failed, didnt clean up. Process still using this FS :
-                       list_using_fs "/mnt/pnd/$PND_NAME"
+                       MOUNT_CMD="mount -t aufs -o exec,dirs=\"${APPDATADIR}=rw+nolwh\":\"$PND_MOUNT_DIR/$PND_NAME=rr$append\" none \"$UNION_MOUNT_DIR/$PND_NAME\""
+               fi
+               echo "Mounting the Union FS : $MOUNT_CMD"
+               eval $MOUNT_CMD
+
+               if ! is_union_mounted;then
+                       sleep 1
+                       echo "WARNING : mount faild, re-tring"
+                       sleep 1
+                       eval $MOUNT_CMD
+                       if ! is_union_mounted;then
+                               echo "ERROR: The Union File-system is not mounted !"
+                               show_mounted_info
+                               return 1
+                       fi
                fi
        else
-               echo umount failed, didnt clean up. Process still using this FS :
-               list_using_fs "/mnt/utmp/$PND_NAME"
+               echo "WARNING Union already mounted, using it"
+               show_mounted_info
        fi
 }
 
-main() {
-       if [ $nox ]; then #the app doesnt want x to run, so we kill it and restart it once the app quits
-               if [ ! $(pidof X) ]; then 
-                       unset $nox
-               else
-                       applist=$(lsof /usr/lib/libX11.so.6 | awk '{print $1}'| sort | uniq)
-                       whitelist=$(cat ~/pndtest/whitelist) #adjust this to a fixed whitelist, maybe in the config dir
-                       filteredlist=$(echo -e "$applist\n\n$whitelist\n\n$whitelist" | sort | uniq -u) #whitelist appended two times so those items are always removed
-                       if [ ${#filteredlist} -ge 1 ]; then
-                               message=$(echo -e "The following applications are still running, are you sure you want to close x? \n$filteredlist")
-                               echo -e "?ae[34me[30m?"
-                               xmessage -center "$message", -buttons yes,no
-                               if [ $? = 102 ]; then
-                                       exit 1
-                               fi
-                               sudo /etc/init.d/slim-init stop
-                               sleep 5s
-                       else
-                               echo -e "?ae[34me[30m?"
-                               xmessage -center "killing x, nothing of value will be lost", -buttons ok,cancel
-                               if [ $? = 102 ]; then
-                                       exit 1
-                               fi
-                               # close x now, do we want to use slim stop or just kill x?
-                               sudo /etc/init.d/slim-init stop
-                               sleep 5s
+cleanups() {
+       #delete folders created by aufs if empty
+       rmdir -rf "${APPDATADIR}/.wh..wh.plnk" 2>/dev/null
+       rmdir -rf "${APPDATADIR}/.wh..wh..tmp" 2>/dev/null
+       rmdir "${APPDATADIR}/.wh..wh.orph" 2>/dev/null
+       rm "${APPDATADIR}/.aufs.xino" 2>/dev/null
+
+       #delete appdata folder and ancestors if _empty_
+       rmdir -p "${APPDATADIR}" 2>/dev/null
+
+       # Clean the loopback device
+       if [ $PND_FSTYPE = ISO ] || [ $PND_FSTYPE = Squashfs ]; then # check if we where running an iso, clean up loop device if we did
+               LOOP=$(/sbin/losetup -a | grep "$(basename $PND)" | tail -n1 | awk -F: '{print $1}')
+               /sbin/losetup -d $LOOP
+               #rm $LOOP
+       fi
+       /sbin/losetup -a|cut -d':' -f 1|while read l;do
+               if ! mount|grep -q $l;then
+                       echo "WARNING Found $l loop as unused. flushing"
+                       /sbin/losetup -d $l
+               fi
+       done
+
+       echo cleanup done
+}
+
+umountPnd() {
+       MOUNT_TARGET="${1:-$PND_MOUNT_DIR}"
+       if is_pnd_mounted;then
+               PND_WaitFor noMoreProcessPnd "Waiting the PND mount dir to be free"
+               umount "$MOUNT_TARGET/$PND_NAME"
+       fi
+       if is_pnd_mounted; then
+               echo WARNING umount PND failed, didnt clean up. Process still using this FS :
+               list_using_fs "$MOUNT_TARGET/$PND_NAME"
+               show_mounted_info
+       else
+               # removing the now useless mountpoint
+               if [ -d "$MOUNT_TARGET/$PND_NAME" ];then
+                       rmdir "$MOUNT_TARGET/$PND_NAME"
+               fi
+               if [ -h "$PND_MOUNT_DIR/$PND_NAME" ];then
+                       rm "$PND_MOUNT_DIR/$PND_NAME"
+               fi
+
+               # All went well, cleaning
+               cleanups
+       fi
+}
+
+umountUnion() {
+       # Are we root yet ?
+       if [ $(id -u) -ne 0 ];then
+               sudo /usr/pandora/scripts/pnd_run.sh -u -p "$PND" -b "$PND_NAME"
+               return $?
+       fi
+
+       # Make sure the Union FS is unmounted
+       #PND_INTERACTIVE=2
+       if is_union_mounted;then
+               PND_WaitFor noMoreProcessUnion "Waiting the Union to be available"
+               umount "$UNION_MOUNT_DIR/$PND_NAME" #umount union
+       fi
+       if is_union_mounted; then
+               echo "WARNING umount UNION failed, didnt clean up. Process still using this FS :"
+               list_using_fs "$UNION_MOUNT_DIR/$PND_NAME"
+               show_mounted_info
+       else
+               # the Union is umounted, removing the now empty mountpoint
+               if [[ "$PND_MOUNT_DIR" != "$UNION_MOUNT_DIR" ]];then
+                       if [ -d "$UNION_MOUNT_DIR/$PND_NAME" ];then
+                               rmdir "$UNION_MOUNT_DIR/$PND_NAME"
+                       elif [ -e "$UNION_MOUNT_DIR/$PND_NAME" ];then
+                               rm "$UNION_MOUNT_DIR/$PND_NAME" >/dev/null 2>&1 # as it might be a symlink
                        fi
                fi
+               # Try umounting the PND
+               umountPnd $UNION_MOUNT_DIR
+       fi
+}
+
+
+
+#=============================================================================
+# Create the condition to run an app, run it and wait for it's end
+runApp() {
+       cd "$UNION_MOUNT_DIR/$PND_NAME"         # cd to union mount
+       if [ "$STARTDIR" ] && [ -d "$STARTDIR" ]; then
+               cd "$STARTDIR";                 # cd to folder specified by the optional arg -s
+       fi
+
+       if [ -d "$UNION_MOUNT_DIR/$PND_NAME/lib" ];then
+               export LD_LIBRARY_PATH="$UNION_MOUNT_DIR/$PND_NAME/lib:${LD_LIBRARY_PATH:-"/usr/lib:/lib"}"
+       else
+               export LD_LIBRARY_PATH="$UNION_MOUNT_DIR/$PND_NAME:${LD_LIBRARY_PATH:-"/usr/lib:/lib"}"
+       fi
+
+       if [ -d "$UNION_MOUNT_DIR/$PND_NAME/bin" ];then
+               export PATH="$UNION_MOUNT_DIR/$PND_NAME/bin:${PATH:-"/usr/bin:/bin:/usr/local/bin"}"
+       fi
+
+       if [ -d "$UNION_MOUNT_DIR/$PND_NAME/share" ];then
+               export XDG_DATA_DIRS="$UNION_MOUNT_DIR/$PND_NAME/share:$XDG_DATA_DIRS:/usr/share"
+       fi
+
+       export REAL_HOME="$HOME"
+       export HOME="$UNION_MOUNT_DIR/$PND_NAME"
+       export XDG_CONFIG_HOME="$HOME"
+       export XDG_DATA_HOME="$HOME"
+       export XDG_CACHE_HOME="$HOME"
+
+       if echo "$EXENAME"|grep -q ^\.\/;then
+               "$EXENAME" $ARGUMENTS "$@"
+       else
+               "./$EXENAME" $ARGUMENTS "$@"
        fi
+       RC=$?
+
+       #the app could have exited now, OR it went into bg, we still need to wait in that case till it really quits!
+       PID=$(pidof -o %PPID -x \"$EXENAME\")   # get pid of app
+       while [ "$PID" ];do                     # wait till we get no pid back for tha app, again a bit ugly, but it works
+               sleep 10s
+               PID=`pidof -o %PPID -x \"$EXENAME\"`
+       done
+       export HOME="$REAL_HOME"
+       return $RC
+}
+
 
+main() {
        case $ACTION in
-       mount)  mountPnd;;
-       umount) unmountPnd;;
+       mount)  
+               mountUnion
+               ;;
+       umount)
+               umountUnion
+               ;;
        run)
-               mountPnd
+               PND_BeginTask "Mount the PND"
+               mountUnion
+               PND_EndTask
+               if [ $? -ne 0 ];then
+                       zenity --warning --title="Mounting the PND failed" --text="Mounting the PND failed. The application wont start. Please have a look at $PND_LOG"
+                       return 3
+               fi
+               if [ -e /proc/pandora/cpu_mhz_max ] && [ ! -z "$PND_CPUSPEED" ];then
+                       PND_BeginTask "Set CPU speed"
+                       PND_setCPUSpeed
+                       PND_EndTask
+               fi
+               if [ $CLOSE_X ]; then
+                       PND_BeginTask "Closing X"
+                       PND_CloseX
+                       PND_EndTask
+               fi
                oPWD=$(pwd)
-               runApp
+               old_fb0_geometry=$(fbset -fb /dev/fb0 -s | grep geometry | awk '{print $2, $3, $4, $5, $6}')
+               if [ -e "${APPDATADIR}/PND_pre_script.sh" ]; then
+                       PND_BeginTask "Starting user configured pre-script"
+                       . ${APPDATADIR}/PND_pre_script.sh # Sourcing so it can shared vars with post-script ;)
+                       PND_EndTask
+               fi
+
+               PND_BeginTask "Starting the application ( $EXENAME $ARGUMENTS "$@")"
+               runApp "$@"
+               PND_EndTask
+
+               if [ -e "${APPDATADIR}/PND_post_script.sh" ]; then
+                       PND_BeginTask "Starting user configured post-script"
+                       . ${APPDATADIR}/PND_post_script.sh
+                       PND_EndTask
+               fi
                cd $oPWD
-               unmountPnd;;
-       esac
+               if [ $CLOSE_X ]; then
+                       PND_BeginTask "Restarting X"
+                       PND_RestartX
+                       PND_EndTask
+               fi
+               if [ ! -z "$CURRENTSPEED" ]; then
+                       PND_BeginTask "Reset CPU speed to $CURRENTSPEED"
+                       PND_resetCPUSpeed
+                       PND_EndTask
+               fi
+               PND_BeginTask "Restoring the frame buffer status"
+               ofbset -fb /dev/fb0 -pos 0 0
+               fbset -fb /dev/fb0 -g $old_fb0_geometry
+               old_res=$(echo $old_fb0_geometry | awk '{print $1, $2}')
+               ofbset -fb /dev/fb0 -size $old_res -en 1
+               if ! lsof /dev/fb1 > /dev/null; then
+                       ofbset -fb /dev/fb1 -mem 0 -size 0 0 -en 0
+               fi
+               PND_EndTask
 
+               running_pnd_count=$(ps ax | grep "pnd_run.s[h]" | wc -l)
+               # restore settings if we are the last exiting pnd
+               # compare with 2 because one is used by subshell where "ps ax | ..." runs
+               if [ "$running_pnd_count" -eq "2" ]; then
+                       PND_BeginTask "Restoring nub mode"
+                       sed -n '1p' /etc/pandora/conf/nubs.state > /proc/pandora/nub0/mode
+                       sed -n '7p' /etc/pandora/conf/nubs.state > /proc/pandora/nub1/mode
+                       PND_EndTask
+               fi
 
-       if [ $nox ]; then #restart x if it was killed
-               echo "starting x in 5s"
-               sleep 5
-               sudo /etc/init.d/slim-init start
-       fi
+               PND_BeginTask "uMount the PND"
+               umountUnion
+               PND_EndTask
+               ;;
+       esac
 }
 
 ######################################################################################
-####   Parse arguments
+####   Parsing the arguments :
 ##
+if [ "$#" -lt 1 ]; then
+       showHelp
+       exit 1
+fi
 
-TEMP=`getopt -o p:e:a:b:s:m::u::n::x::j:c: -- "$@"`
-if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
-# Note the quotes around `$TEMP': they are essential!
-eval set -- "$TEMP"
 ACTION=run
-while true ; do
-       case "$1" in
-               -p) PND=$2;shift 2;;
-               -e) EXENAME=$2;shift 2 ;;
-               -b) PND_NAME=$2;shift 2;;
-               -s) STARTDIR=$2;shift 2;;
-               -m) ACTION=mount;shift 2;;
-               -u) ACTION=umount;shift 2;;
-               -x) nox=1;shift 2;;
-               -j) append=$2;shift 2;;
-               -c) cpuspeed=$2;shift 2;;
-               -a) 
-                       case "$2" in
-                               "") echo "no arguments"; shift 2 ;;
-                               *)  echo "args set to \`$2'" ;ARGUMENTS=$2;shift 2 ;;
-                       esac ;;
-               --) shift ; break ;;
-               *) echo "Error while parsing arguments!" ; exit 1 ;;
-       esac
+while [ "$#" -gt 0 ];do
+       if [ "$1" == "--" ]; then
+               shift
+               break
+       fi
+
+       if [ "$#" -gt 1 ] && ( [[ "$(echo $2|cut -c 1)" != "-" ]] || [[ "$1" = "-a" ]] );then
+               case "$1" in
+                -p) PND="$2";;
+                -e) EXENAME="$2";;
+                -b) PND_NAME="$2";;
+                -s) STARTDIR="$2";;
+                -j) append="$2";;
+                -c) PND_CPUSPEED="$2";;
+                -d) APPDATASET=1;APPDATADIR="$2";;
+                -a) ARGUMENTS="$2";;
+                *)     echo "ERROR while parsing arguments: \"$1 $2\" is not a valid argument"; 
+                       showHelp;
+                       exit 1 ;;
+               esac
+               shift 2
+       else # there's no $2 or it's an argument
+               case "$1" in
+                -m) ACTION=mount;;
+                -u) ACTION=umount;;
+                -x) CLOSE_X=1;;
+                -d) APPDATASET=1;;
+                *)     echo "ERROR while parsing arguments: \"$1\" is not a valid argument"; 
+                       showHelp;
+                       exit 1 ;;
+               esac
+               shift
+
+       fi
 done
+
+if test -z "$PND"; then
+       echo "ERROR: pnd file provided (-p)"
+       showHelp
+       exit 1
+fi
+
+# getting the real full path to the file
+PND="$(readlink -f $PND)"
+
+#PND_NAME really should be something sensible and somewhat unique
+#if -b is set use that as pnd_name, else generate it from PND
+#get basename (strip extension if file) for union mountpoints etc, maybe  this should be changed to something specified inside the xml
+#this should probably be changed to .... something more sensible
+#currently only everything up to the first '.' inside the filenames is used.
+PND_NAME="${PND_NAME:-"$(basename $PND | cut -d'.' -f1)"}"
+
+PND_LOG="/tmp/pndrun_${PND_NAME}.out"
+PND_HEADER="PND PND_FSTYPE APPDATADIR APPDD_FSTYPE PND_CPUSPEED EXENAME ARGUMENTS"
+
 if [ ! -e "$PND" ]; then #check if theres a pnd suplied, need to clean that up a bit more
-       echo "ERROR: selected PND file does not exist!"
+       echo "ERROR: selected PND($PND) file does not exist!"
        showHelp
        exit 1
 fi
+
 if [ ! "$EXENAME" ] && [[ "$ACTION" = "run" ]]; then
-       echo "ERROR: no executable name provided!"
+       echo "ERROR: no executable name provided! (-e)"
        showHelp
        exit 1
 fi
 
-
 PND_FSTYPE=$(file -b "$PND" | awk '{ print $1 }')      # is -p a zip/iso or folder?
-MOUNTPOINT=$(df "$PND" | tail -1|cut -f 1 -d ' ')      # find out on which mountpoint the pnd is
-if [ ! -d "$MOUNTPOINT" ] || [ $MOUNTPOINT = "/" ]; then 
+MOUNTPOINT=$(df "$PND" | tail -1|awk '{print $6}')     # find out on which mountpoint the pnd is
+if [ $(df "$PND"|wc -l) -eq 1 ];then                   # this is actually a bug in busybox
+       MOUNTPOINT="/";
+elif [ ! -d "$MOUNTPOINT" ]; then 
        MOUNTPOINT="";
 fi
-#PND_NAME really should be something sensible and somewhat unique
-#if -b is set use that as pnd_name, else generate it from PND
-#get basename (strip extension if file) for union mountpoints etc, maybe  this should be changed to something specified inside the xml
-#this should probably be changed to .... something more sensible
-#currently only everything up to the first '.' inside the filenames is used.
-PND_NAME=${PND_NAME:-"$(basename $PND | cut -d'.' -f1)"}
+[ ! -z $APPDATASET ] || [ -z ${MOUNTPOINT} ] && APPDATADIR=${APPDATADIR:-$(dirname $PND)/$PND_NAME}
+APPDATADIR=${APPDATADIR:-${MOUNTPOINT}/pandora/appdata/${PND_NAME}}
+APPDD_FSTYPE=$(mount|awk '$3=="'${MOUNTPOINT}'"{print $5}')
+CPUSPEED_FILE=${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed
+if [ -f "$CPUSPEED_FILE" ]; then
+       PND_CPUSPEED=$(cat "$CPUSPEED_FILE")
+fi
+export APPDATADIR PND PND_NAME
 
-if [ $nox ]; then
-       main > "/tmp/pndrun${PND_NAME}_$ACTION.out" 2>&1 & 
-       disown
+#Only logging when running
+if [[ "$ACTION" == "run" ]];then
+       PND_Start
+       {
+       if [ $CLOSE_X ]; then
+               main "$@" 2>&1 & 
+               disown
+       else
+               main "$@" 2>&1
+       fi
+       }>>"$PND_LOG"
+       PND_Stop
 else
-       main > "/tmp/pndrun${PND_NAME}_$ACTION.out" 2>&1
+       main
 fi
-