#!/bin/sh -u # # Bang style ssh for hopping through firewalls etc. # Sshes from host to host to reach destination. # Assorted other minor features. # - Cameron Simpson 28may2004 # : ${SSHTO_OPTS:=''} : ${SSHTO_CONFIG:=$HOME/.sshtorc} : ${SSHTO_PREFIX:=''} oldstyle= cf=$SSHTO_CONFIG trace= ##set-x sshopts= # options for each ssh invocation lsshopts= # options for the outermost ssh invocation # this will include $sshopts mycfg=$HOME/.ssh/config [ -s "$mycfg" -a -r "$mycfg" ] && lsshopts="$lsshopts -F '$mycfg'" topt= fopt= presh= setx=: cmd=`basename "$0"` || cmd=$0 usage="Usage: $cmd [ssh-options...] [sshcfg=value...] [user@]host[![user2@]host2...] [command ...] ssh-options... Passed to all ssh commands. sshcfg=value Transmuted to -o 'sshcfg value' and added to ssh-option. -z, +z Pass -o Compression yes/no to ssh. -E Run login setup at far end." env_presh=': set -vx exec 3<&0 4>&1 &2 [ -s /etc/profile ] && . /etc/profile [ -s $HOME/.profile ] && . $HOME/.profile wSHELL= for sh in zsh bash ksh sh $SHELL do for bin in /bin /usr/bin /usr/local/bin do case "$sh" in /*) binsh=$sh ;; *) binsh=$bin/$sh ;; esac [ -x "$binsh" ] && { wSHELL=$binsh; break; } done [ -n "$wSHELL" ] && break done [ -n "$wSHELL" ] && SHELL=$wSHELL export SHELL tput colors >/dev/null 2>&1 || { TERM=xterm-color; export TERM; } [ -s /opt/css/env.sh ] && . /opt/css/env.sh exec <&3 3<&- >&4 4>&- ' set -- $SSHTO_OPTS ${1+"$@"} badopts= host= havehost= first=1 while [ $# -gt 0 ] do case $1 in -t) topt=-t ;; +t) topt= ;; -f) fopt=-f ;; -E) presh=$env_presh ;; -v) trace=set-x setx='set -x' sshopts="$sshopts $1" ;; -[Fil]) lsshopts="$lsshopts $1 "`shqstr "$2"` shift ##echo "lsshopts=[$lsshopts]" >&2 ;; -[aAgknNqsTxXYC1246]) sshopts="$sshopts $1" ;; -[bceImopLRD]) sshopts="$sshopts $1 "`shqstr "$2"` shift ;; -[bceiIlmopFLRD]?*) sshopts=$sshopts\ `shqstr "$1"` ;; -z) sshopts="$sshopts -o 'Compression yes'" ;; +z) sshopts="$sshopts -o 'Compression no'" ;; [a-zA-Z]*=?*) [ $havehost ] && break # not supported after host - it's the shell command now cfg=`expr "$1" : '\([^=]*\)=.*'` val=`expr "$1" : '[^=]*=\(.*\)'` sshopts="$sshopts -o "`shqstr "$cfg $val"` ;; --) shift; break ;; -?*)echo "$cmd: unrecognised option: $1" >&2; badopts=1 ;; *) [ $havehost ] && break host=$1; havehost=1 ;; esac shift done if [ -z "$havehost" ] then if [ $# = 0 ] then echo "$cmd: missing host" >&2 badopts=1 else host=$1; shift fi fi [ $badopts ] && { echo "$usage" >&2; exit 2; } [ -t 0 -a -t 1 ] && topt=-t [ $# = 0 ] && set -- '[ -n "$SHELL" -a -x "$SHELL" ] || SHELL=/bin/sh; exec "$SHELL"' sshargv="$sshopts $topt" sshcmd=$presh$* expand_host() { _xph_host=$1 # pull off the login for reuse at the final component _xph_loginpfx= case "$_xph_host" in *@*) _xph_loginpfx=`expr "x$_xph_host" : 'x\(.*\)@.*'` _xph_host=` expr "x$_xph_host" : 'x.*@\(.*\)'` esac if [ -f "$cf" -a -s "$cf" ] then _xph_changed= _xph_seenhost= while read _xph_nick _xph_fullhost _xph_junk <&3 do case "$_xph_nick" in '' | \#* ) ;; "$_xph_host" ) case " $_xph_seenhost " in *" $_xph_host "*) echo "$cmd: expand_host: recursive mapping for \"$_xph_host\" in $cf" >&2 break ;; esac _xph_seenhost="$_xph_seenhost _xph_host" _xph_host=$_xph_fullhost _xph_changed=1 break ;; esac done 3<"$cf" fi # restore the login if any if [ -n "$_xph_loginpfx" ] then case "$_xph_host" in *\!*) _xph_left=` expr "x$_xph_host" : 'x\(.*\)!.*'` _xph_right=`expr "x$_xph_host" : 'x.*!\(.*\)'` case "$_xph_right" in *@*) _xph_right=`expr 'x$_xph_right' : 'x.*@\(.*\)'` ;; esac _xph_host=$_xph_left!$_xph_loginpfx@$_xph_right ;; *) _xph_host=$_xph_loginpfx@$_xph_host ;; esac fi printf '%s\n' "$_xph_host" } expand_hostpath() { _xphp_out= _xphp_sep= for _xphp_host in `printf '%s\n' "$1" | tr '!' ' '` do _xphp_out=$_xphp_out$_xphp_sep`expand_host "$_xphp_host"` _xphp_sep='!' done printf '%s\n' "$_xphp_out" } split_target() { set -- `printf "%s\n" "$1" | tr '!' ' '` _st_pcmd= if [ $# -gt 1 ] then while [ $# -gt 1 ] do if [ -z "$_st_pcmd" ] then _st_pcmd="ssh $lsshopts" else _st_pcmd="$_st_pcmd ssh" fi _st_pcmd="${_st_pcmd} -A -T -x -e none -o batchmode=yes -o compression=no $1" shift done _st_pcmd="$_st_pcmd $setx\\; exec nc %h %p" fi printf "%s %s\n" "$1" "$_st_pcmd" } hostpath=`expand_hostpath "$host"` [ -z "$SSHTO_PREFIX" ] || hostpath="$SSHTO_PREFIX!$hostpath" if [ $oldstyle ] then host=$hostpath while : do case "$host" in *!*) rhost=`expr "x$host" : 'x.*!\(.*\)'` host=` expr "x$host" : 'x\(.*\)!.*'` osshcmd=$sshcmd sshcmd="$setx\\; exec ssh $sshargv "`shqstr "$rhost" "$sshcmd"` ;; *) break ;; esac done else set -- `split_target "$hostpath"` host=$1 shift if [ $# -gt 0 ] then qpc=`shqstr "ProxyCommand $*"` lsshopts="$lsshopts -o $qpc -o StrictHostKeyChecking=no" fi fi eval "exec $trace ssh $fopt $lsshopts $sshargv $host \"\$sshcmd\""