about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xmrgrctrnl208
1 files changed, 120 insertions, 88 deletions
diff --git a/mrgrctrnl b/mrgrctrnl index af29269..796470c 100755 --- a/mrgrctrnl +++ b/mrgrctrnl
@@ -1,103 +1,135 @@
1#!/bin/sh 1#!/bin/sh
2# mrgrctrnl 2# mrgrctrnl: configurable ssh tunneler
3# configurable ssh tunneler 3# Author: Case Duckworth <acdw@acdw.net>
4# by Case Duckworth <acdw@acdw.net> 4# Version: 0.2
5# version 0.1 5# License: MIT
6# LICENSE: MIT
7 6
8usage() { 7PRGN="${0##*/}"
9 cat <<-END
10 mrgrctrnl: make magic ssh tunnels
11 usage: mrgrctrnl [-h] [-c CONF] [-d] [-k]
12 8
13 -h show this help 9usage() {
14 -c CONF use config file CONF. 10 cat <<END
15 . default: \$XDG_CONFIG_HOME/mrgrctrnl/config 11$PRGN: make magic ssh tunnels
16 -d do a dry run: don't actually tunnel 12usage: $PRGN [-h] [-k]
17 -k kill all processes and exit 13 $PRGN [-n] [-c CONF | -s SSH]
18 14
19 END 15options:
20 exit "${1:-0}" 16 -h show this help
17 -k kill all processes and exit
18 -r restart $PRGN
19 -n do a dry run: just print what would happen
20 -c CONFIG use a different CONFIG file instead of
21 \$XDG_CONFIG_HOME/$PRGN/config
22 -s CMDLINE directly input an ssh CMDLINE --
23 don't load the config file.
24END
21} 25}
22 26
23die() { 27# entry point
24 [ "$#" -eq 0 ] && exit 1 28main() {
25 case "$1" in 29 __CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/$PRGN/config"
26 0-9*) 30 __SSHCMD="-N \"\$user@\$machine\" -L \"\$local:\$remote\""
27 ec="$1" 31 __PIDF="/tmp/$PRGN.pid"
28 shift 32 _run=true
29 ;; 33 _quiet=false
30 *) ec=1 ;; 34 _use_config=true
31 esac
32 printf '!!%s: %s\n' "mrgrctrnl" "$*"
33 exit "$ec"
34}
35 35
36demolish_tunnels() { 36 while getopts hqkrnc:s: OPT; do
37 printf '%s...' "Demolishing tunnels" 37 case "$OPT" in
38 if [ -f "$pidf" ]; then 38 h)
39 while read -r pid; do 39 usage
40 [ -z "$pid" ] && continue 40 exit 0
41 kill "$pid" 2>/dev/null 41 ;;
42 done <"$pidf" 42 q) _quiet=true ;;
43 rm "$pidf" 43 k)
44 else 44 tear_down
45 pkill -x ssh 45 pkill -x "$PRGN"
46 fi 46 exit
47 printf '%s.\n' "Done" 47 ;;
48} 48 r)
49 tear_down
50 exec "$PRGN"
51 ;;
52 n) _run=false ;;
53 c) __CONFIG="$OPTARG" ;;
54 s)
55 __SSHCMD="$OPTARG"
56 _use_config=false
57 ;;
58 *)
59 usage
60 exit 1
61 ;;
62 esac
63 done
49 64
50config="${XDG_CONFIG_HOME:=$HOME/.config}/mrgrctrnl/config" 65 if $_use_config && [ ! -r "$__CONFIG" ]; then
51pidf=/tmp/mrgrctrnl.pid 66 echo "!! $PRGN: Cannot find config file '$__CONFIG'."
52dry_run=false 67 echo "Aborting."
68 exit 2
69 fi
53 70
54while getopts hc:dkr opt; do 71 if $_use_config; then
55 case "$opt" in 72 awk '{sub(/#.*$/,"");print}' "$__CONFIG" |
56 h) usage ;; 73 while read -r machine user local remote key rest; do
57 c) config="$OPTARG" ;; 74 if [ -z "$machine" ] || [ -z "$user" ] ||
58 d) dry_run=true ;; 75 [ -z "$local" ] || [ -z "$remote" ]; then
59 k) 76 continue
60 demolish_tunnels 77 fi
61 pkill -x mrgrctrnl
62 exit
63 ;;
64 r)
65 demolish_tunnels
66 exec mrgrctrnl
67 exit
68 ;;
69 \?) usage 2 ;;
70 *) usage 2 ;;
71 esac
72done
73shift "$((OPTIND - 1))"
74 78
75[ -f "$config" ] || die "Need a config! Edit $config" 79 # shellcheck disable=2030
76if [ -e "$pidf" ] && ! "$dry_run"; then 80 if [ -n "$key" ]; then
77 demolish_tunnels 81 __SSHCMD="$__SSHCMD -i \"$key\""
78fi 82 fi
83 if [ -n "$rest" ]; then
84 __SSHCMD="$__SSHCMD $rest"
85 fi
79 86
80awk '{sub(/#.*$/,"");print}' "$config" | 87 eval "tunnel $__SSHCMD" &
81 while read -r machine user local remote key rest; do 88 done
82 if [ -z "$machine" ] || [ -z "$user" ] || 89 else
83 [ -z "$local" ] || [ -z "$remote" ]; then 90 # shellcheck disable=2031
84 continue 91 eval "tunnel $__SSHCMD" &
85 fi 92 fi
86 93
87 set -- -N "$user@$machine" -L "$local:$remote" 94 wait
88 [ -n "$key" ] && set -- "$@" -i "$key" 95}
89 #shellcheck disable=2086
90 [ -n "$rest" ] && set -- "$@" $rest
91 96
92 echo ssh "$@" 97tunnel() {
98 # shellcheck disable=2086
99 $_quiet || echo ssh "$@"
100 $_run && {
101 touch "$__PIDF"
102 while [ -e "$__PIDF" ]; do
103 grep -q -e "$*" "$__PIDF" && {
104 sleep 3
105 continue
106 }
107 # shellcheck disable=2015
108 if ssh "$@" & then
109 printf '%s\t%s\n' "$!" "$*" >>"$__PIDF"
110 else
111 badpid="$!"
112 kill "$badpid"
113 sed "/^$badpid/d" "$__PIDF" >"$__PIDF~" &&
114 mv "$__PIDF~" "$__PIDF"
115 continue
116 fi
117 sleep 3
118 done
119 }
120}
93 121
94 touch "$pidf" 122tear_down() {
95 "$dry_run" || { 123 printf '%s...' "Killing extant tunnels"
96 while [ -f "$pidf" ]; do 124 if [ -e "$__PIDF" ]; then
97 ssh "$@" || break 125 while read -r pid _; do
98 echo "$!" >>"$pidf" 126 kill "$pid" 2>/dev/null
99 done & 127 done <"$__PIDF"
100 } 128 rm "$__PIDF"
101 done 129 else
130 pkill -x ssh
131 fi
132 echo Done.
133}
102 134
103wait 135main "$@"