#!/bin/sh

#
# Author: Blake, Kuo-Lien Huang
# License: GPL 
# Description:
#  2003/04/11 the first version, only work on /dev/hda1 & PXE
#  2003/06/01 disk to disk mode & etherboot support 
#             (the etherboot lzdsk images are located in
#              /tftpboot/etherboot-5.0.7 after DRBLCD installed)
#  2003/07/18 `checkInodeForDevice`
#  2003/08/25 1. restart nfs-user-server when start/startdisk,
#             2. sshd is running when ocs start
#             3. fixed path problem
#  2003/12/05 createcd mode
#  2004/02/11 nfs kernel server
#  2004/04/19 new createcd mode, rename it as isoimage_restore

drblroot="/var/lib/diskless/default/"
ocsroot="/home/partimag"
ocs=$0
ocs=${ocs##/*/}

# Check if root or not
#if [ ! "$UID" = "0" ]; then
#  echo
#  echo "[$LOGNAME] You need to run this script \"$0\" as root."
#  echo
#  exit 1
#fi

# must be root
ID=`/usr/bin/id -u`
if [ "$ID" != "0" ]; then
  echo "You must be root to use this script."
  echo "Use sudo to enable it for users."
  exit 1
fi

if [ -f /usr/bin/tput ]; then
  NORMAL=`tput sgr0 2> /dev/null`
  BOLD=`tput bold 2> /dev/null`
else
  NORMAL=""
  BOLD=""
fi

# ocs root
if [ ! -e "$ocsroot" ]; then
  mkdir -p $ocsroot
fi

# usage
usage_save_option() {
  echo " Options for saving:"
  echo " ${BOLD}-z0, --no-compress${NORMAL}"
  echo "   don't compress when saving: very fast but very big image file"
  echo " ${BOLD}-z1, --gzip-compress${NORMAL}"
  echo "   compress using gzip when saving: fast and small image file (default)"
}
usage_restore_option() {
  echo " Options for restoring:"
  echo " ${BOLD}-s, --sfdisk-op [on|off|force_on|manual]${NORMAL}"
  echo "   create the partition table before restoration start,"
  echo "   force_on: force sfdisk in any case"
  echo "   on (default): use sfdisk to create partition table and stop with any error"
  echo "   off: do not create the partiiton table, use the one in MBR"
  echo "   manual: create the partition table manually"
  echo " ${BOLD}-r, --resize-partition${NORMAL}"
  echo "   resize the partition when restoration finishes,"
  echo "   this will try to fix the problem when small partition image is restored to"
  echo "   a larger partition."
  echo "   Now support partition with filesystem reiserfs, fat, ext2 and ext3"
  echo " ${BOLD}-g, --grub-install GRUB_PARTITION${NORMAL}"
  echo "   install grub in hda with root grub directory in GRUB_PARTITION,"
  echo "   GRUB_PARTITION can be one of /dev/hda1, /dev/hda2..."
}
usage_general_option() {
  echo " General options:"
  echo " ${BOLD}-p, --postaction [shutdown|reboot|command]${NORMAL}"
  echo "   when cloning finishs, shutdown, reboot (default) or enter command prompt"
  echo " ${BOLD}-w, --wait-time TIME${NORMAL}     wait for TIME secs before restoring"
  echo " ${BOLD}-c, --confirm${NORMAL}            wait for confirmation before restoring"
  echo " ${BOLD}-d, --debug${NORMAL}              enter command mode to debug before restoring"
  #echo " -v, --verbose            prints verbose information"
}
usage_option() {
  usage_save_option
  echo
  usage_restore_option
  echo
  usage_general_option
}

usage_operation() {
  echo " Operations:"
  echo " ${BOLD}save${NORMAL}        save image from the disk (or hda1) of the client"
  echo " ${BOLD}restore${NORMAL}     use unicast to restore image to the disk (or hda1) of the client"
  echo " ${BOLD}multicast_restore${NORMAL}"
  echo "   use multicast to restore image to the disk (or hda1) of the client"
  echo " ${BOLD}isoimage_restore${NORMAL}"
  echo "   create iso images to restore image to the disk (or hda1) of the client" 
  echo "   by CDROM"
}

usage() {
  echo "Usage:"
  echo "To start clonezilla:"
  echo "${BOLD}`basename $0` [OPTION] {start|startdisk} [OPERATION]${NORMAL}"
  echo
  usage_operation
  echo
  usage_option
  echo
  echo "To stop clonezilla:"
  echo "${BOLD}`basename $0` stop${NORMAL}"
}

# some useful functions
OPT_GRUB_INSTALL=""
OPT_POST_ACTION="reboot"
OPT_TIME_TO_WAIT="0"
OPT_CONFIRM_RESTORE="off"
OPT_DEBUG_MODE="off"
OPT_RESIZE_PARTITION="off"
OPT_SFDISK_OP="force_on"
OPT_PARTIMAGE_SAVEOPT="-V 500 -f3 -z1 -o -d -b -c"
set_option() {
  local option_name="$1"
  local option_value="$2"
  case "$option_name" in
    "grub_install") OPT_GRUB_INSTALL="$option_value" ;;
    "time_to_wait") OPT_TIME_TO_WAIT="$option_value" ;;
    "confirm_restore") OPT_CONFIRM_RESTORE="$option_value" ;;
    "post_action") OPT_POST_ACTION="$option_value" ;;
    "debug_mode") OPT_DEBUG_MODE="$option_value" ;;
    "resize_partition") OPT_RESIZE_PARTITION="$option_value" ;;
    "sfdisk_op") OPT_SFDISK_OP="$option_value" ;;
    "partimage_saveopt") OPT_PARTIMAGE_SAVEOPT="$option_value" ;;
  esac
}
get_option() {
  local option_name="$1"
  local optioin_value=""
  case "$option_name" in
    "grub_install") option_value="$OPT_GRUB_INSTALL" ;;
    "time_to_wait") option_value="$OPT_TIME_TO_WAIT" ;;
    "confirm_restore") option_value="$OPT_CONFIRM_RESTORE" ;;
    "post_action") option_value="$OPT_POST_ACTION" ;;
    "debug_mode") option_value="$OPT_DEBUG_MODE" ;;
    "resize_partition") option_value="$OPT_RESIZE_PARTITION" ;;
    "sfdisk_op") option_value="$OPT_SFDISK_OP" ;;
    "partimage_saveopt") option_value="$OPT_PARTIMAGE_SAVEOPT" ;;
  esac
  echo "$option_value";
}

get_known_partition() {
  local partition_table="$1"
  cat $partition_table | grep "Id=" | awk -F, '{ if($3!=" Id= 0" && $3!=" Id= f" && $3!=" Id=82" && $3!=" Id= 5" && $3!=" Id=85") print $1; }' | cut -d" " -f1 | sed -e 's/\/dev\///g'
}

# sfdisk failed process
sfdisk_fail_process() {
    echo "sfdisk failed, abort!"
    echo "Please make sure your HD exists or the size of HD is big enough!"
    echo "We can NOT go on! Press \"c\" to enter command prompt or any other key to quit the program..." 
    read fail_answer
    case "$fail_answer" in
      [cC])
          /sbin/sulogin
          ;;
         *)
          exit 1
    esac
}

# used when the partition size is umatch with the partition size stored in the image
# Author: Steven Shiau
resize_partition() {
   # Steven todo if partition ($2) is specified, resize that partition only
   local HD="$1"
   local part_info_tmp=
   local part_to_resize=
   HD_DEV="/dev/$HD"
   # find the known filesystem
   part_info_tmp=`mktemp /tmp/part.XXXXXX`
   /sbin/parted $HD_DEV p > $part_info_tmp
   known_fs="fat16 fat32 vfat ext2 ext3 reiserfs"
   for ifs in $known_fs; do
     if  [ -n "`grep $ifs $part_info_tmp`" ]; then
       part_no=$(grep $ifs $part_info_tmp | awk -F" " '{print $1}')
       part_to_resize="$part_to_resize $part_no"
     fi
   done
   echo "The partition to be resize in harddrive $HD : $part_to_resize"

   for ipart in $part_to_resize; do
      echo "Now resize the partition for $HD$ipart"
      $drbl_bin_path_root/sbin/resize_part $HD $ipart
   done

   [ -f "$part_info_tmp" ] && rm -f $part_info_tmp
}

# start ocs services
# parameter: 
#   $1 task 
#      "save" "savedisk" for saving the data to server
#      "restore" "restoredisk" for restoring the data from server  
#      "isoimage_restore" "isoimage_restoredisk" for creating a CD for restore
#   $2 option
#      "$target_file" for save/restore the partition /dev/hda1
#      "$target_dir $target_hd" for save/restore the disk
#   $3 n_clients
#      how many clients will be connected (for multicast only)
#   $4 ocs_option
#      ocs option to control ocs pre process & post process
#   $5 ocsmgrd_option
#      ocsmgrd option to control ocsmgrd
start() {
  local task=$1
  local option=$2
  local n_clients=$3
  local ocs_option=$4
  local ocsmgrd_option=$5

  # isoimage_restore or isoimage_restoredisk ?
  if [ "$task" = "isoimage_restore" -o "$task" = "isoimage_restoredisk" ]; then
    task_isoimage $task "$option" "$ocs_option"
    return
  fi
 
  # is "ocsmgrd" running ?
  if [ -e "$ocsroot/ocsmgrd" ]; then
    echo "OCS is already running! You must stop it first .. (abort)"
    exit 0
  else 
    ## extract ocs
    outname="ocs-$$.zip"
    trap 'rm -f $outname; rm -rf ocsmgr; exit 1' HUP INT QUIT TERM
    tail +${LINENO} $0 > $outname
    unzip $outname
    cp ocsmgr/ocsmgrd $ocsroot/
    cp ocsmgr/checkInodeForDevice.c /tmp/
    cd ocsmgr; make; cd ..
    cp ocsmgr/mcastSender ocsmgr/mcastListener ocsmgr/partimage_stdin ocsmgr/resize_part $drblroot/root/sbin/
    rm -f $outname
    rm -rf ocsmgr

    # make sure next time starup is not ocs mode
    cat <<-EOF > /etc/init.d/ocs
#!/bin/sh
for host in \`ls $drblroot 2> /dev/null\`
do
  if [ "\$host" != "." -a "\$host" != ".." -a "\$host" != "root" ];then
    mv $drblroot/\$host/etc/inittab.ocs $drblroot/\$host/etc/inittab
    ln -fs ../init.d/single $drblroot/\$host/etc/rc1.d/S20single
    rm -f $drblroot/\$host/etc/rc1.d/S99single
    #rm -f $drblroot/\$host/etc/rc1.d/S20ssh
	#mv $drblroot/\$host/etc/rc1.d/S20ssh $drblroot/\$host/etc/rc1.d/K20ssh
    # remove the pxe config file in /tftpboot/pxelinux.cfg
    pxecfg=\$(/usr/bin/gethostip \$host | cut -d" " -f3)
    rm -f /tftpboot/pxelinux.cfg/\$pxecfg
  fi
done
rm -f $ocsroot/ocsmgrd
rm -f /etc/init.d/ocs
rm -f /etc/rc0.d/S05ocs
rm -f /etc/rc6.d/S05ocs
EOF
    chmod 755 /etc/init.d/ocs
    ln -s /etc/init.d/ocs /etc/rc6.d/S05ocs
    ln -s /etc/init.d/ocs /etc/rc0.d/S05ocs
  fi 

  # copy $0 to $drblroot/root/sbin
  if [ -f $0 ]; then 
    cp $0 $drblroot/root/sbin
  else
    for path in `echo $PATH | sed -e "s/:/ /g"`
	do
	  if [ -f $path/$0 ]; then 
	    cp $path/$0 $drblroot/root/sbin
		break
      fi
	done
  fi

  # Blake, 2004/02/09, 
  ## sync_server & routing table
  #if [ "$(echo "$task" | grep -e "^multicast_restore")" != "" ]; then
  #  . /etc/default/dhcp3-server
  #  for eth in `echo $INTERFACES`
  #  do
  #    sync_server=`/sbin/ifconfig $eth | grep "inet addr" | awk -F: '{ print $2; }' | awk '{ print $1; }'`
  #    /sbin/route add -net 234.0.0.0/24 dev $eth
  #  done
  #fi
  if [ "$(echo "$task" | grep -e "^multicast_restore")" != "" ]; then
    . /etc/default/dhcp3-server
    for eth in `echo $INTERFACES`
    do
      ## only the first one interface used to route multicast packet
      /sbin/route add -net 234.0.0.0/24 dev $eth
      break
    done
    ## sync_server will be assigned at runtime
    sync_server="0.0.0.0"
  fi

  # inittab -> inittab.ocs
  for host in `ls $drblroot 2> /dev/null`
  do
    # ocs config
    # Blake, 2003/12/05, write the config everytime ocs start..
    OCSMGRD_PORT="6461"
    #if [ "$host" != "." -a "$host" != ".." -a \
    #     ! -e $drblroot/$host/etc/ocs/config ]; then
    if [ "$host" != "." -a "$host" != ".." ]; then
      mkdir -p $drblroot/$host/etc/ocs
      rm -f $drblroot/$host/etc/ocs/config
      . /etc/default/dhcp3-server
      for eth in `echo $INTERFACES`
      do
        IP=`/sbin/ifconfig $eth | grep "inet addr" | awk -F: '{ print $2; }' | awk '{ print $1; }'`
        echo "$IP $OCSMGRD_PORT" >> $drblroot/$host/etc/ocs/config
      done
    fi

    # inittab -> inittab.ocs
    if [ "$host" != "." -a "$host" != ".." -a "$host" != "root" ];then
      # check if inittab.ocs exist ?
      if [ -e "$drblroot/$host/etc/inittab.ocs" ]; then
        # last time abnormal terminated, keep the file unchanged
        echo -n "."
      else
        mv $drblroot/$host/etc/inittab $drblroot/$host/etc/inittab.ocs
        #mv $drblroot/$host/etc/rc1.d/K20ssh $drblroot/$host/etc/rc1.d/S20ssh
        echo -n "."
      fi
      # inittab for ocs
      if [ "$(echo "$task" | grep -e "^multicast_restore")" != "" ]; then
        multicast_option="$sync_server 234.0.0.1 2232 $option"
        ocs_inittab $drblroot/$host/etc/inittab $task "$multicast_option" "$ocs_option"
      else
        ocs_inittab $drblroot/$host/etc/inittab $task "$option" "$ocs_option"
      fi
      # chanage the initial script for runlevel 1 to enter single user mode
      rm -f $drblroot/$host/etc/rc1.d/S20single
      cat <<-EOF > $drblroot/$host/etc/rc1.d/S99single
#!/bin/sh
PATH="/sbin:/bin:/usr/sbin:/usr/bin"
exec init -t1 S
EOF
      chmod 755 $drblroot/$host/etc/rc1.d/S99single
      # start ssh if debug_mode is on
      #option_debug_mode="$(get_option "debug_mode")"
      #if [ "$option_debug_mode" = "on" ]; then
      #  ln -fs ../init.d/ssh $drblhost/$host/etc/rc1.d/S20ssh
      #fi
    fi
  done
  echo

  case "$task" in
    "multicast_restore")
      target_file=$option
      image=`echo "$target_file" | sed 's/\.000$//'`
      n=1
      while [ $n -le 999 ]; do
        if [ $n -lt 10 ]; then image_file="$image.00$n"
        elif [ $n -lt 100 ]; then image_file="$image.0$n"
        else image_file="$image.$n"
        fi

        if [ -f $image_file ]; then target_file="$target_file $image_file"
        else break
        fi
        n=`expr $n + 1`
      done
     
      #nice -n -10 $drblroot/root/sbin/mcastSender $n_clients 234.0.0.1 2232 $target_file &
      $drblroot/root/sbin/mcastSender $n_clients 234.0.0.1 2232 $target_file &

      ## ocsmgrd -s 
      if [ "$n_clients" = "0" ]; then
        echo "echo \"\$1\" | socket -q 127.0.0.1 2233" >> /tmp/ocsmgrd.$$
        echo "rm -f /tmp/ocsmgrd.$$" >> /tmp/ocsmgrd.$$
        chmod 755 /tmp/ocsmgrd.$$
        ocsmgrd_option="$ocsmgrd_option -s /tmp/ocsmgrd.$$"
      fi
      ##
      ;;
    "multicast_restoredisk")

      i=1
      port=2232
      target_dir=`echo "$option" | cut -d' ' -f1`
      for partition in `get_known_partition $target_dir/pt.sf`
      do
        target_file=""
        n=0
        while [ $n -le 999 ]; do
          if [ $n -lt 10 ]; then partition_file="$target_dir/$partition.00$n"
          elif [ $n -lt 100 ]; then partition_file="$target_dir/$partition.0$n"
          else partition_file="$target_dir/$partition.$n"
          fi

          if [ -f $partition_file ]; then target_file="$target_file $partition_file"
          else break
          fi

          n=`expr $n + 1`
        done
        #nice -n -10 $drblroot/root/sbin/mcastSender $n_clients 234.0.0.$i $port $target_file &
        $drblroot/root/sbin/mcastSender $n_clients 234.0.0.$i $port $target_file &

        ## ocsmgrd -s
        if [ "$n_clients" = "0" ]; then
          pport=`expr $port + 1`
          echo "echo \"\$1\" | socket -q 127.0.0.1 $pport" >> /tmp/ocsmgrd.$$
        fi
        ##

        i=`expr $i + 1`
        port=`expr $port + 2`
      done

      # ocsmgrd -s 
      if [ "$n_clients" = "0" ]; then
        echo "rm -f /tmp/ocsmgrd.$$" >> /tmp/ocsmgrd.$$
        chmod 755 /tmp/ocsmgrd.$$
        ocsmgrd_option="$ocsmgrd_option -s /tmp/ocsmgrd.$$"
      fi
      ##
      ;;
  esac

  # start the deamon
  #tail +${LINENO} $0 > $ocsroot/ocsmgrd
  $ocsroot/ocsmgrd $ocsmgrd_option &
}

# create inittab for ocs
ocs_inittab() {
  local inittab=$1
  local inittab_task=$2
  local inittab_option=$3
  local ocs_option=$4
  cat <<-EOF > $inittab
# /etc/inittab: init(8) configuration.

# The default runlevel.
id:1:initdefault:

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS

# What to do in single-user mode.
#~~:S:wait:/sbin/sulogin
#~~:S:wait:/opt/drbl/sbin/ocs $inittab_task $inittab_option
~~:S:wait:/sbin/$ocs $ocs_option $inittab_task $inittab_option

# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin

# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

# Action on special keypress (ALT-UpArrow).
#kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
#  <id>:<runlevels>:<action>:<process>
#
# Note that on most Debian systems tty7 is used by the X Window System,
# so if you want to add more getty's go ahead but skip tty7 if you run X.
#
1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6

# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100

# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3
EOF
}

# stop ocs services
# parameters:
stop() {

  # is "ocsmgrd" running ?
  if [ ! -e "$ocsroot/ocsmgrd" ]; then 
    echo "OCS is not start!"
    exit 0
  else 
    rm -f /etc/init.d/ocs
    rm -f /etc/rc0.d/S05ocs
    rm -f /etc/rc6.d/S05ocs
  fi

  # remove $drblroot/root/sbin/drbl-ocs
  rm -f $drblroot/root/sbin/$ocs

  # remove $drblroot/root/sbin/mcastListener
  rm -f $drblroot/root/sbin/mcastListener
  rm -f $drblroot/root/sbin/mcastSender
  rm -f $drblroot/root/sbin/partimage_stdin
  rm -f $drblroot/root/sbin/resize_part

  # inittab.ocs -> inittab
  for host in `ls $drblroot 2> /dev/null`
  do
    if [ "$host" != "." -a "$host" != ".." -a "$host" != "root" ];then
      mv $drblroot/$host/etc/inittab.ocs $drblroot/$host/etc/inittab
      ln -fs ../init.d/single $drblroot/$host/etc/rc1.d/S20single
      rm -f $drblroot/$host/etc/rc1.d/S99single
      #rm -f $drblroot/$host/etc/rc1.d/S20ssh
	  #mv $drblroot/$host/etc/rc1.d/S20ssh $drblroot/$host/etc/rc1.d/K20ssh
      # remove the pxe config file in /tftpboot/pxelinux.cfg
      pxecfg=$(/usr/bin/gethostip $host | cut -d" " -f3)
      rm -f /tftpboot/pxelinux.cfg/$pxecfg
    fi
  done

  # kill the deamon
  pid=`/bin/ps -e 2> /dev/null | grep 'ocsmgrd' | sed -e 's/^ *//' -e 's/ .*//'`
  if [ "$pid" != "" ]; then kill -9 $pid; fi

  pid=`/bin/ps -e 2> /dev/null | grep 'mcastSender' | sed -e 's/^ *//' -e 's/ .*//'`
  if [ "$pid" != "" ]; then kill -9 $pid; fi

  rm -f $ocsroot/ocsmgrd

  . /etc/default/dhcp3-server
  for eth in `echo $INTERFACES`
  do
    /sbin/route del -net 234.0.0.0/24 dev $eth
  done
}

# task_isoimage
#task_isoimage() {
#
#  local task=$1
#  local option=$2
#  local ocs_option=$3
#
#  # bootcdwrite (drbl-bootcd)
#  if [ ! -f /opt/drbl/sbin/drbl-bootcd ]; then
#    echo "Cannot find drbl-bootcd at /opt/drbl/sbin. "
#    echo "Please install it using the command: apt-get install drbl-script"
#    exit 0
#  fi
#  bootcdroot="/var/lib/bootcd"
#  if [ -d $bootcdroot ]; then
#    echo -n "$bootcdroot exists.. Do you want to remove it [Y|n]? "
#    read ans
#    if [ "$ans" = "Y" -o "$ans" = "y" -o "$ans" = "" ]; then rm -rf $bootcdroot; fi
#  fi
#  mkdir -p $bootcdroot
#  mkdir -p /var/spool/bootcd
#  if [ -f /var/spool/bootcd/cdimage.iso ]; then
#    rm -f /var/spool/bootcd/cdimage.iso
#  fi
#
#  echo "Please insert Debian CD in your CDROM." 
#  echo -n "Press any key when you are ready to go .."
#  read anykey
#  foundcd=0
#  # Blake, 2003/12/05, use automout feature ...
#  #TMP=`mktemp /tmp/mnt.XXXXXX`
#  #for device in `ls /dev/cdrom[0-9]`; do
#  # if mount -t iso9660 -o ro $device $TMP > /dev/null 2>&1
#  #  then
#  #    # check if this one is Debian CD
#  #    if [ -f $TMP/dists/woody/Release ]; then
#  #      echo "Found Debian CD at $device"
#  #      foundcd=1
#  #      debootstrap --arch i386 woody $bootcdroot file:///$TMP
#  #      umount $TMP
#  #      # eject the CD
#  #      eject
#  #      break
#  #    fi
#  #    umount $TMP
#  #  fi
#  #done
#  #rm -rf $TMP
#  for device in `ls /dev/cdrom[0-9] 2> /dev/null`; do
#    device=${device/\/dev\//}
#    if [ -f /mnt/auto/$device/dists/woody/Release ]; then
#      foundcd=1
#  	debootstrap --arch i386 woody $bootcdroot file:///mnt/auto/$device
#  	kernel_ver=`uname -r`
#  	cp -r /lib/modules/$kernel_ver $bootcdroot/lib/modules
#  	cp -a /boot/* $bootcdroot/boot
#  	ln -fs /boot/vmlinuz-$kernel_ver /var/lib/bootcd/vmlinuz
#    fi
#  done
#
#  # foundcd or not
#  if [ $foundcd -eq 0 ]; then
#    echo "NO Debian CD Found! abort..."
#    exit 0
#  fi
#
#  # copy partimage and related librarys (libbz2-1.0 libssl0.9.6 zlib1g)
#  PKG="libbz2-1.0 libssl0.9.6 zlib1g partimage"
#  for lib in $PKG; do
#    for c in `dpkg -L $lib`; do
#      if [ -d $c ]; then mkdir -p $bootcdroot/$c; fi
#      if [ -f $c ]; then cp -a $c $bootcdroot/$c; fi
#    done
#  done 
#
#  # copy imagefile into $bootcdroot/home/partimag
#  mkdir -p $bootcdroot/opt/partimag
#  imagefile=`echo "$option" | cut -d' ' -f1`
#  echo "Start copying $imagefile .... This will take few minutes..."
#  cp -r -L $imagefile $bootcdroot/opt/partimag
#  ln -fs /opt/partimag $bootcdroot/home/partimag
#
#  # $bootcdroot/sbin/drbl-ocs $bootcdroot/sbin/check
#  head -n ${LINENO} $0 > $bootcdroot/sbin/drbl-ocs
#  chmod 755 $bootcdroot/sbin/drbl-ocs
#  if [ -f /tmp/checkInodeForDevice.c ]; then
#    gcc -o $bootcdroot/sbin/checkInodeForDevice /tmp/checkInodeForDevice.c
#  fi
#
#  # $bootcdroot/etc/inittab
#  task=${task/createcd/restore}
#  ocs_inittab $bootcdroot/etc/inittab $task "$option" "$ocs_option"
#
#  # iso image
#  echo "Start building ISO image ..."
#  echo -n "Press any key to start .."
#  read anykey
#
#  if [ -f /etc/drbl_version ]; then
#    drbl_version=`cat /etc/drbl_version | grep -e "^Version:" | awk '{ print $2; }'`
#  else
#    drbl_version=""
#  fi
#  cdlabel=${option/ /_}
#  cdlabel=${cdlabel/\/home\/partimag\//}
#  /opt/drbl/sbin/drbl-bootcd -f --createcd /var/lib/bootcd clonezilla
#  mv clonezilla.iso clonezilla-$drbl_version-$cdlabel.iso
#  md5sum clonezilla-$drbl_version-$cdlabel.iso > clonezilla-$drbl_version-$cdlabel.md5sum
#}

# task_isoimage
# create iso image
task_isoimage() {

  local task=$1
  local option=$2
  local ocs_option=$3

  # create initrd ramdisk
  initrd="/tmp/initrd.$$"
  initrdimg=`mktemp /tmp/initrd.img.XXXXXX`
  initrdmnt="/tmp/initrd.mnt.$$"
  mkdir -p $initrd
  mkdir -p $initrdmnt
  mkdir -p $initrd/dev
  mkdir -p $initrd/etc
  mkdir -p $initrd/bin
  mkdir -p $initrd/lib
  mkdir -p $initrd/lib/modules
  mkdir -p $initrd/usr/bin
  mkdir -p $initrd/usr/lib
  mkdir -p $initrd/cdrom
  mkdir -p $initrd/proc
  ln -s bin $initrd/sbin
  ln -s bin $initrd/usr/sbin

  # rootfs
  busybox_version="0.60.3"
  busybox=busybox-$busybox_version		  
  busybox_source=busybox-source-$busybox_version

  apt-get update
  [ -f /usr/src/$busybox.tar.bz2 ] || apt-get -y install $busybox_source
  [ -d $busybox ] || tar xvjf /usr/src/$busybox.tar.bz2
  
  perl -pi.orig -e 's/^.*(#define BB_(INSMOD|PIVOT_ROOT|LOSETUP|EXPR|STTY)).*/$1/' $busybox/Config.h
  perl -pi.orig -e 's/^(DOSTATIC).*$/$1 = true/' $busybox/Makefile
  make -C $busybox
  install -m 755 $busybox/busybox $initrd/bin/
  #ln -s busybox $initrd/bin/sh
  ln -s busybox $initrd/bin/echo
  ln -s busybox $initrd/bin/mknod
  ln -s busybox $initrd/bin/chmod
  ln -s busybox $initrd/bin/insmod
  ln -s busybox $initrd/bin/ifconfig
  ln -s busybox $initrd/bin/route
  ln -s busybox $initrd/bin/mount
  ln -s busybox $initrd/bin/pivot_root
  ln -s busybox $initrd/bin/umount
  ln -s busybox $initrd/bin/sleep
  ln -s busybox $initrd/bin/grep
  ln -s busybox $initrd/bin/[
  ln -s busybox $initrd/bin/sed
  ln -s busybox $initrd/bin/cat
  ln -s busybox $initrd/bin/cut
  ln -s busybox $initrd/bin/losetup
  ln -s busybox $initrd/bin/ln
  ln -s busybox $initrd/bin/ls
  ln -s busybox $initrd/bin/swapoff
  ln -s busybox $initrd/bin/swapon
  ln -s busybox $initrd/bin/mkswap
  ln -s busybox $initrd/bin/dd
  ln -s busybox $initrd/bin/mkdir
  ln -s busybox $initrd/bin/cp
  ln -s busybox $initrd/bin/rm
  ln -s busybox $initrd/bin/expr
  ln -s busybox $initrd/bin/stty
  ln -s busybox $initrd/bin/reboot
  ln -s busybox $initrd/bin/halt
  ln -s busybox $initrd/bin/basename
  rm -rf $busybox

  # modules - usb keyboard
  cp /lib/modules/$(uname -r)/kernel/drivers/usb/usbcore.o $initrd/lib/modules
  cp /lib/modules/$(uname -r)/kernel/drivers/usb/host/ehci-hcd.o $initrd/lib/modules
  cp /lib/modules/$(uname -r)/kernel/drivers/usb/host/usb-ohci.o $initrd/lib/modules
  cp /lib/modules/$(uname -r)/kernel/drivers/usb/host/usb-uhci.o $initrd/lib/modules
  cp /lib/modules/$(uname -r)/kernel/drivers/usb/usbkbd.o $initrd/lib/modules
  cp /lib/modules/$(uname -r)/kernel/drivers/input/input.o $initrd/lib/modules
  cp /lib/modules/$(uname -r)/kernel/drivers/input/keybdev.o $initrd/lib/modules

  # bash
  for lib in `ldd /bin/bash | awk '{ print $3; }'`; do
    cp $lib $initrd/$lib
  done
  cp /bin/bash $initrd/bin/
  ln -s bash $initrd/bin/sh
  # partimage
  for lib in `ldd /usr/sbin/partimage | awk '{ print $3; }'`; do
    cp $lib $initrd/$lib   
  done
  cp /usr/sbin/partimage $initrd/usr/sbin
  # setterm
  for lib in `ldd /usr/bin/setterm | awk '{ print $3; }'`; do
    cp $lib $initrd/$lib
  done
  cp /usr/bin/setterm $initrd/usr/bin
  # awk
  for lib in `ldd /usr/bin/awk | awk '{ print $3; }'`; do
    cp $lib $initrd/$lib
  done
  cp /usr/bin/awk $initrd/usr/bin
  # vim - for debug
  #for lib in `ldd /usr/bin/vim | awk '{ print $3; }'`; do
  #  cp $lib $initrd/$lib
  #done
  #cp /usr/bin/vim $initrd/usr/bin/vi
  # grub-install
  cp /sbin/grub-install $initrd/sbin
  # eject, hdparm, sfdisk, stat, id, halt
  # all these programs need /lib/libc.so.6 & /lib/ld-linux.so.2
  # which are copied when we handle partimage libraries
  cp /usr/bin/eject $initrd/usr/bin
  cp /usr/bin/stat $initrd/usr/bin
  cp /sbin/hdparm $initrd/sbin
  cp /sbin/sfdisk $initrd/sbin
  cp /usr/bin/id $initrd/usr/bin
  # checkInodeForDevice, partimage_stdin
  outname="ocs-$$.zip"
  trap 'rm -f $outname; rm -rf ocsmgr; exit 1' HUP INT QUIT TERM
  tail +${LINENO} $0 > $outname
  unzip $outname
  gcc -static -o $initrd/sbin/checkInodeForDevice ocsmgr/checkInodeForDevice.c
  cd ocsmgr; make; cd ..
  cp ocsmgr/partimage_stdin $initrd/sbin/
  rm -f $outname
  rm -rf ocsmgr
  # partimge_stdout
  cat <<-EOF > $initrd/sbin/partimage_stdout
#!/bin/sh
change_cd() {
  umount /cdrom >/dev/null
  /usr/bin/eject /dev/cdrom >/dev/null
  #/bin/stty -echo
  #read anykey
  #/sbin/stty echo
  sleep 5 >/dev/null
  /usr/bin/eject -t /dev/cdrom >/dev/null 
}

imagefile="\$1"
for image in \$imagefile; do
  mount -t iso9660 -o ro /dev/cdrom /cdrom >/dev/null
  if [ ! -f /cdrom/\$image ]; then change_cd; fi
  #i=0
  while [ "\$(/usr/bin/stat -c "%s" /cdrom/\$image)" = "0" ]; do 
    #if [ \$i -gt 5 ]; then echo "Wrong Disc"; echo "Wrong Disc .. Abort!"; break; fi
    #i=\`expr \$i + 1\`
    change_cd
    mount -t iso9660 -o ro /dev/cdrom /cdrom >/dev/null
  done
  cat /cdrom/\$image
  change_cd
done
EOF
  chmod 755 $initrd/sbin/partimage_stdout
  # drbl-ocs
  head -n $(expr ${LINENO} - 1) $0 > $initrd/sbin/drbl-ocs.real
  chmod 755 $initrd/sbin/drbl-ocs.real
  cat <<-EOF > $initrd/sbin/drbl-ocs
#!/bin/sh
ocs_option="$ocs_option"
if [ ! -z "\$1" ]; then 
  case "\$1" in
    "-h"|"--help") 
      echo "\$(basename \$0) [OPTION]"
      /sbin/drbl-ocs.real usage_restore_option
      echo " -h, --help"
      echo " Display this help and exit"
      exit
      ;;
    *) ocs_option="\$1"; 
  esac
fi
/sbin/drbl-ocs.real \$ocs_option $task $option
EOF
  chmod 755 $initrd/sbin/drbl-ocs

  # linuxrc
  cat <<-EOF > $initrd/linuxrc
#!/bin/sh
PATH=/sbin:/bin

echo Busybox /linuxrc starting

echo Mounting /proc filesystem
mount -t proc none /proc

# usb keyboard
if grep -i USB /proc/pci ; then
  echo Insert modules for USB keyboard and mouse
  /sbin/insmod /lib/modules/usbcore.o
  /sbin/insmod /lib/modules/ehci-hcd.o >/dev/null
  /sbin/insmod /lib/modules/usb-ohci.o >/dev/null
  /sbin/insmod /lib/modules/usb-uhci.o >/dev/null
  /sbin/insmod /lib/modules/input.o >/dev/null
  /sbin/insmod /lib/modules/usbkbd.o > /dev/null
  sleep 1
  /sbin/insmod /lib/modules/keybdev.o >/dev/null
fi
 
echo Creating root device
mknod /dev/root b 1 0
chmod 700 /dev/root
echo 0x100 > /proc/sys/kernel/real-root-dev

#/sbin/drbl-ocs $ocs_option $task $option
#/bin/sh
echo "1: Start clone procedure .."
echo "2: Enter command prompt, use /sbin/drbl-ocs to start clone procedure later.."
echo -n "Your choice [1]: "
read -t 5 ans
case "\$ans" in
  "1"|"") /sbin/drbl-ocs ;;
  "2") /bin/sh ;;
esac
EOF
  chmod 755 $initrd/linuxrc

  dd if=/dev/zero bs=1k of=$initrdimg count=$((`du -sk $initrd | cut -f1` * 7 / 6)) 2> /dev/null
  /sbin/mke2fs -q -F $initrdimg 2> /dev/null
  mount -o loop $initrdimg $initrdmnt
  cp -a $initrd/* $initrdmnt/
  mknod $initrdmnt/dev/console c 5 1
  mknod $initrdmnt/dev/null c 1 3
  mknod $initrdmnt/dev/ram b 1 1
  mknod $initrdmnt/dev/systty c 4 0
  mknod $initrdmnt/dev/random c 1 8
  mknod $initrdmnt/dev/urandom c 1 9
  for i in 1 2 3 4; do mknod $initrdmnt/dev/tty$i c 4 $i; done
  mknod $initrdmnt/dev/hda b 3 0
  mknod $initrdmnt/dev/hdb b 3 64
  mknod $initrdmnt/dev/hdc b 22 0
  mknod $initrdmnt/dev/hdd b 22 64
  mknod $initrdmnt/dev/sda b 8 0
  mknod $initrdmnt/dev/sdb b 8 16

  umount -d $initrdmnt
  gzip -9 -n -c $initrdimg > initrd.img

  # cleanup
  rm -rf $initrd
  rm -f $initrdimg
  rmdir $initrdmnt

  # do isolinux
  cdlabel=${target_file/$ocsroot/}
  cdlabel=${cdlabel/\//}
  isodir=/var/lib/ocs
  mkdir -p /$isodir/isolinux
  cp /usr/lib/syslinux/isolinux.bin /$isodir/isolinux
  cp /vmlinuz-$(uname -r) /$isodir/isolinux/vmlinuz
  mv initrd.img /$isodir/isolinux/
  cat <<-EOF > /$isodir/isolinux/isolinux.cfg
default linux
timeout 0
label linux
  kernel /isolinux/vmlinuz
  append initrd=/isolinux/initrd.img ramdisk_size=16384
EOF

  # create iso image
  imagefile=""
  target_file="$(echo "$option" | cut -d' ' -f1)"
  case "$task" in
    "isoimage_restore")
      mkdir -p $isodir/$ocsroot
      cp $ocsroot/size $isodir/$ocsroot

      target_file=${target_file/\.000/}
      i=0
      while [ $i -lt 1000 ]; do
        if [ $i -lt 10 ]; then filename="$target_file.00$i";
        elif [ $i -lt 100 ]; then filename="$target_file.0$i";
        else filename="$target_file.$i";
        fi
        if [ -f $filename ]; then
          imagefile="$imagefile $isodir/$filename"
        else
          break
        fi
        i=`expr $i + 1`
      done
      ;;
    "isoimage_restoredisk")
      mkdir -p $isodir/$target_file
      cp $target_file/size $isodir/$target_file
      cp $target_file/mbr $isodir/$target_file
      cp $target_file/pt.sf $isodir/$target_file
      cp $target_file/disk $isodir/$target_file

      disk="$(cat $target_file/disk)"
      for image in `ls $target_file/$disk*`; do
        image=${image##*/}
        imagefile="$imagefile $isodir/$oscroot/$target_file/$image"
      done
      ;;
  esac

  isoimage_created=""

  touch $imagefile
  i=1
  for image in $imagefile; do
    rm -f $image
    imagesrc=${image/$isodir/}
    cp $imagesrc $image
    /usr/bin/mkisofs -graft-points -R -b isolinux/isolinux.bin -c isolinux/boot.cat -o clonezilla-$cdlabel-$i.iso \
    -no-emul-boot -boot-load-size 4 -boot-info-table /=$isodir
    isoimage_created="$isoimage_created $(pwd)/clonezilla-$cdlabel-$i.iso"
    rm -f $image
    touch $image
    i=`expr $i + 1`
  done
  rm -rf $isodir

  echo "$(expr $i - 1) iso images are created"
  for isoimage in $isoimage_created; do
    echo " $isoimage"
  done
  if [ -f /opt/drbl/sbin/drbl-bootcd ]; then
    echo -n "Do you want to burn these iso images to CD [y|N]? "
    read ANS
    if [ "$ANS" = "N" -o "$ANS" = "n" -o "$ANS" = "" ]; then return; fi
    i=1
    for isoimage in $isoimage_created; do
      echo "Please insert disc #$i,"
      echo -n "Type \"1\" if your disc is CD-R, \"2\" for CD-RW, \"3\" to skip this one [1]: "
      read disc
      case "$disc" in 
       "2") /opt/drbl/sbin/drbl-bootcd --burncd $isoimage --blank ;;
       "3") ;;
       *) /opt/drbl/sbin/drbl-bootcd --burncd $isoimage ;;
      esac
      i=`expr $i + 1`
    done
  fi
}

# task_preprocessing
task_preprocessing() {
  local option_debug_mode="$(get_option "debug_mode")"
  local option_time_to_wait="$(get_option "time_to_wait")"
  local option_confirm_restore="$(get_option "confirm_restore")"

  # option debug mode
  if [ "$option_debug_mode" = "on" ]; then 
    echo "debug mode: before preprocessing..."
    /sbin/sulogin; 
  fi

  # option time to wait before restore
  if [ "$option_time_to_wait" != "0" ]; then 
    #sleep $option_time_to_wait; 
    #n=$option_time_to_wait
    #until [ $n -le 1 ]; do n=`expr $n - 1`; echo -en "$n\b"; sleep 1; done
    n_option_time_to_wait=`echo -n "$option_time_to_wait" | wc -c`

    ## echo format ..
    append_b=""
    i=0
    while [ $i -lt $n_option_time_to_wait ]; do
      append_b="$append_b\b"; i=`expr $i + 1`
    done

    i=$option_time_to_wait
    until [ $i -le 1 ]; do
      i=`expr $i - 1`

      # echo format ..
      n="$i"
      n_n=`echo -n "$n" | wc -c`
      while [ $n_n -lt $n_option_time_to_wait ]; do
        n="$n "; n_n=`echo -n "$n" | wc -c`
      done

      echo -en "$n$append_b"
      sleep 1
    done
  fi

  # option confirm_restore
  if [ "$confirm_restore" = "on" ]; then 
    echo -n "Do you want to begin to restore? [Y/n]? "
    read ANS
    case "$ANS" in
     n|N|[nN][oO]) echo "Program stop!"; task_postprocessing ;;
    esac
  fi

  ## start some needed services
  if [ -f /etc/init.d/ssh ]; then /etc/init.d/ssh start; fi
  if [ -f /etc/init.d/amd ]; then /etc/init.d/amd start; fi
}

# task_postprocessing
task_postprocessing() {
  local option_debug_mode="$(get_option "debug_mode")"
  local option_postaction="$(get_option "post_action")"

  # option debug
  if [ "$option_debug_mode" = "on" ]; then
    /sbin/sulogin
  fi

  # option postaction
  echo "Do postaction: $option_postaction"
  case "$option_postaction" in
   "shutdown") /sbin/halt ;;
   "reboot") /sbin/reboot ;;
   "command") /sbin/sulogin ; exit 0 ;;
  esac

  # Only should get here if something went wrong
  if [ "$option_debug_mode" = "on" ]; then
    echo "Only should get here if something went wrong.."
    /sbin/sulogin
  fi
  exit 0
}

# task_notify_connect
# ask for connect, the request will be blocked if necessary
task_notify_connect() {
  do_notify=0
  netdevices="$(cat /proc/net/dev | grep eth | cut -d":" -f1 | sed 's/ *//')"
  for device in $netdevices
  do
    ip=`/sbin/ifconfig $device | grep "inet addr" | awk -F: '{ print $2; }' | awk '{ print $1; }'`
    if [ "$ip" != "" ]; then
      network=`echo $ip | awk -F. '{print $1"."$2"."$3; }'`
      while read ocsmgrd
      do
        if [ "$(echo $ocsmgrd | grep "$network")" != "" ]; then
          echo ">> Try to connect <<"
          echo ">> It may take a long time if it is not allow to connect right now <<"
          echo "connect" | /usr/bin/socket $ocsmgrd
          if [ $? -eq 0 ]; then do_notify=1; fi
          break
        fi
      done < /etc/ocs/config
    fi
  done
  if [ $do_notify -eq 0 ]; then
    echo "Ask for connection failed.. Press 'c' to continue"
    echo "If you choose to continue, the client will shutdown when cloning finished"
    read con
    case "$con" in
     'c'|'C') set_option "post_action" "shutdown" ;;
     *) task_postprocessing ;;
    esac
  fi
}

# task_notify_localboot
# ask for localboot next time
task_notify_localboot() {
  do_notify=0
  netdevices="$(cat /proc/net/dev | grep eth | cut -d":" -f1 | sed 's/ *//')"
  for device in $netdevices
  do
    ip=`/sbin/ifconfig $device | grep "inet addr" | awk -F: '{ print $2; }' | awk '{ print $1; }'`
    if [ "$ip" != "" ]; then
      network=`echo $ip | awk -F. '{print $1"."$2"."$3; }'`
      while read ocsmgrd
      do
        if [ "$(echo $ocsmgrd | grep "$network")" != "" ]; then
          #echo "$ip" | /usr/bin/socket -q $ocsmgrd
          echo "$ip" | /usr/bin/socket $ocsmgrd
          if [ $? -eq 0 ]; then do_notify=1; fi
          break
        fi
      done < /etc/ocs/config
    fi
  done
  if [ $do_notify -eq 0 ]; then
    echo "[$(date -R)] Ask for localboot failed.. The client will shutdown" >> /var/log/ocs.log
    option_postaction="shutdown"
  fi

}

# task "save" 
# parameter:
#   $1 target_file
task_save() {
  local target_file=$1

  # screen not blank
  /usr/bin/setterm -blank 0
  # HD DMA on
  /sbin/hdparm -d1 /dev/hda
  # swapoff -a, just in case
  /sbin/swapoff -a

  #######################################################
  # 2003/05/12: ask user about target_dir and target_hd #
  #######################################################
  if [ "$target_file" = "ask_user" ]; then
    TMP=`mktemp /tmp/ocs.XXXXXX`
    /usr/bin/dialog --backtitle "NCHC OpenSource Lab" --title "Clonezilla" \
       --inputbox "Input the file name to save" 12 60 "" 2> $TMP
    target_file=$(cat $TMP)
    target_file="$ocsroot/$target_file"
    rm -f $TMP 
  fi
  # save
  if [ -f /sbin/checkInodeForDevice ]; then /sbin/checkInodeForDevice /dev/hda1 ; fi
  #nice -n -10 /usr/sbin/partimage -V 500 -f3 -z0 -o -d -b -c save /dev/hda1 $target_file
  option_partimage_saveopt="$(get_option "partimage_saveopt")"
  #nice -n -10 /usr/sbin/partimage $option_partimage_saveopt save /dev/hda1 $target_file
  /usr/sbin/partimage $option_partimage_saveopt save /dev/hda1 $target_file
  
  echo "Calculate the unzip partimage image size .."
  if [ "$(echo "$option_partimage_saveopt" | grep "\-z1")" != "" ]; then
    # gzip-compress
    for imgf in `ls $ocsroot/$target_file.*`; do
      imgf=${imgf##*/}
      imgf_size="$(gunzip -l -q $ocsroot/$imgf | awk '{ print $2; }')"
      imgf_ratio="$(gunzip -l -q $ocsroot/$imgf | awk '{ print $3; }')"
      if [ "$(echo "$imgf_ratio" | grep -e "^-")" ]; then
        imgf_size="$(gunzip < $ocsroot/$imgf | wc -c)"
      fi
      echo "$imgf:$imgf_size" >> $ocsroot/size
    done
  else
    # no-compress
    for imgf in `ls $ocsroot/$target_file.*`; do
      imgf=${imgf##*/}
      imgf_size="$(stat -c "%s" $ocsroot/$imgf)"
      echo "$imgf:$imgf_size" >> $ocsroot/size
    done    
  fi
}

# task "savedisk"
# parameter:
#  $1 target_dir
#  $2 target_hd
task_savedisk() {
  local target_dir=$1
  local target_hd=$2

  #######################################################
  # 2003/05/12: ask user about target_dir and target_hd #
  #######################################################
  if [ "$target_dir" = "ask_user" ]; then

    # Blake, 2004/05/05, ask image name and check any problem ..
    ASK_IMGNAME=1
    TMP=`mktemp /tmp/ocs.XXXXXX`
    while [ $ASK_IMGNAME -ne 0 ]; do
       /usr/bin/dialog --backtitle "NCHC OpenSource Lab" --title "Clonezilla" \
       --inputbox "Input the file name to save disk" 12 60 "" 2> $TMP
       target_dir=$(cat $TMP)
       if [ -z "$target_dir" ]; then
         /usr/bin/dialog --backtitle "NCHC OpenSource Lab" --title "Clonezilla" \
         --msgbox "You have to input the file name to save disk!\n\nPlease do it again!!" 12 60
       elif [ -d $ocsroot/$target_dir ]; then
         /usr/bin/dialog --backtitle "NCHC OpenSource Lab" --title "Clonezilla" \
         --yesno "The image \"$target_dir\" was saved before!\n\nDo you want to replace it ?" 12 60 2> $TMP
         ASK_IMGNAME=$?
       else
         ASK_IMGNAME=0
       fi
       target_dir="$ocsroot/$target_dir"
    done
    rm -f $TMP
    
    # Blake, 2004/05/05, remove the image which was saved before
    if [ "$target_dir" = "$ocsroot" ]; then
      echo "Impossible!! Call klhaung@nchc.org.tw to fix the problem.."
      echo "Press anykey to reboot!"
      read anykey
      /sbin/reboot
    elif [ -d $target_dir ]; then
      rm -rf $target_dir
    fi
  fi
  if [ "$target_hd" = "ask_user" ]; then
    TMP=`mktemp /tmp/ocs.XXXXXX`
    # Blake, 2004/02/13, show the HDs in the machine
    if [ -f /proc/partitions ] ; then
      NUMHD=0
      while read x x x p x
      do
        case "$p" in
          hd?)
            if [ "`cat /proc/ide/$p/media`" = "disk" ] ; then
              echo "$p `tr ' ' _ </proc/ide/$p/model`" >> $TMP
              NUMHD=$[NUMHD+1]
            fi
            ;;
          sd?)
            x="`scsi_info /dev/$p | grep MODEL | tr ' ' _`"
            x=${x#*\"}
            x=${x%\"*}
            echo "$p $x" >> $TMP
            NUMHD=$[NUMHD+1]
            ;;
          *) ;;
        esac
      done < /proc/partitions
      HARDDISKS="`cat $TMP`"
      /usr/bin/dialog --backtitle "NCHC OpenSource Lab" --title "Clonezilla" \
      --radiolist "Choose the disk to save:" 16 60 $NUMHD \
      $(echo "$HARDDISKS" | while read p model ; do echo "$p" "$model" off ; done) \
      2> $TMP
    else 
      NUMHD=4
      HARDDISKS="hda primary_master off hdb primary_slave off hdc second_master off hdd second_slave off"
      /usr/bin/dialog --backtitle "NCHC OpenSource Lab" --title "Clonezilla" \
      --radiolist "Choose the disk to save:" 16 60 $NUMHD $HARDDISKS \
      2> $TMP
    fi
    target_hd=$(cat $TMP)
    rm -f $TMP
  fi

  # screen not blank
  /usr/bin/setterm -blank 0
  # HD DMA on 
  /sbin/hdparm -d1 /dev/$target_hd
  # swapoff -a, just in case
  /sbin/swapoff -a

  mkdir -p $target_dir
  dd if=/dev/$target_hd of=$target_dir/mbr count=1 bs=512
  #sfdisk -d /dev/$target_hd > $target_dir/pt.sf
  #if [ $? -ne 0 ]; then sfdisk_fail_process; exit 1; fi
  option_sfdisk_op="$(get_option "sfdisk_op")"
  case "$option_sfdisk_op" in
    "off") 
      ;;
    "manual") 
      cfdisk /dev/$target_hd 
      ;;
    "force_on")
      /sbin/sfdisk -f -d /dev/$target_hd > $target_dir/pt.sf
      if [ $? -ne 0 ]; then sfdisk_fail_process; fi 
      ;;
    "on")
      /sbin/sfdisk -d /dev/$target_hd > $target_dir/pt.sf
      if [ $? -ne 0 ]; then sfdisk_fail_process; fi 
  esac

  option_partimage_saveopt="$(get_option "partimage_saveopt")"
  #for partition in `cat $target_dir/pt.sf | grep "Id=" | awk -F, '{ if($3!=" Id= 0" && $3!=" Id= f" && $3!=" Id= 5" && $3!=" Id=82") print $1; }' | cut -d" " -f1 | sed -e 's/\/dev\///g'` 
  for partition in `get_known_partition $target_dir/pt.sf` 
  do
    if [ -f /sbin/checkInodeForDevice ]; then /sbin/checkInodeForDevice /dev/$partition ; fi
    #nice -n -10 /usr/sbin/partimage -f3 -z1 -V 500 -o -d -b -c save /dev/$partition $target_dir/$partition
    #nice -n -10 /usr/sbin/partimage $option_partimage_saveopt save /dev/$partition $target_dir/$partition
    /usr/sbin/partimage $option_partimage_saveopt save /dev/$partition $target_dir/$partition
  done
  echo "$target_hd" > $target_dir/disk

  # Blake, 2004/04/19, calculate the unzip partimage image size
  echo "Calculate the unzip partimage image size .."
  if [ "$(echo "$option_partimage_saveopt" | grep "\-z1")" != "" ]; then
    # gzip-compress
    for imgf in `ls $target_dir/$target_hd*`; do
      imgf=${imgf##*/}
      imgf_size="$(gunzip -l -q $target_dir/$imgf | awk '{ print $2; }')"
      imgf_ratio="$(gunzip -l -q $target_dir/$imgf | awk '{ print $3; }')"
      if [ "$(echo "$imgf_ratio" | grep -e "^-")" ]; then
        imgf_size="$(gunzip < $target_dir/$imgf | wc -c)"
      fi
      echo "$imgf:$imgf_size" >> $target_dir/size
    done
  else
    # no-compress
    for imgf in `ls $target_dir/$target_hd*`; do
      imgf=${imgf##*/}
      imgf_size="$(stat -c "%s" $target_dir/$imgf)"
      echo "$imgf:$imgf_size" >> $target_dir/size
    done    
  fi
}

# task "restore" 
# parameter:
#   $1 target_file
task_restore() {
  local target_file=$1

  # set screen not blank
  /usr/bin/setterm -blank 0
  # HD DMA on
  /sbin/hdparm -d1 /dev/hda
  # swapoff -a, just in case
  /sbin/swapoff -a
  
  # restore
  if [ -f /sbin/checkInodeForDevice ]; then /sbin/checkInodeForDevice /dev/hda1 ; fi
  #nice -n -10 /usr/sbin/partimage -f3 -b restore /dev/hda1 $target_file
  /usr/sbin/partimage -f3 -b restore /dev/hda1 $target_file

  ## resize_partition
  option_resize_partition="$(get_option "resize_partition")"
  [ "$option_resize_partition" = "on" ] && resize_partition "hda" "hda1"

  ## grub_install
  option_grub_install="$(get_option "grub_install")"
  if [ "$option_grub_install" != "" ]; then
    hd_img=`mktemp -d /tmp/hd_img.XXXXXX`
    mount $option_grub_install $hd_img
    /sbin/grub-install --root-directory=$hd_img /dev/hda
    [ -d "$hd_img" ] && rm -rf $hd_img
  fi
}

# task "multicast_restore" 
# parameter:
#   $1 sync_server
#   $2 multicast
#   $3 port
task_multicast_restore() {
  local sync_server=$1  
  local multicast=$2
  local port=$3
  local target_file=$4
  target_file=${target_file/\.000/}

  # screen not blank
  /usr/bin/setterm -blank 0
  # HD DMA on
  /sbin/hdparm -d1 /dev/hda
  # swapoff -a, just in case
  /sbin/swapoff -a

  # restore 
  if [ -f /sbin/checkInodeForDevice ]; then /sbin/checkInodeForDevice /dev/hda1 ; fi
  # Blake, 2004/02/09, sync_server = gateway
  # sync_server=`/sbin/route -n | grep -e "^0.0.0.0" | awk '{ print $2; }'`
  #mcast_routing_dev=`/sbin/route -n | grep -e "^0.0.0.0" | awk '{ print $8; }'`
  #/sbin/route add -net 234.0.0.0/24 dev $mcast_routing_dev

  # Blake, 2004/04/30, find sync_server using /etc/fstab
  while read spec file vfstype others; do
    if [ "$file" = "/" ]; then
      sync_server="$(echo "$spec" | cut -d: -f1)"
      break
    fi
  done < /etc/fstab

  ## partimage_stdin argv
  partimage_stdin_argv=""
  i=0
  while [ $i -lt 1000 ]; do
    if [ $i -lt 10 ]; then imagefile="$target_file.00$i";
    elif [ $i -lt 100 ]; then imagefile="$target_file.0$i";
    else imagefile="$target_file.$i";
    fi
    if [ -f $imagefile ]; then
      #partimage_stdin_argv="$partimage_stdin_argv $(gunzip -l -q $imagefile | awk '{ print $2; }')"
      pattern=${imagefile##*/}
      partimage_stdin_argv="$partimage_stdin_argv $(grep "$pattern" $ocsroot/size | cut -d: -f2)" 
    else
      break
    fi
    i=`expr $i + 1`
  done

  ## do multicast
  #nice -n -10 /sbin/mcastListener $sync_server $multicast $port | /sbin/partimage_stdin -gz $partimage_stdin_argv | /usr/sbin/partimage -f3 -b restore /dev/hda1 stdin
  /sbin/mcastListener $sync_server $multicast $port | /sbin/partimage_stdin -gz $partimage_stdin_argv | /usr/sbin/partimage -f3 -b restore /dev/hda1 stdin

  ## resize_partition
  option_resize_partition="$(get_option "resize_partition")"
  [ "$option_resize_partition" = "on" ] && resize_partition "hda" "hda1"

  ## grub_install
  option_grub_install="$(get_option "grub_install")"
  if [ "$option_grub_install" != "" ]; then
    hd_img=`mktemp -d /tmp/hd_img.XXXXXX`
    mount $option_grub_install $hd_img
    /sbin/grub-install --root-directory=$hd_img /dev/hda
    [ -d "$hd_img" ] && rm -rf $hd_img
  fi
}

# task "isoimage_restore"
# parameter: 
#   $1 target_file
task_isoimage_restore() {
  local target_file=$1
  target_file=${target_file/\.000/}

  # set screen not blank
  /usr/bin/setterm -blank 0
  # HD DMA on
  /sbin/hdparm -d1 /dev/hda
  # swapoff -a, just in case
  #/sbin/swapoff -a

  # ln /proc/mounts to /etc/mtab
  ln -s /proc/mounts /etc/mtab
  # ln /dev/cdrom 
  cddevices="/dev/hda /dev/hdb /dev/hdc /dev/hdd"
  for i in $cddevices; do
    if mount -t iso9660 -o ro $i /cdrom >/dev/null 2>&1
    then
      if [ -d /cdrom/isolinux ]; then ln -s $i /dev/cdrom; break; fi
    fi
  done
  if [ -L /dev/cdrom ]; then
    echo "/dev/cdrom	/cdrom	iso9660	defaults,ro	0 1" > /etc/fstab
    umount /cdrom
    /sbin/hdparm -d1 /dev/cdrom
  fi
 
  # restore
  if [ -f /sbin/checkInodeForDevice ]; then /sbin/checkInodeForDevice /dev/hda1 ; fi

  partimage_stdin_argv=""
  partimage_stdout_argv=""

  mount -t iso9660 -o ro /dev/cdrom /cdrom
  i=0
  while [ $i -lt 1000 ]; do
    if [ $i -lt 10 ]; then imagefile="$target_file.00$i";
    elif [ $i -lt 100 ]; then imagefile="$target_file.0$i";
    else imagefile="$target_file.$i";
    fi
    if [ -f /cdrom/$imagefile ]; then
      #partimage_stdin_argv="$partimage_stdin_argv $(gunzip -l -q $imagefile | awk '{ print $2; }')"
      pattern=${imagefile##*/}
      partimage_stdin_argv="$partimage_stdin_argv $(grep "$pattern" /cdrom/$ocsroot/size | cut -d: -f2)" 
      partimage_stdout_argv="$partimage_stdout_argv $imagefile"
    else
      break
    fi
    i=`expr $i + 1`
  done
  umount /cdrom

  /sbin/partimage_stdout "$partimage_stdout_argv" | /sbin/partimage_stdin -gz $partimage_stdin_argv | partimage -f3 -b restore /dev/hda1 stdin

  ## resize_partition
  option_resize_partition="$(get_option "resize_partition")"
  [ "$option_resize_partition" = "on" ] && resize_partition "hda" "hda1"

  ## grub_install
  option_grub_install="$(get_option "grub_install")"
  if [ "$option_grub_install" != "" ]; then
    hd_img=`mktemp -d /tmp/hd_img.XXXXXX`
    mount $option_grub_install $hd_img
    /sbin/grub-install --root-directory=$hd_img /dev/hda
    [ -d "$hd_img" ] && rm -rf $hd_img
  fi
}

# task "restoredisk" 
# parameter:
#   $1 target_file
#   $2 target_hd
task_restoredisk() {
  local target_dir=$1
  local target_hd=$2

  # screen no blank
  /usr/bin/setterm -blank 0
  # HD DMA on
  /sbin/hdparm -d1 /dev/$target_hd
  # swapoff -a, just in case
  /sbin/swapoff -a

  # restore
  dd if=$target_dir/mbr of=/dev/$target_hd
  #sfdisk /dev/$target_hd < $target_dir/pt.sf
  #if [ $? -ne 0 ]; then sfdisk_fail_process; exit 1; fi
  option_sfdisk_op="$(get_option "sfdisk_op")"
  case "$option_sfdisk_op" in
    "off") 
      ;;
    "manual") 
      cfdisk /dev/$target_hd 
      ;;
    "force_on")
      /sbin/sfdisk -f /dev/$target_hd < $target_dir/pt.sf
      if [ $? -ne 0 ]; then sfdisk_fail_process; fi 
      ;;
    "on")
      /sbin/sfdisk /dev/$target_hd < $target_dir/pt.sf
      if [ $? -ne 0 ]; then sfdisk_fail_process; fi 
  esac

  #for partition in `cat $target_dir/pt.sf | grep "Id=" | awk -F, '{ if($3!=" Id= 0" && $3!=" Id= f" && $3!=" Id= 5" && $3!=" Id=82") print $1; }' | cut -d" " -f1 | sed -e 's/\/dev\///g'` 
  for partition in `get_known_partition $target_dir/pt.sf`
  do
    if [ -f /sbin/checkInodeForDevice ]; then /sbin/checkInodeForDevice /dev/$partition ; fi
    #nice -n -10 /usr/sbin/partimage -f3 -z1 -o -d -b restore /dev/$partition $target_dir/$partition".000"
    /usr/sbin/partimage -f3 -z1 -o -d -b restore /dev/$partition $target_dir/$partition".000"
  done
  # swap partition
  for partition in `cat $target_dir/pt.sf | grep "Id=82" | cut -d" " -f1 | sed -e 's/\/dev\///g'`
  do
    mkswap /dev/$partition > /dev/null 2>&1
	swapon /dev/$partition > /dev/null 2>&1
  done

  ## resize_partition
  option_resize_partition="$(get_option "resize_partition")"
  [ "$option_resize_partition" = "on" ] && resize_partition "$target_hd"

  ## grub_install
  option_grub_install="$(get_option "grub_install")"
  if [ "$option_grub_install" != "" ]; then
    hd_img=`mktemp -d /tmp/hd_img.XXXXXX`
    mount $option_grub_install $hd_img
    /sbin/grub-install --root-directory=$hd_img /dev/hda
    [ -d "$hd_img" ] && rm -rf $hd_img
  fi
}

# task "multicast_restoredisk" 
# parameter:
#   $1 sync_server
#   $2 multicast
#   $3 port
#   $4 target_dir
#   $5 target_hd
task_multicast_restoredisk() {
  local sync_server=$1
  local port=$3
  local target_dir=$4
  local target_hd=$5
  local multicast_prefix=`echo "$2" | awk -F. '{ print $1"."$2"."$3; }'`
  local multicast_n=`echo "$2" | awk -F. '{ print $4; }'`
  local n=$multicast_n

  # Blake, 2004/02/09, sync_server = gateway
  #sync_server=`/sbin/route -n | grep -e "^0.0.0.0" | awk '{ print $2; }'`
  #mcast_routing_dev=`/sbin/route -n | grep -e "^0.0.0.0" | awk '{ print $8; }'`
  #/sbin/route add -net 234.0.0.0/24 dev $mcast_routing_dev

  # Blake, 2004/04/30, find sync_server using /etc/fstab
  while read spec file vfstype others; do
	if [ "$file" = "/" ]; then
	  sync_server="$(echo "$spec" | cut -d: -f1)"
	  break
	fi
  done < /etc/fstab

  # screen not blank
  /usr/bin/setterm -blank 0
  # HD DMA on
  /sbin/hdparm -d1 /dev/$target_hd
  # swapoff -a, just in case
  /sbin/swapoff -a

  # restore
  dd if=$target_dir/mbr of=/dev/$target_hd
  #sfdisk /dev/$target_hd < $target_dir/pt.sf
  #if [ $? -ne 0 ]; then sfdisk_fail_process; exit 1; fi
  option_sfdisk_op="$(get_option "sfdisk_op")"
  case "$option_sfdisk_op" in
    "off") 
      ;;
    "manual") 
      cfdisk /dev/$target_hd 
      ;;
    "force_on")
      /sbin/sfdisk -f /dev/$target_hd < $target_dir/pt.sf
      if [ $? -ne 0 ]; then sfdisk_fail_process; fi 
      ;;
    "on")
      /sbin/sfdisk /dev/$target_hd < $target_dir/pt.sf
      if [ $? -ne 0 ]; then sfdisk_fail_process; fi 
  esac

  #for partition in `cat $target_dir/pt.sf | grep "Id=" | awk -F, '{ if($3!=" Id= 0" && $3!=" Id= f" && $3!=" Id= 5" && $3!=" Id=82") print $1; }' | cut -d" " -f1 | sed -e 's/\/dev\///g'` 
  for partition in `get_known_partition $target_dir/pt.sf`  
  do
    if [ -f /sbin/checkInodeForDevice ]; then /sbin/checkInodeForDevice /dev/$partition ; fi

    ## partimage_stdin argv
    partimage_stdin_argv=""
    i=0
    while [ $i -lt 1000 ]; do
      if [ $i -lt 10 ]; then imagefile="$target_dir/$partition.00$i";
      elif [ $i -lt 100 ]; then imagefile="$target_dir/$partition.0$i";
      else imagefile="$target_dir/$partition.$i";
      fi
      if [ -f $imagefile ]; then
        #partimage_stdin_argv="$partimage_stdin_argv $(gunzip -l -q $imagefile | awk '{ print $2; }')"
        pattern=${imagefile##*/}
        partimage_stdin_argv="$partimage_stdin_argv $(grep "$pattern" $target_dir/size | cut -d: -f2)"
      else
        break
      fi
      i=`expr $i + 1`
    done

    ## do multicast 
    multicast=$multicast_prefix"."$n

    #nice -n -10 /sbin/mcastListener $sync_server $multicast $port | /sbin/partimage_stdin -gz $partimage_stdin_argv | /usr/sbin/partimage -f3 -b restore /dev/$partition stdin
    /sbin/mcastListener $sync_server $multicast $port | /sbin/partimage_stdin -gz $partimage_stdin_argv | /usr/sbin/partimage -f3 -b restore /dev/$partition stdin
    n=`expr $n + 1`
    port=`expr $port + 2`
  done
  # swap partition
  for partition in `cat $target_dir/pt.sf | grep "Id=82" | cut -d" " -f1 | sed -e 's/\/dev\///g'`
  do
    mkswap /dev/$partition > /dev/null 2>&1
	#swapon /dev/$partition > /dev/null 2>&1
  done

  ## resize_partition
  option_resize_partition="$(get_option "resize_partition")"
  [ "$option_resize_partition" = "on" ] && resize_partition "$target_hd"

  ## grub_install
  option_grub_install="$(get_option "grub_install")"
  if [ "$option_grub_install" != "" ]; then
    hd_img=`mktemp -d /tmp/hd_img.XXXXXX`
    mount $option_grub_install $hd_img
    /sbin/grub-install --root-directory=$hd_img /dev/hda
    [ -d "$hd_img" ] && rm -rf $hd_img
  fi
}

# task "isoimage_restoredisk"
# parameter:
#   $1 target_dir
#   $2 target_hd
task_isoimage_restoredisk() {
  local target_dir=$1
  local target_hd=$2

  # screen no blank
  /usr/bin/setterm -blank 0
  # HD DMA on
  /sbin/hdparm -d1 /dev/$target_hd
  # swapoff -a, just in case
  #/sbin/swapoff -a

  # ln /proc/mounts to /etc/mtab 
  ln -s /proc/mounts /etc/mtab
  # ln /dev/cdrom 
  cddevices="/dev/hda /dev/hdb /dev/hdc /dev/hdd"
  for i in $cddevices; do
    if mount -t iso9660 -o ro $i /cdrom >/dev/null 2>&1
    then
      if [ -d /cdrom/isolinux -a -d /cdrom/$target_dir ]; then ln -s $i /dev/cdrom; break; fi
    fi
    umount $i >/dev/null 2>&1
  done
  if [ -L /dev/cdrom ]; then
    cp /cdrom/$target_dir/mbr .
    cp /cdrom/$target_dir/pt.sf .
    echo "/dev/cdrom	/cdrom	iso9660	defaults,ro	0 1" > /etc/fstab
    umount /cdrom
    /sbin/hdparm -d1 /dev/cdrom
  fi

  # restore
  /bin/dd if=mbr of=/dev/$target_hd
  #/sbin/sfdisk /dev/$target_hd < pt.sf
  #if [ $? -ne 0 ]; then sfdisk_fail_process; exit 1; fi
  option_sfdisk_op="$(get_option "sfdisk_op")"
  case "$option_sfdisk_op" in
    "off") 
      ;;
    "manual") 
      cfdisk /dev/$target_hd 
      ;;
    "force_on")
      /sbin/sfdisk -f /dev/$target_hd < pt.sf
      if [ $? -ne 0 ]; then sfdisk_fail_process; fi 
      ;;
    "on")
      /sbin/sfdisk /dev/$target_hd < pt.sf
      if [ $? -ne 0 ]; then sfdisk_fail_process; fi 
  esac

  #for partition in `cat $target_dir/pt.sf | grep "Id=" | awk -F, '{ if($3!=" Id= 0" && $3!=" Id= f" && $3!=" Id= 5" && $3!=" Id=82") print $1; }' | cut -d" " -f1 | sed -e 's/\/dev\///g'` 
  for partition in `get_known_partition pt.sf`
  do
    if [ -f /sbin/checkInodeForDevice ]; then /sbin/checkInodeForDevice /dev/$partition ; fi

    mount -t iso9660 -o ro /dev/cdrom /cdrom
    partimage_stdin_argv=""
    partimage_stdout_argv=""
    i=0
    while [ $i -lt 1000 ]; do
      if [ $i -lt 10 ]; then imagefile="$target_dir/$partition.00$i";
      elif [ $i -lt 100 ]; then imagefile="$target_dir/$partition.0$i";
      else imagefile="$target_dir/$partition.$i";
      fi
      if [ -f /cdrom/$imagefile ]; then
        #partimage_stdin_argv="$partimage_stdin_argv $(gunzip -l -q $imagefile | awk '{ print $2; }')"
        pattern=${imagefile##*/}
        partimage_stdin_argv="$partimage_stdin_argv $(grep "$pattern" /cdrom/$target_dir/size | cut -d: -f2)"
        partimage_stdout_argv="$partimage_stdout_argv $imagefile"
      else
        break
      fi
      i=`expr $i + 1`
    done
    umount /cdrom

    /sbin/partimage_stdout "$partimage_stdout_argv" | /sbin/partimage_stdin -gz $partimage_stdin_argv | /usr/sbin/partimage -f3 -b restore /dev/$partition stdin

  done
  # swap partition
  for partition in `cat pt.sf | grep "Id=82" | cut -d" " -f1 | sed -e 's/\/dev\///g'`
  do
    mkswap /dev/$partition > /dev/null 2>&1
	swapon /dev/$partition > /dev/null 2>&1
  done

  ## resize_partition
  option_resize_partition="$(get_option "resize_partition")"
  [ "$option_resize_partition" = "on" ] && resize_partition "$target_hd"

  ## grub_install
  option_grub_install="$(get_option "grub_install")"
  if [ "$option_grub_install" != "" ]; then
    hd_img=`mktemp -d /tmp/hd_img.XXXXXX`
    mount $option_grub_install $hd_img
    /sbin/grub-install --root-directory=$hd_img /dev/hda
    [ -d "$hd_img" ] && rm -rf $hd_img
  fi

  # housekeeping
  rm -f mbr pt.sf
  rm -f /dev/cdrom
}

#### main ####
ocsmgrd_option=""

# parse argument
parse_option=1
ocs_option=""
while [ $parse_option -eq 1 ]; do
  case "$1" in
    -p|--post-action) 
      shift; set_option "post_action" "$1" ;
      ocs_option="$ocs_option -p $1" ; shift ;;
    -g|--grub-install) 
      shift; set_option "grub_install" "$1" ;
      ocs_option="$ocs_option -g $1" ; shift ;;
    -s|--sfdisk-op)
      shift ; set_option "sfdisk_op" "$1" ;
      ocs_option="$ocs_option -s $1" ; shift ;;
    -w|--wait-time) 
      shift; set_option "time_to_wait" "$1";
      ocs_option="$ocs_option -w $1" ; shift ;;
    -c|--confirm) 
      set_option "confirm_restore" "on" ;
      ocs_option="$ocs_option -c" ; shift ;;
    -d|--debug) 
      set_option "debug_mode" "on" ;
      ocs_option="$ocs_option -d" ; shift ;;
    -r|--resize-partition)
      set_option "resize_partition" "on" ;
      ocs_option="$ocs_option -r" ; shift ;;
    -z0|--no-compress)
      set_option "partimage_saveopt" "-V 500 -f3 -z0 -o -d -b -c" ;
      ocs_option="$ocs_option -z0"; shift ;;
    -z1|--gzip-compress)
      set_option "partimage_saveopt" "-V 500 -f3 -z1 -o -d -b -c" ;
      ocs_option="$ocs_option -z1"; shift ;;
    --ocsmgrd_option)
      shift ; ocsmgrd_option="$ocsmgrd_option $1" ; shift ;;
    -*) echo "${0}: ${1}: invalid option"; usage; exit ;;
    *) parse_option=0 ;;
  esac
done

case "$1" in
  "start")
    task=$2
    target_file=$3
    n_clients=$4
 
    ## check dhcp3-server
    if [ ! -e /etc/default/dhcp3-server ]; then
      echo "You must setup DRBL first. Use /opt/drbl/sbin/drblpush-desktop to set it up. Abort!"
      exit 0
    fi
    # target_file
    if [ "$target_file" = "" ]; then
      # ask user to choose the target_file
      case "$task" in
        "save")
           ##################################################
           # 2003/05/12: ask the filename when client boots #
           ##################################################
           #TMP=`mktemp /tmp/ocs.XXXXXX`
           #/usr/bin/dialog --backtitle "$0" --title "OpenSource Clone System" \
           #  --inputbox "Input the file name to $task" 12 60 "" 2> $TMP
           #target_file=$(cat $TMP)
           #target_file="$ocsroot/$target_file"
           #rm -f $TMP
           target_file="ask_user"
	       ;;
        "restore"|"isoimage_restore"|"multicast_restore")
           TMP=`mktemp /tmp/ocs.XXXXXX`
           numfiles=`ls $ocsroot/*.000 2> /dev/null | wc -l`
           numfiles=`expr $numfiles + 0`
           if [ "$debug_mode" = "on" -o  $numfiles -gt 10 ]; then
             nofiles=1
             for file in `ls $ocsroot/*.000 2> /dev/null`
             do
               # only file ..., not directory
               if [ -d $file ]; then continue; fi
               if [ "$file" = "$ocsroot/ocsmgrd" ]; then continue; fi
               if [ "$file" = "$ocsroot/size" ]; then continue; fi
               
               fileinfo=`ls -lh $file | awk '{ print $6"_"$7"_"$5; }'`
               filename=${file##/*/}
               filename=${file##*/}
               echo "$nofiles. $filename $fileinfo" >> $TMP
               nofiles=`expr $nofiles + 1`
             done
             more $TMP
             echo -n "Choose the file to $task: "
             read ANS
             if [ "$ANS" != "" ]; then
                target_file=`grep -e "^$ANS\." $TMP | cut -d" " -f2`
                target_file="$ocsroot/$target_file"
             fi
           else
             filelist=""
             numfiles=0
             for file in `ls $ocsroot/*.000 2> /dev/null`
             do
               # only file ..., not directory
               if [ -d $file ]; then continue; fi
               if [ "$file" = "$ocsroot/ocsmgrd" ]; then continue; fi
               if [ "$file" = "$ocsroot/size" ]; then continue; fi
 
               fileinfo=`ls -lh $file | awk '{ print $6"_"$7"_"$5; }'`
               filename=${file##/*/}
               filename=${file##*/}
               filelist="$filelist $filename $fileinfo off"
               numfiles=`expr $numfiles + 1`
             done
             if [ $numfiles -gt 0 ]; then
               /usr/bin/dialog \
                 --backtitle "NCHC OpenSource Lab" \
                 --title "Clonezilla" \
                 --radiolist "Choose the file to $task:" 16 60 \
                 $numfiles $filelist 2> $TMP
               target_file=$(cat $TMP)
               target_file="$ocsroot/$target_file"
             else
               echo "No Image in $ocsroot.. (abort)"
               exit
             fi
           fi
           rm -f $TMP
           ;;
         *)
           echo "Usage: ${BOLD}$(basename $0) [OPTION] start [OPERATION] target_file${NORMAL}"
           usage_operation
           echo
           usage_option
           exit 0
           ;;
      esac
    fi

    # start 
    if [ "$target_file" = "" -o "$target_file" = "$ocsroot/" ]; then 
      echo "You didn't specify which file to $task ... (abort)"
      exit 0; 
    fi

    # n_clients (for multicast only)
    if [ "$n_clients" = "" -a "$task" = "multicast_restore" ]; then 
      
      TMP=`mktemp /tmp/ocs.XXXXXX`
      /usr/bin/dialog \
      --backtitle "NCHC Opensource Lab" --title "Clonezilla" \
      --radiolist "Choose the method:" 12 80 2 \
      "time-to-wait" "Wait for a while and then start" on \
      "clients-to-wait" "Wait for a number of clients and then start" off 2> $TMP
      M="$(cat $TMP)"
      case "$M" in
        "time-to-wait") 
           /usr/bin/dialog --backtitle "NCHC Opensource Lab" --title "Clonezilla" \
             --inputbox "Time to wait (Sec)?" 12 60 "120" 2> $TMP
           W="$(cat $TMP)"
           n_clients="0"
           ocsmgrd_option="$ocsmgrd_option -t $W"
           ;;
        "clients-to-wait")
           ## ask how many clients to restore
           n_clients=0
           while read line
           do
             if [ "$(echo "$line" | grep "hardware ethernet")" != "" ]; then
               n_clients=`expr $n_clients + 1`
             fi
           done < /etc/dhcp3/dhcpd.conf
           /usr/bin/dialog --backtitle "NCHC Opensource Lab" --title "Clonezilla" \
           --inputbox "How many clients to restore ?" 12 60 "$n_clients" 2> $TMP
           n_clients=$(cat $TMP)
           ocsmgrd_option="$ocsmgrd_option -c $n_clients"
           ;;
      esac 
      rm -f $TMP
    fi

    start $task $target_file $n_clients "$ocs_option" "$ocsmgrd_option"

    # restart nfs-kernel-server
	if [ -f /etc/init.d/nfs-user-server ]; then
	  /etc/init.d/nfs-kernel-server restart
	fi
    # checkInodeForDevice
    if [ -f /tmp/checkInodeForDevice.c ]; then
      gcc -o $drblroot/root/sbin/checkInodeForDevice /tmp/checkInodeForDevice.c
    fi
    ;;
  "startdisk")
    task=$2
    target_file=$3
    target_hd=$4
    n_clients=$5

    # target_file
    if [ "$target_file" = "" ]; then
      # ask user to choose the target_file
      case "$task" in
        "save")
           ##################################################
           # 2003/05/12: ask the filename when client boots #
           ################################################## 
           #TMP=`mktemp /tmp/ocs.XXXXXX`
           #/usr/bin/dialog --backtitle "$0" --title "OpenSource Clone System" \
           #  --inputbox "Input the file name to $task" 12 60 "" 2> $TMP
           #target_file=$(cat $TMP)
           #target_file="$ocsroot/$target_file"
           #rm -f $TMP
           target_file="ask_user"
	       ;;
        "restore"|"isoimage_restore"|"multicast_restore")
           TMP=`mktemp /tmp/ocs.XXXXXX`
           numfiles=`ls $ocsroot 2> /dev/null | wc -l`
           numfiles=`expr $numfiles + 0`
           if [ "$debug_mode" = "on" -o $numfiles -gt 10 ]; then
             nofiles=1
             for file in `ls $ocsroot 2> /dev/null`
             do
               # only directory ..., not file
               if [ ! -d $ocsroot/$file ]; then continue; fi
               
               fileinfo=`ls -lh $ocsroot/$file/disk | awk '{ print $6"_"$7; }'`
               fileinfo=$fileinfo"_"$(cat $ocsroot/$file/disk)
               echo "$nofiles. $file $fileinfo" >> $TMP
               nofiles=`expr $nofiles + 1`
             done
             more $TMP
             echo -n "Choose the file to $task: "
             read ANS
             if [ "$ANS" != "" ]; then
                target_file=`grep -e "^$ANS\." $TMP | cut -d" " -f2`
                target_file="$ocsroot/$target_file"
                target_hd=$(cat $target_file/disk)
             fi
           else
             filelist=""
             numfiles=0
             for file in `ls $ocsroot 2> /dev/null`
             do
               # only directory ..., not file
               if [ ! -d $ocsroot/$file ]; then continue; fi
           
               fileinfo=`ls -lh $ocsroot/$file/disk | awk '{ print $6"_"$7; }'`
               fileinfo=$fileinfo"_"$(cat $ocsroot/$file/disk)
               filelist="$filelist $file $fileinfo off"
               numfiles=`expr $numfiles + 1`
             done
             if [ $numfiles -gt 0 ]; then
               /usr/bin/dialog \
                 --backtitle "NCHC OpenSource Lab" \
                 --title "Clonezilla" \
                 --radiolist "Choose the file to $task:" 16 60 \
                 $numfiles $filelist 2> $TMP
               target_file=$(cat $TMP)
               target_file="$ocsroot/$target_file"
               target_hd=$(cat $target_file/disk)
             else
               echo "No Image in $ocsroot.. (abort)"
               exit 0
             fi
           fi
           rm -f $TMP
           ;;
         *)
           echo "Usage: ${BOLD}$(basename $0) [OPTION] startdisk [OPERATION] target_file target_hd${NORMAL}"
           usage_operation
           echo
           usage_option
           exit 0
           ;;
      esac
    fi

    # target_hd
    if [ "$targe_hd" = "" ]; then
      # ask user to choose the target_hd
      case "$task" in
        "save")
           ##############################################
           # 2003/05/12: ask the disk when client boots #
           ############################################## 
           #NUMHD=4
           #HARDDISKS="hda primary_master off hdb primary_slave off hdc second_master off hdd second_slave off"
           #/usr/bin/dialog --backtitle "$backtitle" --title "$title" \
           #  --radiolist "Choose the disk to $task:" 16 60 $NUMHD $HARDDISKS \
           #2> $TMP
           #target_hd=$(cat $TMP)
           #rm -f $TMP
           target_hd="ask_user"
           ;;
        "restore"|"isoimage_restore"|"multicast_restore")
           target_hd=$(cat $target_file/disk)
           ;;
      esac
    fi

    # start
    if [ "$target_file" = "" -o "$target_file" = "$ocsroot/" -o "$target_hd" = "" ]; then 
      echo "You didn't specify which file or disk to $task"
      exit 0; 
    fi

    # n_clients (for multicast only)
    if [ "$n_clients" = "" -a "$task" = "multicast_restore" ]; then 
      
      TMP=`mktemp /tmp/ocs.XXXXXX`
      /usr/bin/dialog \
      --backtitle "NCHC Opensource Lab" --title "Clonezilla" \
      --radiolist "Choose the method:" 12 80 2 \
      "time-to-wait" "Wait for a while and then start cloning" on \
      "clients-to-wait" "Wait for a number of clients and then start cloning" off 2> $TMP
      M="$(cat $TMP)"
      case "$M" in
        "time-to-wait") 
           /usr/bin/dialog --backtitle "NCHC Opensource Lab" --title "Clonezilla" \
             --inputbox "Time to wait (Sec)?" 12 60 "120" 2> $TMP
           W="$(cat $TMP)"
           n_clients="0"
           ocsmgrd_option="$ocsmgrd_option -t $W"
           ;;
        "clients-to-wait")
           ## ask how many clients to restore
           n_clients=0
           while read line
           do
             if [ "$(echo "$line" | grep "hardware ethernet")" != "" ]; then
               n_clients=`expr $n_clients + 1`
             fi
           done < /etc/dhcp3/dhcpd.conf
           /usr/bin/dialog --backtitle "NCHC Opensource Lab" --title "Clonezilla" \
           --inputbox "How many clients to restore ?" 12 60 "$n_clients" 2> $TMP
           n_clients=$(cat $TMP)
           ocsmgrd_option="$ocsmgrd_option -c $n_clients"
           ;;
      esac 
      rm -f $TMP
    fi

    start $task"disk" "$target_file $target_hd" $n_clients "$ocs_option" "$ocsmgrd_option"

    # restart nfs-kernel-server
	if [ -f /etc/init.d/nfs-kernel-server ]; then
	  /etc/init.d/nfs-kernel-server restart
	fi
    # checkInodeForDevice
    if [ -f /tmp/checkInodeForDevice.c ]; then
      gcc -o $drblroot/root/sbin/checkInodeForDevice /tmp/checkInodeForDevice.c
    fi
    ;;
  "stop")
    if [ -f $drblroot/root/sbin/checkInodeForDevice ]; then
      rm -f $drblroot/root/sbin/checkInodeForDevice
    fi
    stop
    # restart nfs-kernel-server
	if [ -f /etc/init.d/nfs-user-server ]; then
	  /etc/init.d/nfs-kernel-server restart
	fi
    ;;
  "save")
    task_preprocessing
    task_notify_connect
    task_save $2
    task_notify_localboot
    task_postprocessing
    ;;
  "restore")
    task_preprocessing
    task_notify_connect
    task_restore $2
    task_notify_localboot
    task_postprocessing
    ;;
  "savedisk")
    task_preprocessing
    task_notify_connect
    task_savedisk $2 $3
    task_notify_localboot
    task_postprocessing
    ;;
  "restoredisk")
    task_preprocessing
    task_notify_connect
    task_restoredisk $2 $3
    task_notify_localboot
    task_postprocessing
    ;;
  # mulitcast restore
  "multicast_restore")
    task_preprocessing
    task_notify_connect
    task_multicast_restore $2 $3 $4 $5
    # in case of failed this time, use unicast restore next time
    ocs_inittab /etc/inittab restore "$5" "$ocs_option"
    task_notify_localboot
    task_postprocessing
    ;;
  # multicast restoredisk
  "multicast_restoredisk")
    task_preprocessing
    task_notify_connect
    task_multicast_restoredisk $2 $3 $4 $5 $6
    ## in case of failed this time, use unicast restoredisk next time
    ocs_inittab /etc/inittab restoredisk "$5 $6" "$ocs_option"
    task_notify_localboot
    task_postprocessing
    ;;
  "isoimage_restore")
    task_preprocessing
    task_isoimage_restore $2
    task_postprocessing
    ;;
  "isoimage_restoredisk")
    task_preprocessing
    task_isoimage_restoredisk $2 $3
    task_postprocessing
    ;;
  "usage_option") usage_option ;;
  "usage_restore_option") usage_restore_option ; echo ; usage_general_option ;;
  "usage_save_option") usage_save_option ; echo ; usage_general_option ;;
  *) usage ;;
esac
exit 0
