#!/bin/bash

# /usr/sbin/lessdisks-install
# install script for lessdisks, with easydialog frontend

# copyright 2004 vagrant@freegeek.org, distributed under the terms of the
# GNU General Public License version 2 or any later version.

# TODO generate the /etc/lessdisks/server.config file
# or as much as we can get...

# TODO make firstMenu pretty

# TODO get rid of easydialog?

# process commandline arguments
for ARGUMENT in "$@"
do
  case $1 in
    -a|--arch) newarch="$2"
      echo "setting terminal architechure to $newarch"
      shift ;;
    -c|--configfile) LESSDISKS_CONFIG="$2"
      echo "setting configuration file to $LESSDISKS_CONFIG"
      shift ;;
    -d|--dialog) DIALOG="$2"
      echo "setting dialog to $DIALOG"
      shift ;;
    --skip|--skip-menus) echo -e "skipping menu configuration,\
        proceeding with default values"
      BEGIN_INSTALL="yes";;
    --logfile|-l) logfile="$2"
      echo "setting log file to $logfile"
      shift ;;
    -h|--help) echo -e "lessdisks-install [options] [blah blah]\n\
        -c, --configfile  configuration file, normally /etc/lessdisks-install.conf\n\
        -l , --logfile  log file, normally /var/log/lessdisks-install.log\n\"
        -d, --dialog  set dialog type: whiptail, dialog, Xdialog, cmdline\n\
        --skip, --skip-menus  skip menu configuration and proceed with defaults\n\
        -h, --help  show these help options"
      exit 0;;
  esac
  shift
done

showValues() {
  egrep -v "^#" $1
}

# if configuration file not specified set default
if [ "" = "$LESSDISKS_CONFIG" ]
then
  LESSDISKS_CONFIG="/etc/lessdisks-install.conf"
fi

if [ ! -e "$LESSDISKS_CONFIG" ]
then
  # can't use exitbox yet.
  echo -e "configuration file for lessdisks\n\
    not found!\n\
    exiting..."
  exit 1
fi

firstMenu() {
echo ""
echo "1: Begin Install"
echo "2: Show Values"
echo "3: Simple Configuration"
echo "4: Advanced Configuration"
echo "5: Exit, Quit, etc.."
echo ""
read response
case $response in
  1) BEGIN_INSTALL="yes" ;;
  2) showValues $LESSDISKS_CONFIG ;;
  3) dpkg-reconfigure --priority=medium lessdisks
  . $LESSDISKS_CONFIG ;;
  4) dpkg-reconfigure --priority=low lessdisks
  . $LESSDISKS_CONFIG ;;
  5) exit 15 ;;
  *) echo "urk! something went wrong..."
  exit 20 ;;
esac
}

while [ "yes" != "$BEGIN_INSTALL" ]; do
  firstMenu
done

# get default values from config file...
. $LESSDISKS_CONFIG

if [ -z "$logfile" ]; then
  logfile="/var/log/lessdisks-install.log"
  echo "setting logfile to $logfile"
  logmessage="maybe check the logfile, $logfile"
fi
touch $logfile

PATH="/usr/local/lib/easydialog:/usr/lib/easydialog:$PATH" . easydialog.sh

# TODO test for existance of easydialog?

# dialog's size detection seems broken... so lets set a few stupid
# defaults
if [ "$DIALOG" = "dialog" ] ; then
  if [ -z "$LINES" ]; then
    LINES=20
  fi
  if [ -z "$COLUMNS" ]; then
    COLUMNS=70
  fi
  setDimension $((COLUMNS-10)) $(($LINES-5))
fi

exitBox() { 
  if [ "" = "$1" ]; then 
    msgBox "exiting" "exiting..."
  else
    msgBox "exiting" "$@" 
  fi 
  exit 1 
}

# if defined, export 
if [ -n "$http_proxy" ]; then
  HTTP_PROXY="$http_proxy"
  export HTTP_PROXY http_proxy
fi

#### debootstrap configuration

debootstrapvalid="no"
while [ "no" = "$debootstrapvalid" ]; do
  if [ -x $debootstrap ]; then
    echo " "
    echo "debootstrap is where we expect it, we can continue as planned"
    echo " "
    debootstrapvalid="yes"
  else
    inputBox "debootstrap missing" \
    "debootstrap not found, or is not executable\n\
    where is a valid path to an executable debootstrap?"
    debootstrap="$REPLY"
    if [ "1" = "$?" ]; then
      exitBox
    fi
    debootstrapvalid="no"
  fi
done

if [ "" = "$newarch" ]; then
  msgBox "determining architecture" \
  "debootstrap will attempt to automatically determine\n\
  the machine architecture automatically\n\
  if the wrong architecture is detected, such as\n\
  i386-none, edit $LESSDISKS_CONFIG to\n\
  specify the arch manually or specify it on command\n\
  line:\n\n\
  lessdisks-install <arch>\n\n\
  some valid arch values- i386, powerpc, m68k, sparc"
else
  echo "setting terminal architecture to $newarch"
  debootstrap_opts="$debootstrap_opts --arch $newarch "
fi


msgBox "about to install lessdisks..." \
  "about to go through the installation process.\n\
  this will install 100-150 MB of files into\n\
  $lessdisks_path\n\
  hopefully you have enough space to install it.\n\n\
  if doing a web-based install, this process may\n\
  download approximately 20-30 MB of files- \n\
  i wouldn't reccomend trying it over a modem."

# TODO support other methods...
# someday we might support methods other than web, but for now just go with it.
method="web"

TestArchive() {
#### get information about archive location

if [ "web" = "$method" ]; then
  if [ "" = "$archive" ]; then
    echo "setting archive to default: $defaultarchive"
    archive="$defaultarchive"
  fi
  archive=`echo $archive | awk -F "http://" '{print $1 $2}'`
else
  while [ "" = "$archive" ]; do
    validarchive="no"
    while [ "no" = "$validarchive" ]; do
      inputBox "location of archive" \
        "where the $method mounted?\n\
        it must already be mounted,\n\
        and must begin with a /"
      archive="$REPLY"

      # test to see if base archive is a valid path
      if [ -d "$archive/dists/$debian_dist" ]; then
        echo " "
        echo "using archive $archive"
        echo " "
        validarchive="yes"
      else
        # TODO attempt to mount archive
        msgBox "archive invalid" \
        "$archive invalid, please\n\
        specify valid path to archive\n\
        \n\
        perhaps it needs to be mounted?"
        validarchive="no"
      fi
    done
  done
fi
}

getPercent() {
  filename="$logfile"
  sleep_time=2
  percent=0
  i=0
  while [ "$percent" -lt "100" ]; do
    # this gets us a rough idea of how much has been done
    steps=$(awk '/^I:/{print $2}' $filename | sort -u)
    number_steps=$(echo $steps | wc -w)
    if [ -n "$(echo $steps | egrep Base)" ]; then
      # if we hit the "Base system installed" line, we're 101%
      echo 101
      break
    fi
    if [ "$number_steps" -gt "0" ]; then
      # attempt a tiny bit of illusory granularity
      if [ "$percent" -lt "$(($number_steps*14))" ]; then
        percent=$(($percent+1))
      fi
    fi
    echo $percent
    sleep $sleep_time
  done
}

gaugeBox() {
  $DIALOG --gauge "lessdisks installer..." $(($HEIGHT/2)) $(($WIDTH)) 0
}

getPackageList() {
  package_list=""
  list_type="$1"
  for package in $2; do
    if [ -z "$package_list" ]; then
      package_list="--$list_type=$package"
    else
      package_list="$package_list,$package"
    fi
  done
  echo $package_list
}

DebootstrapInstall() {
  #### begin the download process

  if [ "web" = "$method" ]; then
    archive="http://$archive"
  else
    archive="file:$archive"
  fi
  excludes=$(getPackageList exclude "$exclude_packages")
  includes=$(getPackageList include "$include_packages")
  if [ -n "$DEBIAN_FRONTEND" ]; then
    export DEBIAN_FRONTEND=$DEBIAN_FRONTEND
  fi
  if [ -n "$DEBIAN_PRIORITY" ]; then
    export DEBIAN_PRIORITY=$DEBIAN_PRIORITY
  fi
  debootstrap_opts="$debootstrap_opts $includes $excludes $debian_dist $lessdisks_path $archive $dbs_script"

  downloadok="1"
  while [ "0" != "$downloadok" ]; do
  echo "proceeding with installation... (this will also check for missing or incomplete files again)"
    if [ -z "$logfile" ]; then
      $debootstrap $debootstrap_opts
      downloadok="$?"
    elif [ -w "$logfile" ]; then
      echo "this may take a long long time...."
      echo "switch to another console and tail -f $logfile if you get bored"
      mv -f $logfile $logfile.old
      echo "beginning debootstrap install..." >> $logfile
      date >> $logfile
      # TODO it's a little too fragile backgrounding this...
      getPercent | gaugeBox &
      $debootstrap $debootstrap_opts >> $logfile 2>&1
      # give a little time for the progress bar to catch up
      downloadok="$?"
      sleep 5
    fi
    if [ "0" != "$downloadok" ]
    then
        echo "OH NO... what happened now... "
        echo "look for error messages and hit enter to continue"
        read
        booleanBox "verify download" "download appears to\
           have failed, would you like to try again? $logmessage"
        if [ "$?" != "0" ]
        then
          exitBox
        fi
    fi
  done
}

CheckInstalled () {
  # checks to see if installed already, and changes
  # behavior if so.
  for somefile in etc/hostname etc/hosts usr/bin/awk bin/bash usr/bin/dpkg
  do
    if [ -e $lessdisks_path/$somefile ]
    then
      update="yes"
    fi
  done
  if [ "yes" = "$update" ]
  then
    echo "it seems like you've got an existing lessdisks install..."
    echo "setting to update mode..."
  fi
}

AptSources () {
# TODO include more intelligent generation of sources.list stuff

# slightly more intelligent generation of sources.list...
sources_list="$lessdisks_path/etc/apt/sources.list"
if [ -e "$sources_list" ]
then
  mv $sources_list $sources_list.old
fi

echo "generating $sources_list"
if [ -n "$lessdisksarchive" ]; then
  # only include lessdisks archive if it is set.
  echo "deb http://$lessdisksarchive" >> $sources_list
fi
echo "deb http://$defaultarchive $debian_dist main" >> $sources_list
echo "deb http://$archive_nonus $debian_dist/non-US main" >> $sources_list
echo "deb http://$archive_security $debian_dist/updates main" >> $sources_list

# needed for proper hostname resolution
echo "copying resolv.conf file"
cp /etc/resolv.conf $lessdisks_path/etc/resolv.conf
# useful if nameserver is installed
echo "nameserver 127.0.0.1" >> $lessdisks_path/etc/resolv.conf
}

updateExistingInstall() {
  AptSources
  lessdisks-aptget -f install
  lessdisks-aptget update
  lessdisks-aptget dist-upgrade
  updateok="$?"
  if [ "0" != "$updateok" ]
  then
    booleanBox "update failed" "update appears to\
      have failed, would you like to \
      try a regular install?"
    if [ "$?" = "0" ]
    then
      tar cvzpf $lessdisks_path/lessdisks_backup.tgz \
        $lessdisks_path/etc/lessdisks/*
      if [ -d "$lessdisks_path" ]
      then
        cd $lessdisks_path
        if [ "$?" = "0" ]
        then
          # remove the whole lessdisks filesystem
           # except var, lessdisks_backup.tgz, lost+found
          rm -rvf $(ls | egrep -v "lessdisks_backup.tgz|var|lost+found")
          cd -
          mkdir -p $lessdisks_path/etc/lessdisks/
          DebootstrapInstall
          AptSources
        else
          exitBox "couldn't cd to $lessdisks_path... update failed..."
        fi
      else
        exitBox "couldn't cd to $lessdisks_path... update failed..."
      fi
    else
      exitBox
    fi
  fi
}

TestArchive

CheckInstalled

if [ "yes" = "$update" ]
then
  updateExistingInstall
else
  DebootstrapInstall
  AptSources
fi

# redirect configuration directory appropriately
ln -s $lessdisks_path/etc/lessdisks /etc/
cd $lessdisks_path
echo "ok to install lessdisks-base" > etc/ok-to-install

# TODO cleaner way to handle this?
# server.config values have been incorporated into lessdisks-install.conf
# just need to migrate them over, like so....

mkdir -p $lessdisks_path/etc/lessdisks/
egrep -A 99 "### begin lessdisks server.config ###" $LESSDISKS_CONFIG | \
  egrep -B 99 "### end lessdisks server.config ###" > \
    $lessdisks_path/etc/lessdisks/server.config

########## stage2 install

# copy fake start-stop-daemon into place
# TODO use dpkg-divert 
cd $lessdisks_path/sbin/
mv start-stop-daemon start-stop-daemon.REAL
cp /usr/lib/lessdisks/start-stop-daemon.FAKE start-stop-daemon
cp /usr/lib/lessdisks/start-stop-daemon.FAKE start-stop-daemon.FAKE

# populate kernel-img.conf file
echo "image_in_boot = Yes" >> $lessdisks_path/etc/kernel-img.conf
echo "do_symlinks = Yes" >> $lessdisks_path/etc/kernel-img.conf
echo "relative_links = Yes" >> $lessdisks_path/etc/kernel-img.conf
echo "do_initrd = Yes" >> $lessdisks_path/etc/kernel-img.conf
echo "do_bootloader = No" >> $lessdisks_path/etc/kernel-img.conf
echo "do_bootifloppy = No" >> $lessdisks_path/etc/kernel-img.conf

# in case gid is not present, make it so...
if [ ! -e "$lessdisks_path/etc/lessdisks/gid" ]; then
  awk -F : '/^lessdisks:/{print $3}' /etc/group >> $lessdisks_path/etc/lessdisks/gid
fi

# TODO are the variables available in server.config already available?
. /etc/lessdisks/server.config

lessdisks-aptget update

if [ "0" != "$?" ]
then
  sleep 5
  lessdisks-aptget update
  if [ "0" != "$?" ]
  then
    echo "apt-get update failed, exiting..." 
    exit 1
  fi 
fi

OLD_DEBIAN_FRONTEND=$DEBIAN_FRONTEND
if [ -n "$lessdisks_frontend" ]; then
  # temporarily use this frontend...
  export DEBIAN_FRONTEND=$lessdisks_frontend
fi

# download-only first to assure packages download properly
lessdisks-aptget -yd install lessdisks-terminal $packages $kernel_packages
lessdisks-aptget -y install lessdisks-terminal
# set default values for symlinked files...
# (ssmtp breaks on installs without fully qualified domain names otherwise)
mkdir -p $lessdisks_path/var/state/lessdisks/etc/
echo "127.0.0.1 $disk_server" > $lessdisks_path/var/state/lessdisks/etc/hosts
echo "$disk_server" > $lessdisks_path/var/state/lessdisks/etc/hostname
if [ -n "$packages" ]; then
  lessdisks-aptget -y install $packages
fi

# need to configure initrd to use stock debian kernel
if [ "yes" = "$use_initrd" -o "true" = "$use_initrd" ]; then
  initrd_packages="lessdisks-mkinitrd"
  lessdisks-aptget -yd install $initrd_packages
  lessdisks-aptget -y install $initrd_packages
  # TODO put the rest of this stuff into mkinitrd package
  cd $lessdisks_path
  # TODO behave like a good package and don't muck with other packages config files :)
  mv -vf etc/mkinitrd/mkinitrd.conf etc/mkinitrd/mkinitrd.conf.old
  sed -e 's/MODULES=.*/MODULES=none/g' -e 's/ROOT=.*/ROOT=""/g' etc/mkinitrd/mkinitrd.conf.old > /tmp/mkinitrd.conf && mv -vf /tmp/mkinitrd.conf etc/mkinitrd/mkinitrd.conf
  mkdir -p etc/mkinitrd/scripts
  cd etc/mkinitrd
  cp -v /etc/lessdisks/mkinitrd/files .
  cp -v /etc/lessdisks/mkinitrd/exe .
  cd scripts
  cp -v /etc/lessdisks/mkinitrd/scripts/* .
fi

if [ -n "$kernel_packages" ]; then
  lessdisks-aptget -y install $kernel_packages
fi

lessdisks-aptget -f install

case $export_type in
  none|"") echo "no export type configured" ;;
  khttpd) echo "using khttpd for export type..." ;;
  thy|thttpd) lessdisks-aptget -yd install $export_type 
    lessdisks-aptget -y install $export_type ;;
  *) echo "uknown export type, $export_type, you'll have to install it manually"
    echo "perhaps \"lessdisks-aptget install $export_type\"" ;;
esac

if [ "0" != "$?" ]
then
  echo "apt-get install failed, exiting..." 
  exit 1
fi

# restore DEBIAN_FRONTEND
DEBIAN_FRONTEND=$OLD_DEBIAN_FRONTEND

# TODO move into post-install script: lessdisks-terminal
#chroot $lessdisks_path dpkg-reconfigure lessdisks-terminal
lessdisks-chroot /usr/lib/lessdisks/lessdisks-terminal-install

# TODO move into post-install script: lessdisks-xterminal
#if [ -x $lessdisks_path/var/lib/dpkg/info/lessdisks-xterminal.postinst 
#  chroot $lessdisks_path dpkg-reconfigure lessdisks-xterminal
#fi
if [ -x $lessdisks_path/usr/lib/lessdisks/lessdisks-xterminal-install ]; then
  lessdisks-chroot /usr/lib/lessdisks/lessdisks-xterminal-install
fi

echo "lessdisks stage2 install finished. hit enter to continue"
read pause

booleanBox "run lessdisks-configure?" "would you like to run\n\
  the lessdisks-configure script?\n\
  lessdisks-configure walks you through a few other\n\
  installation steps, such as setting up NFS, dhcpd, etc..."
if [ "$?" = "0" ] ; then
  lessdisks-configure
fi

umount $lessdisks_path/proc 2> /dev/null
