#!/bin/sh
# $Id: ssh-init,v 1.6 2006/11/10 11:40:59 abs Exp $
#
# Setup ssh environment/agent to use consistent ssh socket.
#
# Add to startup scripts
# {ba,k,}sh: [ -f /usr/pkg/bin/ssh-init ] && eval $(ssh-init -s)
# t?csh:     if ( -f /usr/pkg/bin/ssh-init ) eval `ssh-init -c`

auth_sock_canonify()
    {
    if [ -z "$SSH_AUTH_SOCK" ] ; then
        verbose "\$SSH_AUTH_SOCK not set"
    elif [ $SSH_AUTH_SOCK != $CANONICAL_AUTH_SOCK ] ; then
	dir=$(dirname $CANONICAL_AUTH_SOCK)
	if [ -d $dir ] ; then
	    eval $(stat -L -s $dir)
	    if [ $st_uid != $(id -u) ] ; then
		fatal "$dir already present and owned by another user"
	    fi
	    chmod 700 $dir
	else
	    verbose "mktemp -q -d $dir"
	    mktemp -q -d $dir >/dev/null
	fi
	verbose "rename($SSH_AUTH_SOCK,$CANONICAL_AUTH_SOCK)"
	mv -f $SSH_AUTH_SOCK $CANONICAL_AUTH_SOCK
	export SSH_AUTH_SOCK=$CANONICAL_AUTH_SOCK
    else
	verbose "auth sock already $CANONICAL_AUTH_SOCK"
    fi
    }

fatal()
    { echo $*; exit 1; }

setup_server()
    {
    verbose Server...
    export SSH_AUTH_SOCK=$CANONICAL_AUTH_SOCK

    if [ ! -e $CANONICAL_AUTH_SOCK ]; then
        start_ssh_agent
	ssh-add $SSH_KEY
    else
	verbose "SSH_AUTH_SOCK defined..."
	# Ignore any non 'CANONICAL_AUTH_SOCK' SSH_AUTH_SOCK, and create new if needed
	if [ -n "$opt_f" -o -z "$opt_l" -o "$TERM" != screen -o "$WINDOW" = 0 ] ;then
	    verbose "Not (screen & WINDOW=0)... or -f given"
	    SSH_ADD=$(ssh-add -l 2>&1)
	    verbose "SSH_ADD=$SSH_ADD"
	    case "$SSH_ADD" in
		# Create new ssh agent, and add default identity
		"Could not open a connection to your authentication agent." | \
                "Error connecting to agent"*)
                    start_ssh_agent
		    ssh-add $SSH_KEY
		    ;;
		# Add identity to agent
		"The agent has no identities.")
		    ssh-add $SSH_KEY
		    ;;
		# All OK
		*$SSH_KEY\ *)
		    ;;
	    esac
	fi
    fi
    }

start_ssh_agent()
    {
    verbose "Start ssh-agent"
    if [ -n "$opt_v" ] ; then
        eval $(ssh-agent -s)
    else
        eval $(ssh-agent -s | grep -v '^echo')
    fi
    auth_sock_canonify
    }

verbose()
    {
    [ -n "$opt_v" ] && echo "ssh-init:" $@ >&2
    }

args=$(getopt cfhilprv $*)
if [ $? != 0 ]; then
    opt_error=1
fi
set -- $args
while [ $# != 0 ]; do
    case "$1" in
	-c )    opt_c=1 ;;
	-f )    opt_f=1 ;;
	-h )    opt_h=1 ;;
	-i )    opt_i=1 ;;
	-l )    opt_l=1 ;;
	-p )    opt_p=1 ;;
	-r )    opt_r=1 ;;
	-v )    opt_v=1 ;;
	-- )	shift ; break ;;
    esac
    shift
done

if [ -n "$opt_h" -o -n "$opt_error" ] ; then
    cat << END
Usage: ssh-init [opts]
opts:	-c Output suitable for a csh shell to eval
	-f Force key input
	-h This help
	-i Initialise ssh-agent & socket but do not add identities
	-l Running on login (designed to be called from login scripts)
        -r Run as remote (just setup socket location)
	-s Output suitable for a Bourne shell to eval
	-p Print out the value of SSH_AUTH_SOCK
	-v Verbose
END
    [ -z "$opt_error" ]
    exit
fi

CANONICAL_AUTH_SOCK=/$HOME/.ssh/agent/sock

if [ -n "$opt_r" ] ; then
    auth_sock_canonify
else
    setup_server
fi

if [ -z "$opt_p" -a -z "$opt_s" -a -z "$opt_c" ]; then
    case "$SHELL" in
	*csh) opt_c=1 ;;
	*)    opt_s=1 ;;
    esac
fi

if [ -n "$opt_s" ];then
    echo "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK"
elif [ -n "$opt_c" ];then
    echo "setenv SSH_AUTH_SOCK $SSH_AUTH_SOCK"
elif [ -n "$opt_p" ];then
    echo $SSH_AUTH_SOCK
fi
