#!/bin/ash
#(c) Copyright 2008 Barry Kauler puppylinux.com
#2008 Lesser GPL licence v2 (http://www.fsf.org/licensing/licenses/lgpl.html)
#this is /sbin/pup_event_frontend_d, created June 2008 for Puppy Linux 4.x, by Barry Kauler.
#This script is part of 'pup_event', my (very) light-weight alternative to udev.
#responds to events posted to /tmp/pup_event_backend_s by /sbin/pup_event_backend_d.
#this script is launched from /root/.xinitrc.
#v407 added hotplug support for zip and ls120 diskettes.
#v407 hotplug fix for /dev/hd* optical drives.
#v408 fix for k2.6.21.7, does not set DEVTYPE.
#v408 rewrite, now works by polling /sys/block.
#v410 rerwin: detect optical disc not inserted.
#v410 avoid exact overlapping icons.
#v411 rerwin: avoid icon getting duplicated if it is renamed
#v412 workaround, someone had RAMSAVEINTERVAL not set.
#w004 LANG=C, faster. /bin/ash, even faster.
#w007 mouse inactivity computer power-down.
#w015 handle request to update one drives icons.
#w471 fix for slow rox startup on slow cpus.
#w476 add support for ext4 f.s.
#w482 k2.6.25.16 /proc/partitions (read by probepart) can be slow to update.
#v424 add right-click menu item to unmount all mounted partitions.
#v424 experimental automatic unmounting.
#v431 shinobar: fix for overlapping icons at some screen resolutions.
#091208 fine-tune placement of desktop drive icons.
#091223 partial fix, some interfaces, no change in /sys/block when insert/remove a card.
# 4jan11 shinobar: some locales (ex: nl_BE) have ',' instead of '.' in numeric, ex o/p of 'dc'.

# i18n gettext, eval_gettext
export TEXTDOMAIN=pup_event
export TEXTDOMAINDIR=/usr/share/locale
export OUTPUT_CHARSET=UTF-8
eval_gettext () {
  local myMESSAGE=$(gettext "$1")
  eval echo \"$myMESSAGE\"
}
#. /usr/bin/gettext.sh

OLDLANG=$LANG #100613
export LANG=C #w004

#v408 when testing k2.6.21.7, no DEVTYPE, had to modify udev rules which causes udevd to
#do multiple overlapping writes to /tmp/pup_event_backend_s. Even with 2.6.25.x, plugging
#in two USB drives at once can cause this. So, dropping that, going back to primitive,
#simple polling loop.

sleep 2 #let the dust settle after X has started.
#w471 slow cpus need more delay (well, rox does)...
DELAYFACTOR=0
CPUMHZ=`grep -m 1 -i '^cpu MHz' /proc/cpuinfo | tr -d ' ' | cut -f 2 -d ':' | cut -f 1 -d '.'`
[ $CPUMHZ ] && [ $CPUMHZ -gt 100 ] && DELAYFACTOR=`expr 1100 \/ $CPUMHZ`
[ $DELAYFACTOR -gt 0 ] && sleep $DELAYFACTOR

[ "$DISPLAY" = "" ] && exit #X not running.

#v404 /usr/sbin/video-wizard (Xvesa) does create /tmp/pup_event_icon_change_flag
#which /sbin/clean_desk_icons reads via .xinirc when X starts, to wipe all drive icons.
#however I think it would be good to test here also if X mode not yet settled on...
if [ -f /tmp/videomode ];then #only exists during X resolution setup.
 if [ "`readlink /usr/bin/X`" = "Xvesa" ];then
  while [ -f /tmp/videomode ];do
   sleep 1
  done
 fi
fi

TOGGLE=1
SAVECNT=0
MOUSECNT=0 #w007
MINUTECNT=0 #w007
CURPOS1="" #w007
echo -n "" > /tmp/pup_event_frontend_d_curpos.log #w007

ZDRV='';ZDRVINIT='no' #these usually set in PUPSTATE.
. /etc/rc.d/PUPSTATE
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/X11R7/bin"
KERNVER="`uname -r`"
. /etc/eventmanager #has RAMSAVEINTERVAL, ICONDESK, HOTPLUGNOISY, ICONPARTITIONS, BACKENDON, POWERTIMEOUT
. /etc/rc.d/functions4puppy4

SCRNXY="`xwininfo -root | grep -o '\-geometry .*' | tr -s ' ' | cut -f 2 -d ' ' | cut -f 1 -d '+'`"
SCRN_X="`echo -n "$SCRNXY" | cut -f 1 -d 'x'`"
SCRN_Y="`echo -n "$SCRNXY" | cut -f 2 -d 'x'`"

[ "$RAMSAVEINTERVAL" = "" ] && RAMSAVEINTERVAL=30 #412
RAMSAVEINTERVAL=`expr $RAMSAVEINTERVAL \* 60` #convert minutes to seconds.

[ "$POWERTIMEOUT" = "" ] && POWERTIMEOUT=0 #w007
POWERTIMEOUT=`expr $POWERTIMEOUT \* 60` #convert minutes to seconds.

SIZE_MODS_M=0
if [ "$ZDRVINIT" = "yes" ];then 
 #all mods were in initrd at bootup, then moved to main f.s.
 SIZE_MODS_M=`du -m -s /lib/modules | cut -f 1`
fi
RETVALm=1
PREVSIZETMPM=0
PREVSIZEFREEM=0

#v424 experiment, automatic unmounting...
auto_unmount_func() {
 for ONEMNTPT in `mount | grep '^/dev/' | grep -vE '^/dev/loop|^/dev/ram' | cut -f 3 -d ' ' | grep -v '^/initrd/' | grep -v '^/$' | tr '\n' ' '`
 do
  if [ "`fuser -v -m $ONEMNTPT`" = "" ];then
   sync
   umount $ONEMNTPT ; umVAL=$?
   #code from pmount: fix zombie process prevents partition unmount, invisible to fuser...
   if [ $umVAL -ne 0 ];then
    ZOMBIES="`ps -H -A | grep '<defunct>' | sed -e 's/  /|/g' | grep -v '|||' | cut -f 1 -d ' ' | tr '\n' ' '`"
    for ONEZOMBIE in $ZOMBIES
    do
     kill $ONEZOMBIE 2>/dev/null
    done
    umount $ONEMNTPT ; umVAL=$?
   fi
  fi
 done
}

format_size_func() {
 export LC_ALL=C # 4jan11 shinobar
 [ ! $SIZE ] && SIZE=0
 if [ $SIZE -gt 1048576 ];then #1024*1024
  SIZE="`dc $SIZE 1048576 \/ p`"
  SIZE="`printf "%.1f" $SIZE`GB"
 else
  if [ $SIZE -gt 99 ];then
   SIZE="`expr $SIZE \/ 1024`MB"
  else
   SIZE="`dc $SIZE 1024 \/ p`"
   SIZE="`printf "%.1f" $SIZE`MB"
  fi
 fi
 [ "$SIZE" = "0.0MB" ] && SIZE="0"
 export LC_ALL= # 4jan11 shinobar
}

create_appinfo_func() { #needs INFO, DRV_CATEGORY, MOREITEMS, ONEDRVNAME
   echo "<?xml version=\"1.0\"?>
<AppInfo>
  <Summary>${INFO}</Summary>
  <About>
   <Purpose>`gettext \"Drive icons are part of Puppy Event Manager, see System menu\"`</Purpose>
   <Authors>Barry Kauler LGPL 2008</Authors>
  </About>
  <AppMenu>
   <Item option=\"pmount_${DRV_CATEGORY}\" icon=\"gtk-harddisk\"><Label>`gettext \"Run Pmount Puppy Drive Mounter\"`</Label></Item><Item option=\"eventmanager\" icon=\"gtk-execute\"><Label>`gettext \"Run Desktop Drive Icon Manager\"`</Label></Item>${MOREITEMS}
  </AppMenu>
</AppInfo>" > /root/.pup_event/drive_${ONEDRVNAME}/AppInfo.xml
}

#free_coord() {
# #find a free place on desktop. v410 avoid exact overlapping icons...
# COORDSGRID="`grep -o ' x="[0-9]*" y="[0-9]*" ' /root/Choices/ROX-Filer/PuppyPin | sed 's/[0-9]"/"/g'`"
# COORD_Y=`expr $SCRN_Y - 64`
# COORD_X=32
# MAX_X=`expr $SCRN_X - 96`
# xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
# while [ 1 ];do
#  xgPATTERN="`echo -n "$xPATTERN" |  sed 's/[0-9]"/"/g'`"
#  [ "`echo "$COORDSGRID" | grep "$xgPATTERN"`" = "" ] && break
#  COORD_X=`expr $COORD_X + 64`
#  xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
#  [ $COORD_X -gt $MAX_X ] && break
# done
#}
#v431 shinobar: fix for overlapping icons at some screen resolutions...
free_coord() {
 #find a free place on desktop. v410 avoid exact overlapping icons...
 #for left or right, i have flipped logic, so 'y' is horizontal...
 COORDSGRID="`grep -o ' x="[0-9]*" y="[0-9]*" ' /root/Choices/ROX-Filer/PuppyPin | sed 's/[0-9]"/"/g'`"
 case $ICON_PLACE_ORIENTATION in #091208 see /etc/eventmanager
  bottom|right)
   COORD_Y=`expr $SCRN_Y - $ICON_PLACE_EDGE_GAP` #091208 default 64, see /etc/eventmanager
  ;;
  *) #top or left
   COORD_Y=$ICON_PLACE_EDGE_GAP
 esac
 # import from v4.20p1JP 5Jun09, 18aug09 by Masaki Shinomiya : snap on the grid
 PIN_GRID_STEP=`grep "pinboard_grid_step" $HOME/.config/rox.sourceforge.net/ROX-Filer/Options | sed -e "s/ *<[^>]*>//g"`
 if [ "$PIN_GRID_STEP" ] && [ $PIN_GRID_STEP -gt 0 ];then
  PIN_GRID_STEP2=`expr $PIN_GRID_STEP / 2`
  COORD_Y=`expr \( $COORD_Y + $PIN_GRID_STEP2 \) / $PIN_GRID_STEP '*'  $PIN_GRID_STEP`
 fi
 COORD_X=$ICON_PLACE_START_GAP #091208 default 32, see /etc/eventmanager
 MAX_X=`expr $SCRN_X - 96`
 xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
 xyCNT=0 #precaution.
 while [ 1 ];do
  xgPATTERN="`echo -n "$xPATTERN" |  sed 's/[0-9]"/"/g'`"
  [ "`echo "$COORDSGRID" | grep "$xgPATTERN"`" = "" ] && break
  COORD_X=`expr $COORD_X + $ICON_PLACE_SPACING` #091208
  if [ $COORD_X -gt $MAX_X ];then #091208 start next line up.
   xyCNT=`expr $xyCNT + 1`
   [ $xyCNT -gt 1 ] && break
   case $ICON_PLACE_ORIENTATION in #091208 see /etc/eventmanager
    bottom)
     COORD_Y=`expr $SCRN_Y - $ICON_PLACE_SPACING`
    ;;
    *)
     COORD_Y=`expr $SCRN_Y + $ICON_PLACE_SPACING`
    ;;
   esac
   COORD_X=$ICON_PLACE_START_GAP
  fi
  xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
 done
}

free_coord() {
 #find a free place on desktop. v410 avoid exact overlapping icons...
 #091208 finetune placement, also any side of screen...
 #read the coords grid, code from shinobar...
 COORDSGRID="`grep -o ' x="[0-9]*" y="[0-9]*" ' /root/Choices/ROX-Filer/PuppyPin | sed 's/[0-9]"/"/g'`"
 PIN_GRID_STEP=`grep "pinboard_grid_step" $HOME/.config/rox.sourceforge.net/ROX-Filer/Options | sed -e "s/ *<[^>]*>//g"`
 [ ! $PIN_GRID_STEP ] && PIN_GRID_STEP=16 #16=medium.
 [ $PIN_GRID_STEP -eq 0 ] && PIN_GRID_STEP=16 #precaution.
 PIN_GRID_STEP2=`expr $PIN_GRID_STEP \/ 2`
 MAX_X=`expr $SCRN_X - 96`
 MAX_Y=`expr $SCRN_Y - 96`
 case $ICON_PLACE_ORIENTATION in #see /etc/eventmanager
  bottom)
   COORD_Y=`expr $SCRN_Y - $ICON_PLACE_EDGE_GAP` #default 64, see /etc/eventmanager
   COORD_Y=`expr \( $COORD_Y + $PIN_GRID_STEP2 \) / $PIN_GRID_STEP '*'  $PIN_GRID_STEP`
   COORD_X=$ICON_PLACE_START_GAP #default 32, see /etc/eventmanager
   xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
   xyCNT=0 #precaution.
   while [ 1 ];do
    xgPATTERN="`echo -n "$xPATTERN" |  sed 's/[0-9]"/"/g'`"
    [ "`echo "$COORDSGRID" | grep "$xgPATTERN"`" = "" ] && break
    COORD_X=`expr $COORD_X + $ICON_PLACE_SPACING`
    if [ $COORD_X -gt $MAX_X ];then #start next line up.
     xyCNT=`expr $xyCNT + 1`
     [ $xyCNT -gt 1 ] && break
     COORD_Y=`expr $COORD_Y - $ICON_PLACE_SPACING`
     COORD_X=$ICON_PLACE_START_GAP
    fi
    xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
   done
  ;;
  top)
   COORD_Y=$ICON_PLACE_EDGE_GAP
   COORD_Y=`expr \( $COORD_Y + $PIN_GRID_STEP2 \) / $PIN_GRID_STEP '*'  $PIN_GRID_STEP`
   COORD_X=$ICON_PLACE_START_GAP #default 32, see /etc/eventmanager
   xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
   xyCNT=0 #precaution.
   while [ 1 ];do
    xgPATTERN="`echo -n "$xPATTERN" |  sed 's/[0-9]"/"/g'`"
    [ "`echo "$COORDSGRID" | grep "$xgPATTERN"`" = "" ] && break
    COORD_X=`expr $COORD_X + $ICON_PLACE_SPACING`
    if [ $COORD_X -gt $MAX_X ];then #start next line down.
     xyCNT=`expr $xyCNT + 1`
     [ $xyCNT -gt 1 ] && break
     COORD_Y=`expr $COORD_Y + $ICON_PLACE_SPACING`
     COORD_X=$ICON_PLACE_START_GAP
    fi
    xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
   done
  ;;
  left)
   COORD_X=$ICON_PLACE_EDGE_GAP #default 64, see /etc/eventmanager
   COORD_Y=$ICON_PLACE_START_GAP #default 32, see /etc/eventmanager
   COORD_Y=`expr \( $COORD_Y + $PIN_GRID_STEP2 \) / $PIN_GRID_STEP '*'  $PIN_GRID_STEP`
   xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
   xyCNT=0 #precaution.
   while [ 1 ];do
    xgPATTERN="`echo -n "$xPATTERN" |  sed 's/[0-9]"/"/g'`"
    [ "`echo "$COORDSGRID" | grep "$xgPATTERN"`" = "" ] && break
    COORD_Y=`expr $COORD_Y + $ICON_PLACE_SPACING`
    if [ $COORD_Y -gt $MAX_Y ];then #start next row.
     xyCNT=`expr $xyCNT + 1`
     [ $xyCNT -gt 1 ] && break
     COORD_X=`expr $COORD_X + $ICON_PLACE_SPACING`
     COORD_Y=$ICON_PLACE_START_GAP
    fi
    xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
   done
  ;;
  right)
   COORD_X=`expr $SCRN_X - $ICON_PLACE_EDGE_GAP` #default 64, see /etc/eventmanager
   COORD_Y=$ICON_PLACE_START_GAP #default 32, see /etc/eventmanager
   COORD_Y=`expr \( $COORD_Y + $PIN_GRID_STEP2 \) / $PIN_GRID_STEP '*'  $PIN_GRID_STEP`
   xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
   xyCNT=0 #precaution.
   while [ 1 ];do
    xgPATTERN="`echo -n "$xPATTERN" |  sed 's/[0-9]"/"/g'`"
    [ "`echo "$COORDSGRID" | grep "$xgPATTERN"`" = "" ] && break
    COORD_Y=`expr $COORD_Y + $ICON_PLACE_SPACING`
    if [ $COORD_Y -gt $MAX_Y ];then #start next row back.
     xyCNT=`expr $xyCNT + 1`
     [ $xyCNT -gt 1 ] && break
     COORD_X=`expr $COORD_X - $ICON_PLACE_SPACING`
     COORD_Y=$ICON_PLACE_START_GAP
    fi
    xPATTERN=" x=\"${COORD_X}\" y=\"${COORD_Y}\" "
   done
  ;;
 esac
}





add_pinboard_func() { #needs ONEDRVNAME, DRV_CATEGORY, FSTYPE
 #ppPATTERN=' label="'"$ONEDRVNAME"'"'
 #v411 rerwin: avoid icon getting duplicated if it is renamed...
 ppPATTERN="/root/.pup_event/drive_${ONEDRVNAME}<"
 [ "`grep "$ppPATTERN" /root/Choices/ROX-Filer/PuppyPin`" != "" ] && return #precaution.
 free_coord
 echo "<?xml version=\"1.0\"?>
<env:Envelope xmlns:env=\"http://www.w3.org/2001/12/soap-envelope\">
 <env:Body xmlns=\"http://rox.sourceforge.net/SOAP/ROX-Filer\">
  <PinboardAdd>
   <Path>/root/.pup_event/drive_${ONEDRVNAME}</Path>
   <X>${COORD_X}</X>
   <Y>${COORD_Y}</Y>
   <Label>${ONEDRVNAME}</Label>
   <Args>${DRV_CATEGORY} ${FSTYPE}</Args>
  </PinboardAdd>
 </env:Body>
</env:Envelope>"  | rox -R
}

create_icon_func() {
 #create desktop icon, and directory with handler script, icon and help...
 #requires global variables DRV_NAME, DRV_CATEGORY, DRV_DESCRIPTION.
 #if a passed param $1, then PROBEPART already known, inefficient to rerun here each time.
 DRVINFO="$DRV_NAME"'|0|0'
 if [ "$ICONPARTITIONS" = "true" ];then
  #display an icon for each partition... w476 add ext4...
  [ ! $1 ] && PROBEPART="`probepart -k | grep -E '\|ext4\||\|ntfs\||\|msdos\||\|vfat\||\|ext2\||\|ext3\||\|iso9660\||\|xfs\||\|reiser'`"
  drvPATTERN='^/dev/'"${DRV_NAME}" #important, no space on end!
  DRVINFO="`echo "$PROBEPART" | grep "$drvPATTERN" | cut -f 1,2,3 -d '|' | tr '\n' ' '`"

  #w482 k2.6.25.16 /proc/partitions (read by probepart) can be slow to update...
  diCNT=0
  if [ "`echo -n "$DRV_NAME" | grep -E '^sd|^mmc'`" != "" ];then
   while [ "$DRVINFO" = "" ];do
    diCNT=`expr $diCNT + 1`
    [ $diCNT -gt 3 ] && break
    sleep 1
    PROBEPART="`probepart -k | grep -E '\|ext4\||\|ntfs\||\|msdos\||\|vfat\||\|ext2\||\|ext3\||\|iso9660\||\|xfs\||\|reiser'`"
    DRVINFO="`echo "$PROBEPART" | grep "$drvPATTERN" | cut -f 1,2,3 -d '|' | tr '\n' ' '`"
   done
  fi
  
 fi

 LANG=$OLDLANG

 for ONEDRVINFO in $DRVINFO
 do
  ONEDRVNAME="`echo -n "$ONEDRVINFO" | cut -f 1 -d '|' | cut -f 3 -d '/'`"
  FSTYPE="`echo -n "$ONEDRVINFO" | cut -f 2 -d '|'`"
  SIZE=`echo -n "$ONEDRVINFO" | cut -f 3 -d '|'`
  drvPATTERN='^/dev/'"${ONEDRVNAME}"' ' #important, a space on end!
  if [ ! -d /root/.pup_event/drive_${ONEDRVNAME} ];then
   mkdir /root/.pup_event/drive_${ONEDRVNAME}
   cp -af /usr/local/bin/drive_all /root/.pup_event/drive_${ONEDRVNAME}/AppRun
   if [ -e /sys/block/${ONEDRVNAME} ];then
    #device is an entire drive.
    SIZE=`cat /sys/block/${ONEDRVNAME}/size`
    SIZE=$(($SIZE/2)) #get KB.
    format_size_func #formats SIZE for display.
    INFO="`eval_gettext \"Description: \\\${DRV_DESCRIPTION} Size: \\\${SIZE}\"`"  #  translate same "Size:" in clean_desk_icons !!!
   else
    if [ "$FSTYPE" = "0" -a "$SIZE" = "0" ];then
     INFO="`gettext \"Puppy drive manager\"`"
    else
     #pPATTERN=' '"$ONEDRVNAME"'$'
     #SIZE=`grep "$pPATTERN" /proc/partitions | tr -s ' ' | cut -f 4 -d ' '`
     format_size_func #formats SIZE for display.
     INFO="`eval_gettext \"Filesystem: \\\${FSTYPE} Size: \\\${SIZE}\"`"
    fi
   fi
   #v424 add item to unmount all partitions...

   MOREITEMS="<Item option=\"unmount\" icon=\"gtk-harddisk\"><Label>`eval_gettext \"Unmount \\\${ONEDRVNAME} (if currently mounted)\"`</Label></Item><Item option=\"unmountall\" icon=\"gtk-harddisk\"><Label>`gettext \"Unmount ALL mounted partitions\"`</Label></Item>"
   create_appinfo_func #needs INFO, DRV_CATEGORY, MOREITEMS, ONEDRVNAME
  fi
#  if [ "$ICONDESK" = "true" ];then #see /etc/eventmanager.
   MNTSTATUS="`df | grep "$drvPATTERN"`"
   if [ "$MNTSTATUS" = "" ];then
    icon_unmounted_func $ONEDRVNAME $DRV_CATEGORY #see functions4puppy4.
   else
    icon_mounted_func $ONEDRVNAME $DRV_CATEGORY #see functions4puppy4.
   fi
   add_pinboard_func #needs ONEDRVNAME, DRV_CATEGORY, FSTYPE.
#  fi
 done
 #always create a handler for entire drive, even if no icon displayed...
 if [ ! -d /root/.pup_event/drive_${DRV_NAME} ];then
  if [ -e /sys/block/${DRV_NAME} ];then
   mkdir /root/.pup_event/drive_${DRV_NAME}
   cp -af /usr/local/bin/drive_all /root/.pup_event/drive_${DRV_NAME}/AppRun
   SIZE=`cat /sys/block/${DRV_NAME}/size`
   SIZE=$(($SIZE/2)) #get KB.
   format_size_func #formats SIZE for display.
   INFO="`eval_gettext \"Description: \\\${DRV_DESCRIPTION} Size: \\\${SIZE}\"`"
   #v424 add item to unmount all mounted partitions...
   MOREITEMS="</Item><Item option=\"unmountall\" icon=\"gtk-harddisk\"><Label>`gettext \"Unmount ALL mounted partitions\"`</Label></Item>"
   ONEDRVNAME="$DRV_NAME"
   create_appinfo_func #needs INFO, DRV_CATEGORY, MOREITEMS, ONEDRVNAME
  fi
 fi
 LANG=C
}

remove_pinboard_func() { #needs DRV_NAME (name of entire drive)
 ppPATTERN=' label="'"$DRV_NAME"'.*" '
 [ "`grep "$ppPATTERN" /root/Choices/ROX-Filer/PuppyPin`" = "" ] && return
 ALLNAMES="`grep -o "$ppPATTERN" /root/Choices/ROX-Filer/PuppyPin | cut -f 2 -d '"' | tr '\n' ' '`" #'geany
 for ONEDRVNAME in $ALLNAMES
 do
  echo "<?xml version=\"1.0\"?>
<env:Envelope xmlns:env=\"http://www.w3.org/2001/12/soap-envelope\">
 <env:Body xmlns=\"http://rox.sourceforge.net/SOAP/ROX-Filer\">
  <PinboardRemove>
   <Path>/root/.pup_event/drive_${ONEDRVNAME}</Path>
  </PinboardRemove>
 </env:Body>
</env:Envelope>"  | rox -R
 done
}

#note that init script in initrd takes care of restoring modules if enough space.
delete_func() { #called from free_func() and free_flash_func(). delete modules to create more free space.
 #passed param: /pup_rw=delete tmpfs top layer only.
 DEL_LAYER=$1
 #find out what modules are loaded, keep those...
 for ONEKEEP_MOD in `lsmod | cut -f 1 -d ' ' | grep -v 'Module'`
 do
  ONEKEEP_SPEC="`modinfo -F filename ${ONEKEEP_MOD}`"
  ONEKEEP_PATH="`dirname $ONEKEEP_SPEC`"
  mkdir -p /tmp${ONEKEEP_PATH}
  cp -af ${ONEKEEP_SPEC} /tmp${ONEKEEP_PATH}/
 done
 if [ "$DEL_LAYER" != "" ];then
  rm -rf ${DEL_LAYER}/lib/modules
 else
  if [ $PUPMODE -eq 3 -o $PUPMODE -eq 7 -o $PUPMODE -eq 13 ];then
   rm -rf ${SAVE_LAYER}/lib/modules
  fi
  rm -rf /lib/modules
 fi
 cp -af /tmp/lib/modules /lib/modules
 depmod -a
}

free_initrd_func() { #UniPup, runs entirely in initramfs.
 SIZEFREEK=`free | grep '^Total:' | tr -s ' ' | cut -f 4 -d ' '`
 SIZEFREEM=`expr $SIZEFREEK \/ 1024`
 [ -s /tmp/pup_event_sizefreem ] && PREVSIZEFREEM=`cat /tmp/pup_event_sizefreem`
 [ "$PREVSIZEFREEM" = "$SIZEFREEM" ] && return
 #save to a file, freememapplet can read this...
 echo "$SIZEFREEM" > /tmp/pup_event_sizefreem
}

free_func() { #called every 4 seconds.
 case $PUPMODE in
  6|12)
   SIZEFREEM=`df -m | grep ' /initrd/pup_rw$' | tr -s ' ' | cut -f 4 -d ' '`
  ;;
  *)
   SIZEFREEM=`df -m | grep ' /$' | tr -s ' ' | cut -f 4 -d ' '`
  ;;
 esac
 WARNMSG=""
 [ -s /tmp/pup_event_sizefreem ] && PREVSIZEFREEM=`cat /tmp/pup_event_sizefreem`
 [ $PREVSIZEFREEM -eq $SIZEFREEM ] && return
 if [ $SIZEFREEM -lt 10 ];then
  if [ -d /initrd/pup_rw/lib/modules/all-firmware -a "$ZDRVINIT" = "yes" ];then
   delete_func /initrd/pup_rw #save layer is at top, delete mods.
  else
   LANG=$OLDLANG WARNMSG="`gettext \"WARNING: Personal storage file getting full, strongly recommend you resize it or delete files!\"`"
  fi
 fi
 VIRTUALFREEM=$SIZEFREEM
 if [ "$ZDRVINIT" = "yes" ];then #full set of modules present, moved from initrd.
  if [ -d /initrd/pup_rw/lib/modules/all-firmware ];then #have not yet deleted modules.
   #calc the "virtual" free space (would have if modules not there...)
   VIRTUALFREEM=`expr $SIZEFREEM + $SIZE_MODS_M`
   VIRTUALFREEM=`expr $VIRTUALFREEM - 1` #allow for some mods will not be deleted.
  fi
 fi
 #save to a file, freememapplet can read this...
 echo "$VIRTUALFREEM" > /tmp/pup_event_sizefreem
 [ $PUPMODE -eq 5 -o $PUPMODE -eq 2 ] && return 0 #5=first boot, no msgs at top of screen.
 if [ "$WARNMSG" != "" ];then
  killall yaf-splash
  yaf-splash -margin 2 -bg red -bw 0 -placement top -outline 0 -text "$WARNMSG" & # deleted -font "9x15B" for russian locale rodin.s
 fi
}

free_flash_func() { #PUPMODE 3,7,13. called every 4 seconds.
 WARNMSG=""
 SIZEFREEM=`df -m | grep ' /initrd/pup_ro1$' | tr -s ' ' | cut -f 4 -d ' '`
 SIZETMPM=`df -m | grep ' /initrd/pup_rw$' | tr -s ' ' | cut -f 4 -d ' '`
 [ -s /tmp/pup_event_sizefreem ] && PREVSIZEFREEM=`cat /tmp/pup_event_sizefreem`
 [ -s /tmp/pup_event_sizetmpm ] && PREVSIZETMPM=`cat /tmp/pup_event_sizetmpm`
 [ $PREVSIZEFREEM -eq $SIZEFREEM -a $PREVSIZETMPM -eq $SIZETMPM ] && return
 if [ $SIZEFREEM -lt 10 ];then
  if [ -d /initrd/pup_ro1/lib/modules/all-firmware -a "$ZDRVINIT" = "yes" ];then
   delete_func /initrd/pup_ro1 #delete modules in save layer only.
  else
   LANG=$OLDLANG WARNMSG="`gettext \"WARNING: Personal storage file getting full, strongly recommend you resize it or delete files!\"`"
  fi
 fi
 if [ $SIZETMPM -lt 5 ];then
  if [ -d /initrd/pup_rw/lib/modules/all-firmware -a "$ZDRVINIT" = "yes" ];then
   delete_func /initrd/pup_rw #delete modules in top tmpfs layer only.
  else
   LANG=$OLDLANG WARNMSG="`gettext \"WARNING: RAM working space only ${SIZETMPM}MB, recommend a reboot which will flush the RAM\"`"
  fi
 fi
 VIRTUALFREEM=$SIZEFREEM
 if [ "$ZDRVINIT" = "yes" ];then #full set of modules present at bootup.
  if [ -d /initrd/pup_ro1/lib/modules/all-firmware ];then #have not yet deleted modules.
   #calc the "virtual" free space (would have if modules not there...)
   VIRTUALFREEM=`expr $SIZEFREEM + $SIZE_MODS_M`
   VIRTUALFREEM=`expr $VIRTUALFREEM - 1` #allow for some mods will not be deleted.
  fi
 fi
 echo "$SIZETMPM" > /tmp/pup_event_sizetmpm
 #save to a file, freememapplet can read this...
 echo "$VIRTUALFREEM" > /tmp/pup_event_sizefreem
 if [ "$WARNMSG" != "" ];then
  killall yaf-splash
  yaf-splash -margin 2 -bg red -bw 0 -placement top -outline 0 -text "$WARNMSG" & # deleted -font "9x15B" for russian locale rodin.s
 fi
}

savepuppy_func() { #called every 4 seconds.
 if [ -f /tmp/snapmergepuppyrequest ];then #by request.
  rm -f /tmp/snapmergepuppyrequest
  yaf-splash  -outline 0 -margin 4 -bg orange -placement top -text "`gettext \"Saving RAM to 'pup_save' file...\"`" & # deleted -font "9x15B" for russian locale rodin.s
  YAFPID=$!
  sync
  nice -n 19 /usr/sbin/snapmergepuppy
  kill $YAFPID
 fi
}

#v407 fixed so works for sr* and hd* optical...
probe_optical_func() { #passed param is sr<0-9> or hd<a-z>
 DRV_NAME="$1"
 DRV_CATEGORY="optical"
 CDSTATUS2="0"
 opticalPATTERN='^/dev/'"${DRV_NAME}"' '
 [ "`grep "$opticalPATTERN" /proc/mounts`" != "" ] && return #only check cd if unmounted.
 cddetect_quick -d/dev/${DRV_NAME} >/dev/null 2>&1 #very fast.
 #...returns 0 if disc inserted, else 255.
 CDSTATUS2="$?"
 [ "$CDSTATUS2" != "0" ] && [ -d /root/.pup_event/drive_${DRV_NAME} ] && rm -rf /root/.pup_event/drive_${DRV_NAME} #v410 ensure no drive directory if drive empty.
 echo "$CDSTATUS2" > /tmp/pup_event_frontend_identify2_${DRV_NAME}
 [ ! -f /tmp/pup_event_frontend_identify1_${DRV_NAME} ] && cp /tmp/pup_event_frontend_identify2_${DRV_NAME} /tmp/pup_event_frontend_identify1_${DRV_NAME}
 CDSTATUS1="`cat /tmp/pup_event_frontend_identify1_${DRV_NAME}`"
 [ "$CDSTATUS1" = "$CDSTATUS2" ] && return
 cp -f /tmp/pup_event_frontend_identify2_${DRV_NAME} /tmp/pup_event_frontend_identify1_${DRV_NAME}
 if [ "$CDSTATUS2" = "0" ];then
  #VENDOR="`cat /sys/block/${DRV_NAME}/device/vendor | tr -s ' '`"
  #MODEL="`cat /sys/block/${DRV_NAME}/device/model | tr -s ' '`"
  #DRV_DESCRIPTION="$VENDOR $MODEL"
  opticalPATTERN='^/dev/'"${DRV_NAME}"'|'
  DRV_DESCRIPTION="`echo "$PROBEDISK" | grep "$opticalPATTERN" | cut -f 3 -d '|'`"
  create_icon_func #requires DRV_NAME, DRV_CATEGORY, DRV_DESCRIPTION.
  [ "$HOTPLUGNOISY" = "true" ] && /root/.pup_event/drive_${DRV_NAME}/AppRun optical & #handler script.
 else
  rm -rf /root/.pup_event/drive_${DRV_NAME} 2>/dev/null
  remove_pinboard_func #needs DRV_NAME
 fi
}

#v407 detect ls120 and zip disc inserted...
probe_floppy_func() { #passed param is drive name (exs: hdc, sdc)
 DRV_NAME="$1"
 DRVMAIN="`echo -n "$DRV_NAME" | cut -c 1,2`" #sd or hd.
 DRV_CATEGORY="floppy"
 floppyPATTERN="^/dev/$DRV_NAME"
 [ "`grep "$floppyPATTERN" /proc/mounts`" != "" ] && return #mounted.
 if [ "$DRVMAIN" = "hd" ];then
  cat /proc/ide/${DRV_NAME}/identify > /tmp/pup_event_frontend_identify2_${DRV_NAME}
 else
  #this method not as good, as only detects disc if it has a partition...
  floppyPATTERN=" ${DRV_NAME}"
  grep "$floppyPATTERN" /proc/partitions > /tmp/pup_event_frontend_identify2_${DRV_NAME}
 fi
 [ ! -f /tmp/pup_event_frontend_identify1_${DRV_NAME} ] && cp /tmp/pup_event_frontend_identify2_${DRV_NAME} /tmp/pup_event_frontend_identify1_${DRV_NAME}
 [ "`diff -s /tmp/pup_event_frontend_identify1_${DRV_NAME} /tmp/pup_event_frontend_identify2_${DRV_NAME} | grep ' are identical'`" != "" ] && return
 cp -f /tmp/pup_event_frontend_identify2_${DRV_NAME} /tmp/pup_event_frontend_identify1_${DRV_NAME}
 FLOPPYSTATUS=1
 [ "`disktype /dev/${DRV_NAME} 2>&1 | grep 'I/O error'`" = "" ] && FLOPPYSTATUS=0
 if [ "$FLOPPYSTATUS" = "0" ];then
  if [ "$DRVMAIN" = "hd" ];then
   DRV_DESCRIPTION="`cat /proc/ide/${DRV_NAME}/model`"
  else
   DRV_DESCRIPTION="`cat /sys/block/${DRV_NAME}/device/model | tr -s ' '`"
  fi
  create_icon_func #requires DRV_NAME, DRV_CATEGORY, DRV_DESCRIPTION.
  [ "$HOTPLUGNOISY" = "true" ] && /root/.pup_event/drive_${DRV_NAME}/AppRun floppy & #handler script.
 else
  rm -rf /root/.pup_event/drive_${DRV_NAME} 2>/dev/null
  remove_pinboard_func #needs DRV_NAME
 fi
}

######################################################################
#stuff to setup at entry...
mkdir -p /root/.pup_event

#build the desktop icons...
DRV_CATEGORY='drive'
PROBEDISK="`probedisk2`"
#v407 ls120/zip floppy drives are probed every 4 secs...
DRVS_FLOPPY="`echo "$PROBEDISK" | grep '|floppy|' | cut -f 1 -d '|' | cut -f 3 -d '/'`"
#v407 same thing for all optical drives...
DRVS_OPTICAL="`echo "$PROBEDISK" | grep '|optical|' | cut -f 1 -d '|' | cut -f 3 -d '/'`"
if [ "$ICONDESK" = "false" ];then
 #only show a single 'drives' icon on desktop...
 DRV_NAME='drives'               # do NOT translate
 DRV_CATEGORY='any' #see pmount. # do NOT translate
 DRV_DESCRIPTION='all drives'    # do NOT translate
 create_icon_func #needs DRV_NAME, DRV_CATEGORY, DRV_DESCRIPTION.
else
 #show all drives on desktop... w476 add ext4...
 PROBEPART="`probepart -k | grep -E '\|ext4\||\|ntfs\||\|msdos\||\|vfat\||\|ext2\||\|ext3\||\|iso9660\||\|xfs\||\|reiser'`"
 if [ "$FD0ICON" = "true" ];then #see /etc/eventmanager
  if [ -e /sys/block/fd0 ];then
   PROBEDISK="/dev/fd0|floppy|Legacy floppy drive
$PROBEDISK"
   PROBEPART="/dev/fd0|vfat|1440
$PROBEPART"
  fi
 fi
 for ONEDRV in `echo "$PROBEDISK" | cut -f 1,2,3 -d '|' | tr ' ' '_' | tr '\n' ' '`
 do
  DRV_NAME="`echo -n "$ONEDRV" | cut -f 1 -d '|' | cut -f 3 -d '/'`"
  DRV_CATEGORY="`echo -n "$ONEDRV" | cut -f 2 -d '|'`"
  DRV_DESCRIPTION="`echo -n "$ONEDRV" | cut -f 3 -d '|' | tr '_' ' '`"
  [ "`echo "$PROBEPART" | grep "$DRV_NAME"`" = "" ] && continue #precaution (such as CD not inserted).
  create_icon_func startup #needs DRV_NAME, DRV_CATEGORY, DRV_DESCRIPTION, PROBEPART.
 done
fi

if [ "$BACKENDON" = "false" ];then #see /etc/eventmanager.
 killall hotplug2stdout #pup_event_backend_d #no module/firmware hotplug support.
 #...kill hotplug2stdout, as that will cause pup_eventd_backend_d to die.
 [ -f /sbin/udevd ] && killall udevd #alternative to pup_event_backend_d.
 exit
fi
[ "$HOTPLUGON" = "false" ] && exit #turn off all frontend hotplug support. see /etc/eventmanager.


###################################################################
#now go into a two-second loop...
while [ 1 ]
do
 sleep 2

 #graceful exit if shutdown X (see /usr/X11R7/bin/restartwm,wmreboot,wmpoweroff)...
 [ -f /tmp/wmexitmode.txt ] && break

 #test for any change in /sys/block...
 ls -1 --hide=ram* --hide=loop* /sys/block > /tmp/pup_event_frontend_block2
 if [ -f /tmp/pup_event_frontend_block_request ];then #w015 (see gparted_shell, puppyinstaller, bootflash)
  sleep 0.1
  REMOVEBLOCK='^'"`cat /tmp/pup_event_frontend_block_request`"'$'
  BLOCKS2="`grep -v "$REMOVEBLOCK" /tmp/pup_event_frontend_block2`"
  echo "$BLOCKS2" > /tmp/pup_event_frontend_block2
  rm -f /tmp/pup_event_frontend_block_request
 fi
 [ ! -f /tmp/pup_event_frontend_block1 ] && cp /tmp/pup_event_frontend_block2 /tmp/pup_event_frontend_block1
 BLOCKDIFF="`diff /tmp/pup_event_frontend_block1 /tmp/pup_event_frontend_block2`"
 
 #091223 some interfaces, no change in /sys/block when insert/remove a card...
 #note, /proc/partitions can be very slow to update, particularly when remove a card.
 #note, /sys/block/sd*/sd* shows card insertion but may not update on removal -- /usr/local/bin/drive_all will remove an invalid drive icon if clicked on.
 if [ "$BLOCKDIFF" = "" ];then
  BLOCKSPROBE=""
  for ONETESTDRV in `cat /tmp/pup_event_frontend_block2 | grep '^sd'` 
  do
   [ "`echo "$ATADRIVES" | grep "$ONETESTDRV"`" != "" ] && continue
   [ "`cat /sys/block/${ONETESTDRV}/removable 2>/dev/null`" = "0" ] && continue
   if [ ! -e /sys/block/${ONETESTDRV}/${ONETESTDRV}1 ];then #drive exists, but no partition (no card plugged in).
    [ -d /root/.pup_event/drive_${ONETESTDRV}1 ] && BLOCKSPROBE="${BLOCKSPROBE}< ${ONETESTDRV}:"
    dd if=/dev/${ONETESTDRV} of=/dev/null bs=512 count=1 > /dev/null 2>&1 #try force kernel to update.
   else
    [ ! -d /root/.pup_event/drive_${ONETESTDRV}1 ] && BLOCKSPROBE="${BLOCKSPROBE}> ${ONETESTDRV}:"
   fi
  done
  [ "$BLOCKSPROBE" != "" ] && BLOCKDIFF="`echo -n "$BLOCKSPROBE" | tr ':' '\n'`"
 fi
 
 #########hotplug block event##########
 if [ "$BLOCKDIFF" != "" ];then
 
  cp -f /tmp/pup_event_frontend_block2 /tmp/pup_event_frontend_block1
 
  BLOCKSADD="`echo "$BLOCKDIFF" | grep '^> ' | cut -f 2-9 -d ' ' | tr '\n' ' '`"
  BLOCKSREM="`echo "$BLOCKDIFF" | grep '^< ' | cut -f 2-9 -d ' ' | tr '\n' ' '`"
  
  ACTION=add
  SUBSYSTEM=block
  DEVTYPE=disk
  for DRV_NAME in $BLOCKSADD
  do
   [ ! -e /sys/block/$DRV_NAME ] && continue #precaution
   DEVPATH=/block/$DRV_NAME
   odPATTERN='^/dev/'"$DRV_NAME"'|'
   PROBEDISK="`probedisk2`"
   DRVS_OPTICAL="`echo "$PROBEDISK" | grep '|optical|' | cut -f 1 -d '|' | cut -f 3 -d '/'`" #update
   DRVS_FLOPPY="`echo "$PROBEDISK" | grep '|floppy|' | cut -f 1 -d '|' | cut -f 3 -d '/'`" #update
   DRV_CATEGORY="`echo -n "$PROBEDISK" | grep "$odPATTERN" | cut -f 2 -d '|'`"
   DRV_DESCRIPTION="`echo -n "$PROBEDISK" | grep "$odPATTERN" | cut -f 3 -d '|' | tr -s ' '`"
   [ "$ICONDESK" = "true" ] && create_icon_func #uses DRV_NAME, DRV_CATEGORY, DRV_DESCRIPTION
   [ "$HOTPLUGNOISY" = "true" ] && /root/.pup_event/drive_${DRV_NAME}/AppRun ${DRV_CATEGORY} & #handler script.
  done
 
  ACTION=remove
  for DRV_NAME in $BLOCKSREM
  do
   #[ -e /sys/block/$DRV_NAME ] && continue #precaution. w015 must remove.
   DRVS_OPTICAL="`echo "$DRVS_OPTICAL" | grep -v "$DRV_NAME"`" #update
   DRVS_FLOPPY="`echo "$DRVS_FLOPPY" | grep -v "$DRV_NAME"`" #update
   DEVPATH=/block/$DRV_NAME
   if [ "`pidof gtkdialog_pmount`" != "" ];then #if pmount running, refresh it.
    killall gtkdialog_pmount 2>/dev/null
    sleep 0.1
    LANG=$OLDLANG pmount &
   fi
   remove_pinboard_func #needs DRV_NAME
   rm -rf /root/.pup_event/drive_${DRV_NAME}* 2>/dev/null
  done
 
 fi

 if [ $TOGGLE -eq 0 ];then #slow down to every 4 seconds.
  TOGGLE=1
  continue
 else
  TOGGLE=0
 fi

 #######four second timeout procesing#########
 SAVECNT=`expr $SAVECNT + 4`
 if [ $RAMSAVEINTERVAL -ne 0 -a $SAVECNT -gt $RAMSAVEINTERVAL ];then
  touch /tmp/snapmergepuppyrequest #request to savepuppy_func.
  SAVECNT=0
 fi
 if [ $POWERTIMEOUT -ne 0 ];then #w007 power-off computer after inactivity.
  MOUSECNT=`expr $MOUSECNT + 4`
  MINUTECNT=`expr $MINUTECNT + 4`
  if [ $MINUTECNT -gt 59 ];then #come in here every minute...
   MINUTECNT=0
   CURPOS2="`getcurpos`"
   echo "MOUSECNT=$MOUSECNT CURPOS2=$CURPOS2" >> /tmp/pup_event_frontend_d_curpos.log
   [ "$CURPOS1" = "" ] && CURPOS1="$CURPOS2"
   [ "$CURPOS1" != "$CURPOS2" ] && MOUSECNT=0
   CURPOS1="$CURPOS2"
   [ $MOUSECNT -gt $POWERTIMEOUT ] && wmpoweroff &
  fi
 fi
 #some apps should not be disturbed by this background stuff...
 RUNPS="`ps`"
 #w482 add xorriso...
 [ "`echo "$RUNPS" | grep -E 'xorriso|xorrecord|xine|petget|wget|axel|dotpup|mplayer|gcurl|gimv|burniso2cd|growisofs|cdrecord|pcdripper|xfmedia|xmms|ripoff|pdvdrsab|pburn|mhwaveedit|installpkg\.sh|downloadpkgs\.sh'`" != "" ] && continue

 [ "$AUTOUNMOUNT" = "true" ] && auto_unmount_func #v424 automatially unmount a partition if no longer being used (AUTOUNMOUNT set in eventmanager).
 
 #monitor free memory, periodic save of tmpfs top layer...
 case $PUPMODE in
  3|7|13)
   free_flash_func
   savepuppy_func
  ;;
  16|24|17|25) #unipup.
   free_initrd_func
  ;;
  *)   
   free_func
  ;;
 esac
 [ "$ICONDESK" = "false" ] && continue #v405 see /etc/eventmanager
 #unfortunately, we have to poll at regular intervals to see if a cd is inserted...
 for ONEOPTICAL in $DRVS_OPTICAL
 do
  [ "$ONEOPTICAL" = "" ] && continue #precaution
  probe_optical_func $ONEOPTICAL
 done
 #v407 poll to see if a ls120 or zip floppy diskette inserted...
 for ONEFLOPPY in $DRVS_FLOPPY
 do
  [ "$ONEFLOPPY" = "" ] && continue #precaution
  probe_floppy_func $ONEFLOPPY
 done


done #2 second loop.


###END###
