#! /bin/bash
#
# install script for a suse-based user mode linux system
# (c) 2003,04 Gerd Knorr <kraxel@suse.de>
#

###########################################################################
# default settings

# where to install
ROOT_FILE="./root.img"
ROOT_SIZE="512"
ROOT_FS="ext2"
SWAP_FILE="./swap.img"
SWAP_SIZE="256"

# install source
MEDIA="${UML_MEDIA-/media/dvd}"
SELECTIONS="${UML_SELECTIONS-Minimal+X11}"
EXTRA_RPMS="${UML_EXTRA_RPMS-kernel-um}"

# system setup
HOSTNAME="linux-uml.local"
COPY_ETC="${UML_COPY_ETC}"
SERVICES="${UML_SERVICES-network syslog sshd portmap}"

# tmp dir for my files
WORK="${TMPDIR-/tmp}/umlinst-$$"
mkdir "$WORK" || exit 1
trap 'rm -rf "$WORK"' EXIT

# create tmp mount point
DEST="$WORK/mnt"
mkdir -p "$DEST"

# misc
CMDS="$WORK/y2pmsh"
MODS=""

###########################################################################
# various helper functions

function progress() {
	local msg="$*"
	echo
	echo "### -> $msg <-" >&2
}

# fetch files if needed
function getfile() {
	local filename=$1 outfile

	case "$filename" in
		[Hh][Tt][Tt][Pp]://* | [Ff][Tt][Pp]://*)
			outfile="$WORK/`basename $filename`"
			if test ! -f "$outfile"; then
				echo "fetching $filename" >&2
				wget -q -O $outfile $filename
			fi
			echo $outfile
			;;
		*)
			echo $filename
			;;
	esac
}

# build y2pmsh script
function y2pmsh_base_init() {
cat <<-EOF > "$CMDS"
	set verbose 0
	set quitonfail true
	set cachetodisk false
	set autosource false
	set root $DEST
EOF
}

function y2pmsh_media_init() {
	local orderfile order desc path

	# http://www.suse.de/~nashif/autoinstall/multiplesource.html
	orderfile=`getfile $MEDIA/yast/order`
	if test -s "$orderfile"; then
		egrep -v '^(#|$)' "$orderfile" \
		  | while read desc path; do
			echo "source -a ${MEDIA}${path}" >> "$CMDS"
		done
	else
		echo "source -a $MEDIA" >> "$CMDS"
	fi
	echo "source -s" >> "$CMDS"
}

function y2pmsh_selections() {
	local sel

	for sel in $SELECTIONS; do
		echo "selinstall $sel" >> "$CMDS"
	done
	echo "selsolve" >> "$CMDS"
}

function y2pmsh_packages() {
	local pkg

	for pkg in $EXTRA_RPMS; do
		case $pkg in
			-*)	pkg=${pkg#-};
				echo "remove $pkg"  >> "$CMDS"
				;;
			*)	echo "install $pkg" >> "$CMDS"
				;;
		esac
	done
	echo "solve" >> "$CMDS"
}

function y2pmsh_install() {
	echo "commit" >> "$CMDS"
}

function y2pmsh_list_selections() {
	echo "selstate" >> "$CMDS"
}


###########################################################################
# system configuration

function setup_uml() {
	local minor service

	progress "setup: user-mode-linux tweaks"

	# create fstab
	cat <<-EOF > $DEST/etc/fstab
	/dev/ubd0	/	$ROOT_FS	defaults	1 1
	/dev/ubd1	swap	swap		pri=42		0 0

	proc		/proc	proc		defaults	0 0
	sysfs		/sysfs	sysfs		noauto		0 0
EOF

	# create block devices
	for minor in `seq 0 7`; do
		mknod $DEST/dev/ubd$minor b 98 $(( $minor * 16 ))
	done

	# fixup /etc/inittab
	sed	-e 's|^\([3-9]:\)|#\1|'					\
		-e '/^1:/ic:2345:respawn:/sbin/agetty 9600 console'	\
		< $DEST/etc/inittab > /tmp/x$$
	mv /tmp/x$$ $DEST/etc/inittab
	echo "console" >> $DEST/etc/securetty
}

function setup_uml_kernel() {
	local kver;

	progress "setup: user-mode-linux kernel"

	kver=$(ls $DEST/boot/linux-* | sed -e 's|.*/linux-||' | head -1)
	echo "### $kver"
	chroot $DEST /sbin/mkinitrd -m "$MODS"	\
		-k /boot/linux-${kver}		\
		-i /boot/initrd-${kver}
	cp -v $DEST/boot/*-${kver} .
}

function setup_services() {
	local sboot

	progress "setup: services"

	sboot=$(find $DEST/etc/init.d -name boot.* -type f \
		| sed -e "s|$DEST/etc/init.d/||")
	echo -n " +boot.*" >&2
	chroot $DEST insserv -d -f $sboot

	for service in $SERVICES; do
		test -f $DEST/etc/init.d/$service || continue
		echo -n " +$service" >&2
		chroot $DEST insserv $service
	done
	for service in hwscan kbd; do
		test -f $DEST/etc/init.d/$service || continue
		echo -n " -$service" >&2
		chroot $DEST insserv -r $service
	done
	echo "" >&2
}

###########################################################################
# parse cmd line args, sanity checks

function usage() {
cat <<EOF

This is a installer for a user mode linux system based on SuSE Linux.
Requires SuSE version 9.1 or newer.

usage: `basename $0` [ options ]

get help:
    --help               print this text
    --list-selections    list available selections

install target:
    --root-file <file>   file for root filesystem     [$ROOT_FILE]
    --root-size <size>   rootfs size in megabytes     [$ROOT_SIZE]
    --root-fs <type>     rootfs type                  [$ROOT_FS]
    --swap-file <file>   swapfile                     [$SWAP_FILE]
    --swap-size <size>   swapfile size                [$SWAP_SIZE]
    --dest <dir>         mount point for the loop-mounted
                         root filesystem image        [$DEST]

package selection:
    --media <dir>        where to install from        [$MEDIA]
    --selections <list>  which selections to install  [$SELECTIONS]
    --extra-rpms <list>  which extra rpms to install  [$EXTRA_RPMS]

system configuration:
    --hostname <name>    set hostname                 [$HOSTNAME]
    --copy-etc <dir>     copy config files from <dir> into the
			 /etc directory               [$COPY_ETC]
    --services <list>    enable services
                         [$SERVICES]

The environment variables UML_MEDIA, UML_LANGUAGES, UML_SELECTIONS,
UML_EXTRA_RPMS, UML_COPY_ETC and UML_SERVICES are used as defaults
for the package selection and sysconfig options.

EOF
}

done=0
while test "$done" = "0"; do
	case "$1" in
		-h | -help | --help)	usage; exit 0;;
		--list-selections)	LIST=1; shift;;

		--root-file)		ROOT_FILE="$2";	shift; shift;;
		--root-size)		ROOT_SIZE="$2";	shift; shift;;
		--root-fs)		ROOT_FS="$2";	shift; shift;;
		--swap-file)		SWAP_FILE="$2";	shift; shift;;
		--swap-size)		SWAP_SIZE="$2";	shift; shift;;
		--dest)			DEST="$2";	shift; shift;;

		--media)		MEDIA="$2";	shift; shift;;
		--selections)		SELECTIONS="$2"; shift; shift;;
		--extra-rpms)		EXTRA_RPMS="$2"; shift; shift;;

		--hostname)		HOSTNAME="$2";	shift; shift;;
		--copy-etc)		COPY_ETC="$2";	shift; shift;;
		--services)		SERVICES="$2";	shift; shift;;

		"")	done=1;;
		*)	echo "unknown arg $1, try --help"; exit 1;;
	esac
done

CONTENT=`getfile $MEDIA/content`
if test ! -f "$CONTENT"; then
	echo "$MEDIA is not a valid install medium"
	exit 1
fi
if test ! -x "`which y2pmsh 2>/dev/null`"; then
	echo "y2pmsh seems not to be installed, I need that."
	echo "please run 'yast2 -i y2pmsh'"
	exit 1
fi

if test "$LIST" = 1; then
	y2pmsh_base_init
	y2pmsh_media_init
	y2pmsh_list_selections
	y2pmsh < "$CMDS"
	echo "FIXME: list selections not working yet with y2pmsh"
	exit 0
fi

if test "$DEST" = "/" -o ! -d "$DEST"; then
	echo "$DEST is no usable mount point"
	exit 1
fi
if test "`id -u`" != "0"; then
	echo "need root priviliges, sorry"
	exit 1
fi
progress "installing system from $MEDIA"


###########################################################################
# install the system

set -e

# swap file/device
progress "setup $SWAP_FILE"
if test ! -e "$SWAP_FILE"; then
	dd if=/dev/zero of="$SWAP_FILE" bs=$((1024 * 1024)) count=$SWAP_SIZE
fi
mkswap $SWAP_FILE

# root file/device
progress "setup $ROOT_FILE"
if test ! -e "$ROOT_FILE"; then
	dd if=/dev/zero of="$ROOT_FILE" bs=$((1024 * 1024)) count=$ROOT_SIZE
fi
case "$ROOT_FS" in
	ext2)
		mkfs.ext2 -q -b 4096 -F $ROOT_FILE
		;;
	ext3)
		mkfs.ext2 -j -q -b 4096 -F $ROOT_FILE
		MODS="$MODS ext3"
		;;
	reiserfs)
		mkreiserfs --block-size 4096 -f -f $ROOT_FILE
		MODS="$MODS reiserfs"
		;;
	xfs)
		mkfs.xfs -q -f $ROOT_FILE
		MODS="$MODS xfs"
		;;
	*)
		echo "unknown filesystem type: $ROOT_FS"
		exit 1
		;;
esac
if test -f "$ROOT_FILE"; then
	mount -t "$ROOT_FS" -o loop $ROOT_FILE $DEST
else
	mount -t "$ROOT_FS" $ROOT_FILE $DEST
fi
trap 'umount "$DEST"; rm -rf "$WORK"' EXIT

# go install ...
progress "install packages"
y2pmsh_base_init
y2pmsh_media_init
y2pmsh_selections
y2pmsh_packages
y2pmsh_install
#cat $CMDS; exit 1
y2pmsh < "$CMDS"

###########################################################################
# configure system

progress "configure system"
setup_uml;
setup_uml_kernel;
setup_services;

# copy some config files
progress "setup: /etc"
echo "$HOSTNAME" > $DEST/etc/HOSTNAME
if test "$COPY_ETC" != "" -a -d "$COPY_ETC"; then
	cp -av "$COPY_ETC"/* $DEST/etc/
fi

# SuSEconfig
#chroot $DEST /sbin/SuSEconfig

# show disk usage
progress "finished"
df $DEST
