#!/bin/sh
#
# 	$Source: /cvsroot/bootcd/bootcd/Attic/bootcdcreate,v $
#       $Id: bootcdcreate,v 1.1 2007-09-13 13:34:58 debdin-guest Exp $
#    author: Carsten Dinkelmann <din@foobar-cpa.de>
#     start: 12.09.2007
#     topic: create a small debian cd and configured it for bootcd
#

# use for temporary files
TMPDIR=/tmp/.debootstrap

# used as basis directory
WORKDIR=/var/spool/bootcd-img

# only for help, the download path
DOWNLOADPATH="http://packages.debian.org/etch/debootstrap"

# build deboostrap for this distribution
DISTRI="etch"

# links for debootstrap
DEBOOTLINKS="/usr/lib/debootstrap"

# needed tools
TOOLS="ar tar chroot"

# kernel
KERNEL="linux-image-2.6-486"

# needed packages
PACKAGES="bootcd bootcd-mkinitramfs bootcd-i386 grub"

# usefull packages
UPACKAGES="lvm2 less psmisc net-tools ssh vim netbase xbase-clients"

######################### nothing to configure behind this line ###############

SCRIPTNAME=$(basename $0)

# function: usage
# get: $1 -- error string
usage()
{
  [ "$1" ] && echo -e >&2 "\n$1\n"

  echo -e "\n $SCRIPTNAME creates a debian bootcd image in a chroot-enviroment."
  echo -e " After that, you can backup your running system to a CD/DVD.\n"
  echo -e " syntax: $SCRIPTNAME [-i] [-d <directory>] <debootstrap path>"
  echo -e ""
  echo -e "                 -i   -- do all things interactive"
  echo -e "       -d <directory> -- create image in this directory (Space needed!)"
  echo -e "                         default: \"$WORKDIR\""
  echo -e "   <debootstrap path> -- path to debootstrap debian package"
  echo -e ""                         
  echo -e " download debootstrap: \"$DOWNLOADPATH\" "
  echo -e ""
  echo -e " example: $SCRIPTNAME /tmp/debootstrap_0.3.3.2etch1_all.deb"
  echo -e ""
 
  exit 0
}


# function: script_error -- echo error and exit
script_error()
{
  echo -e >&2 "\n ERROR:" "$@" "\n"
  exit 10
}




# function: interactive -- print menu with functions and call it step by step
# get: $1..n -- list of functions
# comment: use ANSW to change the next point from external
function interactive()
{
  local ANSW A I i y t
  y=""
  t="-i "
  if [ "$1" = "-y" ]; then
    y="$1"
    t=""
    shift
  fi
  if [ $# -gt 0 ]; then
    ANSW="1"
    while :; do
      if [ ! "$y" ]; then
        i=1
        while [ $i -le $# ]; do
          echo "$i $(eval echo "\${$i}")" | sed "s/<-i>[[:space:]]*/$t/g" 
          let i=i+1
        done
        [ "$(echo "$*"|grep "<-i>")" ] && echo "i toggle -i flag"
        [ "$ANSW" != "q" ] && [ $ANSW -lt $# ] && echo "c continue without questions"
        echo "q quit"
        echo -n "? [$ANSW]"
        read A
        [ "$A" -a "$A" != "c" -a "$A" != "i" -a "$A" != "d" ] && ANSW="$A"
      fi
  
      if [ "$ANSW" = "q" ]; then
        return
      elif [ "$A" = "i" ]; then
        [ "$t" ] && t="" || t="-i "
      elif [ "$(echo "$ANSW" | sed 's/[0-9]//g')" ]; then
        ANSW="?"
      elif [ "$ANSW" -ge 1 -a "$ANSW" -le $# ]; then
        [ "$A" = "c" ] && y="-y"
        eval "$(echo "$(eval echo "\${${ANSW}}")" | sed "s/<-i>/$t/g")"
        ANSW=$(($ANSW+1))
        [ $ANSW -gt $# ] && ANSW=q
      fi
    done
  fi
}


# function: ask_user -- ask user
# get: question = string
#      default  = y|n
# ret: 1 == yes | 0 == no
ask_user()
{
  local quest=$1
  [ "$2" == "y" -o "$2" == "n" ] && local default=$2 || local default=""

  while [ 1 ]; do
    echo -ne "$quest"
    read a
    [ "$a" == "" ] && a=$default
    if [ "$a" == "Y" -o "$a" == "y" -o "$a" == "J" -o "$a" == "j" ]; then
      # echo "yes"
      return 1;
    fi
    if [ "$a" == "N" -o "$a" == "n" ]; then
      # echo "no"
      return 0;
    fi
    echo >&2 "Error: \"$a\" is not a allowed answer!"
  done
}


# function: check_tools -- check if tools exist
# get: $1..$n -- tools
check_tools()
{
  while [ "$1" ]; do 
    echo -n >&2 " check for \"$1\" ..."
    [ ! "$(which $1)" ] && script_error "Can't foung tool \"$1\" in PATH!"
    echo >&2 "ok"
    shift
  done
}


# function: do_dir -- create directory
# get: $1 -- directory
do_dir()
{
  local dir=$1

  if [ -d "$dir" ]; then
    ask_user "Directory \"$dir\" exist's, remove it [Y|n] " "y"
    [ $? == 0 ] && script_error "Can't work without directory \"$dir\"."
    rm -rf $dir
  fi
  mkdir -p $dir
}


# function: ext_debootstrab -- extract debootstrap
# get: $1 -- tmpdir
#      $2 -- path to debfile
ext_debootstrap()
{
  local tmpdir=$1
  local debfile=$2

  (cd $tmpdir; ar -x $debfile)

  tar -xvz -C$tmpdir -f /$tmpdir/data.tar.gz

  # we need one link that debootstrap is working
  for i in $DEBOOTLINKS; do 
     [ ! -e "${i}" ] && ln -s ${tmpdir}${i} ${i}
  done
}


# function: do_debootstrab -- start it
# get: $1 -- tmpdir
#      $2 -- distribution
#      $3 -- workdir
do_debootstrap()
{
  local tmpdir=$1
  local distri=$2
  local workdir=$3

  $tmpdir/usr/sbin/debootstrap --variant=buildd $distri $workdir
}   


# function: install_packages
# get: $1 -- workdir
#      $2 -- kernel
#      $3 -- packages
#      $4 -- usefull packages
#      $5 -- interactive
install_packages()
{
  local workdir=$1
  local kernel=$2
  local packages=$3
  local usepkg=$4
  local interact=$5
  local TODO=""

  TODO="$TODO \"chroot $workdir apt-get update\""
  TODO="$TODO \"chroot $workdir apt-get -y -f install $kernel\""
  TODO="$TODO \"chroot $workdir apt-get -y -f install $packages\""
  [ "$usepkg" ] && TODO="$TODO \"chroot $workdir apt-get -y -f install $usepkg\""

  [ "$interact" ] && interact="" || interact="-y"
  eval "interactive $interact $TODO"
}   



# function: do_clean -- clean all things
# get: $1 -- tmpdir
do_clean()
{
  local tmpdir=$1

  rm -rf $tmpdir

  # remove only links!! link that debootstrap is working
  for i in $DEBOOTLINKS; do 
     [ -L $i ] && rm -f $i
  done
}


#################### the real things #########################################


TODO=""
workdir=$WORKDIR
upackages=""
DEBOOTSTRAP=""
while [ "$1" ]; do
  case "$1" in
    "-d")
      shift
      workdir="$1"
      ;;
    "-u")
      upackages=$UPACKAGES
      ;;
   "-i")
     interact="$1"
     ;;
    --help|-h) 
      usage
      ;;
    *) 
      [ ! "$DEBOOTSTRAP" ] && DEBOOTSTRAP=$1 || usage "parameter \"$1\" unknown!"
      ;;
  esac
  shift
done

[ ! "$DEBOOTSTRAP" ] && usage "Mandatory parameter \"debootstrap path\" not found!"

TODO="$TODO \"check_tools $TOOLS\""
TODO="$TODO \"do_dir $TMPDIR\""
TODO="$TODO \"do_dir $WORKDIR\""
TODO="$TODO \"ext_debootstrap $TMPDIR $DEBOOTSTRAP\""
TODO="$TODO \"do_debootstrap $TMPDIR $DISTRI $WORKDIR\""
TODO="$TODO \"install_packages $WORKDIR \\\"$KERNEL\\\" \\\"$PACKAGES\\\" \\\"$upackages\\\" <-i>\"" 
TODO="$TODO \"do_clean $TMPDIR\""

[ "$interact" ] && interact="" || interact="-y"
eval "interactive $interact $TODO"



