#!/bin/sh
###########################################################################
# Provides a quick way to do some simple remote support.
#
# Copyright (C) 2010 Alkis Georgopoulos <alkisg@gmail.com>
#
# 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 3 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 program.  If not, see <http://www.gnu.org/licenses/>.
#
# On Debian GNU/Linux systems, the complete text of the GNU General
# Public License can be found in `/usr/share/common-licenses/GPL'.
###########################################################################

usage() {
    local script
    
    script=$(basename $0)
    echo "\
Usage: $script <port>
Provides a quick way to do some simple remote support.

You, the supporter:
 * Port forward <port> in your router, if necessary
 * Run: $script <port>
 * And tell the person needing support your external IP
 
The person needing support on the remote system:
 * Runs: bash 0<>/dev/tcp/<your-external-ip>/<port>
 
Then you enter the commands to execute at the remote system.
Keep in mind that only stdin, stdout and stderr are redirected, so you can't
use full screen commands like vi or top or even the up/down arrow keys.
To terminate the connection, press Ctrl+D.

If you want to display a message in the remote console, you can use:
 * sendm message

To get his reply, use:
 * getm
Note that getm will block until the remote person writes something and presses [Enter]."
}

case "$1" in
    # A port may have one to five digits.
    [0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9])
        PORT="$1"
        ;;
    *)
        usage
        exit 1
        ;;
esac

echo "Listening on port $PORT. Tell the person needing support to run:"
echo "  bash 0<>/dev/tcp/<your-external-ip>/$PORT"

# Remember the local stdout.
exec 3>&1

# Get the local bold/normal combinations.
bold_face=$(tput bold 2>/dev/null) || true
normal_face=$(tput sgr0 2>/dev/null) || true

# The rest of the script is ran with stdout redirected to nc.
{
    # This is displayed on the person being supported.
    echo "echo 'Connection established with $USER@$(hostname).'"
    echo "echo 'Press Ctrl+C to terminate the connection.'"
    echo "echo 'Please stand by while the technician helps you.'"

    # Get bold/normal sequences for the remote terminal.
    echo 'bold_face=$(tput bold 2>/dev/null) || true'
    echo 'normal_face=$(tput sgr0 2>/dev/null) || true'

    # The person being supported redirected only stdin, now redirect stdout and
    # stderr too, but keep stdout in file descriptor 3 for sendm/getm to work.
    echo '\
exec 3>&1
exec 1>&0
exec 2>&0
echo "Enter the commands to execute as $USER@$(hostname)."
echo "To terminate the connection, press Ctrl+D."'

    while read line; do
        read cmd params <<EOF
$line
EOF
        case "$cmd" in
            sendm)
                escaped_params=$(echo "$params" | sed "s/'/'\\\\''/g")
                echo 'echo "${bold_face}"'\''The technician says: '$escaped_params\''"${normal_face}" >&3'
                ;;
            getm)
                echo 'echo -n "${bold_face}The technician waits for an answer: ${normal_face}" >&3'
                echo 'read reverse_bash_input <&3'
                echo 'echo "'${bold_face}'The person being supported said: $reverse_bash_input'${normal_face}'"'
                ;;
            *)
                escaped_line=$(echo "$line" | sed "s/'/'\\\\''/g")
                echo "echo 'The technician executes: $escaped_line' >&3"
                echo "$line"
                ;;
        esac
    done
    echo "echo 'The technician terminated the connection.' >&3"
} | nc -v -l $PORT
