#!/bin/bash

################################################################################
# blahp-over-ssh shim script
#
# command [options] [user@]hostname [options] command [remote arguments]
#
# Options:
#   see usage string 
#
# Arguments:
#   mandatory: hostname, command
#
# Remote arguments are passed along
#
# Assumes public/private key pair is already created and exists on host
#
# Exits with 0 on success, 1 if wrong arguments, < 0 if ssh-add failed, > 0 if ssh failed
################################################################################

#Defaults
REMOTE_CMD=""
REMOTE_HOSTNAME=""
REMOTE_USER=`whoami`
# Fix the home directory when spawned from a root process
unset HOME
export HOME=`echo ~`
# Needs '~' because resolved on remote site
REMOTE_GLITE="~/bosco/glite"
# We do this in case $HOME isn't set properly
PASSPHRASE_LOCATION=`echo ~/.bosco/.pass`
PRIVATE_KEY_LOCATION=`echo ~/.ssh/bosco_key.rsa`


# Parse command line arguments 
PROG_NAME=$0
USAGE="Usage: $PROG_NAME [options] remote_hostname [options] REMOTE_CMD [remote arguments]\n \
$PROG_NAME [options] remote_hostname [remote options and arguments]\n \
Options: \n \
 --rgahp-user REMOTE_USER \tuser name on the remote host\n \
 --rgahp-key PRIVATE-KEY-PATH \tlocation of ssh private key (~/.ssh/bosco_key.rsa)\n \
 --rgahp-nokey  \t\tno ssh private key or key already enabled (same as empty rgahp-key)\n \
 --rgahp-pass PASSPHRASE \tlocation of passphrase protecting ssh private key (~/.bosco/.pass)\n \
 --rgahp-nopass \t\tno passphrase protecting ssh private key (same as empty rgahp-pass)\n \
 --rgahp-glite PATH \tpath to the directory of the script (~/bosco/glite)\n \
 --rgahp-script SCRIPT \tpath to script to start up blahp (PATH/bin/batch_gahp)\n \
 --help, -h \t\t\tprint this\n \
 remote_hostname: USER@HOST same string that can be used to ssh to the host\n \
 remote arguments are passed to the REMOTE_CMD
 REMOTE_CMD can be expressed as argument or option
"

while [ $# != 0 ] ; do
    case "$1" in
        -h | --help  ) echo -e "$USAGE"
            exit 0;;
        --rgahp-user  ) REMOTE_USER="$2"
            shift 2;;
        --rgahp-nokey  ) PRIVATE_KEY_LOCATION=""
            shift ;;
        --rgahp-key  ) PRIVATE_KEY_LOCATION="$2"
            shift ; shift  ;;
        --rgahp-pass  ) PASSPHRASE_LOCATION="$2"
            shift 2;;
        --rgahp-nopass  ) PASSPHRASE_LOCATION=""
            shift ;;
        --rgahp-glite ) REMOTE_GLITE="$2"
            shift 2;;
        --rgahp-script ) REMOTE_CMD="$2"
            shift 2;;
        --rgahp-* ) echo "Unknown option: $1" 1>&2
            echo -e "$USAGE"
            exit 1;;
        -- ) shift
            if [ "$REMOTE_CMD" = "" ] ; then
                REMOTE_CMD="$1"
                shift
            fi
            break;;
        -* ) break;;
        * )
            if [ "$REMOTE_HOSTNAME" = "" ] ; then
                REMOTE_HOSTNAME=`echo "$1" | sed 's/.*@//'`
                echo "$1" | grep -q '@'
                if [ $? -eq 0 ] ; then
                    REMOTE_USER=`echo "$1" | sed 's/@.*//'`
                fi
                shift
            elif [ "$REMOTE_CMD" = "" ] ; then
                REMOTE_CMD="$1"
                shift
            else
                break
            fi
            ;;
    esac
done

if [ "$REMOTE_HOSTNAME" = "" ] ; then
    echo "Missing hostname" 1>&2
    echo -e "$USAGE"
    exit 1
fi
if [ "$REMOTE_CMD" = "" ] ; then
    echo "Missing remote command" 1>&2
    echo -e "$USAGE"
    exit 1
fi

##### Handling authentication #####
# Start and init ssh agent if key file is specified


# if a ssh key is required, start up a ssh-agent and do ssh-add
if [ -n "$PRIVATE_KEY_LOCATION" -a -f "$PRIVATE_KEY_LOCATION" ] ; then
	# start the ssh-agent
	eval `ssh-agent -s` 1>&2

	# Call the external program to do ssh-add
        # If a passphrase is required pass it to the script
        if [ -n "$PASSPHRASE_LOCATION" ]; then
	    bosco_ssh_start --key "$PRIVATE_KEY_LOCATION" --pass "$PASSPHRASE_LOCATION"
        else
	    bosco_ssh_start --key "$PRIVATE_KEY_LOCATION" --nopass
        fi
	ADD_STATUS=$?

	# check if ssh-add failed
	if [ $ADD_STATUS != 0 ] ; then
		eval `ssh-agent -sk` 1>&2
		exit $ADD_STATUS
	fi
fi


##### Running remote command and cleanup #####

# remove hostname from arglist
shift

# use BatchMode so we fail if a password is requested
#echo "** Follows output of: ssh -o \"BatchMode yes\" $REMOTE_USER@$REMOTE_HOSTNAME /bin/bash -c \"'GLITE_LOCATION=$REMOTE_GLITE $REMOTE_GLITE/bin/batch_gahp $*'\""
if [ "${REMOTE_CMD}" = "batch_gahp" ] ; then
    ssh -o "BatchMode yes" $REMOTE_USER@$REMOTE_HOSTNAME /bin/bash -l -c "'GLITE_LOCATION=$REMOTE_GLITE $REMOTE_GLITE/bin/batch_gahp $*'"
    SSH_STATUS=$?
elif [ "${REMOTE_CMD}" = "condor_ft-gahp" ] ; then
    # We need to set up a tunnel from the remote machine for the file
    # transfer TCP connections. If we knew that both sides were running
    # OpenSSH 5.2p1 or later, we could have ssh pick the port on the
    # remote end. But we don't, so we pick a random port and hope it's
    # not already in use.
    # We mimic the message that newer versions of OpenSSH print when
    # binding a dynamic port for tunneling. The gridmanager looks for
    # this message to know which port to tell the ft-gahp to use.
    # If the local OpenSSH is 4.4p1 or later (we check for 5.0 or later
    # for simplicity), then we can use ExitOnForwardFailure and try
    # several random ports in case we get unlucky on the first attempt.
    # We extract the IP and port on which the gridmanager can be
    # contacted from $CONDOR_INHERIT.
    GRIDMANAGER_ADDRESS=`echo "$CONDOR_INHERIT" | sed 's/[^<]*<\([^?>]*\).*/\1/'`
    SSH_STATUS=255
    if [[ `ssh -V 2>&1` =~ ^OpenSSH_[5-9].* ]] ; then
        SSH_ARGS="-o ExitOnForwardFailure=yes"
        tries=3
    else
        tries=1
    fi
    while ((tries-- > 0 && SSH_STATUS == 255)) ; do
        let port=${RANDOM}+32768
        ssh $SSH_ARGS -R $port:$GRIDMANAGER_ADDRESS -o "BatchMode yes" $REMOTE_USER@$REMOTE_HOSTNAME /bin/bash -l -c "'echo Allocated port $port for remote forward to 1>&2 ; CONDOR_CONFIG=$REMOTE_GLITE/etc/condor_config.ft-gahp $REMOTE_GLITE/bin/condor_ft-gahp -f $*'"
        SSH_STATUS=$?
    done
else
    echo "Unknown remote command (${REMOTE_CMD})" 1>&2
    SSH_STATUS=1
fi

# kill the ssh-agent if it exists
eval `ssh-agent -sk` 1>&2

exit $SSH_STATUS