#!/bin/sh

# copyright 2009 Vagrant Cascadian <vagrant@freegeek.org>,
# 2010 Alkis Georgopoulos <alkisg@gmail.com>, distributed under the
# terms of the GNU General Public License version 2 or any later version.

usage() {
cat <<EOF
$0 [OPTION] command
  -a, --arch                Architecture of the chroot.  Default is arch of the host.
  -b, --base                Base of ltsp chroot.  Default is /opt/ltsp if unspecified.
  -c, --mount-package-cache Mount package cache dir from server.
  -d, --mount-dev-pts       Mount /dev/pts from server.
  -h, --help                This message.
  -p, --mount-proc          Mount /proc from server.
  -r, --copy-resolv-conf    Copy /etc/resolv.conf from server.
EOF
}

die() {
    echo "$@" >&2
    exit 1
}

analyze_command_line() {
    local done_opts

    while [ -z "$done_opts" ] ; do
        case "$1" in
            -a|--arch) ARCH=$(echo $2 | sed -e "s,',,g") ; shift 2 ;;
            -b|--base) BASE=$(echo $2 | sed -e "s,',,g") ; shift 2 ;;
            -c|--mount-package-cache) MOUNT_PACKAGE_CACHE=true ; shift 1 ;;
            -d|--mount-dev-pts) MOUNT_DEV_PTS=true; shift 1 ;;
            -h|--help) usage ; exit 0 ;;
            -p|--mount-proc) MOUNT_PROC=true; shift 1 ;;
            -r|--copy-resolv-conf) COPY_RESOLV_CONF=true; shift 1 ;;
            --) shift ; done_opts=true ;;
            *) die "$0: Internal error!" ;;
        esac
    done
    COMMAND="$@"
}

default_options() {
    if [ -n "$ROOT" ]; then
        # If $ROOT contains a terminating /, remove it
        ROOT=${ROOT%/}
        # Extract $BASE and $ARCH from $ROOT in case they're needed afterwards
        BASE=${ROOT%/*}
        ARCH=${ROOT##*/}
    else
        BASE=${BASE:-/opt/ltsp}
        # If $BASE contains a terminating /, remove it
        BASE=${BASE%/}
        if [ -z "$ARCH" ]; then
            # Prefer the chroot that corresponds to the server arch,
            # but if that doesn't exist, use the first one available.
            if [ -x /usr/bin/dpkg ]; then
                ARCH=$(dpkg --print-architecture)
            # TODO: put other distro arch-detecting code here
            else
                ARCH=i386
            fi
            if [ ! -d "$BASE/$ARCH" ]; then
                for dir in "$BASE"/*/; do
                    # If it's not "images" and it's not "*" because of no subdirs
                    if [ -n "${dir##*/images/}" ] && [ -d "$dir" ]; then
                        # Keep only the subdir name
                        ARCH=${dir%/}
                        ARCH=${ARCH##*/}
                        break
                    fi
                done
            fi
        fi
        ROOT="$BASE/$ARCH"
    fi
}

pre_chroot() {
    test -d "$ROOT" || die "ERROR: ltsp chroot not found: $ROOT"
    if boolean_is_true "$MOUNT_PACKAGE_CACHE"; then
        if ! mount --bind /var/cache/apt/archives "$ROOT/var/cache/apt/archives"; then
            die "Could not mount $ROOT/var/cache/apt/archives"
        fi
    fi
    if boolean_is_true "$MOUNT_DEV_PTS"; then
        if ! mount -t devpts -o rw,noexec,nosuid,gid=5,mode=620 devpts "$ROOT/dev/pts"; then
            die "Could not mount $ROOT/dev/pts"
        fi
    fi
    if boolean_is_true "$MOUNT_PROC"; then
        if ! mount -t proc proc "$ROOT/proc"; then
            die "Could not mount $ROOT/proc"
        fi
    fi
    if boolean_is_true "$COPY_RESOLV_CONF"; then
        cp /etc/resolv.conf "$ROOT/etc/"
    fi
}

post_chroot() {
    # Stop trapping
    trap - 0 HUP INT QUIT KILL SEGV PIPE TERM
    if boolean_is_true "$MOUNT_PROC"; then
        # binfmt_misc might need to be unmounted manually, see LP #534211
        if grep -q "^binfmt_misc $ROOT/proc/sys/fs/binfmt_misc" $ROOT/proc/mounts; then
            umount "$ROOT/proc/sys/fs/binfmt_misc"
        fi
        umount "$ROOT/proc"
    fi
    if boolean_is_true "$MOUNT_DEV_PTS"; then
        umount "$ROOT/dev/pts"
    fi
    if boolean_is_true "$MOUNT_PACKAGE_CACHE"; then
        umount "$ROOT/var/cache/apt/archives"    
    fi
}

# Main

# Parse command line arguments
if ! ARGS=$(getopt -o +a:b:cdhpr -l 'arch:,base:,mount-package-cache,mount-dev-pts,help,mount-proc,copy-resolv-conf' -n $0 -- "$@"); then
    exit 1
fi

# Source the ltsp common functions, mainly for boolean_is_true
. /usr/share/ltsp/ltsp-common-functions

# First, include the configuration file, if it exists
if [ -f /etc/ltsp/ltsp-chroot.conf ]; then
    . /etc/ltsp/ltsp-chroot.conf
fi

# The command line parameters override the configuration file settings
analyze_command_line $ARGS

# Finally, fall back to using default values for any unset options
default_options

trap "post_chroot" 0 HUP INT QUIT KILL SEGV PIPE TERM
pre_chroot
eval LTSP_HANDLE_DAEMONS=false chroot "$ROOT" $COMMAND
