#!/bin/bash help() { echo "Usage: `basename $0` [-v] [-h] [-X] [-A] directory" ; echo echo "Used to chroot into a build environment created by build-env." ; echo "In addition to calling chroot, this command copies a few" ; echo "config files from the host machine into the chroot environment," ; echo "and makes sure /proc and /dev are properly mounted and unmounted" ; echo "in the chroot environment" ; echo echo "Options:" echo echo " -X Allow access to host's X server" echo " -A Allow access to host's ssh-agent server" echo " -v Verbose. Runs with set -xv" echo " -h Print this help" echo " - Unknown option is passed on to 'kill' as a signal." } SEMAPHORE=".use-env-count" enter () { if [ -e "$SEMAPHORE" ] ; then COUNT=$(cat $SEMAPHORE) COUNT=$((COUNT+1)) echo $COUNT >$SEMAPHORE INUSE=true else INUSE=false echo 1 >$SEMAPHORE fi $INUSE } leave () { if [ -e "$SEMAPHORE" ] ; then COUNT=$(cat $SEMAPHORE) COUNT=$((COUNT-1)) if [ "$COUNT" = "0" ] ; then rm $SEMAPHORE INUSE=false else echo $COUNT >$SEMAPHORE INUSE=true fi else echo $0: error, semaphore does not exist exit 1 fi $INUSE } show () { if [ -e $SEMAPHORE ] ; then COUNT=$(cat $SEMAPHORE) echo "SEMAPHORE=Just $COUNT" else echo SEMAPHORE=Nothing. fi } testSemaphore () { case "$1" in +) if enter ; then echo someone is already here ; else echo you are the only one here ; fi ; show ;; -) if leave ; then echo leaving someone behind ; else echo close the door on your way out; fi ; show ;; .) show ;; "") show ;; *) echo $0: unknown option $1 ; exit 1 ;; esac } # Copy a file or directory, but only if the src exists and the # destination does not # Note: if you specify a file as the first # argument, the second argument must also be a filename. maybe_cp () { if [[ -e "$1" && ! -e "$2" ]] ; then cp "$1" "$2" fi } # Kill all the process with current working directory $1 # written by dsf. kill_by_cwd () { SIG= if [ "$SIG" = "" ]; then SIG="-TERM"; fi if [ ! -e $1 ]; then exit 0; fi DIR="`readlink -f $1`" if [ ! "$DIR" ]; then exit 1; fi # Kill processes whose cwd begins with $DIR PIDS="" pushd /proc > /dev/null ls -1d [0-9]* | while read i; do if readlink /proc/$i/cwd | grep -q "^$DIR"; then ps uw $i if [ "$NODO" != "yes" ]; then kill $SIG $i; fi fi done popd > /dev/null } # Called when the chroot environment is exited cleanup() { echo Cleaning up.... # Disabled, because the semantics are not clear # with the new enter/leave semantics # Allow the user to do some cleanup while still in the chroot # with /proc and /dev mounted. if false ; then if [ -e $HOME/.build-env/use-env.post1 ] ; then . $HOME/.build-env/use-env.post1 fi fi # Kill any processes started in the chroot, so they don't hold # file handle open in /proc or /dev kill_by_cwd "$1" umount $1/sys umount $1/dev umount $1/proc for o in $OPTIONS ; do case $o in X11) echo "Disabling X access." ; umount $1/tmp/.X11-unix ;; SSH) echo "Disabling SSH agent access." ; umount $1$SSH_AUTH_SOCK_DIR ;; esac done # Disabled, because the semantics are not clear # with the new enter/leave semantics # Allow the user to do some cleanup after exiting the chroot # and umount /dev and /proc if false ; then if [ -e $HOME/.build-env/use-env.post2 ] ; then . $HOME/.build-env/use-env.post2 fi fi # Restore daemon tools. deneuter $1/sbin/start-stop-daemon deneuter $1/sbin/invoke-rc.d echo done. exit 0 } function neuter() { prog=$1 if [ -f $prog ] ; then mv $prog ${prog}.real (echo "#!/bin/bash"; echo "exit 0") > $prog chmod +x $prog fi } function deneuter() { prog=$1 if [ -f ${prog}.real ] ; then rm -f $prog mv $prog.real $prog fi } ### Main #### OPTIONS="" # Process options while [ "${1#-}" != "$1" ]; do case "$1" in -v) set -xv; shift;; -X) OPTIONS="X11 $OPTIONS"; shift;; -A) OPTIONS="SSH $OPTIONS"; shift;; -h) help ; exit 0 ;; *) echo "$0: Unexpected argument $1"; exit 1; ;; esac done # Make sure a directory was specified if [ -e "$1" ]; then ROOT="$1" CHROOT_CMD="chroot $*" else help ; exit 1; fi prepare () { # copy in things that we will probably want in the chroot environment # only copy if the destination file do not exist in case the user # wants to modify them. maybe_cp /etc/hosts $1/etc/hosts ; maybe_cp /etc/mailname $1/etc/mailname ; maybe_cp /etc/resolv.conf $1/etc/resolv.conf ; maybe_cp /etc/dupload.conf $1/etc/dupload.conf ; if [[ -d $HOME/.ssh && ! -d $1$HOME/.ssh ]] ; then cp -a $HOME/.ssh $1$HOME/ fi # things to copy everytime if [ -e ~/.Xauthority ] ; then cp ~/.Xauthority $1$HOME/ ; fi # Ask me no questions and I'll tell you no lies. export DEBIAN_FRONTEND="noninteractive" export PS1="[ue: `basename $1`] \w\\$ " export debian_chroot=`basename $1` mount -t proc none $1/proc if [[ `grep devfs /proc/filesystems` ]] ; then mount -t devfs none $1/dev fi mount -t sysfs sysfs $1/sys for o in $OPTIONS ; do case $o in X11) echo "Enabling X access." ; mkdir -p $1/tmp/.X11-unix ; mount --bind /tmp/.X11-unix $1/tmp/.X11-unix ;; SSH) echo "Enabling SSH agent access." ; SSH_AUTH_SOCK_DIR=`dirname $SSH_AUTH_SOCK` mkdir -p $1$SSH_AUTH_SOCK_DIR ; mount --bind $SSH_AUTH_SOCK_DIR $1$SSH_AUTH_SOCK_DIR ;; esac done neuter $1/sbin/start-stop-daemon neuter $1/sbin/invoke-rc.d # Disabled, because the semantics are not clear # with the new enter/leave semantics # run user script if false ; then if [ -e $HOME/.build-env/use-env.pre ] ; then . $HOME/.build-env/use-env.pre fi fi } if enter ; then echo I: Someone else is already here. Not preparing. 1>&2 else prepare $ROOT fi echo Entering chroot trap '(cleanup $1 $OPTIONS)' SIGHUP $CHROOT_CMD if leave ; then echo I: Not cleaning up. Someone is still here. 1>&2 else cleanup $ROOT $OPTIONS fi