X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=blobdiff_plain;f=testdata%2Fscripts%2Fpnd_run.sh;h=2b52416a571bd0bf431d332dff2065af6ecbb57a;hp=f9e309c102c0dfb1321ea6d6a7b9a40604c55888;hb=5d906b85757ca445f84899067062fed7346f89f2;hpb=ac2d2f889b10a4c02419518a730296775a8427cd diff --git a/testdata/scripts/pnd_run.sh b/testdata/scripts/pnd_run.sh index f9e309c..2b52416 100755 --- a/testdata/scripts/pnd_run.sh +++ b/testdata/scripts/pnd_run.sh @@ -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 @@ -14,13 +10,142 @@ #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:-''}")" + 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 "$RES" + PND_ISEXEC=0 + exec 3>&- + }|{ + while read line;do + if echo "$line"|grep -q ".*";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 </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 - if ! [ -d "/mnt/utmp/${PND_NAME}" ]; then - sudo mkdir -p "/mnt/utmp/${PND_NAME}" # union over the two +} + +PND_resetCPUSpeed() { + if [ ! -z "$CURRENTSPEED" ]; then + sudo $CPUSPEEDSCRIPT $CURRENTSPEED fi - rm /tmp/cpuspeed - if ! [ -f "${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed" ]; then - if [ ${cpuspeed:-$(cat /proc/pandora/cpu_mhz_max)} -gt $(cat /proc/pandora/cpu_mhz_max) ]; then - 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") - if [ ${cpuselection} = "yes" ]; then - cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed - sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed - elif [ ${cpuselection} = "custom" ]; then - cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed - sudo /usr/pandora/scripts/op_cpuspeed.sh - elif [ ${cpuselection} = "customsave" ]; then - cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed - sudo /usr/pandora/scripts/op_cpuspeed.sh - zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed" - cat /proc/pandora/cpu_mhz_max > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed - elif [ ${cpuselection} = "yessave" ]; then - cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed - zenity --info --title="Note" --text="Speed saved.\n\nTo re-enable this dialogue, please delete the file\n${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed" - sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed - cat /proc/pandora/cpu_mhz_max > ${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed - fi - fi - else - cpuspeed=$(cat "${MOUNTPOINT}/pandora/appdata/${PND_NAME}/cpuspeed") - cat /proc/pandora/cpu_mhz_max > /tmp/cpuspeed - echo Setting to CPU-Speed $cpuspeed MHz - sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed - - - #gksudo --message ", enter your password to allow" "echo $cpuspeed>/proc/pandora/cpu_mhz_max" +} + +#============================================================================= +# 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 +} - #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 +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 +} + + +#============================================================================= +# (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 $FREELOOP "$PND" #attach the pnd to the loop device + mntline="mount" #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 $FREELOOP "$PND" #attach the pnd to the loop device + mntline="mount -t squashfs" + 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 [ -f /tmp/cpuspeed ]; then - cpuspeed=$(cat /tmp/cpuspeed) - sudo /usr/pandora/scripts/op_cpuspeed.sh $cpuspeed - rm /tmp/cpuspeed +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 - 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 + #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 XDG_CONFIG_HOME="$UNION_MOUNT_DIR/$PND_NAME" + export REAL_HOME="$HOME" + export HOME="$UNION_MOUNT_DIR/$PND_NAME" + + 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) + 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;; + 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 + if ! lsof /dev/fb1 > /dev/null; then + PND_BeginTask "Restoring the frame buffer status" + ofbset -fb /dev/fb1 -mem 0 -size 0 0 -en 0 + PND_EndTask + fi + PND_BeginTask "uMount the PND" + umountUnion + PND_EndTask + ;; esac - - - if [ $nox ]; then #restart x if it was killed - echo "starting x in 5s" - sleep 5 - sudo /etc/init.d/slim-init start - fi } ###################################################################################### -#### Parse arguments +#### Parsing the arguments : ## - -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 [ "$#" -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"; + echo "Arguments were : $PND_ARGS" + 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"; + echo "Arguments were : $PND_ARGS" + showHelp; + exit 1 ;; + esac + shift + + fi done + +# 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!" showHelp exit 1 fi - PND_FSTYPE=$(file -b "$PND" | awk '{ print $1 }') # is -p a zip/iso or folder? MOUNTPOINT=$(df "$PND" | tail -1|awk '{print $6}') # find out on which mountpoint the pnd is -if [ ! -d "$MOUNTPOINT" ] || [ $MOUNTPOINT = "/" ]; then +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 - - \ No newline at end of file