#! /bin/sh
#
# Author:	Matt Zimmerman <mdz@ubuntu.com>
#
### BEGIN INIT INFO
# Provides:          ltsp-client-setup
# Required-Start:    mountvirtfs $local_fs
# Required-Stop:     mountvirtfs $local_fs
# Default-Start:     S 1 2 3 4 5
# Default-Stop:      0 6
# Short-Description: Script for LTSP client initialization
# Description:
### END INIT INFO

set -e

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="LTSP client setup"
NAME=ltsp-client-setup
SCRIPTNAME=/etc/init.d/$NAME

# Gracefully exit if the package has been removed.
test -f /usr/lib/ltsp/ltsp_functions || exit 0
# Gracefully exit if ltsp_chroot file is not present
test -f /etc/ltsp_chroot || exit 0

. /lib/lsb/init-functions
. /usr/lib/ltsp/ltsp_functions
. /usr/lib/ltsp/ltsp_config
test -f /etc/default/ltsp-client-setup && . /etc/default/ltsp-client-setup

load_modules() {
    for module in $(env | awk -F= '$1 ~ /^MODULE_/ { print $2 }'); do
        modprobe $module
    done
}

configure_localdev() {
    if boolean_is_true "$LOCALDEV" ; then
        if [ ! -d /var/run/drives ];then
            mkdir /var/run/drives
        fi
        /usr/bin/ltspfsd -a
        # cdrom devices are handled by the cdpingerponger
        /usr/sbin/cdpinger cdrom # default for usb cdroms

        # and start one for every additional cdrom device
        if [ -L /dev/cdrom?* ];then
            for CDDEV in $(ls /dev/cdrom?*); do
                /usr/sbin/cdpinger $(basename ${CDDEV})
            done
        fi
        # handle already plugged devices on login
        /usr/sbin/delayed_mounter
    fi
}

configure_console() {
    if [ -n "$CONSOLE_KEYMAP" ]; then
        loadkeys "$CONSOLE_KEYMAP"
    fi
}

configure_swap() {
    if boolean_is_true "$USE_LOCAL_SWAP" ; then
        # Enable local swap partition if found on local disk
        for part in `sfdisk -l 2>/dev/null | awk '/ 82 / { print $1}'`; do
            swap_devices="$swap_devices $part"
        done
    fi
    if boolean_is_true "$NBD_SWAP" ; then
        SWAP_SERVER=${SWAP_SERVER:-"$SERVER"}
        NBD_PORT=${NBD_PORT:-"9210"}
        modprobe nbd
        nbd-client $SWAP_SERVER $NBD_PORT /dev/nbd0 && swap_devices="$swap_devices /dev/nbd0"
    fi
    if boolean_is_true "$ENCRYPT_SWAP" ; then
        if [ -x /sbin/cryptsetup ]; then
            modprobe dm_crypt
        else
            echo "ERROR: ENCRYPT_SWAP=Y, but /sbin/cryptsetup not found. disabling swap."
            swap_devices=""
        fi
    fi
    num=0
    for device in $swap_devices ; do
        swap="$device"
        if boolean_is_true "$ENCRYPT_SWAP" ; then
            if [ -x /sbin/cryptsetup ]; then
                cryptsetup -d /dev/urandom create swap$num $swap && swap="/dev/mapper/swap$num"
                num=$(($num+1))
            fi
        fi
        mkswap $swap
        swapon $swap
    done
}

configure_resolver() {
    hostname=$(hostname)
    if [ "(none)" = "$hostname" ] ; then
        /etc/init.d/hostname.sh start
        hostname="$(hostname)"
    else
        echo $hostname > /etc/hostname
    fi
    cat <<EOF > /etc/hosts
127.0.0.1 localhost
127.0.0.2 $hostname
$SERVER server
EOF
    if [ -f /etc/hosts.ltsp ]; then
        cat /etc/hosts.ltsp >> /etc/hosts
    fi

    if [ -n "$DNS_SERVER" ] && [ -n "$SEARCH_DOMAIN" ]; then
        cat <<EOF > /etc/resolv.conf
search $SEARCH_DOMAIN
nameserver $DNS_SERVER
EOF
    fi
}

configure_network() {
    cat <<EOF > /etc/network/interfaces
auto lo
iface lo inet loopback
EOF
}

configure_syslog() {
    cat <<EOF > /etc/syslog.conf
*.* @${SYSLOG_HOST-$SERVER}
EOF
}

configure_fstab() {
  echo "/dev/root       /       unionfs defaults        0       0" > /etc/fstab
  echo "tmpfs           /tmp    tmpfs   defaults,nosuid,nodev 0 0" >> /etc/fstab
  mount /tmp
}

preseed() {
    package="$1"
    question="$2"
    value="$3"

    if [ -n "$value" ]; then
        echo "set $question $value" | debconf-communicate $package
        echo "fset $question seen true" | debconf-communicate $package
    fi
}

configure_x() {
    if [ -z "$xserver_package" ]; then
      # set default xserver
      if [ -d /usr/share/doc/xserver-xorg/ ]; then
        xserver_package="xserver-xorg"
      elif [ -d /usr/share/doc/xserver-xfree86/ ]; then
        xserver_package="xserver-xfree86"
      else
        echo "WARNING: no known xserver detected"
        return
      fi
    fi
    # set default configuration file
    case $xserver_package in
      xserver-xfree86) xserver_config="/etc/X11/XF86Config-4" ;;
      xserver-xorg) xserver_config="/etc/X11/xorg.conf" ;;
    esac
    if [ -n "$XF86CONFIG_FILE" ]; then
        # User has specified a custom config
        cp "$XF86CONFIG_FILE" "$xserver_config"
    else
      # Autoconfigure
      if [ -n "$(which xdebconfigurator)" ]; then
        xdebconfigurator
      fi
      # Handle overrides of specific parameters
      if [ -n "$XSERVER" ] && [ "$XSERVER" != "auto" ]; then
        preseed $xserver_package $xserver_package/autodetect_video_card "false"
        preseed $xserver_package $xserver_package/config/device/driver "$XSERVER"
      fi
      X_USE_SYNC_RANGES=${X_USE_SYNC_RANGES:-Y}
      if [ -n "$X_HORZSYNC" ] && [ -n "$X_VERTREFRESH" ]; then
        preseed $xserver_package $xserver_package/autodetect_monitor "false"
        preseed $xserver_package $xserver_package/config/monitor/selection-method "Advanced"
        preseed $xserver_package $xserver_package/config/monitor/vert-refresh "$X_VERTREFRESH"
        preseed $xserver_package $xserver_package/config/monitor/horiz-sync "$X_HORZSYNC"
        if [ Y = "$X_USE_SYNC_RANGES" ]; then
            preseed $xserver_package $xserver_package/config/monitor/use_sync_ranges "true"
        else
            preseed $xserver_package $xserver_package/config/monitor/use_sync_ranges "false"
        fi
      fi

      # Color depth preseeding
      if [ -n "$X_COLOR_DEPTH" ]; then
        preseed $xserver_package $xserver_package/config/display/default_depth "$X_COLOR_DEPTH"
      fi

      # set compatbility for X_VIDEORAM with ltsp 4.x
      X_VIDEO_RAM=${X_VIDEO_RAM:-"$X_VIDEORAM"}

      # set video ram
      if [ -n "$X_VIDEO_RAM" ]; then
        preseed $xserver_package $xserver_package/config/device/video_ram "$X_VIDEO_RAM"
      fi

      # Mouse preseeding options.  Use inputattach if available
      if [ -n "$X_MOUSE_DEVICE" ] && \
        [ -n "$X_MOUSE_PROTOCOL" ] && \
        type inputattach >/dev/null 2>/dev/null && \
        [ -n "$(echo $X_MOUSE_DEVICE | awk '/\/dev\/ttyS[0-9]/')" ]; then
          inputattach --"$X_MOUSE_PROTOCOL" "$X_MOUSE_DEVICE" &
      else
        if [ -n "$X_MOUSE_DEVICE" ]; then 
          preseed $xserver_package $xserver_package/config/inputdevice/mouse/port "$X_MOUSE_DEVICE"
        fi
        if [ -n "$X_MOUSE_PROTOCOL" ]; then 
          preseed $xserver_package $xserver_package/config/inputdevice/mouse/protocol "$X_MOUSE_PROTOCOL"
        fi
      fi
      if [ -n "$X_MOUSE_EMULATE3BTN" ]; then
        preseed $xserver_package $xserver_package/config/inputdevice/mouse/emulate3buttons "$X_MOUSE_EMULATE3BTN"
      fi

      X_MODE=$( echo "$X_MODE_0 $X_MODE_1 $X_MODE_2" | sed -r 's/ +/, /g;s/, *$//g')
      if [ -n "$X_MODE" ]; then
	    preseed $xserver_package $xserver_package/config/display/modes "$X_MODE"
      fi

      # This require fontserver preseeding to work (Debian bug
      # #323262, fixed in xorg-x11 version 6.8.99.901.dfsg.1-1).
      # Also done using code in screen.d/startx and screen.d/ldm until
      # the xorg-x11 version make it into unstable and testing.
      if [ Y = "${USE_XFS}" ] ; then
        if [ -z "${XFS_SERVER}" ] ; then
          XFS_SERVER="${SERVER}"
        fi
        preseed $xserver_package $xserver_package/config/fontpath/fontserver "tcp/${XFS_SERVER}:7100"
      fi

      # Make sure xkb values only get preseeded if the variables are actually set
      # (saves boottime to not call debconf-communicate on every empty value)
      if [ -n "$XKBLAYOUT" ]; then
        preseed $xserver_package $xserver_package/config/inputdevice/keyboard/layout "$XKBLAYOUT"
      fi
      if [ -n "$XKBMODEL" ]; then
        preseed $xserver_package $xserver_package/config/inputdevice/keyboard/model "$XKBMODEL"
      fi
      if [ -n "$XKBRULES" ]; then
        preseed $xserver_package $xserver_package/config/inputdevice/keyboard/rules "$XKBRULES"
      fi
      if [ -n "$XKBOPTIONS" ]; then
        preseed $xserver_package $xserver_package/config/inputdevice/keyboard/options "$XKBOPTIONS"
      fi
      if [ -n "$XKBVARIANT" ]; then
        preseed $xserver_package $xserver_package/config/inputdevice/keyboard/variant "$XKBVARIANT"
      fi

      # Autoconfigure using dexconf when using xdebconfigurator, or X
      # package postinst if not.  Using dexconf directly might save
      # some memory on the client.
      if [ -n "$(which xdebconfigurator)" ] &&
         [ "$root_write_method" = "bind_mounts" ]; then
        # Using dexconf instead of reconfigure to save memory ?
        dexconf -o $xserver_config
      else
        dpkg-reconfigure -fnoninteractive -pcritical $xserver_package
      fi
    fi
}

bind_mounts () {
  # set defaults
  test -z "$tmpfs_dir" && tmpfs_dir=/var/lib/ltsp-client-setup
  test -z "$rw_dirs" && rw_dirs="/var/cache/man /var/lib/xkb /var/lock /var/run /var/log /var/spool /var/tmp /tmp /var/lib/discover"
  test -z "$copy_dirs" && copy_dirs=""
  test -z "$temp_copy_dirs" && temp_copy_dirs="/var/cache/debconf"
  test -z "$bindfiles" && bindfiles="/etc/X11/xorg.conf /etc/X11/XF86Config-4"
  mount -t tmpfs -o mode=0755 tmpfs $tmpfs_dir
  # preserve directory structure
  for d in $rw_dirs ; do
    if [ -d "$d" ]; then
      cd $tmpfs_dir
      tar --no-recursion -cpf - $(find $d -type d 2> /dev/null) 2> /dev/null | tar xpf -
      mount --bind $tmpfs_dir/$d $d
    else
      echo "WARNING: $d does not exist"
    fi
  done  
  # copy contents into tmpfs
  for d in $copy_dirs $temp_copy_dirs; do
    if [ -d "$d" ]; then
      cd $tmpfs_dir
      tar -cpf - $d 2> /dev/null | tar xpf -
      mount --bind $tmpfs_dir/$d $d
    else
      echo "WARNING: $d does not exist"
    fi
  done
  # mount one file on top of another
  for f in $bindfiles ; do
    if [ -e "$f" ]; then
      mkdir -p "$(dirname $tmpfs_dir/$f)"
      cp $f $tmpfs_dir/$f
      mount --bind $tmpfs_dir/$f $f
    else
      echo "WARNING: $f does not exist"
    fi
  done
}

bind_unmounts() {
  for dir in $temp_copy_dirs; do
    umount $dir
    rm -rf $tmpfs_dir/${dir#/}
  done
}

run_rcfiles() {
  for rcfile in $(env | sort | awk -F= '$1 ~ /^RCFILE_/ { print $2 }'); do
    if [ -x "$rcfile" ]; then
      "$rcfile" $@
    fi
  done
}

case "$1" in
  start)
        log_begin_msg "Setting up LTSP client..."
	type usplash_write >/dev/null 2>/dev/null && usplash_write "TIMEOUT 120" || true
        if [ "$root_write_method" = "bind_mounts" ]; then
          bind_mounts
        fi
        load_modules || true
        configure_console || true
        configure_network || true
        configure_resolver || true
        configure_swap || true
        configure_syslog || true
        configure_fstab || true
        run_rcfiles || true
        configure_x || true
        configure_localdev ||true

	if [ "$root_write_method" = "bind_mounts" ]; then
          bind_unmounts
        fi

        log_end_msg 0
	;;
  stop)
#	echo -n "Stopping $DESC: $NAME"
#	d_stop
#	echo "."
	;;
  restart|force-reload)
	#
	#	If the "reload" option is implemented, move the "force-reload"
	#	option to the "reload" entry above. If not, "force-reload" is
	#	just the same as "restart".
	#
	echo -n "Restarting $DESC: $NAME"
	d_stop
	sleep 1
	d_start
	echo "."
	;;
  *)
	# echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
	exit 1
	;;
esac

exit 0
