3 ### SSH wrapper to spawn separate SSH master connections on demand
5 ### (c) 2010 Mark Wooding
8 ###----- Licensing notice ---------------------------------------------------
10 ### This program is free software; you can redistribute it and/or modify
11 ### it under the terms of the GNU General Public License as published by
12 ### the Free Software Foundation; either version 2 of the License, or
13 ### (at your option) any later version.
15 ### This program is distributed in the hope that it will be useful,
16 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ### GNU General Public License for more details.
20 ### You should have received a copy of the GNU General Public License
21 ### along with this program; if not, write to the Free Software Foundation,
22 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 ###--------------------------------------------------------------------------
27 : ${REAL_SSH=/usr/bin/ssh}
28 : ${SSH_HOME=$(unset HOME; bash -c 'echo ~/.ssh')}
29 : ${SSH_LOGDIR=$SSH_HOME/log-$(hostname)}
31 ###--------------------------------------------------------------------------
32 ### Parse the command line and dredge out information.
34 ## This is a reasonable approximation to SSH's command-line argument parser.
37 declare -a opts masteropts
41 ## Nothing left. We're done.
46 ## A command line option group. Parse it and work out what's going on.
49 opts=("${opts[@]}" "$opt")
52 ## Strip off the first character, because it's the one we dealt with
57 ## Phase 1: identify the option and whether it needs an argument.
61 ## Empty group. We're done.
66 ## Options with arguments.
70 ## You're going to lose because there's no argument. But we'll
71 ## let SSH deal with that.
76 ## There's an argument cuddled on to the end of the option. It
77 ## will have been committed to the `opts' array as part of the
84 ## Nope. There's an argument in the next word. Grab it and
88 opts=("${opts[@]}" "$arg")
94 ## Anything else. Let it go even if it's not valid: SSH will moan
95 ## if it wants. Note that `--' is ignored by SSH, but this isn't
96 ## documented; in particular, `--' is /not/ a POSIX end-of-options
97 ## marker, so we don't try to handle it specially here either.
102 ## Phase two. Figure out whether what this means for us.
105 ## `-O foo' and `-S foo' mean that the caller wants to take
106 ## control of the multiplexing process.
111 ## Catch the login name if there is one. Make sure the master
114 masteropts=("${masteropts[@]}" "-l$arg")
118 ## Catch the port number. We want this for building the logfile
121 masteropts=("${masteropts[@]}" "-p$arg")
125 ## These options are interesting to the master connection.
127 masteropts=("${masteropts[@]}" "-${o:0:1}$arg")
130 ## SSH options on the command line merit special attention. Pass
131 ## them onto the master, if necessary.
133 masteropts=("${masteropts[@]}" "${opt:0:1}$arg")
136 ## User wants to control the process. Let him.
137 ?,ControlMaster=* | ?,ControlPath=*)
147 ## A bare word. Maybe it's the hostname, or the start of the command.
149 case ${host-t}${host+nil} in
158 ###--------------------------------------------------------------------------
159 ### Now to actually do the job.
161 ## If there's no host, pass straight through. We can't do anything useful
168 ## Actually do something useful.
171 exec "$REAL_SSH" "${opts[@]}" ${host+"$host"} "$@"
174 mkdir -p -m700 "$SSH_LOGDIR"
175 logfile=$SSH_LOGDIR/${login+"$login@"}"$host"${port+":$port"}.log
176 if ! "$REAL_SSH" -Ocheck \
177 ${port+-p$port} ${login+"$login@"}"$host" \
180 "$REAL_SSH" -MNf "${masteropts[@]}" "$host" \
181 </dev/null >/dev/null 2>$logfile
183 exec "$REAL_SSH" ${opts[@]} "$host" "$@"
187 ###----- That's all, folks --------------------------------------------------