#!/bin/sh

# boot-halt-uml.sh v0.4
# description: a script to start and stop a user-mode linux machine \
# for a single user at host system boot, and host system reboot/shutdown
# written by Gregory Nowak <http://www.romuald.net.eu.org>
# Copyright (C) 2009 by Gregory Nowak

# This script 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 3 of the License, or
# (at your option) any later version.

# This script 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 at <http://www.gnu.org/licenses/gpl.html>


# we assume that all paths and program names are correct,
# and that all programs/scripts are executable
# please verify that this is the case before using this script
# yes, this script could use further improvement

# I tested this script on
# Debian Lenny, Fedora 9, and have found it works for me as intended
# your mileage however may very

# this script should be run very late in the boot process,
# and it should be run very early in the reboot/shutdown process

# note that in order for the stop functionality to work correctly,
# you will need to configure the guest system running inside the uml machine
# to halt when ctrl+alt+del is pressed, rather than rebooting it
# this could be changed on most systems by editing /etc/inittab
# also see the SHOULD_SLEEP option in the configuration section below

# also note that if the uml machine is stopped by the user,
# and restarted with a different umid, this script will not be able
# to stop that machine

# set the following variables as appropriate
U_USER="greg" # name/uid of user running the uml machine
U_DIR="/uml" # absolute path to the directory containing the uml's files
U_SCRIPT="./startuml" # the script used to start the uml machine,
U_UMID="uml" # the uml machine's umid
HOME="/home/greg" # the home directory of the user running the uml
PID_DIR="/tmp/uml/uml" # the directory of the uml machine's pid
# it is recommended that the uml's socket and pid
# be placed in /tmp, which should be mounted on /dev/shm
# (I.E. on the kernel's command-line in the start script, put "uml_dir=/tmp/uml",
# which would place the socket and pid for a machine named myuml into /tmp/uml/myuml)
# that way, if the host crashes, you won't
# be left with an invalid pid file at boot

SCREEN_PROG="/usr/bin/screen" # path to screen(1)
UML_MCONSOLE_PROG="/usr/bin/uml_mconsole" # path to the uml_mconsole program
SUDO_PROG="/usr/bin/sudo" # path to sudo(8)
SLEEP_PROG="/bin/sleep" # path to sleep(1)

# if you are really, really sure that the guest inside the uml
# is configured to shutdown when ctrl+alt+del is pressed,
# you can set the below option to "no"
# if you aren't sure what to do here, leave the default of "yes",
# you have been warned!

SHOULD_SLEEP="yes"
# end of variables section

case "$1" in
  start)
# we check if a uml is already running
# if there's no pid file, there's no uml
# if there is a pid file, then there's an already running uml

if [ ! -r $PID_DIR/pid ] ; then
# we start the uml, there's no pid
echo "starting" $U_UMID "for" $U_USER
cd $U_DIR
$SUDO_PROG -u $U_USER $SCREEN_PROG -d -m -S $U_UMID $U_SCRIPT
echo

else
echo $0: $U_USER "is already running a uml machine, another one will not be started"
exit 1
fi
;;

stop)
echo "stopping" $U_UMID "for" $U_USER
# we cd twice, so as to avoid configuring more variables above
cd $PID_DIR >/dev/null 2>&1
cd .. >/dev/null 2>&1
$SUDO_PROG -u $U_USER $UML_MCONSOLE_PROG $U_UMID cad >/dev/null 2>&1
# if SHOULD_SLEEP is set to no, we exit this script
# only after the uml's pid is removed, which means the uml halted
# if SHOULD_SLEEP is set to yes, we sleep for 20 seconds,
# which should be long enough for the uml to halt
# if SHOULD_SLEEP is set to no, and the uml is configured to
# reboot when ctrl+alt+del is pressed, this script will hang waiting for the uml to halt
# which will never happen
if [ "$SHOULD_SLEEP" = "no" ] ; then
while [ -r $PID_DIR/pid ] ; do
$SLEEP_PROG 1;
done
else
$SLEEP_PROG 20
fi
echo

;;

*)
echo $0: "Invalid parameter" $1", please look at the script for documentation and help."

esac

# we could have also implemented a restart/reload option,
# but there should really be no need for a host admin
# to restart users' uml machines

