#!/bin/bash -e
# Copyright (c) 2009 Alon Swartz <alon@turnkeylinux.org> - all rights reserved

write_dummy_initctl() {
    fpath=$1

    cat>$fpath<<'EOF'
#!/bin/bash

set -e
set -u
${DEBIAN_SCRIPT_DEBUG:+ set -v -x}

. /lib/lsb/init-functions
ERR_LOGGER="logger -p daemon.err -t /etc/init.d/mysql -i"
MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf"

mysqld_get_param() {
        /usr/sbin/mysqld --print-defaults \
                | tr " " "\n" \
                | grep -- "--$1" \
                | tail -n 1 \
                | cut -d= -f2
}

mysqld_status () {
    ping_output=`$MYADMIN ping 2>&1`; ping_alive=$(( ! $? ))

    ps_alive=0
    pidfile=`mysqld_get_param pid-file`
    if [ -f "$pidfile" ] && ps `cat $pidfile` >/dev/null 2>&1; then ps_alive=1; fi

    if [ "$1" = "check_alive"  -a  $ping_alive = 1 ] ||
       [ "$1" = "check_dead"   -a  $ping_alive = 0  -a  $ps_alive = 0 ]; then
        return 0 # EXIT_SUCCESS
    else
        if [ "$2" = "warn" ]; then
            echo -e "$ps_alive processes alive and '$MYADMIN ping' resulted in\n$ping_output\n" | $ERR_LOGGER -p daemon.debug
        fi
        return 1 # EXIT_FAILURE
    fi
}

status_mysql()
{
    if mysqld_status check_alive nowarn; then
        pid=`ps -A |grep mysqld$ | cut -d " " -f 1`
        echo "mysql start/running, process $pid"
        return 0
    else
        echo "mysql stop/waiting"
        return 1
    fi
}

start_mysql()
{
    test -x /usr/sbin/mysqld || exit 0

    log_daemon_msg "Starting MySQL database server" "mysqld"
    if mysqld_status check_alive nowarn; then
       log_progress_msg "already running"
       log_end_msg 0
    else
        /usr/bin/mysqld_safe > /dev/null 2>&1 &
        # 6s was reported in #352070 to be too few when using ndbcluster
        for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14; do
            sleep 1
            if mysqld_status check_alive nowarn ; then break; fi
            log_progress_msg "."
        done
        if mysqld_status check_alive warn; then
            log_end_msg 0
            # Now start mysqlcheck or whatever the admin wants.
            output=$(/etc/mysql/debian-start)
            [ -n "$output" ] && log_action_msg "$output"
        else
            log_end_msg 1
            log_failure_msg "Please take a look at the syslog"
        fi
    fi
}

stop_mysql()
{
        # * As a passwordless mysqladmin (e.g. via ~/.my.cnf) must be possible
        # at least for cron, we can rely on it here, too. (although we have
        # to specify it explicit as e.g. sudo environments points to the normal
        # users home and not /root)
        log_daemon_msg "Stopping MySQL database server" "mysqld"
        if ! mysqld_status check_dead nowarn; then
          set +e
          shutdown_out=`$MYADMIN shutdown 2>&1`; r=$?
          set -e
          if [ "$r" -ne 0 ]; then
            log_end_msg 1
            [ "$VERBOSE" != "no" ] && log_failure_msg "Error: $shutdown_out"
            log_daemon_msg "Killing MySQL database server by signal" "mysqld"
            killall -15 mysqld
            server_down=
            for i in 1 2 3 4 5 6 7 8 9 10; do
              sleep 1
              if mysqld_status check_dead nowarn; then server_down=1; break; fi
            done
          if test -z "$server_down"; then killall -9 mysqld; fi
          fi
        fi
}

start()
{
    if [ "$1" == "mysql" ]; then
        start_mysql
    fi

}

stop()
{
    if [ "$1" == "mysql" ]; then
        stop_mysql
    fi
}

status()
{
    if [ "$1" == "mysql" ]; then
        status_mysql
    fi
}

op=$(basename $0)
service=$1

case "$op" in
    start)
        start $1
        ;;

    stop)
        stop $1
        ;;

    status)
        status $1
        ;;

    *)
        ;;
esac

exit
EOF
    chmod +x $fpath
}

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

usage() {
cat<<EOF
Syntax: $(basename $0) root-dir [ command ...]
Executes command chrooted inside root-dir.

Example usage:

    # this will execute an interactive shell inside turnkey-core.rootfs
    tklpatch-chroot turnkey-core.rootfs /bin/bash

Environment variables:

    TKLPATCH_DEBUG       Turn on debugging. Increases verbosity.
EOF
    exit 1
}
if [[ "$#" < "1" ]]; then
    usage
fi

[ "$(id -u)" != "0" ] && fatal "must be run as root"

[ -n "$TKLPATCH_DEBUG" ] && set -x

root=$1
shift 1;
command=$@

[ -d $root ] || fatal "no such directory: $root"
[ -n "$command" ] || command=/bin/bash


if [ ! "$root" == "/" ]; then
    initctl=/sbin/initctl
    if [ -f "$root/$initctl" ] && ! [ -f "$root/${initctl}.distrib" ]; then
        chroot $root dpkg-divert --local --rename --add $initctl
        write_dummy_initctl $root/$initctl
        traphook="rm $root/$initctl; chroot $root dpkg-divert --local --rename --remove $initctl;"
    fi

    if ! [ -f $root/etc/debian_chroot ]; then
        echo tklpatch > $root/etc/debian_chroot
        traphook="${traphook}rm -f $root/etc/debian_chroot;"
    fi

    resolvconf=$root/etc/resolv.conf
    if ! [ -f $resolvconf.bak ]; then
        mv $resolvconf $resolvconf.bak
        cp /etc/resolv.conf $resolvconf
        traphook="${traphook}[[ -f $resolvconf.bak || -h $resolvconf.bak ]] && mv $resolvconf.bak $resolvconf;"
    fi

    if ! [ -f $root/proc/mounts ]; then
        mount -t proc proc-chroot $root/proc
        mount -t devpts devpts-chroot $root/dev/pts

        traphook="${traphook}umount devpts-chroot && umount proc-chroot;"
    fi
    
    if [ -n "$traphook" ]; then
        trap "$traphook" INT TERM EXIT
    fi
fi

echo "# chroot execute: $command" 1>&2
bin=$(which chroot)
$bin $root env -i \
    TERM=$TERM \
    HOME=/root \
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/bin:/usr/sbin \
    DEBIAN_FRONTEND=noninteractive \
    /bin/sh -c "$command"

