#!/bin/bash
# Karsten M. Self Tue Apr 26 14:40:29 PDT 2005
# ----------------------------------------------------------------------
# sshstartx  Start an ssh-forwarded X session to an empty display.  
#            Use is generally comperable to xinit, though (currently)
#            argument format differs.  No way to pass X server
#            arguments, can add if desired.  A local xterm is also
#            launched with a reddish background, for interacting with
#            the local host.
#
# Copyright (C) 2005  Karsten M. Self
#
# 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 program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
# USA
# ----------------------------------------------------------------------
#
# Note that you need to:
#
#     1. Start this script from console.
#     2. Allow 'console' users in /etc/X11/Xwrapper.config
#     3. Can't background this script, or the 'xinit' invocation, or
#        run from a non-console terminal, and yes, Virginia, that
#        includes 'screen' sessions.
#     4. You will have a console session running.  Recognize the
#        security implications.
#
# ----------------------------------------------------------------------

export PATH=/usr/bin:/bin:/usr/bin/X11


SSH=/usr/bin/ssh
SSH_CIPHER="-c blowfish"
SSH_OPTS="-o RSAAuthentication=yes -o PasswordAuthentication=no"

# Assume user == $USER unless -u specified.
REMOTE_USER=$USER

# $HOME/.sshstartxrc may include the following values:
# REMOTE_USER=<username>
# REMOTE_HOST=<hostname or IP address>
# REMOTE_COMMAND=<remote X client to start>
if [ -f ~/.sshstartxrc ]; then
    . ~/.sshstartxrc
fi

function help_text () {
echo "usage: $( basename $0 ) [-u remote_user] [-c remote_command] [host]"
cat <<EOF
    Start an X session on a remote host
    Default user is  your local username ($USER)
    Default host is ${REMOTE_HOST:-not set}
    Default command (client) is null, can use specified command if given, 
      otherwise sane defaults of .Xsession, .xsession, .xinitrc, 
      x-session-manager, x-window-manager, twm, or xterm.
    Values for REMOTE_USER, REMOTE_HOST, and REMOTE_COMMAND may be
      specified in ~/.sshstartxrc using bash syntax.
EOF
exit 1
}

while test $# -gt 0; do
    case $1 in
       -h) help_text;;
       -u) shift; REMOTE_USER=$1; shift;;
       -c) shift; REMOTE_COMMAND="$1"; shift;;
       *)  REMOTE_HOST=$1; shift;;
    esac
done

SSH_CON="$REMOTE_USER@$REMOTE_HOST"

# start an agent if not already set (not foolproof, should check PID)
if [ "$SSH_AUTH_SOCK"x = x -o "$SSH_AGENT_PID"x = x ]; then
    KILL_SSH_AGENT='YES'
    eval $( ssh-agent )
fi

# Add keys
if ! ssh-add -l > /dev/null;  then
    ssh-add
fi


# Find out what sort of environment we've got on the remote side --
# basically sit here and test for stuff.   Hrm...
# 'x-session-manager' and 'x-window-manager' are Debianisms.  Modify to
# suit for other distros.

echo -e "Checking startup options ... \c"
if [ "$REMOTE_COMMAND"x = x ]; then
    REMOTE_COMMAND=$(
	$SSH $SSH_CIPHER $SSH_OPTS $SSH_CON '
	    if test -f ~/.xsession; then echo ". ~/.xsession";
	    elif test -f ~/.Xsession; then echo ". ~/.Xsession";
	    elif test -f ~/.xinitrc;  then echo ". ~/.xinitrc";
	    elif which x-session-manager >/dev/null; 
		  then echo "x-session-manager";
	    elif which x-window-manager  >/dev/null; 
		then echo "x-window-manager";
	    elif which twm >/dev/null; then echo "twm";
	    else echo "xterm";
	    fi' )
    fi

echo "OK: using $REMOTE_COMMAND"
sleep 1

# Kick off X at lowest free session between 0 and 9...
# NOTE THAT THIS LEAVES AN EXTANT CONSOLE SESSION RUNNING...
# HRM, let's warn the user about that.
for i in $( seq 0 9 );
do
    if ! test -f /tmp/.X${i}-lock; then
        echo "Trying to start X at :${i}"
	cat <<-EOF

	PLEASE NOTE THAT YOU WILL HAVE AN ACTIVE CONSOLE SESSION RUNNING
	ON $( tty ).  OTHERS WILL BE ABLE TO ACCESS YOUR ACCOUNT IF YOU
	LEAVE YOUR SYSTEM UNATTENDED.

	YOU HAVE BEEN WARNED.

EOF

	sleep 5;
	export DISPLAY=":${i}"

	# For accessing stuff on the _local_ system, we'll run an xterm,
	# *after* firing off the X server.
	( 
	    sleep 10; 
	    xterm -bg '#663333' -fg white -cr blue -geometry -0-0 -display ${DISPLAY}
	) &

	# Kick off X.
        startx $SSH -X $SSH_CIPHER $SSH_OPTS $SSH_CON "$REMOTE_COMMAND" -- ${DISPLAY} 

	# Your mother doesn't work here....
	# Try a soft kill, then a hard kill, of ssh-agent, if we started
	# it.
	# NOTE:  This doesn't work reliably.  <sigh>
	if [ "KILL_SSH_AGENT"x = 'YESx' ]; then
	    test -d /proc/$SSH_AGENT_PID && kill -15 $SSH_AGENT_PID; 
	    sleep 1;  
	    test -d /proc/$SSH_AGENT_PID && kill -9 $SSH_AGENT_PID; 
	fi

	exit 0
        break # Never happens ... right?
    fi
done

