#!/bin/sh
#set -x
# C. Ostheimer 05-2006, 10-2006, 01-2007; usb_install framework by dynamic
# 01-2008 dropbear-0.50, included libutil.so.0, only kernel 2.6 has been updated!
#  set stricter limits: MAX_AUTH_TRIES 3, MAX_UNAUTH_PER_IP 2, MAX_UNAUTH_CLIENTS 3
#  disable shadow passwords (in dropbear and in passwd), no shadow support in avm uClibc
# template cfg script
addon=dropbear
[ "$addon_bin" ] || addon_bin=$addon
#put used defined post install commands into file cfg.customize

# note: when using cfg_dropbear usb_install the config files 
#       are COPIED from usb device (addons/dropbear/etc/dropbear)
#       to /var/tmp/dropbear because a vfat usb device does not allow chmod 600
#       (changes made to /var/tmp are lost if not copied back to usb device)

#server=http://192.168.222.10
server=http://www.spblinux.de/fbox
# cfg.common and cfg.customize are downloaded from $server and
# firmware version specific files are downloaded from $server$svr24 (or $svr26)
# (kernel 2.4/uClibc-0.9.26 or kernel 2.6/uClibc-0.9.28);
# default sub directories are /24[.zlib|.zlib16] and /26.
# svr24=/24
# svr26=/26

# command line option parsing
unset verbose quiet show_usage
[ $# -eq 0 ] && show_usage=1
while [ x$1 != x ]; do case $1 in
 -z) [ "$svr24" ] || svr24=24.zlib;;
 -Z) [ "$svr24" ] || svr24=24.zlib16;;
 -v) verbose=1;;
 -q) quiet=1;;
 -h | -\? | --help) show_usage=1;;
 -*) echo "warning: unknown option $1";;
 *) break
esac; shift; done

# Source common functions for installation, (download if missing)
f=cfg.common
if [ -f ${0%cfg_*}$f ]; then 
 . ${0%cfg_*}$f
else
 wget $server/$f -O /var/$f || errorexit " Couldn't download $f from $server"
 . /var/$f
fi
modext=`_fct modext`
svrsub=`_fct svrsub`
export PATH=$PATH:/sbin:/usr/sbin:/var/$addon/bin


usage()
{
 echo -e "usage:\n" \
	 " [INST_DIR=installation_directory] ${0##*/} [-v] install\n" \
         "   (installs to ramdisk or to INST_DIR/addons if INST_DIR is given)\n" \
	 " ${0##*/} [-v] usb_install | remove\n" \
         "   (usb_install: installs to /addons of autodetected usb device or to INST_DIR)\n" \
	 " ${0##*/} [-v] start [onlykey] | [-v] stop \n"
 exit
}

is_addon_installed()
{
 unset msg
 if mount |grep -q "on /var/$addon"; then
  msg="$addon is still mounted to /var/$addon"
 elif [ -L /var/$addon/bin/$addon_bin -a -x /var/$addon/bin/$addon_bin ]; then
  msg="(usb_install: `ls -l /var/${addon}_usb |sed 's/^[^\/]*//'`)"
 fi
 if [ x$1 != x-q -a "$msg" ]; then
  echo "$addon is still installed. Installation aborted. Run ${0##*/} [remove|usb_remove] first"
  errorexit "$msg" 
 fi
 #create return value
 [ "$msg" ]
}

#echo TEST
#echo "modext $modext, svrsub $svrsub."
#get_inst_realdir_ $INST_DIR
#get_inst_realdir_
#get_missing_file_ chroot
#_fct rdsk@new:ramdev && echo "--$ramdev--"
#echo END_TEST

[ "$show_usage" ] && usage
cd /var
case $1 in
usb_install | install)
 is_addon_installed
 unset is_usb
 [ $1 = usb_install ] && is_usb=1
 free
 if [ "$INST_DIR" ]; then
  if [ -d "$INST_DIR" ]; then
   [ $1 = install ] && echo -n "defaulting to "
   echo "usb_install on $INST_DIR(="`get_inst_realdir_ $INST_DIR`") (given by variable INST_DIR)"
   echo "(if this is not correct run: unset INST_DIR)"
   is_usb=1
  else
   echo "warning: INST_DIR(=$INST_DIR) defined, but not a directory"
   echo "         using default install to ramdisk (press ctrl+c to stop)"
   sleep 10
  fi
 else
  echo "installing $addon ($server$svrsub) ..."
 fi
 [ -d $addon ] || mkdir $addon
 if [ "$is_usb" ]; then 
 ############ USB-INSTALL ####################################
  # check for user defined installation directory given in $INST_DIR
  if [ "$INST_DIR" ]; then
   _fct instdir@`get_inst_realdir_ $INST_DIR`:addons/$addon:inst_dir:inst_fs_type
  else
   _fct instdir@/var/media/ftp:addons/$addon:inst_dir:inst_fs_type
  fi
  case $inst_fs_type in
   msdos | vfat | ntfs)
    cp_opts=""
    ;;
   *)
    cp_opts="-pd"
  esac
  ############ USB-INSTALL, EXTRACT TO USB IF NOT EXTRACTED YET #######
  if ! [ -f $inst_dir/addons/$addon/bin/dropbearmulti ]; then
   echo "installing $addon on usb device (${inst_dir##*/})"
   # get $addon specific squashfs-archives from $server$svrsub
   _fct wgetx@$server$svrsub:$inst_dir/addons/$addon:$addon.sqf
   # get common install scripts / tools / modules from $server$svrsub
   file_path=`_fct path_abs@$0`
   if [ $file_path != $inst_dir/addons ];then
    # not called from $inst_dir/addons: install on $inst_dir/addons
    cp $cp_opts $file_path/cfg.common $inst_dir/addons
    cp $cp_opts $file_path/${0##*/} $inst_dir/addons
   fi
   _fct wgetx@$server$svrsub:$inst_dir/addons:freeramdisk:rd.$modext
   _fct wgetx@$server:$inst_dir/addons:cfg.customize
   chmod +x $inst_dir/addons/${0##*/} $inst_dir/addons/cfg.customize $inst_dir/addons/freeramdisk
   [ -d $addon.tmp ] || mkdir $addon.tmp
   mount |grep -q "on /var/$addon.tmp" && umount $addon.tmp
   if mount |grep -q "on /var/$addon.tmp"; then
    errorexit "error: /var/$addon.tmp already mounted; failed to unmount /var/$addon.tmp"
   else
    _fct rdsk@start:$inst_dir/addons
    # get free ramdisk and store device_name_and_path in variable ramdev
    _fct rdsk@new:ramdev:$inst_dir/addons
    echo -n "$addon.sqf -> $ramdev: "
    cat $inst_dir/addons/$addon/${addon}.sqf >$ramdev
    [ $? -eq 0 ] && mount $ramdev $addon.tmp || _fct fallback@$inst_dir/addons/$addon/$addon.sqf
   fi
   if mount |grep -q "on /var/$addon.tmp"; then
    echo "Start extracting files ... please wait!"
    fr=/var/$addon.tmp
    to=$inst_dir/addons/$addon
    # special treatment part1 (cpnL) of bin/, lib/, usr/bin/, usr/lib/
    _fct cprs@$cp_opts:$fr:$to:bin:lib:usr:etc:dev:sys:proc
    _fct mkdr@$to:bin:lib:usr/bin:usr/lib:etc/$addon
    _fct cprs@$cp_opts:$fr/usr:$to/usr:bin:lib
    _fct cpnL@$cp_opts:$fr/etc:$to/etc:$addon
    _fct cpdf@$cp_opts:$fr/etc/$addon:$to/etc/$addon
    _fct cpnL@$cp_opts:$fr/bin:$to/bin
    _fct cpnL@-R${cp_opts#-}:$fr/lib:$to/lib
    _fct cpnL@$cp_opts:$fr/usr/bin:$to/usr/bin
    _fct cpnL@-R${cp_opts#-}:$fr/usr/lib:$to/usr/lib
    umount /var/$addon.tmp
    _fct rdsk@free:$ramdev:$inst_dir/addons
    rm -r $addon.tmp
    echo "$addon has been successfully installed to usb device ${inst_dir##*/}"
   else
    errorexit "error: failed to download and mount $addon (on /var/$addon.tmp)"
   fi
  else  
   ############ USB-INSTALL, NO NEED TO EXTRACT FILES. ALREADY ON USB #####
   echo "$addon already on USB-Device ... skipping extract phase."
  fi 
  ########### CONTINUE USB-INSTALL AFTER REQUIRED FILES CONFIRMED ON USB-PATH ###########
  file_path=`_fct path_abs@$0`
  if [ $file_path = $inst_dir/addons ]; then
   # called from $inst_dir/addons: create copy in /var
   cp $cp_opts $inst_dir/addons/cfg.common /var
   cp $cp_opts $inst_dir/addons/${0##*/} /var
  fi
  [ -L ${addon}_usb ] || _fct lnsf@${addon}_usb:$inst_dir/addons/$addon
  #create links in /var/$addon pointing to /var/${addon}_usb
  #special treatment part2 (cpnL) of bin/, lib/, usr/bin/, usr/lib/
  # - link all directories except bin/, ...
  # - in bin/, ... : link contents of these directories
  _fct lndfe@/var/$addon:/var/${addon}_usb:bin:lib:usr:etc:proc:sys:dev
  _fct mkdr@/var/$addon:bin:lib:usr/bin:usr/lib:etc:proc:sys:dev
  _fct lndfe@/var/$addon/lib:/var/${addon}_usb/lib
  _fct lndfe@/var/$addon/bin:/var/${addon}_usb/bin
  _fct lndfe@/var/$addon/usr:/var/${addon}_usb/usr:lib:bin
  _fct lndfe@/var/$addon/usr/lib:/var/${addon}_usb/usr/lib
  _fct lndfe@/var/$addon/usr/bin:/var/${addon}_usb/usr/bin
  # special treatment part3 (cpnL) of bin/, lib/, usr/bin/, usr/lib/
  #  - additional symlinks in bin/, usr/bin, lib ...
  # create symbolic links in /var/$addon for all files which have been skipped
  # when extracting to usb with _fct cpnL (=copy to usb but skip symbolic links)
  # (if installed to ramdisk ls -l /var/$addon/bin displays these links in bin/)
  if [ "$modext" = "o" ]; then
   d=/var/$addon/lib
   _fct lnsf2@$d:libutil.so:libutil.so.0:libutil-0.9.26.so
  else
   d=/var/$addon/usr/lib
   [ -f $d/libutil-0.9.28.so ] && _fct lnsf2@$d:libutil.so:libutil.so.0:libutil-0.9.28.so
  fi
  d=/var/$addon/bin
  _fct lnsf2@$d:dbclient:dropbear:dropbearconvert:dropbearkey:ssh:scp:dropbearmulti
  d=/var/$addon/usr/bin
  _fct lnsf2@$d:dbclient:dropbear:dropbearconvert:dropbearkey:ssh:scp:dropbearmulti
  # create devices in /var/$addon/dev if required
  # [ -d /var/$addon/dev ] || mkdir /var/$addon/dev
  # msdos/vfat does not have permissions:
  #    copy config files from usb back to /var/tmp/$addon and adjust permissions
  #    and link from /var/$addon/etc/$addon to /var/tmp/$addon 
  # Create required directory structures
  _fct mkdr@/var:tmp/$addon:$addon/etc/$addon
  # Copy default conf files if not existing on target dir strcuture 
  echo "Copying $addon configuration files from usb device addons/$addon/etc/$addon to /var/tmp/$addon"
  _fct cprs@$cp_opts:/var/${addon}_usb/etc/$addon:/var/tmp/$addon
  _fct lnsf@/var/$addon/etc:../../tmp/$addon
  chmod 600 /var/tmp/$addon/*
  cd /var
 else 
  ########### RAM-INSTALL #############################################
  _fct wgetx@$server$svrsub:/var:freeramdisk:rd.$modext
  _fct wgetx@$server:/var:cfg.customize
  chmod +x freeramdisk cfg.customize
  _fct rdsk@start
  _fct rdsk@new:ramdev
  echo -n "$addon.sqf -> $ramdev: "
  if [ -f $addon.sqf ]; then
   cat $addon.sqf > $ramdev
  else
   _fct wgetx@$server$svrsub:$ramdev:$addon.sqf
  fi 
  mount $ramdev $addon || _fct fallback@$addon.sqf
  # Create required directory structures
  _fct mkdr@/var:tmp/$addon
  # Copy default conf files if not existing on target dir strcuture 
  _fct cpdf@$cp_opts:/var/$addon/etc/$addon:/var/tmp/$addon
  # Remove symlinks which might be left over from last usb_install
  for f in /var/${addon}_usb ; do
   [ -L $f ] && rm $f
  done
 fi
 ########### COMMON-INSTALL (RAM and USB) #############################
 # Create required directory structures
 _fct mkdr@/var:tmp/$addon/dev/pts
 if [ "$modext" = "ko" ]; then
   # allow write access to /dev/pts using mount -o bind
   for d in tmp/$addon tmp/$addon/dev tmp/$addon/dev/pts; do
    [ -d $d ] || mkdir $d
   done
   for i in 0 1 2 3 4 5 6 7; do
    [ -c $d/$i ] || mknod $d/$i c 136 $i
   done
   mount -o bind $d /dev/pts
 fi
 free
 echo "to use $addon (ssh server) type ./cfg_$addon start"
 if ! [ "$is_usb" ]; then
  [ "$0" != "./cfg_$addon" ] && echo "(or $0 start)"
 else
  echo "(or $inst_dir/addons/${0##*/} start)"
  echo
  echo "After a reboot you may reinstall $addon from usb with"
  echo "$inst_dir/addons/${0##*/} usb_install"
 fi
 # check for existence of "cfg.customize" to perform user specific cfg_xyz customizations
 for d in /var $inst_dir/addons;do
  if [ -f $d/cfg.customize -a -x $d/cfg.customize ];then
   [ "$verbose" ] && echo "Found addons customization script cfg.customize in $d. Will check & run customizations for $addon now."
   $d/cfg.customize allow ${0##*/}
   break
  fi
 done  
 echo "(important: use /var/$addon/bin/passwd to set a root password;"
 echo "you might want to generate your own host key files in /var/tmp/$addon"
 echo "with /var/$addon/bin/dropbearkey)"
 ;;
usb_remove | remove)
 [ $1 = usb_remove ] && is_usb=1
 inst_dir=`get_inst_realdir_`
 [ "$inst_dir" ] && is_usb=1 && echo -e "default set to usb_remove\n(if this is not correct run: rm /var/${addon}_usb )\n"
 if ! is_addon_installed -q; then
  [ "$quiet" ] || echo "addon $addon is not installed (has already been removed?)"
 else
  free
  echo "removing $addon ..."
  $0 -q stop ask || exit
  sleep 1
  if ! [ "$is_usb" ]; then
   _fct rdsk@get_device:ramdev:/var/$addon || unset ramdev
   umount /var/$addon
   [ "$ramdev" ] && _fct rdsk@free:$ramdev
   _fct rdsk@stop
  fi
  if ! mount |grep -q "on /var/$addon"; then
   f=$addon.sqf
   [ -f $f ] && rm $f
   if mount |grep -q "ramfs on /dev/pts"; then
    if umount /dev/pts; then
     rm -r /var/tmp/$addon/dev
    fi
   fi
   if [ "$is_usb" ]; then
     [ -d $addon ] && rm -r $addon
     [ -L  ${addon_usb} ] && rm ${addon}_usb
   else
#   [ -d $addon ] && rmdir $addon # labor firmware 4883 busybox comes without rmdir
    if [ -d $addon ]; then for x in $addon/*; do [ -r $x ]; break; rm -r $addon; done; fi
   fi
   echo -n "done - (addon $addon has been removed"
   if [ "$is_usb" ]; then echo " from ram, not from usb)"; else echo ")"; fi
  fi
  free
 fi
 ;;
start)
 d=/var/dropbear/etc/dropbear/dropbear_dss_host_key
 r=/var/dropbear/etc/dropbear/dropbear_rsa_host_key
 unset x
 [ "$2" = "onlykey" ] && x="-s" 
 if [ -x $addon/bin/$addon_bin ]; then
  $addon/bin/$addon_bin -d $d -r $r $x
 else
  errorexit "error: executable /var/$addon/bin/$addon_bin not found (try to run ${0##*/} install)"
 fi
 ;;
stop)
 unset do_ask
 [ "x$2" = "xask" ] && do_ask=1 && shift
 f1=$addon
  for x in TERM KILL result; do
   unset is_running
   for f in $f1; do
    [ "$f" ] || continue 
    if ps |grep -v grep |grep -v ${0##*/} |grep -q "$f "; then
     case $x in
      result)
       errorexit "error: cannot terminate process $f"
       ;;
      *)
       is_running=1
       key=y
       if [ "$do_ask" ]; then
        echo "$addon is running; do you want to terminate process $f (Y/n)"
	read key
	[ "n" = "$key" ] && errorexit "script terminated by user"
	echo "(to reset a terminal use command: stty sane)"
       fi
       killall -$x $f
       sleep 2
     esac
    fi
   done
   [ "$is_running" ] || break
  done
  [ "$quiet" ] || echo "run ${0##*/} remove to free memory by removing addon $addon from the system"
 ;;
*)
 usage
esac

