--- /dev/null
+#! /usr/lib/util-vserver/sigexec /bin/bash
+
+# Copyright (C) 2004 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.
+
+## Usage: vshelper <xid> <action> <args>
+
+: ${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"
+
+function showHelp
+{
+ echo $"\
+Usage: vshelper <xid> <event> <args>*
+
+Report bugs to <$PACKAGE_BUGREPORT>."
+ exit 0
+}
+
+function showVersion
+{
+ echo $"\
+vshelper $PACKAGE_VERSION -- userspace reboot helper
+This program is part of $PACKAGE_STRING
+
+Copyright (C) 2004 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 doInternalMethod
+{
+ local method=$1
+ case "$method" in
+ (restart)
+ case "$ACTION" in
+ (restart)
+ logging $"Restarting vserver '$VSERVER'"
+ spawn killContext "$XID"
+ execute $_VSERVER --defaulttty "$VSERVER" restart
+ ;;
+ (halt|poweroff)
+ logging $"Stopping vserver '$VSERVER'"
+ spawn killContext "$XID"
+ execute $_VSERVER --defaulttty "$VSERVER" stop
+ ;;
+ (swsusp)
+ ## TODO: any senseful action here? Perhaps shutdown scheduler for it?
+ exit 0
+ ;;
+ (restart2) ;;
+ (*)
+ warning $"Unknown action '$ACTION' for vserver '$VSERVER'"
+ exit 1
+ esac
+ ;;
+
+ (async)
+ spawn killContext "$XID"
+ ;;
+
+ (sync)
+ local f=${METHOD_ARGS[0]}
+ test -n "$f" ||
+ panic $"Insufficent arguments for method '$method' and vserver '$VSERVER'"
+
+ test -p "$f" ||
+ panic $"File '$f' which is required for synchronisation of vserver '$VSERVER' is not a pipe"
+
+ spawn killContext "$XID"
+ echo "$ACTION" >"$f"
+ ;;
+
+ (*)
+ local script
+ findObject -x script "$__CONFDIR"/.defaults/apps/vshelper-methods/"$method" "$__PKGLIBDIR"/vshelper-methods/"$method" ''
+
+ test -n '$script' || {
+ warning $"No handler for internal method '$method' found"
+ exit 1
+ }
+
+ export VSERVER
+ execute "$script" "${ARGS[@]}"
+ esac
+}
+
+function doDefaultMethod
+{
+ local handler
+
+ vshelper.getHandler handler "$VSERVER" "$ACTION" || {
+ warning $"No handler configured for action '$ACTION' on vserver '$VSERVER'"
+ exit 1
+ }
+
+ case "$handler" in
+ (/*) execute "$handler" "${ARGS[@]}";;
+ (:*) doInternalMethod "${handler##:}" "$@";;
+ esac
+}
+
+#===========
+
+test "$1" != '--version' || showVersion
+test "$1" != '--help' || showHelp
+
+if ! tty -s; then
+ findObject -e _VS_LOGFILE "$__CONFDIR"/.defaults/apps/vshelper/logfile /dev/null
+ findObject -e _VS_ERRFILE "$__CONFDIR"/.defaults/apps/vshelper/logfile /dev/null
+
+ exec </dev/null
+ exec >>$_VS_LOGFILE
+ exec 2>>$_VS_ERRFILE
+fi
+
+logging "$(date): vshelper $*"
+
+test "$#" -ge 2 ||
+ panic $"vshelper called with missing arguments; try '--help' for more information"
+
+
+vshelper.isEnabled || exit 0
+! vshelper.isDebug || set -x
+
+set -eu
+
+if $_VSERVER_INFO - FEATURE vshelper0; then
+ declare -r XID=$1
+ declare -r ACTION=$2
+elif $_VSERVER_INFO - FEATURE vshelper; then
+ declare -r ACTION=$1
+ declare -r XID=$2
+else
+ panic $"vshelper functionality not supported by kernel"
+fi
+
+findObject -x delegate "$__CONFDIR"/.defaults/apps/vshelper-delegate/"$ACTION" "$__PKGLIBDIR"/vshelper-delegate/"$ACTION" ''
+test -e "$delegate" && exec -a "$ACTION" "$delegate" "$@"
+
+this_xid=$($_VSERVER_INFO - XID)
+pxid=
+responsible_xid=$XID
+while true; do
+ pxid=$($_VSERVER_INFO "$responsible_xid" PXID) || break
+ test "$pxid" -ne "$this_xid" || break
+ responsible_xid=$pxid
+done
+
+vserver_id=$($_VSERVER_INFO "$responsible_xid" ID) ||
+ panic $"No responsible vserver found for xid '$responsible_xid' ($XID); aborting..."
+
+test "$XID" = "$responsible_xid" || {
+ logging "Giving 'vshelper' task for '$XID' to parent vserver '$vserver_id' ($responsible_xid)"
+ execute $_VSERVER "$vserver_id" exec $_VSHELPER "$@"
+}
+
+#===========
+
+ARGS=( "$@" )
+
+declare -a state
+getFileArray state "$__VSHELPERSTATEDIR/$XID" && test ${#state[@]} -ge 2 || {
+ logging "'vshelper' not configured for xid '$XID'"
+ exit 0
+}
+
+declare -r VSERVER=${state[0]}
+
+cfg_xid=$($_VSERVER_INFO "${state[0]}" CONTEXT false) ||
+ panic $"Configured vserver '$VSERVER' does not seem to run; aborting..."
+
+test "$cfg_xid" = "$XID" ||
+ panic $"Configured ($cfg_xid) and actual ($XID) xid for vserver '$VSERVER' are mismatching; aborting..."
+
+cur_xid=$($_VSERVER_INFO "$VSERVER" CONTEXT false) ||
+ panic $"Vserver '$VSERVER' with '$XID' does not seem to run; strange..."
+
+test "$cur_xid" = "$XID" ||
+ panic $"Expected ($XID) and actual ($cur_xid) xid for vserver '$VSERVER' are mismatching; strange..."
+
+
+method=${state[1]}
+if test "${#state[@]}" -gt 2; then
+ unset state[0] state[1]
+ declare -ra METHOD_ARGS=( "${state[@]}" )
+else
+ declare -ra METHOD_ARGS=()
+fi
+
+case "$method" in
+ (default) doDefaultMethod "$@";;
+ (sync|async) doInternalMethod "$method" "$@";;
+ (*) panic $"Unknown method '$method' used by vserver '$VSERVER'";;
+esac