#! /bin/bash
# $Id: vserver 2661 2008-01-13 18:26:41Z dhozac $

# Copyright (C) 2003,2004,2005 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
#  
# 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; version 2 of the License.
#  
# 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.
#  
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

# set -e

: ${UTIL_VSERVER_VARS:=/usr/lib/util-vserver/util-vserver-vars}
test -e "$UTIL_VSERVER_VARS" || {
    echo $"Can not find util-vserver installation (the file '$UTIL_VSERVER_VARS' would be expected); aborting..." >&2
    exit 1
}
. "$UTIL_VSERVER_VARS"
. "$_LIB_FUNCTIONS"

### Some local functions

function showHelp()
{
    echo \
$"Usage: $(basename $0) [-s|--sync] [-v|--verbose] [--silent] [--debug]
             [--] <vserver> <command> <args>*

<vserver> is the name of a vserver.

Possible commands are:
    start [--rescue [--rescue-init] <rescue-cmd> <args>*]]
                ... starts the specified vserver
    stop [--rescue-init]
                ... stops the specified vserver
    restart     ... restarts the specified vserver; this is the subsequent
                    execution of a synchronized 'stop' and a 'start'
    condrestart ... restarts the vserver when it is running already
    suexec <user> <command> <args*>
                ... executes a command as the specified user in the vserver
    exec <command> <args*>
                ... executes a command as root in the vserver
    enter       ... executes the configured shell in the vserver
    chkconfig <chkconfig-options*>
                ... modifies the init-system; currently, only Red Hat's
		    chkconfig is supported
    running     ... succeeds iff the vserver is running
    status      ... gives out some human readable status information about
                    the vserver, and succeeds iff the vserver is running

    build <buildopts>*
                ... builds a new vserver from scratch, see
                    vserver ... build --help for details
    delete      ... remove a vserver

    unify [-R] <vunify-opts>*
		... (de)unify the vserver with its reference vserver(s).
		
    pkg install <pkg>
		... installs package(s) in the vserver
		
    apt-get,apt-config,apt-cache <apt-opts>*
		... execute the apt-* command for the given vserver
    rpm <rpm-opts>*
		... execute the rpm command for the given vserver

    pkgmgmt externalize|internalize [-y]
		... externalize or internalize the package-management for the
		    given vserver. 'Externalize' means that package metadata
		    and management tools (apt-get,rpm) are living in the host,
		    while 'internalize' means that data and programs from the
		    vserver will be used.

    hashify
                ... hashify the guest.
		    

Please report bugs to $PACKAGE_BUGREPORT"
    exit 0
}

function showVersion()
{
    echo \
$"vserver $PACKAGE_VERSION -- manages the state of vservers
This program is part of $PACKAGE_STRING

Copyright (C) 2003,2004,2005 Enrico Scholz
This program is free software; you may redistribute it under the terms of
the GNU General Public License.  This program has absolutely no warranty."
    exit 0
}

function suexec()
{
    . $__PKGLIBDIR/vserver.suexec
}

function restart()
{
    "${SELF[@]}" --sync "$vserver" stop
    exec "${SELF[@]}" "$vserver" start
}

function msg()
{
    test -z "$OPTION_SILENT" || return 0
    echo "$@"
}

### main starts here

set +e

OPTIONS_ORIG=( "$@" )
tmp=$(getopt -o +sv --long nonamespace,--nonamespace,--insecure,defaulttty,help,debug,strace,debug-sysv,version,sync,verbose,silent -n "$0" -- "$@") || exit 1
eval set -- "$tmp"

OPTION_FORCE_SYNC=
OPTION_VERBOSE=
OPTION_SILENT=
OPTION_DEBUG=
OPTION_NONAMESPACE=
OPTION_INSECURE=
OPTION_DEFAULTTTY=
OPTION_STRACE=
OPTION_DEBUG_SYSV=

while true; do
    case "$1" in
	(--help)    	showHelp $0 ;;
	(--version) 	showVersion ;;
	(--debug)	OPTION_DEBUG=$1; set -x;;
	(-v|--verbose)	OPTION_VERBOSE=$1;;
	(-s|--sync) 	OPTION_FORCE_SYNC=$1;;
	(--silent) 	OPTION_SILENT=$1;;
	(----nonamespace)OPTION_NONAMESPACE=$1;;
	(--defaulttty)	OPTION_DEFAULTTTY=$1;;
	(----insecure)	OPTION_INSECURE=1;;
	(--strace)	OPTION_STRACE=1;;
	(--debug-sysv*)	OPTION_DEBUG_SYSV=$1;;
	(--)	   	shift; break;;
	(*)	   	echo $"vserver: internal error; arg=='$1'" >&2; exit 1;;
    esac
    shift
done

OPTION_ALL=( $OPTION_SILENT $OPTION_VERBOSE $OPTION_DEBUG $OPTION_DEFAULTTTY )
SELF=( "$0" "${OPTION_ALL[@]}" )

vserver=$1
cmd=$2

test "$cmd" != build || { shift 2; exec $_VNAMESPACE --new -- \
    "$_VSERVER_BUILD" $OPTION_DEBUG -n "$vserver" "$@"; }


allow_legacy=

case "$vserver" in
    (./*) VSERVER_DIR=`pwd`/$vserver;;
    (/*)  VSERVER_DIR=$vserver;;
    (*)	  VSERVER_DIR=$__CONFDIR/$vserver
	  allow_legacy=1
	  ;;
esac

if test -n "$allow_legacy"; then
    do_legacy=
    test ! -e "$VSERVER_DIR/legacy" || do_legacy=1
    test -d "$VSERVER_DIR" -o ! -e "$__CONFDIR/$vserver.conf" || do_legacy=1

    test -z "$do_legacy" || {
	echo $"WARNING: can not find configuration, assuming legacy method" >&2
	exec "$_VSERVER_LEGACY" "$@"
    }
fi

test -d "$VSERVER_DIR" || {
    echo $"\
Can not find a vserver-setup at '$VSERVER_DIR/'.

Possible solutions:
* fix the spelling of the '$vserver' vserver name
* read 'vserver $vserver build --help' about ways to create a new vserver
* see 'vserver --help' for the syntax of this command
"
    exit 5
} >&2

_setVserverName

# Create a new namespace when starting the guest
test "$cmd" != start -o -n "$OPTION_NONAMESPACE" || isAvoidNamespace "$VSERVER_DIR" || \
    exec $_VNAMESPACE --new -- $_VSERVER ----nonamespace "${OPTIONS_ORIG[@]}"

# Enter the namespace early so we can test for files inside the guest
test "$cmd" != enter -a "$cmd" != stop || \
    test -n "$OPTION_NONAMESPACE" || isAvoidNamespace "$VSERVER_DIR" || \
    ! isVserverRunning "$VSERVER_DIR" || \
    exec $_VNAMESPACE --enter "$VSERVER_DIR" -- $_VSERVER ----nonamespace "${OPTIONS_ORIG[@]}"

set_init_cwd
cd /

. $__PKGLIBDIR/vserver.functions
case "$2" in
    (start|stop|delete)
	shift 2
	. $__PKGLIBDIR/vserver.$cmd
	;;
    (suexec|restart)
	shift 2
	$cmd "$@"
	;;
    (condrestart)
	! isVserverRunning "$VSERVER_DIR" || restart
	;;
    (exec)
	shift 2
	suexec 0 "$@"
	;;
    (chkconfig)
	shift 2
	suexec 0 chkconfig "$@"
	;;
    (enter)
	useVlogin && \
	  OPTS_VCONTEXT_ENTER=( "${OPTS_VCONTEXT_ENTER[@]}" --vlogin )
	getEnterShell "$VSERVER_DIR"
	suexec 0 "${ENTER_SHELL[@]}"
	;;
    (running)
	isVserverRunning "$VSERVER_DIR"
	;;

    (unify)
	shift 2
	exec $_VUNIFY "$@" "$vserver"
	;;

    (hashify)
	shift 2
	exec $_VHASHIFY "$@" "$vserver"
	;;
		
    (pkg)
	shift 2
	exec $_VPKG "$vserver" "$@"
	;;

    (pkgmgmt)
	op=$3
	shift 3
	exec $_VNAMESPACE --new -- $_PKGMGMT ${op:+--$op} "$@" -- "$vserver"
	;;

    (apt-get|apt-config|apt-cache)
	export APT_GET=$2
	shift 2
	exec $_VAPT_GET "$VSERVER_DIR" -- "$@"
	;;

    (rpm)
	shift 2
	exec $_VRPM "$VSERVER_DIR" -- "$@"
	;;
	
    (status)
	if getVserverStatus "$VSERVER_DIR" ctx procnum; then
	    msg $"Vserver '$vserver' is running at context '$ctx'"

	    if test "$2" = status; then
		msg $"Number of processes: " $procnum
		msg $"Uptime:              "	$("$_FILETIME" "$VSERVER_DIR/run")
	    fi
	    exit 0
	else
	    msg $"Vserver '$vserver' is stopped"
	    exit 3
	fi
	;;
    (*)
	echo $"Usage: $0 <vserver> {start|stop|suexec|restart|condrestart|exec|enter|chkconfig|running|status|delete}" >&2
	exit 2
	;;
esac
