#!/bin/sh # (c) 2008 Quest Software, Inc. All rights reserved. # This file's licence text is at the bottom of the file. # By Ted Percival set -e # Where the virtual machine chroots are # Do not include the trailing slash VMDIR=/srv/vm PREFERRED_SHELL=/bin/bash FALLBACK_SHELL=/bin/sh die () { echo "$@" >&2 exit 1 } if [ $# -lt 1 ]; then echo "Usage: $0 " >&2 echo " or $0 -l to list available chroots" >&2 echo " or $0 -r to unmount the given chroot" >&2 echo " or $0 -m to mount the chroot directories but not " >&2 echo " actually execute a shell in the chroot" >&2 exit 1 fi # Mounts all known directories for the given chroot mount_dirs () { test -d "$VMDIR/$1" || die "mount_dirs: $VMDIR/$1 is not a directory" # Ensure the directory is slash-terminated, so if there are entries like # 4.0-etch and 4.0-etch-gtk, specifying the first will not match the second case "$1" in */);; *) set -- "$1/";; esac # Find all the mounts in fstab that belong to this chroot dirs=`grep -v '^#' < /etc/fstab | awk '{print $2}' | grep -- "^$VMDIR" | grep -- "$1"` for dir in $dirs; do sudo mount $dir >/dev/null 2>&1 || echo "WARNING: Failed to mount $dir, is it already mounted?" >&2 done } # Unmounts known directories for the given chroot # Pass a single chroot name (directory) unmount_dirs () { test -d "$VMDIR/$1" || die "unmount_dirs: $VMDIR/$1 is not a directory" # mtab does not list mounts that are the result of an rbind, so we use # /proc/mounts instead. Use a reverse sort to do depth-first unmount # so that the top level of an rbind will be unmounted last dirs=`awk '{print $2}' /proc/mounts | grep -- "^$VMDIR/$1" | sort -r` if [ -z "$dirs" ]; then return; fi sudo umount $dirs } list_chroots () { (cd "$VMDIR" && find -maxdepth 3 -name proc | sed -e 's,\./\(.*\)/proc$,\1,') } remove_chroots () { while [ $# -ge 1 ]; do unmount_dirs "$1" shift done } find_shell () { for shell in "$PREFERRED_SHELL" "$FALLBACK_SHELL"; do if [ -x "$VMDIR/$1/$shell" ]; then echo "$shell" return 0 fi done die "Could not find a suitable shell for $1" } # FIXME: This doesn't work. Maybe because of sudo. sanitise_environment () { if `which getent >/dev/null 2>&1`; then HOME=`getent passwd 0 | cut -d: -f6` else HOME=/root fi export HOME } # Executes a shell in the chroot. Never returns. # On error a message is printed and the command exits exec_chroot () { if [ `id -u` -eq 0 ]; then SUDO= else SUDO=sudo fi shell=`find_shell $1` sanitise_environment exec $SUDO chroot "$VMDIR/$1" $shell } case "$1" in -l) list_chroots exit 0 ;; -r) shift remove_chroots "$@" exit 0 ;; -m) shift mount_dirs "$1" exit 0 ;; *) mount_dirs "$1" exec_chroot "$1" # not reached ;; esac # # Licence # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # a. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # b. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # c. Neither the name of Quest Software, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #