#!/bin/bash

PORT="2022"
USER=${USER}
ET_COMMAND=""
SSH_COMMAND=""
TMP_DIR=${TMPDIR:-${TMP:-${TEMP:-/tmp}}}
LOG_DIR=$TMP_DIR
VERBOSITY=""
INITIAL_COMMAND=""
TUNNEL=""
SERVER_BINARY="etserver"
CLIENT_BINARY="etclient"

for i in "$@"
do
    case $i in
        -s=*|--ssh=*)
            SSH_COMMAND="${i#*=}"
            shift
            ;;
        -p=*|--port=*)
            PORT="${i#*=}"
            shift
            ;;
        -u=*|--user=*)
            USER="${i#*=}"
            shift
            ;;
        -l=*|--logdir=*)
            LOG_DIR="${i#*=}"
            shift
            ;;
        -v)
            VERBOSITY="--v=9"
            shift
            ;;
        -c=*|--command=*)
            INITIAL_COMMAND="${i#*=}"
            shift
            ;;
        -t=*|--tunnel=*)
            TUNNEL="${i#*=}"
            shift
            ;;
        --version)
            etclient --version
            exit 0
            shift
            ;;
        -h|--help)
            printf "et (options) [user@]hostname[:port]

Options:
-h Basic usage
-s Special ssh command if necessary, otherwise set to user@hostname:22
   example: et -s '-p 8888 user@hostname' user@hostname:8080 (et running on port 8080)
-p Port for etserver to run on.  Don't set to the same port as ssh.  Default: 2022
-u Username to connect to ssh & ET
-l Directory where log files will go
-v verbose log files
-c Initial command to execute upon connecting
-t Map local to remote TCP port (TCP Tunneling)
   example: et -t=\"18000:8000\" user@hostname maps localhost:18000 to hostname:8000
"
            exit 0
            ;;
        *)
            ET_COMMAND="${i}"
            ;;
    esac
done

ET_COMMAND_REGEX="^(([0-9a-zA-Z]+)@)?([^\/:?@#]+)(:([0-9]+))?$"

if [[ $ET_COMMAND =~ $ET_COMMAND_REGEX ]]; then
    ET_USER="${BASH_REMATCH[2]}"
    ET_HOSTNAME="${BASH_REMATCH[3]}"
    ET_PORT="${BASH_REMATCH[5]}"
    if [[ -n "$ET_USER" ]]; then
        USER=$ET_USER
    fi
    if [[ -n "$ET_HOSTNAME" ]]; then
        HOSTNAME=$ET_HOSTNAME
    fi
    if [[ -n "$ET_PORT" ]]; then
        PORT=$ET_PORT
    fi
else
    printf "Usage: ET (options) [user@]hostname[:port]\n"
    exit 1
fi

if [[ -z "$SSH_COMMAND" ]]; then
    # Assume we want to bring the user into the ssh command but not
    # the port.
    SSH_COMMAND=${USER}@${HOSTNAME}
fi

CLIENT_TERM=$TERM
PASSKEY_GENERATOR="env LC_ALL=C tr -dc \"a-zA-Z0-9\" < /dev/urandom | head -c 32"
ID_GENERATOR="env LC_ALL=C tr -dc \"a-zA-Z0-9\" < /dev/urandom | head -c 16"
TMPFILE=$(mktemp "$TMP_DIR"/et-client.XXXXXXXXXXXX)
SSH_SCRIPT="
SERVER_TMP_DIR=\${TMPDIR:-\${TMP:-\${TEMP:-/tmp}}}
TMPFILE=\$(mktemp \"\$SERVER_TMP_DIR\"/et-server.XXXXXXXXXXXX)
PASSKEY=\$($PASSKEY_GENERATOR)
ID=\$($ID_GENERATOR)
printf \"%s/%s\\n\" \"\$ID\" \"\$PASSKEY\" > \"\${TMPFILE}\"
export TERM=$CLIENT_TERM
$SERVER_BINARY --idpasskeyfile=\"\${TMPFILE}\"
true
"
SSH_OUTPUT=$(printf "%s\n" "$SSH_SCRIPT" | ssh -T $SSH_COMMAND '/bin/bash')

SSH_EXIT_STATUS=$?

if [[ $SSH_EXIT_STATUS != 0 ]]
then
    echo "SSH handshake failed."
    exit $SSH_EXIT_STATUS
fi

IDPASSKEY=$(printf "%s" "$SSH_OUTPUT" | grep IDPASSKEY: | cut -d: -f2)
if [ -z "$IDPASSKEY" ]
then
    echo "Error communicating with ET daemon."
    echo "${SSH_OUTPUT}"
else
    echo "${IDPASSKEY}" > "${TMPFILE}"
    IDPASSKEY=""
    SSH_OUTPUT=""
    $CLIENT_BINARY --idpasskeyfile="$TMPFILE" $VERBOSITY --host="$HOSTNAME" --port="$PORT" --log_dir="$LOG_DIR" --command="$INITIAL_COMMAND" --portforward="$TUNNEL" 2> /tmp/etclient_err
fi
