#!/bin/sh
#
# Copyright (C)    2005-2007 Jari Aalto
# Author:          Jari Aalto
# Maintainer:      Jari Aalto
#
# COPYRIGHT NOTICE
#
# 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 of the License, 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. Visit http://www.gnu.org/copyleft/gpl.html
#
# You should have received a copy of the GNU General Public License along
# with GNU Emacs.  If you did not, write to the Free Software Foundation,
# Inc., 675 Mass Ave., Cambridge, MA 02139, USA.
#
# DESCRIPTION
#
# This installer program of Stem desktop. The current system must be an
# initial Debian installation without any changes or added packages. This
# program pulls various packages on top of it and constructs desktop
# which is suitable for low end hanrdware (166Mhz/64M)
#
# Open network connection is needed. This script will authenticate
# itself by downloading a md5sum checksum file.

URLHOST="debian.cante.net"
URLHOME="http://$URLHOST/stem"
URLDEB="http://$URLHOST/debian"
URLPING="www.google.com"      # to test network connection

SCRIPT="netinstall.sh"
VERSIONSTR="$Id: netinstall.sh,v 1.96 2007-04-14 07:07:28 jaalto Exp $"
VERSION=$(echo $VERSIONSTR | cut -d' ' -f3)
INSTALL_MEGS=550  # Std Debian install takes about 300M + 550 = 850M

APT_LIST=/etc/apt/sources.list
APT_URL_DEB_UNSTABLE="deb http://ftp.debian.org/debian/ unstable main"
DOC_LOCAL=/usr/share/doc/stem-desktop-doc

# If run with --memory option, change users' shell to one that uses very
# little memory. But do it only if there are not many users (pristine Debian)

SHELL_LITTLE_MEMORY=/bin/mksh
SHELL_MAX_USERS=4

INSTALL_MAIN_FILE=${INSTALL_MAIN_FILE:-"/tmp/stem-install-main.lst"}
INSTALL_UNSTABLE_FILE=${INSTALL_UNSTABLE_FILE:-"/tmp/stem-install-unstable.lst"}
UNSTABLE_LIST=${UNSTABLE_LIST:-"/tmp/stem-unstable-sources.list"}
LOGFILE=${LOGFILE:-"/tmp/stem-install.log"}

# runnning apt-get withuiout lockinf the database.
APT_NOLOCK="-o Debug::nolocking=true"

# Debian policy mandates that font's cannot be REQUIRED by *.deb
# packages. Install the basic fonts "manually"

PKG_LST_X_FONTS="
xfonts-base
xfonts-scalable
xfonts-100dpi
xfonts-75dpi
"

#  Special list for 3rd party packages
PKG_LST_STABLE="
beaver/stable
gxproc/stable
ircatlite/stable
"
#  Internal state variables

FLAG_KERNEL=
FLAG_XDM=
FLAG_OPERA=
FLAG_APT_GET_UPDATE=
FLAG_STABLE=
FLAG_STABLE_DONE=

#  Command line options - how they affect program

OPT_TRUST=      # Run withou md5sum check
OPT_BATCH=      # Do not ask questions
OPT_TYPE=       # Install type: heavy, default|normal, small, minimal
OPT_PURGE=      # Should the 'stem-pkg-clean' package be run. DANGEROUS
OPT_OFFICE=     # Should openoffice.org be installed.
OPT_XVESA=      # Should Xvesa be installed.
OPT_MEMORY=     # Turn on all memory optimisations known

Warn ()
{
    echo "$*" >&2
}

Die ()
{
    Warn "$0: [ERROR] $*"
    exit 1
}

Run ()
{
    ${test+echo} "$@"
}

YN ()
{
    echo -n "$* (y/N): "
    read ans

    case "$ans" in
	[yY]*) return 0 ;;
	*)     return 1 ;;
    esac
}

Yn ()
{
    echo -n "$* (Y/n): "
    read ans

    case "$ans" in
	[nN]*) return 1 ;;
	*)     return 0 ;;
    esac
}

YNdie ()
{
    if ! YN "$1" ; then
	Die "$2"
    fi
}

Echo ()
{
    if [ "$1" = "1" ]; then  # Initial message
	shift
	echo "== $*"
    else
	echo "-- $*"
    fi
}

EchoLines ()
{
    opt=1                # First line is special

    for msg in "$@"
    do
	Echo $opt "$msg"
	opt=
    done
}

MountList ()
{
    mount | awk '/ on .*type/ {print $3}' | sort -r
}

MountDir ()
{
    #  What is the mount point of physical disk

    for tmp in $(MountList)
    do
	case "$1" in
	    $tmp*)
		echo $tmp
		return
		;;
	esac
    done

    return 1
}

IsConfirm ()
{
    [ ! "$OPT_BATCH" ]
}

IsOpt ()
{
    [ "$1" = "batch"  ] && [ "$OPT_BATCH"  ] && return 0
    [ "$1" = "memory" ] && [ "$OPT_MEMORY" ] && return 0
    [ "$1" = "purge"  ] && [ "$OPT_PURGE"  ] && return 0
    [ "$1" = "office" ] && [ "$OPT_OFFICE" ] && return 0
    [ "$1" = "trust"  ] && [ "$OPT_TRUST"  ] && return 0

    if [ "$1" = "xvesa"  ]; then
	[ "$OPT_XVESA"  ] && return 0
	[ "$OPT_MEMORY" ] && return 0
    fi

    return 1
}

PkgVersion ()
{
    dpkg -l ${1:-"none-at-all"} | awk '/^ii/ {print $3}'
}

Lines2List ()
{
    #   This is a "trick". Parameter to function can be
    #   in format "one\ntwo..." due to IFS, but we can
    #	return them back without \n's

    echo $*
}

PkgXserverName ()
{
    # Under stable, it's XFree86

    if apt-get --dry-run --yes -y xserver-xorg > /dev/null 2>&1 ; then
	echo xserver-xorg
	return
    fi

    echo xserver-xfree86
}

IsNetwork ()
{
    ping -n -c 1 $URLPING > /dev/null 2>&1
}

IsLibc6_23 ()
{
    ver=$(PkgVersion libc6)
    echo $ver | grep -q '2\.3\.[0-3]'
}

IsStable ()
{
    #  Do this only once and cache the result

    if [ ! "$FLAG_STABLE_DONE" ]; then
	FLAG_STABLE_DONE="done"

	#  There isn't much better way to find out if running under "stable"
	if apt-get --dry-run --reinstall install nano \
	   | egrep -q 'Inst.*Debian:.*stable'
	then
	    FLAG_STABLE="stable"
	fi
    fi

    [ "$FLAG_STABLE" = "stable" ]
}

IsPs ()
{
    ps -ef | egrep " $1( |\$)" | grep -v "grep"
}

IsXinstalled ()
{
    [ -x /usr/bin/X11/X ]
}

IsXrunning ()
{
    IsPs 'Xvesa|/bin/X |X11/(startx|xinit|xdm)|kdm|gdm|x-window-manager'
}

IsDebian ()
{
    grep -q 'Debian.*GNU' /etc/issue.net
}


IsAptCD ()
{
    grep -q '^[ \t]*deb[ \t]+cdrom' /etc/apt/sources.list 2> /dev/null
}

IsDiskSizeOk ()
{
    mount=$(MountDir $(pwd))

    size=$INSTALL_MEGS
    sizestr="$INSTALL_MEGS M"

    if [ ! "$mount" ]; then
	Warn "Opps, Cannot determine MOUNT POINT for current directory."
	Warn "Hope you have enough disk space to hold installation: $size M"
	return
    fi

    #  /dev/hda7             450M  308M  118M  73% /

    echo "Wait, determining free space in current partition"

    free=$(df -h | awk '/%/ && $0 ~ re {gsub("M",""); print $4; exit}' re="$mount")

    if [ ! "$free" ]; then
	Warn "Oops, cannot read disk free for partition: $mount"
	Warn "Hope you have enough disk space to hold installation: $sizestr"
	return
    fi

    if [ $free -lt $size ]; then
	EchoLines "Hm, free disk space is ${free}M, but $sizestr is needed" \
		  "If this is initial install, you should select the" \
		  "the 'clean' option to free up space. If this is" \
		  "reinstall, you can safely select additional packages."
	Yn "Want to proceed"
    else
	echo ".. ok (approx $sizestr needed)."
    fi
}

ExistsPkg ()
{
    apt-cache search "$1" 2> /dev/null | grep -q "^$1[ \t]"
}

IsPkg ()
{
    regexpmode=$2

    if [ "$regexpmode" ]; then
	dpkg -l | egrep "$1" | awk '{print $2}'
    else
	dpkg -l "$1" 2> /dev/null | grep -q 'ii'
    fi
}

CheckPkg ()
{
    pkg=$1
    msg=${2:-"Ok, $pkg has already been installed"}

    if IsPkg "$pkg" ; then
	Echo "$msg"
	return
    fi

    return 1
}

IsPkgFirewall ()
{
    #  There is no virtual "Provides: firewall" yet in Debian that
    #  could be tested. Now rely on package names.

    for tmp in shorewall \
	       firehol \
	       firestarter \
	       fwbuilder \
	       guarddog \
	       kmyfirewall \
	       pyroman \
	       uif \
	       uruk
    do
      IsPkg $tmp && return
    done

    return 1
}

BannerMain ()
{
    echo "
-----------------------------------------------------------------------
Stem Desktop - Net installer $VERSION <$URLHOME>
by <jari.aalto@cante.net>
-----------------------------------------------------------------------

Stem Desktop is a minimalistic desktop designed for low end hardware.
It is a straight forward Debian installation with few 3rd party packages.

Stem (bot.) means a little branch like those found in trees. The programs
included have been selected by their conservative memory usage for
low end hardware (166Mhz/64Meg). Learn more by visiting site above.

Stem is designed to be installed on top of pristine Debian install. If
this is a production system which has already been configured, it is
not recommend that the installation should continue because the
consequences may be unpredictable.
"
}

Help ()
{
    BannerMain

    echo "\
Install options:

--batch  No questions asked (for non-attended install)

--memory Install minimalistic system (memory consumption wise).
	 E.g. Jwm, Xvesa, only two VTs, send mail to smarthost, etc.

--type heavy
	 Add more capable and more graphical set of
	 programs (xchat, xfe file manager, gaim, gimp)

--oo     Select open office (huge download; takes space).
	 The default install includes Abiword, but OO has more features.

--purge  install stem-pkg-clean prior starting installation (DANGEROUS).
	 This will make fresh Debian install as small as possible by
	 removing compilers, code development tools etc.

--xvesa  Select Xvesa; A 50% lighter than the standard X.org server

Examples:

   Ask to install better set of programs
   # netinstall.sh --type heavy

   Configure install to arrange system to save the most memory
   # netinstall.sh --purge --memory"

    exit 1
}

MsgInfoX ()
{
    echo "\
  In case standard X behaves incorrectly, try these commands:
    dpkg-reconfigure --priority=low xserver-xfree86 (under stable)
    dpkg-reconfigure --priority=low xserver-xorg (under testing)
    invoke-rc.d xdm {start|stop}
    invoke-rc.d gpm {start|stop}
    less /var/log/Xorg.0.log
    sensible-editor /etc/X11/xorg.conf (check sections Monitor; InputDevice)
    <Control-Alt-Backspace>   to terminate X immediately

    ** Notice that Kernel 2.4 uses different Mouse device.
    ** Kernel 2.6 uses /dev/input/mice which meand that kernel must have
    ** the mouse modules loaded and listed at boot in /etc/modules
    ==> IF you upgraded kernel, PLEASE REBOOT

    cat  /etc/modules

  In case Xvesa (if installed) does not work correctly
    sensible-editor /etc/stem-xvesa/xvesa.conf"
}

PasswdUserLines ()
{
    regexp=${1:-"."}

    awk -F: '/\/home|root/ && $0 ~ re {print} '  re=$regexp  /etc/passwd
}

Md5sum ()
{
    file=$1
    md5=$2

    now=$(md5sum $file | cut -d' ' -f1)
    correct=$(cat $md5 | cut -d' ' -f1)

    [ "$now" = "$correct" ]
}

SelfCheck ()
{
    file=$(basename $0)
    md5=$file.md5sum

    Echo "Using $md5 to check integrity of install"

    #  Check local file first

    if  [ -f $md5 ] &&  Md5sum $file $md5 ; then
	echo "Good, md5check passed. Script is authentic"
	return
    fi

    Echo "Need to authenticate this script. Downloading checksum"
    url=$URLHOME/$md5

    wget --quiet --timestamping --tries 1 $url ||
    Die "Checksum download failure from $url"

    if ! Md5sum $file $md5 ; then
	Echo "Checksums error. Try downloading newer script with"
	Echo "wget -qN $URLHOME/$SCRIPT"
	Die  "Will not use this program for install"
    fi

    echo "md5sum check passed. Script is authentic."
}

AddToFileMaybe ()
{
    file=$1

    if [ ! "$file" ] || [ ! -w $file ]; then
	Die "AddToFileMaybe ARG error [$file] [$*]"
    fi

    shift

    for tmp in "$@"
    do
	if ! grep -q "^$tmp" $file; then
	    echo "$tmp" >> $file
	fi
    done
}

AptUpdateNow ()
{
    if [ ! "$FLAG_APT_GET_UPDATE" ]; then

	FLAG_APT_GET_UPDATE="updated"

	if ! apt-get --yes -y $APT_NOLOCK update ; then
	    EchoLines "Hm, apt seems to have problems. " \
		"- If this is problem with marillat access (ftp busy)" \
		"  then try again and skip: acroread"

	    Die "[FATAL] Need working apt repository /etc/apt/sources.list"
	fi
    fi
}

AptUpdateMaybe ()
{
    if [ ! "$FLAG_APT_GET_UPDATE" ]; then
	Echo 1 "Up to date package list is needed before starting installation"
	AptUpdateNow
    fi
}

AptQueueRemove ()
{
    for tmp in "$@"
    do
      for file in $INSTALL_MAIN_FILE $INSTALL_UNSTABLE_FILE
      do
	[ -f $file ] || continue

	if grep -q "^${tmp}$" $file ; then
	    grep -v "^${tmp}$" $file > $file.new
	    mv $file.new $file || Die "[FATAL] AptQueueRemove $tmp $file"
	fi

      done
    done
}

AptQueueAdd ()
{
    touch $INSTALL_MAIN_FILE
    AddToFileMaybe "$INSTALL_MAIN_FILE" "$@"
}

AptQueueAddUnstable ()
{
    touch $INSTALL_UNSTABLE_FILE
    AddToFileMaybe "$INSTALL_UNSTABLE_FILE" "$@"
}

AptQueueToInstall ()
{
    pkg="$1"
    msg=${2:-"Install $pkg"}
    type="$3"

    stat=1

    if IsOpt batch || YN "$msg" ; then
	if [ "$type" = "unstable" ]; then
	    AptQueueAddUnstable "$pkg"
	else
	    AptQueueAdd "$pkg"
	fi
	stat=0
    fi

    return $stat
}

AptUnstableWrite ()
{
    #  Don't make this permanet, use temporarily
    tmp=$UNSTABLE_LIST

    cat $APT_LIST                >  $tmp
    echo                         >> $tmp
    echo "$APT_URL_DEB_UNSTABLE" >> $tmp
}

AptList ()
{
    entry="$1"
    conf="$2"
    [ ! "$conf" ] && conf=$APT_LIST
    function=${3:-"YN"}

    site=$(echo $entry | awk '{print $2}')
    section=$(echo $entry | awk '{print $3}')
    grep="^[^#]+$site[ \t]+$section"

    if egrep -q "$grep" $conf ; then
	echo "Good, $conf includes $entry"
    else
	if ! IsConfirm || $function "Use $entry" ; then
	    echo "$entry" >> $conf || Die "Cannot modify $conf"
	else
	    return 1
	fi
    fi
}

AptAdd ()
{
    pkg="$1"
    deb="$2"
    shift 2

    CheckPkg $pkg && return

    EchoLines "$@"
    AptList "$deb"    || return 0

    AptQueueToInstall $pkg
}

KernelLatest ()
{
    #  2.4.27-2-386
    #  ^==== ^= ^==
    #  $1    $2 $3

    now=$(uname -r)
    type=$(echo $now | awk -F- '{ver=$1 "-" $2 "-"; gsub(ver,""); print}' )

    pkg=$(IsPkg linux-image regexp | sort | tail -1)

    [ ! "$pkg" ] && pkg=$(IsPkg kernel-image regexp | sort | tail -1)

    #  Search latest kernel with higher class
    [ "$type" = "386" ] && type="686"

    #  UNUSED: The apt's regexp insn't powerful enough to restrict the
    #  items only to kernels.
    #  egrep "^(kernel|linux)-image.*$type "

    apt-cache search "^(linux|kernel)-image-[0-9.]+-[0-9]+-$type\$" |
	sort | tail -1 | awk '{print $1}'
}

SymlinkPointer ()
{
    ls -l $1 | awk '/->/ {print $(NF)}'
}

SymlinkMakeLatest ()
{
    ls="$1"
    file="$2"
    tmp=$(ls $ls | tail -1)  # Latest
    doit="symlink"

    if [ -f $file ]; then
	lnk=$(SymlinkPointer $file)

	if [ "$tmp" = "$lnk" ]; then
	    Echo "Good, nothing to do $file points to latest $tmp"
	    doit=""
	else
	    Run rm $file
	fi
    fi

    if [ "$doit" ]; then
	Run ln -sfv $tmp $file
    fi
}

InstallPackage ()
{
    pkg="$1"
    shift

    CheckPkg $pkg && return 1

    EchoLines "$@"
    AptQueueToInstall $pkg
}

InstallPackageUnstable ()
{
    pkg="$1"
    shift

    CheckPkg $pkg && return 1

    EchoLines "$@"
    AptQueueToInstall $pkg "install $pkg"  unstable
}

InstallPkgList ()
{
    for tmp in "$@"
    do
	if ! IsPkg "$tmp"; then
	    AptQueueAdd "$tmp"
	fi
    done
}

InstallPurge ()
{
    if IsPkg stem-pkg-clean || IsPkg stem-desktop-base ; then
	Echo "Not an initial install. Skipping install of stem-pkg-clean"
	return 0
    fi

    EchoLines \
      "Even the Base Debian install is big and fat, it can be slimmed." \
      "Packages like compilers, code development tools, code tracing" \
      "utilities etc. are not usually needed by average user." \
      "These can be purged from system so that future updates" \
      "will download faster. In addition the exim MTA will be removed to" \
      "make room for much smaller and lighter MTA (nullmailer)." \
      "You should consider running this cleaner ONLY IF this is" \
      "initial Stem Desktop installation"

    pkg="stem-pkg-clean"

    if IsOpt purge ||
	YN "Read the above carefully. May I clean unneeded packages"
    then

	AptUpdateNow

	if ! apt-get install $pkg ; then
	    Die "Can't install cleaner. Install aborted."
	fi

	apt-get install $pkg
	/usr/lib/$pkg/clean.sh --force --yes -y &&
	apt-get --yes -y remove  $pkg
    else
	Echo "Ok, not using package: $pkg"
    fi
}

InstallKernel ()
{
    pkg=$(KernelLatest)

    if [ ! "$pkg" ]; then
	Warn "Hm, coudn't determine kernel upgrade package. Update manually."
	return
    fi

    echo ".. Checking if kernel is up to date"

    if InstallPackage "$pkg" \
	"Kernel is the heart of the whole Operating System." \
	"There seems to be newer kernel available. Upgrading it may not" \
	"necessarily be easy (from 2.4 => 2.6), because many things may" \
	"have changed. It is recommended that you upgrade ONLY IF you" \
	"have prior Linux experience to sort out probelems that may" \
	"arise."
    then
	Echo "You NEED to reboot real soon after kernel upgrade"
	FLAG_KERNEL="kernel-upgrade"  # Set global

	#  New kernels need separate mouse driver
	InstallPkgList udev

	# /etc/modules may also need these: usbmouse mousedev

	EchoLines "New kernels handle mouse differently" \
	  "In order to use mouse under X, additional modules are most likely" \
	  "needed to be included in /etc/modules"

	if YN "Add usbmouse, mousedev" ; then
	    AddToFileMaybe /etc/modules usbmouse mousedev
	fi
    fi
}

InstallXserverStandard ()
{
    if IsPkg xserver-xfree86 || IsPkg xserver-xorg ; then
	Echo "Ok, standard X server has already been installed."
    fi

    tmp=$(PkgXserverName)

    InstallPkgList "$tmp $PKG_LST_X_FONTS"

    if IsPkg kdm || IsPkg gdm || IsPkg xdm ; then
	Echo "Ok, Found some graphical login manager (xdm, kdm or gdm)"
    else
	AptQueueAdd "xdm"
    fi
}

InstallXserverXvesa ()
{
    xvesa="stem-pkg-xserver-xvesa"
    pkg="$xvesa stem-pkg-xscreensaver-mode-one"
    xvesaok=

    if IsPkg $xvesa ; then
	Echo "Ok, $xvesa already installed (light X server)"
	xvesaok="xvesaok"
    else
	EchoLines "X server is responsible for handling video card signal" \
	  "Standard server consumes lot of memory. A lighter " \
	  "Xvesa suite uses 30-50% less memory"

	if IsXinstalled ; then
	    Echo "[!] It seems that standard X is already installed."

	    if IsOpt xvesa ||
	       AptQueueToInstall "$pkg" "Install lighter Xvesa too"
	    then
		AptQueueAdd "stem-pkg-xdm"
	    fi
	else
	    if IsOpt xvesa ||
	       AptQueueToInstall "$pkg" "Install light Xvesa"
	    then
		AptQueueAdd "stem-pkg-xdm"
	    else
		name=$(PkgXserverName)
		AptQueueAdd "$name"
	    fi
	fi
    fi
}

InstallMTA ()
{
    pkg="nullmailer"

    if IsPkg nullmailer ; then
	Echo "Ok, nullmailer has already been installed (mail delivery agent)"
	return
    fi

    tmp=

    for tmp in exim4 exim postfix mail-transport-agent ssmtp;
    do
	if IsPkg $tmp ; then
	    Echo "Hm, this system already includes mail system ($tmp)."
	    Echo "Skipping Mail server install"
	    return
	fi
    done

    InstallPackage "nullmailer" \
	"Mail Transport agent (MTA) is responsible for mail delivery" \
	"It is essential in order to send mail. Nullmailer is easy to" \
	"configure and it can cache mail if destination host is temporarily" \
	"unavailable. It is much more smaller than exim or postfix and ideal" \
	"for low end hardware. This system does not" \
	"currenly have recognized MTA and cannot send mail." \
	|| :
}

InstallExternalPackages ()
{
    IsOpt batch && return

    YN "See install options for 3rd party (opera, acroread etc.)" || return

    if AptAdd "opera" \
	"deb http://deb.opera.com/opera unstable non-free" \
	"Opera browser is available from deb.opera.com" \
	"It uses 30-50% less memory than Firefox, but is bigger." \
	"(about 7 Meg) and needs Qt libraries."
    then
	FLAG_APT_GET_UPDATE=""
	InstallPackageUnstable "opera-plugin-macromedia-flash-player" \
	    "Flash plugin for Opera enhances viewing web page animations" || :
    fi

    if AptAdd "acroread" \
      "deb ftp://ftp.nerim.net/debian-marillat unstable main" \
      "Adobe's acroread is available from 'marillat'" \
      "It is big and slow to start, but more capable than Open Source xpdf"
    then
      FLAG_APT_GET_UPDATE=""
    fi
}

InstallMemoryPackages ()
{
    if IsOpt memory ; then

	Echo "Selecting all packages which reduce memory consumption."

	AptQueueRemove nullmailer

	AptQueueAdd \
	    stem-pkg-xserver-xvesa \
	    stem-pkg-xserver-disable-ssh-agent \
	    stem-pkg-xscreensaver-mode-one \
	    ssmtp \
	    stem-pkg-mksh \
	    stem-pkg-inittab-vt-minimal \
	    stem-pkg-dash

	return
    fi

    YN "See install options for memory reduction (Xvesa, VTs etc.)" ||
    return

#    InstallXserverXvesa

#    InstallPackage "jwm" \
#	"A very small window manager (WM) can be installed" || :

    if InstallPackage "ssmtp" \
	"Ssmtp is very small mail forwarding delivery program." \
	"Every Mail server will consume memory, even the small nullmailer." \
	"A simple way of getting mail off a system is to use program that" \
	"can forward all mail to the remote smarthost (ISP etc.)"
    then
	AptQueueRemove nullmailer
    fi

    #  "busybox sh"  would also provide small shell, but then the cp(1) and
    #  other commands would not be real ones.

    InstallPackage "stem-pkg-mksh" \
      "Bash is the standard shell for working on command line." \
      "However, for each opened terminal the memory consumption of bash" \
      "is quite considerable. It is possibe to use more lighter alternative" \
      "For interactive use. The 'mksh' containst 90% of bash features" \
      "but uses considerably less memory." || :

    InstallPackage "stem-pkg-inittab-vt-minimal" \
      "It is possible to save memory by reducing virtual terminals (VTs)" || :

    InstallPackage "stem-pkg-xserver-disable-ssh-agent" \
      "Disabling ssh-agent during X startup saves memory" || :

    InstallPackage "stem-pkg-dash" \
      "Boot times are faster with sh => /bin/dash instead of /bin/bash" \
      "Downside: future non-sh compliant package installs MAY break" \
      "(unlikely). Brightside: you can always uninstall the package" || :
}

InstallInetd ()
{
    #  Under testing, things have changed. Need to install inetd separately

    if ExistsPkg "openbsd-inetd" ; then
	AptQueueAdd openbsd-inetd
	return
    fi

    if ExistsPkg "netkit-inetd" ; then
	AptQueueAdd netkit-inetd
    fi
}

InstallStemPackages ()
{
    if IsPkgFirewall ; then
	Echo "Ok, firewall already installed (not installing stem-pkg-firehol)"
    else
	InstallPackage "stem-pkg-firehol" \
	    "Firehol is a small, simple and easily configured Firewall" || :
    fi

    if IsPkg "httpd" ; then
	Echo "Ok, httpd already installed (not installing stem-pkg-bozohttpd)"
    else
	if InstallPackage "stem-pkg-bozohttpd" \
	    "To share files from ~/public_html a very small web server can be used"
	then
	    InstallInetd
	fi
    fi

    InstallPackage "stem-pkg-dropbear" \
      "To allow remote administration, small SSH server can be used" || :
}

InstallOffice ()
{
    if IsOpt batch ; then
	IsOpt office || return
    fi

    if IsOpt office ; then
	AptQueueAdd openoffice.org openclipart-openoffice.org
	return
    fi

    if InstallPackage "openoffice.org" \
      "There is standard OpenOffice (huge download; demands lot of memory)"
    then
      InstallPackage "openclipart-openoffice.org" || :
    fi
}

InstallConfigType ()
{
    if IsOpt heavy ; then
	InstallPackage "gaim" \
	    "A better Instant messanger client can be installed" || :

	InstallPackage "gimp" \
	    "A better Image manipulation program can be installed" || :

	InstallPackage "xfe" \
	    "A better File manager can be installed" || :

	InstallPackage "xchat" \
	    "A better IRC client can be installed" || :
    fi
}

InstallMain ()
{
    flags="$1"
    shift

    list="$@"

    pkg="stem-desktop-installer-etch"

    if IsStable ; then
	apt-get $flags install $(Lines2List $PKG_LST_STABLE)
    else
	pkg="stem-desktop-installer"
    fi

    apt-get install $pkg $list ||
    Die "Please try again or report problem";
}

InstallUnstable ()
{
    flags="$1"
    shift
    pkg="$@"

    tmp="$UNSTABLE_LIST"

    if [ ! "$pkg" ]; then
	return
    fi

    Echo "Some packages are installed from unstable repository"

    apt-get -o Dir::Etc::sourcelist=$tmp update
    apt-get $flags -o Dir::Etc::sourcelist=$tmp install $pkg

    Echo "Extra install done. Restoring package list..."
    apt-get --quiet update
}

InstallRun ()
{
    InstallMain "--yes -y --force-yes" "$(cat $INSTALL_MAIN_FILE)" &&
    InstallUnstable "--yes -y --force-yes" "$(cat $INSTALL_UNSTABLE_FILE)"
}

ConfigureXdm ()
{
    if IsXrunning ; then
	FLAG_XDM="running"
	return
    fi

    if ! IsXinstalled ; then
	Warn "[ERROR] X server has not been installed? Report this."
	return 100
    fi

    Echo 1 "Stem desktop install is almost ready"

    status=0

    if YN "Start Graphical login manager now" ; then
	cmd="invoke-rc.d xdm start"
	$cmd
	status=$?

	if IsPs xdm ; then
	   FLAG_XDM="running"
	else
	   Warn "Hm, failed. $cmd (status $status)."
	   grep -n xdm /var/log/{messages,syslog,daemon} 2> /dev/null
	fi
    else
	   FLAG_XDM="manual"
    fi

    return $stat
}

ConfigureWm ()
{
    IsOpt memory || return

    #  Select jwm as default window manager to save memory

    update-alternatives --set x-window-manager /usr/bin/jwm
}

ConfigureXserver ()
{
    IsOpt memory || return

    #  Select Xvesa as default

    update-alternatives --set x-server \
	/usr/lib/stem-pkg-xserver-xvesa/Xvesa.stem
}

ConfigureUsers ()
{
    IsOpt memory || IsPkg stem-pkg-mksh || return

    bin=$SHELL_LITTLE_MEMORY

    [ -x $bin ] || return

    set -- $(PasswdUserLines)

    if [ $# -gt $SHELL_MAX_USERS ]; then
       Echo "[NOTE] Not configuring $bin to be default shell for users" \
	    "(too many found). In order to save memory, please change" \
	    "users' shells manually with commands:" \
	    "usermod -s $bin USER"
    fi

    for tmp in "$@"
    do
      user=$(echo $tmp | cut -d: -f1)
      if [ "$user" ]; then
	  cmd="usermod -s $bin $user"
	  echo ".. Changing $user's shell to $cmd to save memory"
	  $cmd
      fi
    done
}

ConfigureSsh ()
{
    if ! IsPkg stem-pkg-dropbear ; then
	return # Not installed
    fi

    if ! IsPs sshd ; then
       return # Not running
    fi

    EchoLines "Lightweight 'dropbear' needs OpenSSH server to be disabled." \
	"If you're connected through ssh to this host, this would probably kill" \
	"your current connection"

    if YN "Stop OpenSSH server now" ; then
	invoke-rc.d ssh stop
    else
	Echo "Hm, please run: invoke-rc.d ssh stop when you have the chance"
    fi
}

ConfigureKernel ()
{
    #  There ha been rush of package installs, so print message
    #  to notify that we're still under the installer.

    Echo 1 "Stem Desktop install - verifying boot symlinks"

    if IsOpt batch || YN "May I update vmlinuz links in /boot"
    then
    (
	cd /boot
	SymlinkMakeLatest "vmlinuz-*"    "vmlinuz"
	SymlinkMakeLatest "initrd.img-*" "initrd.img"
    )
    fi
}

Finish ()
{
    echo "
-----------------------------------------------------------------------
Stem Desktop install finished. See $DOC_LOCAL
-----------------------------------------------------------------------
"
}

CleanPackages ()
{
    list=$(deborphan)

    if [ "$list" ]; then
	Echo "Cleaning unneeded libraries"
	apt-get --yes remove  $list
    fi
}

CleanApt ()
{
    if YN "Free disk space by cleaning saved packages" ; then
	apt-get --yes clean
    fi
}

Prepare ()
{
    for file in $INSTALL_MAIN_FILE \
		$INSTALL_UNSTABLE_FILE \
		$LOGFILE
    do
	: > $file
    done
}

TheEnd ()
{
    if [ "$FLAG_XDM" = "running" ]; then
	Echo "Good, graphical login is already running (try Alt-F* keys)"
    elif [ "$FLAG_XDM" = "manual" ]; then
	echo "Start graphical login manually with: invoke-rc.d xdm start"
    fi

    if [ "$FLAG_KERNEL" ]; then
	ls /boot
	EchoLines "Hm, Kernel was upgraded. That's all good news" \
	  "but it is essential that you REBOOT as soon as possible." \
	  "Otherwise X server and mouse may not work correctly."
    fi

    Echo "NOTE: if you graphical login does not work try REBOOT."
    Echo "NOTE: or run this program again to see 'X server troubleshooting'"
    Echo "Done."
}

InitialChecks ()
{
    if ! IsNetwork ; then
	Die "Network connection is not up. Cannot install."
    fi

    Prepare    # files that will hold the installed packages
    BannerMain

    IsAptCD &&
	Warn "[WARNING] /etc/apt/sources.list contains CD ROM sources"

    IsDebian ||
	Warn "[WARNING] Standard Debian OS check failed. (Press C-c to exit install now!)"

    IsDiskSizeOk
}

CommandLine ()
{
    while [ $# -gt 0 ]
    do
      item="$1"

      if [ "$item" = "--help"  -o  "$item" = "-h" ]; then
	  shift
	  Help

      elif [ "$item" = "--trust" ]; then
	  shift
	  OPT_TRUST="trust"

      elif [ "$item" = "--batch" ]; then
	  shift
	  OPT_BATCH="batch"

      elif [ "$item" = "--oo" ]; then
	  shift
	  OPT_OFFICE="office"

      elif [ "$item" = "--memory" ]; then
	  shift
	  OPT_MEMORY="memory"

      elif [ "$item" = "--purge" -o  "$item" = "--clean" ]; then
	  shift
	  OPT_PURGE="purge"

      elif [ "$item" = "--type" ]; then

	  shift
	  OPT_TYPE="normal"

	  if [ "$1" = "small" ]; then
	      OPT_TYPE="small"
	      shift

	  elif [ "$1" = "tiny" ] || [ "$1" = "minimal" ] ; then
	      OPT_TYPE="minimal"
	      shift

	  elif [ "$1" = "heavy" ]; then
	      OPT_TYPE="heavy"
	      OPT_OFFICE="office"
	      shift
	  fi

      elif [ "$item" = "--xvesa" ]; then
	  shift
	  OPT_XVESA="xvesa"

      else
	  shift
	  Warn "[WARN] Unknown option: $item"
      fi

    done
}

Main ()
{
    CommandLine "$@"

    IsConfirm && InitialChecks
    IsOpt trust   || SelfCheck

    if IsConfirm && YN "Display X server trouble shooting information"; then
	MsgInfoX
    fi

    Echo "Stem Desktop repository is available from other site"
    AptList "deb $URLDEB stable main"   "" Yn || Die "Need it. Cannot continue"
    AptList "deb $URLDEB unstable main" "" Yn || Die "Need it. Cannot continue"

    InstallPurge
    InstallXserverStandard
    InstallMTA
    InstallOffice

    AptUnstableWrite

    InstallStemPackages
    InstallExternalPackages
    InstallMemoryPackages

    InstallConfigType

    AptUpdateMaybe

    # InstallKernel

    finish=

    if IsOpt batch || YN "[stem desktop] Start installation" ; then
	InstallRun
    fi

    # ConfigureKernel

    ConfigureSsh
    ConfigureXdm
    ConfigureWm
    ConfigureXserver
    ConfigureUsers

    CleanPackages

    if [ "$finish" ]; then
	CleanApt
	Finish
    fi

    TheEnd
}

# To read this file as library only:
#
#    $  test=1 . netinstall.sh
#    $  ... call functions to test them.

[ ! "$test" ] && Main "$@"

# End of file

