#!/bin/bash
#
# linuxenv.bash - Set up basic environment under UML, then run script
#
# Written 2004 by Werner Almesberger
#
# Copyright (c) 2004 Koninklijke Philips Electronics N.V. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# 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
# version 2 for more details.
#

#
# Usage:
#
# . linuxenv.bash [UML arguments]
#
# Note that this script must be sourced and must be called linuxenv.bash !!!
# Also, this only works if the caller is also a bash script.
#
# The UML kernel must be in the PATH, with the name "linux". Likewise, this
# script must be in the PATH, with the name "linuxenv.bash".
#
# The script sourcing linuxenv.bash must have the following structure:
#
# #!/bin/sh
# <setup before entering UML>
# . linuxenv.bash ...
# <stuff to do in UML>
#
# WARNING: DO NOT USE THE WORD linuxenv.bash ANYWHERE ELSE IN THE FILE !
#
# After this script finishes, the environment will have the following state:
#
# - we're now running under UML
# - the host's file system is mounted read-write on /
# - a tmpfs is mounted on /tmp
# - our current directory has not changed
# - all variables defined before sourcing linuxenv.bash are available
#
# This script is known to work with UML kernels from uml-2.6.4-1 to
# uml-2.6.7-1. It may also work with older kernels. Due to changes in hostfs,
# it does not work with uml-2.6.7-2 and newer.
#

#
# This part runs on the host
#

rel="`uname -r`"
if [ "${rel%um}" = "$rel" ]; then
    __self=
    case "$0" in
	/*)	__self=$0;;
	*/*)	__self=`pwd`/$0;;
	*)	# crappy [t]csh and zsh don't fix $0 for us, so we have to
		# repeat the lookup manually.
		for n in `echo $PATH | tr : ' '`; do
		    if [ -x "$n/$0" ]; then
			if [ -z "${n#/*}" ]; then
			    __self=$n/$0
			else
			    __self=`pwd`/$n/$0
			fi
			break
		    fi
		done;;
    esac
    if [ -z "$__self" -o ! -x "$__self" ]; then
	echo "can't find myself ($0)" 1>&2
	exit 1
    fi
    __env_file=${TMPDIR:-/tmp}/.linuxenv.$$
    cat >$__env_file <<EOF
host_cwd=`pwd`
host_path=$PATH
EOF
    #
    # DCL deja-vu ...
    #
    declare |
      sed '/^\('"`readonly | sed '/^[^=]* \([^=]*=\).*/s//\1\\\\|/p;d' |
        tr -d '\012'`"'=\)/d' >>$__env_file
    export >>$__env_file

    exec linux rw \
      root=/dev/root rootflags=/ rootfstype=hostfs \
      HOST_ENV=$__env_file \
      init=`type -p linuxenv.bash` "$@"
fi

#
# This part runs in UML
#

. $HOST_ENV
rm -f $HOST_ENV
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t tmpfs tmpfs /tmp
cd $host_cwd
sed '/^#!/p;1,/\<linuxenv\.bash\>/d' <$__self >/tmp/host_script
chmod 755 /tmp/host_script
. /tmp/host_script
