#!/bin/bash
#
# save-config
#
# --------------------------------------------------------------------------
# Copyright notice
# --------------------------------------------------------------------------
# Copyright: Rene Mayrhofer, Mar. 2000
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.  If not, write to
# the Free Software Foundation, 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# On Debian GNU/Linux systems, the complete text of the GNU General
# Public License can be found in `/usr/share/common-licenses/GPL'.
# --------------------------------------------------------------------------
#

# do not edit below this line
# ------------------------------------------------------------

. /etc/default/rcS
. /etc/default/common-definitions.sh

umask 077
set -e

beforesave() {
  return 0
}

aftersave() {
  if [ $1 -eq 0 ]; then
    # Ok, we tried it X times but the admin has still not supplied a disk for
    # saving the config. Therefore he probably wants to discard the config.
    # Do nothing.
    echo "Warning: The configuration will be lost."
    beepconsole -f 1000 -l 750
  else
    beepconsole -f 750 -l 200
  fi
}

try_mount_configdisk() {
  rm -f /tmp/mount-errors > /dev/null
  # try to create the mount-errors file and ignore its use if it can not be created
  if touch /tmp/mount-errors; then
    outstream=/tmp/mount-errors
    errstream=/tmp/mount-errors
  else
    echo "Unable to create log file on /tmp - printing error messages directly."
    outstream=/dev/fd/0
    errstream=/dev/fd/2
  fi
  echo "0 0 0 0" > /proc/sys/kernel/printk
  for fs in $2; do
    if mount -t $fs $1 $save_mntpoint >>$outstream 2>>$errstream; then
      echo "$old_printk" > /proc/sys/kernel/printk
      return 0
    fi
  done
  echo "$old_printk" > /proc/sys/kernel/printk
  return 1
}

print_mount_error() {
  if [ -r /tmp/mount-errors ]; then
    echo "Unable to mount $1 - error was:"
    cat /tmp/mount-errors
  fi
}

format_configdisk() {
  echo "0 0 0 0" > /proc/sys/kernel/printk
  if [ "$SAVE_FILESYSTEM" = "vfat" ]; then
    mkdosfs -c -n CONFIG -m $save_txtfile $1 >/dev/null 2>/dev/null
    ret=$?
  else
    mke2fs -c -L CONFIG -q  -r 1 $1 >/dev/null 2>/dev/null
    ret=$?
  fi
  echo "$old_printk" > /proc/sys/kernel/printk

  if [ $ret -eq 0 ]; then
    if mount -t $SAVE_FILESYSTEM $1 $save_mntpoint >/dev/null 2>/dev/null; then
      # successfully created file system - now create the files
      echo "The disk has been successfully formatted. Now copying configuration."
      create_configdisk $save_mntpoint $save_etcimage
      umount $save_mntpoint
      return 0
    fi
  else
    # else: unable to format - probably no disk has been inserted
    echo "Unable to format the disk. Please insert (another) one."
  fi
  return 1
}

# this method takes 2 parameters: the path to save to and the name of the 
# saved etc image
create_configdisk() {
  save-etc /etc $2
  cp $save_txtfile $1
  gibraltar_version=`cat /system/etc-static/gibraltar_version`
  echo -n "This disk has been created by Gibraltar version $gibraltar_version on:" \
    > $1/time.txt
  date >> $1/time.txt
}

save_config_floppy() {
  local found_disk=0
  local try=0
  local formatit=0
  local found_disk=0
  local mounted=0

  # also be sure that the floppy disk is not mounted
  umount "$SAVE_TARGET_FLOPPY" >/dev/null 2>/dev/null || true

  echo "Trying to save configuration to floppy disk."
  while true; do
    formatit=0
    # try to mount the disk
    if try_mount_configdisk "$SAVE_TARGET_FLOPPY" "$save_filesystems_floppy"; then
      # check if the disk is write-protected
      #state=`expr "\`mount | grep $floppy\`" : ".*\(r[ow]\).*"`
      state=`cat /proc/mounts | grep $save_mntpoint | cut -d' ' -f4,4`
      if [ $state = "ro" ]; then
        echo "The inserted disk is write-protected. Please insert another one."
      elif [ -w $save_etcimage ]; then
        # perfect, the config disk is still inserted and writable - just
        # overwrite the file
        echo "Found old writeable configuration disk. Overwriting it now."
        create_configdisk $save_mntpoint $save_etcimage
        umount $save_mntpoint
        found_disk=1
        break
      elif ! ls -a $save_mntpoint/* >/dev/null 2>/dev/null; then
        echo "Found empty disk in drive. Using it."
        create_configdisk $save_mntpoint $save_etcimage
        umount $save_mntpoint
        found_disk=1
        break
      else
        # else: if the disk is mountable, but the file does not exist, it
        # could still be the boot disk - do not overwrite it
        echo "The inserted disk is not an old configuration disk and is not"\
             "empty."
        echo "Please insert an old configuration disk or an empty disk."
      fi
      umount $save_mntpoint
    else
      # disk is not mountable - but maybe there is an unformated disk in the
      # drive - just try to format it
      if [ "$SAVE_AUTOFORMAT" = "YES" ] || [ "$SAVE_AUTOFORMAT" = "yes" ]; then
        echo "No already formatted disk found in drive. Trying to format it."
        formatit=1
      else
        echo "Not formatting floppy disk automatically. To do this, set "
	echo "SAVE_AUTOFORMAT=YES in /etc/gibraltar_config."
	echo
	print_mount_error floppy
      fi
    fi

    if [ $formatit -eq 1 ]; then
      if format_configdisk "$SAVE_TARGET_FLOPPY"; then
        found_disk=1
        break
      fi
    fi

    if [ $try -ge $MAX_DISK_TRIES ]; then
      break;
    fi

    echo "If you want to pause the save procedure now, press any key."
    echo ""
    beepconsole -f 500 -l 200 -r 2 -d 200
    #sleep 30s
    if read -n 1 -r -s -t $DISK_TIMEOUT; then
      # the user wants to pause
      echo "Save procedure paused. Press enter to continue."
      echo ""
      read -s
    fi

    try=`expr $try + 1`
  done
  aftersave $found_disk
}

save_config_hdd() {
  local saved=0

  # check if the partition is already mounted
  if [ ! -e "$SAVE_TARGET_HDD" ]; then
    echo "Error: $SAVE_TARGET_HDD does not exist !"
    exit 10
  fi
  local target_mntpath=`get_mount_path "$SAVE_TARGET_HDD"`
  if [ -n "$target_mntpath" ]; then
    # already mounted, just use it
    create_configdisk $target_mntpath $target_mntpath/$save_etcimage_name
    saved=1
  else
    # not mounted, mount it
    echo "Trying to save configuration to harddisk partition."
    # try to mount the partition
    if try_mount_configdisk "$SAVE_TARGET_HDD" "$save_filesystems_hdd"; then
      echo "Mounted the harddisk partition, now saving configuration data."
      create_configdisk $save_mntpoint $save_etcimage
      umount $save_mntpoint
      saved=1
    else
      # disk is not mountable - but maybe there is an unformated disk in the
      # drive - just try to format it
      #if[ "$SAVE_AUTOFORMAT" = "YES" ] || [ "$SAVE_AUTOFORMAT" = "yes" ]; then
      #  echo "Unable to mount partition. Trying to format it."
      #  if format_configdisk "$SAVE_TARGET_HDD"; then
      #    saved=1
      #  fi
      #else
        print_mount_error partition
      #fi
    fi
  fi

  aftersave $saved
}

save_config_ssh() {
  local saved=0

  # first try to create the temporary file - /tmp might not be writable now
  if touch /tmp/etc.gz; then
    echo "Saving configuration to a temporary location."
    save-etc /etc /tmp/etc.tgz
    echo -n "Trying to copy the configuration via scp..."
    if /usr/bin/scp /tmp/etc.tgz "$SAVE_TARGET_SSH"; then
      echo "done."
      saved=1
    else
      echo "failed."
    fi

    aftersave $saved
  else
    echo "Error: Unable to create temporary file for saving - /tmp is not writable."
    echo "Aborting."
  fi
}

save_config_email() {
  echo "Currently not implemented."
}

usage() {
  echo "$0 [--target=(floppy|hdd|ssh|email) [--to=<target>]]"
  echo "    where <target> is dependent on the target option"
  exit 1
}


old_printk=`cat /proc/sys/kernel/printk`

# get the current runlevel (this works even when not started from INIT - i.e.
# when the environment variable $RUNLEVEL is not set)
runlev=`runlevel | cut -d' ' -f2,2`

modprobe floppy

# be sure that the mountpoint is available to mount onto it
umount $save_mntpoint >/dev/null 2>/dev/null || true

# check parameters
if [ $# -ge 1 ]; then
  if expr "$1" : "--target=.*" > /dev/null; then
    SAVE_TARGET=`expr "$1" : "--target=\(.*\)"`
  elif [ "$1" = "stop" ]; then
    # simply ignore it - this parameter is set by init when called on shutdown
    true
  else
    usage
  fi

  if [ $# -ge 2 ]; then
    if expr "$2" : "--to=.*" > /dev/null; then
      to=`expr "$2" : "--to=\(.*\)"`
      case $SAVE_TARGET in
        "floppy")   SAVE_TARGET_FLOPPY=$to
                    ;;
        "hdd")      SAVE_TARGET_HDD=$to
                    ;;
        "ssh")      SAVE_TARGET_SSH=$to
                    ;;
        "email")    SAVE_TARGET_EMAIL=$to
                    ;;
      esac
    else
      usage
    fi
  fi
fi

# check some parameters
if [ "$SAVE_TARGET" != "floppy" -a \
     "$SAVE_TARGET" != "hdd" -a \
     "$SAVE_TARGET" != "ssh" -a \
     "$SAVE_TARGET" != "email" ]; then
  echo "Error: unsupported target (you might need to check /etc/gibraltar_config)"
  exit 1
fi
if [ "$SAVE_FILESYSTEM" != "vfat" -a "$SAVE_FILESYSTEM" != "ext2" ]; then
  echo "Error: unsupported filesystem type SAVE_FILESYSTEM in /etc/gibraltar_config"
  exit 1
fi

case $SAVE_TARGET in
  "floppy")    save_config_floppy
              ;;
  "hdd")      save_config_hdd
              ;;
  "ssh")      save_config_ssh
              ;;
  "email")    save_config_email
              ;;
esac

exit 0
