From afd8272ac0a049d6b7da4b3370b476613ce9a3cf Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Thu, 30 Apr 2020 15:45:19 -0500 Subject: Version 0.2 A LOT of changes here. Mostly I tried to make it more robust, and to actually quit when I want it to quit. I also rewrote a lot of the functions and stuff. I feel pretty happy with it now, enough to make it an actual project on sourcehut. --- mrgrctrnl | 200 +++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 120 insertions(+), 80 deletions(-) diff --git a/mrgrctrnl b/mrgrctrnl index d51be58..796470c 100755 --- a/mrgrctrnl +++ b/mrgrctrnl @@ -1,95 +1,135 @@ #!/bin/sh -# mrgrctrnl -# configurable ssh tunneler -# by Case Duckworth -# version 0.1 -# LICENSE: MIT +# mrgrctrnl: configurable ssh tunneler +# Author: Case Duckworth +# Version: 0.2 +# License: MIT -usage() { - cat <<-END - mrgrctrnl: make magic ssh tunnels - usage: mrgrctrnl [-h] [-c CONF] [-d] [-k] +PRGN="${0##*/}" - -h show this help - -c CONF use config file CONF. - . default: \$XDG_CONFIG_HOME/mrgrctrnl/config - -d do a dry run: don't actually tunnel - -k kill all processes and exit +usage() { + cat </dev/null - done <"$pidf" - rm "$pidf" - sleep 3 - printf '%s.\n' "Done" -} + while getopts hqkrnc:s: OPT; do + case "$OPT" in + h) + usage + exit 0 + ;; + q) _quiet=true ;; + k) + tear_down + pkill -x "$PRGN" + exit + ;; + r) + tear_down + exec "$PRGN" + ;; + n) _run=false ;; + c) __CONFIG="$OPTARG" ;; + s) + __SSHCMD="$OPTARG" + _use_config=false + ;; + *) + usage + exit 1 + ;; + esac + done -config="${XDG_CONFIG_HOME:=$HOME/.config}/mrgrctrnl/config" -pidf=/tmp/mrgrctrnl.pid -dry_run=false + if $_use_config && [ ! -r "$__CONFIG" ]; then + echo "!! $PRGN: Cannot find config file '$__CONFIG'." + echo "Aborting." + exit 2 + fi -while getopts hc:dk opt; do - case "$opt" in - h) usage ;; - c) config="$OPTARG" ;; - d) dry_run=true ;; - k) - demolish_tunnels - pkill -x mrgrctrnl - exit - ;; - \?) usage 2 ;; - *) usage 2 ;; - esac -done -shift "$((OPTIND - 1))" + if $_use_config; then + awk '{sub(/#.*$/,"");print}' "$__CONFIG" | + while read -r machine user local remote key rest; do + if [ -z "$machine" ] || [ -z "$user" ] || + [ -z "$local" ] || [ -z "$remote" ]; then + continue + fi -[ -f "$config" ] || die "Need a config! Edit $config" -if [ -e "$pidf" ] && ! "$dry_run"; then - demolish_tunnels -fi + # shellcheck disable=2030 + if [ -n "$key" ]; then + __SSHCMD="$__SSHCMD -i \"$key\"" + fi + if [ -n "$rest" ]; then + __SSHCMD="$__SSHCMD $rest" + fi -awk '{sub(/#.*$/,"");print}' "$config" | - while read -r machine user local remote key rest; do - if [ -z "$machine" ] || [ -z "$user" ] || - [ -z "$local" ] || [ -z "$remote" ]; then - continue - fi + eval "tunnel $__SSHCMD" & + done + else + # shellcheck disable=2031 + eval "tunnel $__SSHCMD" & + fi - set -- -N "$user@$machine" -L "$local:$remote" - [ -n "$key" ] && set -- "$@" -i "$key" - #shellcheck disable=2086 - [ -n "$rest" ] && set -- "$@" $rest + wait +} - echo ssh "$@" +tunnel() { + # shellcheck disable=2086 + $_quiet || echo ssh "$@" + $_run && { + touch "$__PIDF" + while [ -e "$__PIDF" ]; do + grep -q -e "$*" "$__PIDF" && { + sleep 3 + continue + } + # shellcheck disable=2015 + if ssh "$@" & then + printf '%s\t%s\n' "$!" "$*" >>"$__PIDF" + else + badpid="$!" + kill "$badpid" + sed "/^$badpid/d" "$__PIDF" >"$__PIDF~" && + mv "$__PIDF~" "$__PIDF" + continue + fi + sleep 3 + done + } +} - "$dry_run" || { - while :; do - ssh "$@" - echo "$!" >>"$pidf" - sleep 5 - done & - } - done +tear_down() { + printf '%s...' "Killing extant tunnels" + if [ -e "$__PIDF" ]; then + while read -r pid _; do + kill "$pid" 2>/dev/null + done <"$__PIDF" + rm "$__PIDF" + else + pkill -x ssh + fi + echo Done. +} -wait +main "$@" -- cgit 1.4.1-21-gabe81