1#!/usr/bin/env zsh23local usage=(4 "$0 -L local_port:remote_addr:remote_port target"5 "$0 [-k|--kill] target"6 "$0 [-l|--list]"7 "$0 [-h|--help]"8)91011function _forward(){12 local o_target addr_parts1314 o_addr="$1"15 o_target="$2"1617 addr_parts=(${(s/:/)o_addr})18 case ${#addr_parts[@]} in19 1)20 o_addr="$addr_parts[1]:0:$addr_parts[1]"21 ;;22 2)23 o_addr="$addr_parts[1]:0:$addr_parts[2]"24 ;;25 esac2627 [[ -d $HOME/.ssh/controlmaster ]] || mkdir -p $HOME/.ssh/controlmaster2829 ssh -f -N -L $o_addr \30 -o ExitOnForwardFailure=yes \31 -o ControlMaster=auto \32 -o ControlPath="$HOME/.ssh/controlmaster/%n|$o_addr|%r@%h|%p" \33 $o_target34}3536function _list() {37 local controllers38 controllers=`find $HOME/.ssh/controlmaster -maxdepth 1 -type s -exec basename {} \;`3940 for c in $controllers; do41 echo $c42 done43}4445function _kill() {46 setopt globstarshort47 setopt null_glob48 for pattern in $@; do49 for controlpath in $(eval "echo $HOME/.ssh/controlmaster/$pattern(=)"); do50 file=$(basename $controlpath)51 echo "$file exiting"52 ssh -o ControlMaster=auto \53 -o ControlPath="$controlpath" -O exit ${(s/:/)o_addr} \54 ${${(s/|/)file}[1]}55 done5657 done58}5960local o_help o_addr o_list o_kill6162zmodload zsh/zutil63zparseopts -D -F -K -- \64 L:=o_addr \65 {l,-list}=o_list \66 {k,-kill}=o_kill \67 {h,-help}=o_help || return 16869[[ -z "$o_help" ]] || { print -l $usage && exit $? }70[[ -z "$o_addr" ]] || { _forward $o_addr[-1] $@ && exit $?}71[[ -z "$o_list" ]] || { _list $@ && exit $?}72[[ -z "$o_kill" ]] || { _kill $@ && exit $?}73