#!/bin/sh

# apt-dater - terminal-based remote package update manager
#
# Authors:
#   Thomas Liske <liske@ibh.de>
#
# Copyright Holder:
#   2009-2014 (C) IBH IT-Service GmbH [https://www.ibh.de/apt-dater/]
#
# License:
#   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; either version 2 of the License, or
#   (at your option) any later version.
#
#   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 package; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#

run_hist_cmd () {
    echo -n > "$AD_HIST_PATH/command"
    for i in "$@"; do
	echo -n "\"$i\" " >> "$AD_HIST_PATH/command"
    done

    chmod +x "$AD_HIST_PATH/command"
    script -c "$AD_HIST_PATH/command" -t "$AD_HIST_PATH/typescript" 2> "$AD_HIST_PATH/timingfile"

    echo -n "Duration=" >> "$AD_HIST_PATH/meta"
    cat "$AD_HIST_PATH/timingfile" | cut '-d ' -f1 | awk '{ s += $1 } END { print s }' >> "$AD_HIST_PATH/meta"

    if (grep -aiqsPe "$AD_HIST_ERRPATTERN" "$AD_HIST_PATH/typescript"); then
	echo "ERRPATTERN=$AD_HIST_ERRPATTERN" >> "$AD_HIST_PATH/meta"
	touch "$AD_HIST_PATH/failed"
    fi
}

run_cmd () {
    $@
}

run_hook () {
    if [ -n "$1" -a -d "$1" ]; then
	run-parts "$1"
    fi
}

if [ -x /usr/bin/lockfile-create -a -x /usr/bin/lockfile-remove ]; then
    LOCK_ACQ=/usr/bin/lockfile-create
    LOCK_REL=/usr/bin/lockfile-remove
else
    if [ -x /usr/bin/lockfile ]; then
	LOCK_ACQ=/usr/bin/lockfile
	LOCK_REL="rm -f"
    fi
fi

lock_acq () {
    if [ -z "$LOCK_ACQ" ]; then
	echo
	echo "FATAL ERROR"
	echo "==========="
	echo
	echo "Your environment does not have lockfile(-create|-remove) available!"
	echo "You need to install lockfile-progs or procmail before using"
	echo "apt-dater-host clusters (see README.clusters)!"
	echo
	exit 1
    fi

    $LOCK_ACQ $1
}

lock_rel () {
    $LOCK_REL $1
}

lock_cluster () {
    if [ "$AD_CLUSTERS" != "0" ]; then
	echo
	echo Acquiring cluster locks:
	REL=""
	for i in `seq 1 $AD_CLUSTERS`; do
	    CLUSTER=`eval echo "\\\$AD_CLUSTER$i"`
	    echo " $CLUSTER"
	    LOCK_FILE="$AD_STATSDIR/_cluster_$CLUSTER"
	    lock_acq $LOCK_FILE
	    REL="echo ' $CLUSTER';lock_rel $LOCK_FILE;$REL"
	    trap "echo;echo Releasing cluster locks:;$REL echo .Done.;echo" INT TERM EXIT
	done
	echo "Done."
	echo
    fi
}

if [ "$AD_HIST_RECORD" = "true" -a "$AD_ACTION" != 'refresh' ]; then
    WRAP="run_hist_cmd"
else
    WRAP="run_cmd"
fi

handle_generic_ssh () {
    AD_CMD_REFRESH="apt-dater-host refresh"
    AD_CMD_UPGRADE="apt-dater-host upgrade"
    AD_CMD_INSTALL="apt-dater-host install %s"

    if [ -n "$AD_SSH_USER" ]; then
	my_ssh_user="-l $AD_SSH_USER";
    else
	my_ssh_user=""
    fi

    if [ -n "$AD_SSH_PORT" ]; then
	my_ssh_port="-p $AD_SSH_PORT";
    else
	my_ssh_port=""
    fi

    case "$AD_ACTION" in
	adsh)
	    run_hook "$AD_HOOK_PRE_CONNECT"
	    $WRAP $AD_SSH_CMD $@
	    run_hook "$AD_HOOK_POST_CONNECT"
	    ;;
	connect)
	    run_hook "$AD_HOOK_PRE_CONNECT"
	    $WRAP $AD_SSH_CMD $AD_SSH_ID $AD_SSH_OPTFLAGS $my_ssh_user $my_ssh_port "$AD_SSH_HOST"
	    run_hook "$AD_HOOK_POST_CONNECT"
	    ;;
	transfer)
	    if [ -n "$AD_SSH_USER" ]; then
		my_sftp_user="$AD_SSH_USER@";
	    else
		my_sftp_user=""
	    fi

	    if [ -n "$AD_SSH_PORT" ]; then
		my_sftp_port="-oPort=$AD_SSH_PORT";
	    else
		my_sftp_port=""
	    fi

	    run_hook "$AD_HOOK_PRE_CONNECT"
	    $WRAP $AD_SFTP_CMD $AD_SSH_ID $my_sftp_port $my_sftp_user"$AD_SSH_HOST"
	    run_hook "$AD_HOOK_POST_CONNECT"
	    ;;
	install)
	    lock_cluster
	    run_hook "$AD_HOOK_PRE_INSTALL"
	    $WRAP $AD_SSH_CMD $AD_SSH_ID $AD_SSH_OPTFLAGS $my_ssh_user $my_ssh_port "$AD_SSH_HOST" `printf "$AD_CMD_INSTALL" "$AD_PARAM"`
	    run_hook "$AD_HOOK_POST_INSTALL"
	    ;;
	upgrade)
	    lock_cluster
	    run_hook "$AD_HOOK_PRE_UPGRADE"
	    $WRAP $AD_SSH_CMD $AD_SSH_ID $AD_SSH_OPTFLAGS $my_ssh_user $my_ssh_port "$AD_SSH_HOST" $AD_CMD_UPGRADE
	    run_hook "$AD_HOOK_POST_UPGRADE"
	    ;;
	refresh)
	    run_hook "$AD_HOOK_PRE_REFRESH"
	    $AD_SSH_CMD $AD_SSH_ID $AD_SSH_OPTFLAGS -n -o BatchMode=yes -o ConnectTimeout=5 $my_ssh_user $my_ssh_port "$AD_SSH_HOST" $AD_CMD_REFRESH 2>&1
	    run_hook "$AD_HOOK_POST_REFRESH"
	    ;;
	*)
	    echo "Unhandled action '$AD_ACTION'!" 1>&2
	    echo 1>&2
	    set | grep ^AD_ 1>&2
	    echo 1>&2
	    exit 1;
	;;
    esac
}

if [ -z "$AD_TYPE" -o "$AD_TYPE" = 'generic-ssh' ]; then
    handle_generic_ssh $@
else
    if [ -x "$AD_PLUGINDIR/$AD_TYPE/cmd" ]; then
	$WRAP "$AD_PLUGINDIR/$AD_TYPE/cmd" $@
    else
	echo "No plugin to handle type '$AD_TYPE'!" 1>&2
	echo 1>&2
	set | grep ^AD_ 1>&2
	echo 1>&2
	exit 2;
    fi
fi
