#!/bin/sh
#(c) Copyright Barry Kauler sept. 2011 bkhome.org
#2011 GPL licence v3 (/usr/share/doc/legal)
#the idea of this script is that it is called when PUPMODE==5 by scripts
#/usr/bin/wmreboot and /usr/bin/wmpoweroff (which are called via the Shutdown menu).
#X is still running.
#the normal shutdown sequence is:
# /usr/bin/wmpoweroff ->(return to) /usr/bin/xwin -> /sbin/poweroff -> /etc/rc.d/rc.shutdown
# /usr/bin/wmreboot ->(return to) /usr/bin/xwin -> /sbin/reboot -> /etc/rc.d/rc.shutdown
#this script is putting up some GUI dialogs while X is still running, so when
#rc.shutdown is reached, it won't have to put up text-mode dialogs.
#to avoid code duplication, get this to work with and without X, and also call this
#script from rc.shutdown. From the console, no X, type "poweroff" or "reboot" will
#also (conditionally) run this script, via rc.shutdown.
#110924 various tweaks. fix default partition highlight.
#111012 a pupdialog window had wrong text, needed different from non-X dialog.
#120327 only show "*RECOMMENDED*" partition for savefile if >256MB free.
#120327 expBOOTDRV needs to be exported to rc.shutdown.
#120427 01micko: support ext4 in save-file. 120428
#120512 Karl Godt: some parameters missing from lines 626, 630, 642.
#120514 Karl Godt: precaution, save-file must be bigger than size used in ram.
#130128 support udf f.s. (see also sfsget, puppyinstaller, pmount, pup_event_frontend_d, drive_all, probepart).
#130216 support f2fs.
#130221 the 240 sec timeout to shutdown without saving, actually aborts timeout. fixed. see also pupdialog, wmpoweroff, wmreboot.
#130525 extend duration of creating save file please wait window.
#130712 fix 130522, 130525 dlgs showing in tray.
killall picom
export SHUTDOWNCONFIG=1

DEFAULT_SAVE_SIZE=512	#MB
TIMELIMIT=$(echo $TIMELIMIT | tr -dc '0-9')
[ "$TIMELIMIT" ] || TIMELIMIT=60

if [ ! $DISPLAY ];then
 export LANG=C #110928 console shutdown using 'dialog', disable i18n.
else
 export OUTPUT_CHARSET=UTF-8
fi

. gettext.sh # enables use of eval_gettext (several named variables) and ngettext (plurals)
export TEXTDOMAIN=shutdownconfig
T_title="$(gettext 'First shutdown: save session')" # used 8 times
T_nosave="$(gettext 'No suitable partitions to save to. Shutting down without saving.')"
T_continue="$(gettext 'Continue')"
T_abort="$(gettext 'Abort')"
T_no="$(gettext 'No')"
T_notsave="$(gettext 'DO NOT SAVE')"

#/etc/rc.d/rc.shutdown will call shutdownconfig if this file does not exist, then will read its contents...
echo -n "" > /tmp/shutdownconfig_results

. /etc/rc.d/PUPSTATE
. /etc/DISTRO_SPECS
if [ -e /sys/block/$PDEV1 ] ; then
	PDEV1_ISOPTICAL=$(probedisk $PDEV1 | grep '|optical')
fi

#puppy.sfs is in a subdirectory, default to saving in it...
PUPSFSFILE="`echo "$PUPSFS" | cut -f 3 -d ','`"
PSUBDIR="`dirname "$PUPSFSFILE"`"
[ "$PSUBDIR" = "/" ] && PSUBDIR=""
[ $PUPMODE -eq 5 ] && [ "$DEV1FS" = "iso9660" ] && PSUBDIR="" #100920 booting off cd, always default have savefile at /.
[ $PUPMODE -eq 5 ] && [ "$DEV1FS" = "udf" ] && PSUBDIR="" #130128 ditto, for udf f.s.
[ "$DEV1FS" = "msdos" ] && DEV1FS="vfat"

if [ $DISPLAY ];then
 export XDIALOG_HIGH_DIALOG_COMPAT=true #for Xdialog.
 DIALOGEXE="pupdialog"
 DIALOGEXE2="Xdialog"
 BACKGROUNDYELLOW='--background \#82A3C3' #110924 change to pale-yellow. yellow' #only works pupdialog.
 BACKGROUNDPINK='--background pink'     #ditto.
 BACKGROUNDORANGE='--background \#FFDC32' #110924 change to pale-orange. orange' #ditto.
 TITLEPARAM='--backtitle'
else
 DIALOGEXE="dialog"
 DIALOGEXE2="dialog"
 TITLEPARAM='--title'
 BACKGROUNDYELLOW=''
 BACKGROUNDPINK=''
 BACKGROUNDORANGE=''
fi

#120514 Karl Godt: precaution, save-file must be at least this big...
DU_INITRD_PUP_RW=0
[ "`mount | grep ' /initrd/pup_rw '`" != "" ] && DU_INITRD_PUP_RW=`du -B 1M -c /initrd/pup_rw |tail -n1 |awk '{print $1}'` #M=1024,MB=1000

#130525 introduced 130522. moved up.
ORANGEGTKRC="style \"windowstuff\"
{
    bg[NORMAL]      = \"#FFDC32\"
    fg[NORMAL]      = \"#000000\"
}
class \"*\" style \"windowstuff\"
"
echo "$ORANGEGTKRC" > /tmp/orange_gtkrc${$}

#================================================================

choosepartfunc() {
 #dialog to choose what partition to create ${DISTRO_FILE_PREFIX}save.2fs on...
 case "$PMEDIA" in ""|cd|scsicd|satacd|idecd|atacd|usbcd) PCHOOSE="yes" ;; esac
 case "$DEV1FS" in ntfs|xxx) PCHOOSE="yes" ;; esac
 [ "$DEV1FS" = "msdos" ] && DEV1FS="vfat"

 expBOOTDRV=''
 if [ "$PMEDIA" = "usbflash" ];then #may have a small boot partition and a big 2nd.
  raspi-version -q || expBOOTDRV="/dev/`echo ${PDEV1} | sed -e 's%[0-9]*$%%'`" # allow raspi save on external drive
  PCHOOSE="yes"
 fi
 if [ "$xPSUBDIR" -a "$PMEDIA" != "cd" ];then #if pup installed in a sub-directory, allow save-file in another partition (in same drive)...
  expBOOTDRV="/dev/`echo ${PDEV1} | sed -e 's%[0-9]*$%%'`"
  PCHOOSE="yes"
 fi
 if [ "$PSAVEMARK" != "" ];then #see /etc/rc.d/PUPSTATE
  devnameonly="`echo -n "$PDEV1" | sed -e 's/[0-9]*$//'`"
  SAVEPART="${devnameonly}${PSAVEMARK}" #partition that will-have ${DISTRO_FILE_PREFIX}save.
 fi
 if [ "$PSAVEPART" != "" ];then #see /etc/rc.d/PUPSTATE
  SAVEPART="${PSAVEPART}"
 fi
 if [ "$SAVEPART" != "" ];then
  spPATTERN='/dev/'"$SAVEPART"'|'
  SAVEFS="`probepart -m | grep "$spPATTERN" | cut -f 2 -d '|'`"
  SAVEFILE="$PSUBDIR/${DISTRO_FILE_PREFIX}save.2fs"
  PUPSAVE="$SAVEPART,$SAVEFS,$SAVEFILE"
  return 0
 fi
 if [ "$PCHOOSE" != "yes" ];then
  SAVEFS="$DEV1FS"
  SAVEPART="$PDEV1"
  SAVEFILE="$PSUBDIR/${DISTRO_FILE_PREFIX}save.2fs"
  PUPSAVE="$PDEV1,$DEV1FS,$SAVEFILE"
  return 0
 fi

 if [ "$expBOOTDRV" = "" ];then
  T_finntitle="$(gettext 'First shutdown: get ready')"
  if [ "$PDEV1_ISOPTICAL" ] ; then
   T_iso="`eval_gettext \"You have booted off a live-CD or DVD, and you can now save your personal settings and files to a USB Flash drive or any hard drive partition.
However, if you have burnt the CD/DVD as multisession (not closed), then sessions can be saved as additional tracks to the CD/DVD -- each saved session will appear on the CD/DVD as a directory with all the saved files in it, not as a single file. \Zb\Z1THIS IS STILL EXPERIMENTAL, AND DOES NOT WORK WITH LAPTOP OPTICAL DRIVES\Zn\ZB\"`"
    T_yesno="$T_iso\n\n$T_yesno
$(eval_gettext "or \Zb${T_cd}\ZB button to save your session back to the CD/DVD..." )"
    ${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_finntitle" --colors --extra-button --ok-label "$T_continue" --extra-label "$T_cd" --cancel-label "$T_abort" --yesno "$T_yesno" 0 0
   SAVECHOICE=$?
   [ "$SAVECHOICE" == "3" ] && PUPMODE=77 && SAVEPART="$PDEV1" && return 1 #save to cd/dvd.
   [ ! $SAVECHOICE -eq 0 ] && return 3 #skip. 
  fi
 fi

 #130216 add f2fs...
 PARTSLIST="`probepart -m 2> /dev/null | grep '^/dev/' | grep "$expBOOTDRV" | grep -E 'f2fs|ext2|ext3|ext4|reiserfs|btrfs|minix|msdos|vfat|exfat|ntfs' | cut -f 1-3 -d '|' | sed -e 's/msdos/vfat/g'`"

 #nothing to save to...
 if [ "$PARTSLIST" = "" ];then
  if [ $DISPLAY ];then
   /usr/lib/gtkdialog/box_splash -bg red -close box -fontsize large -timeout 10 -text "$T_nosave"
  else
   clear
   echo "T_nosave"
   sleep 5
  fi
  return 1
 fi
 T_waitprobing="$(gettext 'Please wait, probing partitions...')"
 if [ "$DISPLAY" ]; then
  /usr/lib/gtkdialog/box_splash -close never -fontsize large -text "$T_waitprobing" &
  ppPID=$!
 fi
 SCHOICES=""; DEFTAG=""
 rm -f /tmp/schoices.txt
 rm -f /tmp/shutdownconfig_deftag
 echo "$PARTSLIST" | grep -qw "$PDEV1" && INSTALLED="y" || INSTALLED=""
 echo "$PARTSLIST" |
 while read APART
 do
  ATAG="`echo -n "$APART" | cut -f 1 -d '|' | cut -f 3 -d '/'`"
  ASIZE="`echo -n "$APART" | cut -f 3 -d '|'`"
  AFS="`echo -n "$APART" | cut -f 2 -d '|'`"
  AFREE=`df -m | grep "/dev/${ATAG} " | tr -s " " | cut -f 4 -d " "`
  if [ ! $AFREE ];then
   mount -t $AFS /dev/$ATAG /mnt/data > /dev/null 2>&1
   #need to put in a check that it is not mounted ro. the
   #mount script will fallback to ro for ntfs if rw mnt fails...
   RETMNTVAL=$?
   if [ $RETMNTVAL -eq 0 ];then
    if [ "`mount | grep '(rw' | grep '/mnt/data'`" = "" ];then
     umount /mnt/data
     RETMNTVAL=1
    else
     #if the ntfs rw mount was forced (see /bin/mount script) it is unwise to use...
     ERRMSG1=""
     [ -s /tmp/ntfsmnterr.txt ] && ERRMSG1="`cat /tmp/ntfsmnterr.txt | grep 'Dirty volume mount'`"
     if [ "$ERRMSG1" != "" ];then
      T_ntfstitle="$(gettext 'First shutdown: NTFS warning')"
      T_WARNING="\Z1\Zb$(gettext 'WARNING:')\ZB"
      T_ntfs="$(eval_gettext "The ntfs-3g driver has determined that the NTFS filesystem in partition \${ATAG} is 'dirty'.")
$(gettext 'It will display in the next dialog box in the list of partitions to save to, but it is recommended that you do not use it.')
$(gettext "Instead, you should first run Microsoft Windows -- most often this problem is due to Windows not being shut down properly the last time it was used, leaving the filesystem in a 'dirty' state.")"
      T_continue="$(gettext 'Click button to continue...')"
      ${DIALOGEXE} ${BACKGROUNDPINK} --foreground black ${TITLEPARAM} "$T_ntfstitle" --colors --msgbox "${T_WARNING}\n${T_ntfs}\Zn\n\n${T_continue}" 0 0
     fi
    fi
   fi
   [ -f /tmp/ntfsmnterr.txt ] && rm -f /tmp/ntfsmnterr.txt
   if [ $RETMNTVAL -eq 0 ];then
     #for ntfs cannot use /dev/$ATAG, use mnt point in grep...
     AFREE=`df -m | grep "/mnt/data" | tr -s " " | cut -f 4 -d " "`
     umount /mnt/data
   fi
  fi
  if [ $AFREE -ne 0 ];then
   if [ -z "$INSTALLED" ] && [ $AFREE -gt 512 ] && [ ! -s /tmp/shutdownconfig_deftag ];then
     case $AFS in
     ext?|reiserfs|minix|btrfs|f2fs) echo -n " --default-item ${ATAG}" > /tmp/shutdownconfig_deftag;;
     esac 
   fi
   if [ "$ATAG" = "$PDEV1" -a $AFREE -gt 256 ];then #120327
    echo -n " --default-item ${ATAG}" > /tmp/shutdownconfig_deftag
    echo "${ATAG} \"f.s.: $AFS  `gettext 'Size:'` ${ASIZE}M  `gettext 'Free:'` ${AFREE}M `gettext '*RECOMMENDED*'`\" " >> /tmp/schoices.txt
   else
    echo "${ATAG} \"`gettext 'Filesystem:'` $AFS  `gettext 'Size:'` ${ASIZE}M  `gettext 'Free:'` ${AFREE}M\" " >> /tmp/schoices.txt
   fi
  fi
 done
 kill $ppPID

 [ -s /tmp/shutdownconfig_deftag ] && DEFTAG="`cat /tmp/shutdownconfig_deftag`"
 [ -s /tmp/schoices.txt ] && SCHOICES="`cat /tmp/schoices.txt`"
 if [ "$SCHOICES" = "" ];then
  if [ $DISPLAY ];then
   /usr/lib/gtkdialog/box_splash -bg red -close box -fontsize large -timeout 10 -text "$T_nosave"
  else
   clear
   echo "$T_nosave"
   sleep 5
  fi
  return 1
 fi
 xSCHOICES="`cat /tmp/schoices.txt | tr '\n' ' '`"

 if [ `echo "$SCHOICES" | wc -l` -eq 1 ];then
  SAVEPART="`echo -n "$SCHOICES" | cut -f 1 -d ' '`" #no need for dlg.
 else
  T_partitiontitle="$(gettext 'First shutdown: choose partition')"
  T_menu="$(gettext 'Please choose a partition to create a pupsave on.')

$(gettext 'For Windows partitions(ntfs/vfat), Puppy makes a file with a Linux filesystem image in it. The size is typically 512MB - 4GB (it can be made bigger later).')
$(gettext 'On linux partitions(ext3 and etc.), Puppy makes a folder for pupsave. Unlike single file, the size is not predetermined but limited by the free space of the partition. A Linux partition is recommended, if available.')

$(gettext 'Highlight desired choice, then click OK button...')"
  echo '#!/bin/sh' > /tmp/savedlg
  echo -n "${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} \"${T_partitiontitle}\" --no-collapse --no-cancel ${DEFTAG} --menu \"${T_menu}\" 0 0 0 " >> /tmp/savedlg
  echo -n "$xSCHOICES"  >> /tmp/savedlg
  echo ' 2>/tmp/tag.txt' >> /tmp/savedlg
  chmod 755 /tmp/savedlg

  #seems some people have problem, do not select anything...
  T_notchosentitle="$(gettext 'First shutdown: Not chosen')"
  T_tryagain="$(gettext 'Try again')"
  T_yesno="$(gettext '\Zb\Z1ERROR:\Zn\ZB you did not choose any partition.')

$(eval_gettext 'Choose \Zb${T_tryagain}\ZB button to try again...')
$(eval_gettext 'Or, \Zb${T_abort}\ZB to shutdown without saving...')"

  while [ 1 ];do
   /tmp/savedlg
   SAVEPART="`cat /tmp/tag.txt | head -n 1`" #head is in case of errs in output.
   if [ "`echo -n "$SAVEPART" | grep --extended-regexp '^hd|^sd|^sc|^fd|^mmcblk|^nvme'`" = "" ];then
    ${DIALOGEXE} ${BACKGROUNDPINK} --foreground black ${TITLEPARAM} "$T_notchosentitle" --colors --yes-label "$T_tryagain" --no-label "${T_abort}" --yesno "$T_yesno" 0 0
    [ ! $? -eq 0 ] && return 1 #abort.
    continue
   fi
   break
  done
 fi

 SAVEFS="`echo "$SCHOICES" | grep "^${SAVEPART} " | tr -s " " | cut -f 2 -d ':' | cut -f 2 -d " "`"
 SAVEFILE="$PSUBDIR/${DISTRO_FILE_PREFIX}save.2fs"
 PUPSAVE="$SAVEPART,$SAVEFS,$SAVEFILE"
 echo "$PUPSAVE" #TEST
 return 0
} #end choosepartfunc

choosesizefunc(){
 local KFREE SIZELIST NUM CHOICES FLABEL SLABEL ACHOICE KSIZE VALUES VALIDS val
 KFREE=$1 ; SIZELIST="" ; NUM=1 ; CHOICES=""
 MFREE=`expr $KFREE \/ 1024`
 FLABEL="${MFREE}MB"
 [ $KFREE -ge 1048576 ] && FLABEL="`dc -e "$KFREE 1048576 2 k / p"`GB"
 VALUES='32 64 128 256 512 768 1024 1280 2048 4096'
 for val in $VALUES;do
 [ "$val" -gt "$DU_INITRD_PUP_RW" ] && VALIDS="$VALIDS $val"
 done
  #global: DEFAULT_SAVE_SIZE in MB
 [ $DEFAULT_SAVE_SIZE -gt 0 ] || DEFAULT_SAVE_SIZE=512
 local NDEFAULT=1
 for ACHOICE in $VALIDS
 do
  [ $ACHOICE -le $DEFAULT_SAVE_SIZE ] && NDEFAULT=$NUM
  KSIZE=`expr $ACHOICE \* 1024`
  SLABEL="${ACHOICE}MB"
  [ $ACHOICE -ge 1024 ] && SLABEL="`dc -e "$ACHOICE 1024 2 k / p"`GB"
  if [ $KSIZE -lt $KFREE ];then
   SIZELIST="$SIZELIST$NUM $SLABEL "
   CHOICES="$CHOICES$KSIZE "
  else
   SIZELIST="$SIZELIST$NUM fill_partition(${FLABEL}) "
   CHOICES="$CHOICES$KFREE "
   break
  fi
  NUM=`expr $NUM + 1`
 done

 T_sizetitle="$(gettext 'First shutdown: size save-file')"
 T_sitemenu="$(gettext 'Please choose the size you would like for the personal save file.')
$(gettext 'Note, 512M is a good choice, or highest if that not available.')
$(gettext 'Select choice, then click OK button...')"
 ${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_sizetitle" --no-collapse --no-cancel --default-item "$NDEFAULT" --menu "$T_sitemenu" 0 0 0 $SIZELIST 2>/tmp/sizetag.txt
 NUM=`cat /tmp/sizetag.txt`
 ACHOICE=`echo -n "$CHOICES" | cut -f $NUM -d ' '`
 #return $ACHOICE
 SIZEPFILE=$ACHOICE #global variable.
} # end of choosesizefunc()

choosestyle() {
 T_fstitle="$(gettext 'First shutdown: choose saving style')"
 T_fsmenu="$(gettext "You can save the session in a 'folder(directory)' because you chose a Linux partition. Unlike single file, saving in a folder is not restricted to the fixed file size but by the free space on the partition. You can save multiple profiles by different name.")
 
 $(gettext "A \Zbfolder\ZB is recommended for this case, but you still have another option if you have some reason and you want it.")"
 T_folder="$(gettext 'Save in a folder.') $(gettext '*RECOMMENDED*')"
 T_partition=$(gettext "Save to the entire partition. Only one profile.")
 T_file=$(gettext 'Single file, ext2/3/4 filesystem image in it.')
 ${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_fstitle" --colors --no-cancel --default-item folder --menu "$T_fsmenu" 0 0 0 folder "$T_folder" file "$T_file" 2>/tmp/rc.shutdown_pupsave_style
 SAVESTYLE=$(cat /tmp/rc.shutdown_pupsave_style)
 [ "$SAVESTYLE" ]
}

choosesize() {
 #we should check to see that there is enough space on the partition...
 PARTFREE=`df | grep "$SMNTPT" | tr -s " " | head -n 1 | cut -f 4 -d " "`
 [ ! $PARTFREE ] && PARTFREE=0
 [ $PARTFREE -lt 32768 ] && PARTFREE=`expr $PARTFREE - 1024` #leave some slack space.
 [ $PARTFREE -gt 32768 ] && PARTFREE=`expr $PARTFREE - 8192` #leave some slack space.
 SIZEPFILE=524288 #512M = 524288K
 [ $SIZEPFILE -gt  $PARTFREE ] && SIZEPFILE=$PARTFREE
 [ $PARTFREE -gt 32768 ] && choosesizefunc $PARTFREE #sets SIZEPFILE
 if [ "`echo -n $SAVEFILE | grep '\.[34]fs$'`" != "" ];then #ext3 f.s. needs minimum size.
  [ $SIZEPFILE -lt 5000 ] && return 1 #precaution. rerwin discovered this.
 fi
}

choosefs(){
 #choose f.s. of save-file... 100410 for now, leave out ext4, doesn't work...
 T_fstitle="$(gettext 'First shutdown: choose filesystem')"
 T_fsmenu="$(gettext 'Previously, Puppy has only used 'ext2', now there is a choice. Regarding power-failure, note that Puppy will do a f.s. check at next boot so ext2 can recover, however journalled filesystems can recover even without a f.s. check. If in doubt, choose 'ext2'. After making the choice, click OK button...')"
 T_ext2="$(gettext 'Maximum storage space, encrypted save-file must use ext2')"
 T_ext3="$(gettext 'Journalled f.s., safest if power failure etc.')"
 #120427 01micko: support ext4...
 T_ext4="$(gettext 'Journalled f.s., safest if power failure etc.')"
 if [ "`grep 'ext4$' /proc/filesystems`" != "" ];then #120428 technosaurus: simplify test. 
  ${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_fstitle" --no-cancel --default-item ext4 --menu "$T_fsmenu" 0 0 0 ext2 "$T_ext2" ext3 "$T_ext3"  ext4 "$T_ext4" 2>/tmp/rc.shutdown_pupsave_fs #120425 01micko
 else
  ${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_fstitle" --no-cancel --default-item ext3 --menu "$T_fsmenu" 0 0 0 ext2 "$T_ext2" ext3 "$T_ext3"  2>/tmp/rc.shutdown_pupsave_fs #110926
 fi
 SFFS="`cat /tmp/rc.shutdown_pupsave_fs`"
 [ "$SFFS" = "" ] && SFFS='ext2'
 SFEXTNUM="`echo -n "$SFFS" | cut -c 4`"
 SFEXT="${SFEXTNUM}fs" #ex: 2fs
}

choosename() {
 #customise the name of the ${DISTRO_FILE_PREFIX}save file...
 T_nametitle="$(gettext 'First shutdown: pupsave name')"
 T_nameinput="$(eval_gettext "Would you like to customise the name of the '\${DISTRO_FILE_PREFIX}save'?")

$(eval_gettext "This is optional, but it is convenient to manage multiple profiles. If you have lots of '\${DISTRO_FILE_PREFIX}save' and you want to choose the right one at startup.")
$(eval_gettext "For example, if you enter 'john' here, the file will become '\${DISTRO_FILE_PREFIX}save-john'.")

$(gettext 'Type any alpha-numeric characters you wish, then click OK button:')"
 MYUSERNAME="`${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_nametitle" --stdout --nocancel --inputbox "$T_nameinput" 0 0 ""`"
 NAMEONLY="${DISTRO_FILE_PREFIX}save${CRYPT_NAME}"
 if [ "$MYUSERNAME" != "" ];then
  MYUSERNAME="`echo -n "$MYUSERNAME" | tr ' ' '_' | tr '-' '_' | sed -e 's/[^a-zA-Z0-9_.]//g'`"
  NAMEONLY="$NAMEONLY-${MYUSERNAME}"
 fi
}

choosecrypt_new() {
 CRYPTO=""
 T_cryptotitle="$(gettext 'First shutdown: encryption')"
 T_cryptono="$(gettext 'NORMAL (no encryp.)')"
 T_cryptoheavy="$(gettext 'Encrypt with LUKS')"
 T_yesno="$(eval_gettext "Do you want to encrypt the '\${DISTRO_FILE_PREFIX}save'?")
$(eval_gettext "If the '\${DISTRO_FILE_PREFIX}save' is encrypted, then a password will have to be entered at every bootup. The reason for doing this is security, as no one else will be able to see what is inside the \${DISTRO_FILE_PREFIX}save. Encryption does slow \${DISTRO_NAME} down.")

LUKS = Linux Unified Key Setup.

$(eval_gettext "Encrypted \${DISTRO_FILE_PREFIX}save files have another advantage, they allow multiple users. Recommended if spouse and kids are going to be using the same \${DISTRO_NAME} installation.")

$(gettext 'Unless you have a good reason to use encryption, it is recommended not to, to avoid the overhead. Recommend choose \ZbNORMAL\ZB button...')"
 ${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_cryptotitle" --colors --ok-label "$T_cryptono" --cancel-label "$T_cryptoheavy" --yesno "$T_yesno" 0 0 #110926
 RETVAL=$?
 if [ $RETVAL -eq 1 ];then
  T_passtitle="$(gettext 'First shutdown: password')"
  T_passtext="$(gettext 'Please choose a password.
This must be remembered and entered at every bootup.')"
  while [ 1 ];do
    if [ "$DISPLAY" ] ; then
      MYPASSWORD="$(/usr/lib/gtkdialog/box_passwd --show --default "puppyisgreat" "$T_passtitle" "$T_passtext")"
    else
      MYPASSWORD="`${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_passtitle" --screen-center --stdout --no-cancel --inputbox "$T_passtext" 0 0 "puppyisgreat"`" #110926
    fi
    [ "$MYPASSWORD" ] && break
  done
  DENSITY="z"
  CRYPTO='luks'
  CRYPT_NAME="_luks"
  SFEXT="4fs"
  SFFS="ext4"
 fi
}

nameclash() {
 #save with different name if clash...
 [ ! -e $SMNTPT$SAVEFILE ] && return 0
 NAMEONLY=$(basename "$SAVEFILE")
 NAMEROOT=${NAMEONLY%.*}
 MNAMEONLY=$NAMEROOT
  T_clashtitle="$(gettext 'First shutdown: name clash')"
  T_save="$(gettext 'SAVE')"
  T_yesno="$(eval_gettext "There already exists '\${NAMEONLY}' on the partition you chose.")

$(eval_gettext 'To create another one, with a slightly different name (such as ${MNAMEONLY}-1.${SFEXT}), select \Zb${T_save}\ZB button...')
$(eval_gettext 'To quit without saving, select \Zb${T_no}\ZB button...')"
  ${DIALOGEXE} ${BACKGROUNDPINK} --foreground black ${TITLEPARAM} "$T_clashtitle" --colors --yes-label "$T_save" --yesno "$T_yesno" 0 0
  [ ! $? -eq 0 ] && return 1
  local BLA=1 #; local SFFIX=`echo "$SAVEFILE" | tail -c 5`
  while [ -e $SMNTPT$SAVEFILE ]; do
   SAVEFILE="$PSUBDIR/${NAMEROOT}-${BLA}"
   [ "${SFEXT}" ] && SAVEFILE="$SAVEFILE.${SFEXT}"
   BLA=`expr $BLA + 1`
  done
}

enmount() {
 sPTN="/dev/${SAVEPART} "
 SMNTPT="`mount | grep "$sPTN" | head -n1 | tr -s " " | cut -f 3 -d " "`"
 #ntfs uses /dev/fuse so '/dev/$SAVEPART' no good for grep... NOTE: this fixed later versions ntfs-3g, so this line actually redundant...
 [ "$SMNTPT" = "" ] && SMNTPT="`ps -e | grep -o 'ntfs\-3g.*' | grep "$sPTN" | tr '\t' ' ' | tr -s ' ' | tr ' ' "\n" | grep '^/mnt/'`"
 if [ "$SMNTPT" = "" ];then
  mkdir /mnt/$SAVEPART 2>/dev/null
  mount -t $SAVEFS /dev/$SAVEPART /mnt/$SAVEPART
  SMNTPT="/mnt/$SAVEPART"
 fi
 return 0
}

changefolder() {
   T_choosefoldertitle="$(gettext 'First shutdown: choose folder')"
   T_inputbox="$(gettext 'Edit path. '/' means top-level of partition.
You are only allowed to save one-deep, for example: '/puppy300'.
If folder does not exist, it will be created. Spaces are not allowed.
If uncertain, just click OK button.')"
   NEWSAVEPATH="`${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_choosefoldertitle" --screen-center --stdout --no-cancel --inputbox "$T_inputbox" 0 0 "$SAVEPATH"`"
   [ "$NEWSAVEPATH" = "" ] && NEWSAVEPATH="$SAVEPATH"
   [ "`echo -n "$NEWSAVEPATH" | cut -b 1`" != "/" ] && NEWSAVEPATH="/${NEWSAVEPATH}"
   [ "$NEWSAVEPATH" != "/" ] && NEWSAVEPATH="`echo -n "$NEWSAVEPATH" | sed -e 's%/$%%'`"
   NEWSAVEPATH="`echo -n "$NEWSAVEPATH" | sed -e 's/ //g'`"
   SAVEPATH="$NEWSAVEPATH"
   SAVEPATHs="$SAVEPATH"
   [ "$SAVEPATH" != "/" ] && SAVEPATHs="${SAVEPATH}/"
   SAVEFILE="${SAVEPATHs}${NAMEONLY}"
   PUPSAVE="$SAVEPART,$SAVEFS,$SAVEFILE"
}

pupsavefunc() {
 SAVEPATH="`dirname $SAVEFILE`"
 #final sanity check...
 AAAMB=`expr $SIZEPFILE \/ 1024`
 T_sanititle="$(gettext 'First shutdown: sanity check')"
 T_saniyes="$(gettext 'YES, SAVE')"
 T_sanichange="$(gettext 'CHANGE FOLDER')"
 while [ 1 ];do
  nameclash || return 1
  SAVEPATH=$(dirname "$SAVEFILE")
  [ "$SAVEPATH" = '/' ] && SAVEPATH=''
  NAMEONLY=$(basename "$SAVEFILE")
  T_sanitext="`eval_gettext \"\Zb\Z1FINAL SANITY CHECK:\Zn\ZB
Partition you are saving to:      \Zb\\\${SAVEPART}\ZB
The filesystem of \\\${SAVEPART} partition: \Zb\\\${SAVEFS}\ZB
Name of the save file:            \Zb\\\${NAMEONLY}\ZB
Path (folder) of the save file:   \Zb\\\${SAVEPATH}\ZB
Size of save file:                \Zb\\\${SIZEPFILE}KB (\\\${AAAMB}MB)\ZB
Filesystem inside save file:      \Zb\\\${SFFS}\ZB

If they definitely look right, choose \Zb\\\${T_saniyes}\ZB button...
Looks ok, but you want to change the folder, choose \Zb\\\${T_sanichange}\ZB...
If anything looks wrong, choose \Zb\\\${T_notsave}\ZB...\"`"
  ${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_sanititle" --colors --no-collapse --extra-button --ok-label "$T_saniyes"  --extra-label "$T_sanichange" --cancel-label "$T_notsave" --yesno "$T_sanitext" 0 0 #110926
  SANITYRET=$?
  [ $SANITYRET -ne 0 -a $SANITYRET -ne 3 ] && return 1
  [ $SANITYRET -eq 0 ] && break
  if [ $SANITYRET -eq 3 ];then #change folder.
    changefolder
  else
   SAVEFILE="${SAVEPATH}${NAMEONLY}"
   PUPSAVE="$SAVEPART,$SAVEFS,$SAVEFILE"
  fi
 done
 [ -f ${SMNTPT}${SAVEPATH} ] && return 1 #abort. must be a directory.
 [ ! -d ${SMNTPT}${SAVEPATH} ] && mkdir -p ${SMNTPT}${SAVEPATH}
 [ ! -d ${SMNTPT}${SAVEPATH} ] && return 1 #some kind of error, abort.

 #echo "Creating $NAMEONLY in /dev/$SAVEPART, please wait awhile..."
 T_createtitle="$(gettext 'First shutdown: creating save-file')"
 T_createsf="$(eval_gettext "Creating \${NAMEONLY} in \${SAVEPART}, please wait awhile (no need to click OK button)...")"
 altT_createsf="$(eval_gettext "Creating \${NAMEONLY} in \${SAVEPART}, please wait awhile...")"
 if [ $DISPLAY ];then
  #create nice window looking like prior ones...
  export SHUTDLG="<window decorated=\"false\">
<vbox>
<text use-markup=\"true\"><label>\"<big><b>${T_createtitle}</b></big>\"</label></text>
<text use-markup=\"true\"><label>\"<big>${altT_createsf}</big>\"</label></text>
</vbox>
</window>"
  GTK2_RC_FILES=/tmp/orange_gtkrc${$}:/root/.gtkrc-2.0 gtkdialog --center --class="splashwindow" --program=SHUTDLG & #130525 130712
  w1PID=$!
 else
  ${DIALOGEXE} ${BACKGROUNDORANGE} ${TITLEPARAM} "$T_createtitle" --colors --ok-label "OK" --msgbox "$T_createsf" 0 0 &
  w1PID=$!
 fi
 dd if=/dev/zero of=${SMNTPT}$SAVEFILE bs=1k count=$SIZEPFILE >&2
 sync
 echo "`eval_gettext \"Creating a \\\${SFFS} filesystem in \\\${NAMEONLY}...\"`"
 if [ "$CRYPTO" = "" ];then
  mkfs.${SFFS} -q -m 0 -F ${SMNTPT}$SAVEFILE
  #...default is f.s. auto checked every 26 mounts or 180 days. tune2fs to change.
  pupkill $w1PID #130525 moved down.
 else
  #note: loop2 is kept available for scripts to use. but, find which is free...
  echo -e "Save this log somewhere and close this window to continue...\n" >/tmp/mk2fs.log
  DEVLOOP="$(losetup -f)"
  if [ "$CRYPTO" = "luks" ] ; then
    losetup -v $DEVLOOP ${SMNTPT}$SAVEFILE >>/tmp/mk2fs.log
    echo -n "$MYPASSWORD" | cryptsetup luksFormat -v $DEVLOOP - &>>/tmp/mk2fs.log
    echo -n "$MYPASSWORD" | cryptsetup luksOpen -v $DEVLOOP savefile - &>>/tmp/mk2fs.log
    FSCK_DEV=/dev/mapper/savefile
  fi
  echo "mke2fs -v -t $SFFS -m 0 -E nodiscard -F $FSCK_DEV" >>/tmp/mk2fs.log
  mke2fs -v -t $SFFS -m 0 -E nodiscard -F $FSCK_DEV &>>/tmp/mk2fs.log && \
  e2fsck -v -f -y -E discard $FSCK_DEV &>>/tmp/mk2fs.log || e2fsck -v -f -y $FSCK_DEV &>>/tmp/mk2fs.log
  if [ $? -ne 0 ] ; then
    pupkill $w1PID
    /usr/lib/gtkdialog/box_ok "$(gettext 'Error')" error "$(gettext 'Unable to create filesystem')"
    defaulttextviewer /tmp/mk2fs.log
  fi
  sync
  pupkill $w1PID #130525 moved down.
  [ "$CRYPTO" = "luks" ] && cryptsetup luksClose savefile
  losetup -d $DEVLOOP
 fi
 sync
 return 0
} #end pupsavefunc

save_directory() {
 #final sanity check...
 T_sanititle="$(gettext 'First shutdown: sanity check')"
 T_saniyes="$(gettext 'YES, SAVE')"
 T_sanichange="$(gettext 'CHANGE FOLDER')"
 while [ 1 ];do
  nameclash || return 1
  SAVEPATH=$(dirname "$SAVEFILE")
  [ "$SAVEPATH" = '/' ] && SAVEPATH=''
  NAMEONLY=$(basename "$SAVEFILE")
  T_sanitext="`eval_gettext \"\Zb\Z1FINAL SANITY CHECK:\Zn\ZB
Partition you are saving to:      \Zb\\\${SAVEPART}\ZB
The filesystem of \\\${SAVEPART} partition: \Zb\\\${SAVEFS}\ZB
Path (folder) of the pupsave:   \Zb\\\${SAVEPATH}/${NAMEONLY}\ZB

If they definitely look right, choose \Zb\\\${T_saniyes}\ZB button...
Looks ok, but you want to change the folder, choose \Zb\\\${T_sanichange}\ZB...
If anything looks wrong, choose \Zb\\\${T_notsave}\ZB...\"`"
  ${DIALOGEXE} ${BACKGROUNDYELLOW} --foreground white ${TITLEPARAM} "$T_sanititle" --colors --no-collapse --extra-button --ok-label "$T_saniyes"  --extra-label "$T_sanichange" --cancel-label "$T_notsave" --yesno "$T_sanitext" 0 0 #110926
  SANITYRET=$?
  [ $SANITYRET -ne 0 -a $SANITYRET -ne 3 ] && return 1
  [ $SANITYRET -eq 0 ] && break
  if [ $SANITYRET -eq 3 ];then #change folder.
    changefolder
  else
   SAVEFILE="${SAVEPATH}${NAMEONLY}"
   PUPSAVE="$SAVEPART,$SAVEFS,$SAVEFILE"
  fi
 done

 mkdir -p $SMNTPT$SAVEFILE 2>/dev/null
 cp -f /usr/share/pixmaps/puppy/puppy_save.svg  "$SMNTPT$SAVEFILE/.DirIcon"

 PUPMODE=128
 SAVEPART=${SAVEPART}
 SAVEFS=${SAVEFS}
 PUPSAVE=${PUPSAVE}
 SAVEFILE=${SAVEFILE}
 NAMEONLY=${NAMEONLY}
 SAVEPATH=${SAVEPATH}
 MYPASSWORD=''
 SFEXT=''
 xPDEV=${PDEV1}
 xDEVFS=${DEV1FS}
 xPSUBDIR=${PSUBDIR}
 SMNTPT=${SMNTPT}
 CRYPTO=''
 expBOOTDRV=${expBOOTDRV}
} #end sace_directory

#================================================================

xDEVFS="$DEV1FS"
xPDEV="$PDEV1"
if [ "$PSAVEMARK" != "" -a "$PDEV1" != "" ];then #see /etc/rc.d/PUPSTATE
 devnameonly="`echo -n "$PDEV1" | sed -e 's/[0-9]*$//'`"
 SAVEPART="${devnameonly}${PSAVEMARK}" #partition that will-have ${DISTRO_FILE_PREFIX}save.
 spPATTERN='/dev/'"$SAVEPART"'|'
 SAVEFS="`probepart -m | grep "$spPATTERN" | cut -f 2 -d '|'`"
 xDEVFS="$SAVEFS"
 xPDEV="$SAVEPART"
fi

[ ! "$DEV1FS" ] && xDEVFS='xxx' #this will enable choice of create a save-file.

SAVECHOICE=255

# some word processing now...
T_canceltitle="$(gettext 'Click close-box to cancel shutdown')"
T_countdown="$(gettext 'Shutdown in TIME seconds')"
T_savetofile="$(gettext 'SAVE TO FILE')"
T_savetopart="`eval_gettext \"SAVE TO \\\${xPDEV}\"`"
T_orwait240=""
[ $TIMELIMIT -gt 0 ] && \
T_orwait240=$(printf "$(gettext '(Or, wait %s seconds to shutdown without saving anything)')" "$TIMELIMIT")

T_save="$(gettext 'SAVE')"
T_cd="$(gettext 'SAVE TO CD')"

#130221 note, pupdialog will exit with 255 if click window close-box, 254 if timeout.
# former, want to abort shutdown, latter, shutdown without saving.
xPSUBDIR="`echo -n "$PUPSFS" | cut -f 3 -d ',' | sed -e 's%/[^/]*$%%'`" #ex: sda3,vfat,/pup220/puppy.sfs will return /pup220
T_ms="`eval_gettext \"You can save the session and all of the settings and personal data created so far.

If unsure, it is recommended that you do save the session, so all your personal settings and files will be automatically loaded at next boot.\"`"
if [ $DISPLAY ];then
  T_display="`eval_gettext \"Click the \Zb\\\${T_save}\ZB button to be provided with the available save options, or click \Zb\\\${T_no}\ZB to exit immediately without saving anything.\"`" #111012 fix.
  STEP=6
  export XY_DIALOG="<window title=\"$T_title\" icon-name=\"gtk-save\" resizable=\"false\"><vbox>
    <text use-markup=\"true\"><label>\"$T_ms\"</label></text>
    <text use-markup=\"true\"><label>\"$T_canceltitle\"</label></text>
    <progressbar><input>for i in \$(seq 0 10 100); do echo \$i; sleep $STEP; done;echo 100</input>
      <label>$(gettext 'Shutdown in 60 seconds.')</label>
      <action type=\"exit\">20</action>
    </progressbar>
    <hbox>
     <button>
     <input file icon=\"gtk-yes\"></input>
     <label>$T_save</label><action>EXIT:0</action>
     </button>
     <button>
      <input file icon=\"gtk-no\"></input>
     <label>$T_no</label><action>EXIT:20</action>
     </button>
    </hbox>
    </vbox></window>"
    
  eval "$(gtkdialog -p XY_DIALOG --center)"
  case "$EXIT" in
    abort) SAVECHOICE=255     ;;
    *)     SAVECHOICE="$EXIT" ;;
  esac

else
  T_display="`eval_gettext \"Select \Zb\\\${T_save}\ZB (just press ENTER key) to be provided with the available save options, or select \Zb\\\${T_no}\ZB (TAB then ENTER) to exit without saving.\"`"
  yesno="$T_ms \n\n$T_display \n\n$T_orwait240"
  dialog --colors --title "$T_title" --timeout $TIMELIMIT --no-label "$T_no" --yes-label "$T_save" --yesno "$yesno" 0 0 #120512
  SAVECHOICE=$?
fi

case $SAVECHOICE in
 0)
  if choosepartfunc; then
    enmount
    case $SAVEFS in
      ext?|reiserfs|minix|btrfs|f2fs) SAVEFS_IS_LINUX="y";;
      *) SAVEFS_IS_LINUX="";;
    esac
    SAVESTYLE='file'
    DENSITY=''
    SFEXT=''
    if cryptsetup --help >/dev/null 2>&1 && modprobe dm-crypt && modprobe xts ; then
      choosecrypt_new
    fi
    [ -z "$DENSITY" ] && [ "$SAVEFS_IS_LINUX" ] && choosestyle
    if [ "$SAVESTYLE" = "file" ]; then
       [ -z "$DENSITY" ] && choosefs
       choosesize || exit	###FIXME###
    fi
    choosename
    NAMEROOT="$NAMEONLY"
    [ "${SFEXT}" ] && NAMEONLY="$NAMEROOT.${SFEXT}"
    if [ "$PSAVEDIR" ];then
      SAVEFILE="${PSAVEDIR}${NAMEONLY}"
    else
      SAVEFILE="$PSUBDIR/$NAMEONLY"
    fi
    #nameclash || exit	###FIXME###
    PUPSAVE="$SAVEPART,$SAVEFS,$SAVEFILE"
    case "$SAVESTYLE" in
      folder) save_directory && PUPMODE=128;;
      file) pupsavefunc && PUPMODE=128;;
    esac
  fi
 ;;
 3)   echo     ;; #case already handled above.
 255) exit 255 ;; #wmreboot and wmpoweroff can cancel shutdown. 130221
 *)   echo "$(gettext 'Shutting down without saving...')" ;;
esac

#--------------------------------------------------
if [ ! -f ${SMNTPT}/pupswap.swp ] ; then
  if pupswap validate_drive ${SAVEPART} ; then
    ONLY_IF_NO_SWAP=1 pupswap set_dir ${SMNTPT}
  fi
fi
#--------------------------------------------------

#record all variables to a file...
#20140716 SFR: but first escape ' (if present) in MYPASSWORD
MYPASSWORD="`echo "$MYPASSWORD" | sed -e "s#'#'\\"'\\"'#g"`"
echo "PUPMODE=${PUPMODE}
SAVEPART='${SAVEPART}'
SAVEFS='${SAVEFS}'
SAVEFILE='${SAVEFILE}'
PUPSAVE='${SAVEPART},${SAVEFS},${SAVEFILE}'
NAMEONLY='${NAMEONLY}'
SAVEPATH='${SAVEPATH}'
MYPASSWORD='${MYPASSWORD}'
SFEXT='${SFEXT}'
xPDEV='${xPDEV}'
xDEVFS='${xDEVFS}'
xPSUBDIR='${xPSUBDIR}'
SMNTPT='${SMNTPT}'
CRYPTO='${CRYPTO}'
expBOOTDRV='${expBOOTDRV}'" > /tmp/shutdownconfig_results

if raspi-version -q ; then
 # Add a bootmenu.txt file if we save on a different drive or in a different
 # partition, but not if PSAVEPART is set in PUPSTATE
 if [ "${PSAVEPART}" = "" -a "${SAVEPART}" != "${xPDEV}" ]; then
  MOUNTED=$(grep "mmcblk0p1" /proc/mounts | cut -f 2 -d ' ')
  if [ ! "$MOUNTED" ]; then
   mkdir -p /mnt/mmcblk0p1
   mount /dev/mmcblk0p1 /mnt/mmcblk0p1
   MOUNTED="/mnt/mmcblk0p1"
  fi
  if [ -n "${SAVEPART}" -a -n "${SAVEFILE}" ] ; then
   echo "
LABEL ${SAVEFILE##*/}
	PMEDIA usbflash
	PUPSFS ${PUPSFS%%,*}:${PUPSFS##*,}
	PSAVE ${SAVEPART}:${SAVEFILE}" >> ${MOUNTED}/bootmenu.txt
   umount ${MOUNTED} 2>/dev/null
  fi
 fi
else
 # Add a savemark file if we save in a diffrent partition
 # But not if defined by PSAVEPART or PSAVEMARK in PUPSTATE
 if [ "${PSAVEPART}" = "" -a "${PSAVEMARK}" = "" -a "${SAVEPART}" != "${xPDEV}" ];then
  SAVEDISK=$(echo "${SAVEPART}" |  sed 's/[0-9]*//g')
  PDEV1DISK=$(echo "${xPDEV}" |  sed 's/[0-9]*//g')
  xSAVEMARK=$(echo "${SAVEPART}" |  sed 's/[^0-9]*//g')
  if [ "${SAVEDISK}" = "${PDEV1DISK}" ];then
   MOUNTED=$(grep "${xPDEV}" /proc/mounts)
   if [ "$MOUNTED" ]; then
    echo "${xSAVEMARK}" > /mnt/${xPDEV}${xPSUBDIR}/SAVEMARK
   else
    mkdir -p /mnt/${xPDEV} && mount /dev/${xPDEV} /mnt/${xPDEV}
    echo "${xSAVEMARK}" > /mnt/${xPDEV}${xPSUBDIR}/SAVEMARK
   fi
   umount /mnt/${xPDEV} 2>/dev/null
  fi
 fi
fi

exit 0
#the end#
