first commit
This commit is contained in:
commit
0610f4aeab
130 changed files with 9897 additions and 0 deletions
519
fn/-z4h-cmd-ssh
Normal file
519
fn/-z4h-cmd-ssh
Normal file
|
@ -0,0 +1,519 @@
|
|||
#!/usr/bin/env zsh
|
||||
|
||||
# TODO: write proper docs for these configuration options.
|
||||
#
|
||||
# zstyle ':z4h:ssh:my_host' enable 'yes'
|
||||
# zstyle ':z4h:ssh:*' send-extra-files '~/foo' '"$ZDOTDIR"/bar'
|
||||
# zstyle ':z4h:ssh:*' retrieve-extra-files '~/foo' '"$ZDOTDIR"/bar'
|
||||
# zstyle ':z4h:ssh:*' ssh-command command ssh
|
||||
# zstyle ':z4h:ssh:*' retrieve-history $ZDOTDIR/.zsh_history.remote
|
||||
# zstyle ':z4h:ssh:*' term tmux-256color
|
||||
#
|
||||
# z4h-ssh-configure() {
|
||||
# z4h_ssh_prelude+=(
|
||||
# "export BLAH=${(q)BLAH}"
|
||||
# )
|
||||
# z4h_ssh_send_files+=(
|
||||
# ~/foo '~/foo'
|
||||
# $ZDOTDIR/bar '"$ZDOTDIR"/bar'
|
||||
# )
|
||||
# z4h_ssh_setup+=(
|
||||
# 'echo "setting up"'
|
||||
# )
|
||||
# z4h_ssh_run=(
|
||||
# 'echo "starting z4h"'
|
||||
# $z4h_ssh_launch_commands
|
||||
# )
|
||||
# z4h_ssh_teardown+=(
|
||||
# 'echo "tearing down"'
|
||||
# )
|
||||
# z4h_ssh_retrieve_files+=(
|
||||
# '~/foo' ~/foo
|
||||
# '"$ZDOTDIR"/bar' $ZDOTDIR/bar
|
||||
# )
|
||||
# }
|
||||
|
||||
eval "$_z4h_opt"
|
||||
-z4h-check-core-params || return
|
||||
|
||||
if (( _z4h_dangerous_root )); then
|
||||
print -Pru2 -- "%F{3}z4h%f: refusing to %Bssh%b as %F{1}root%f"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local -i must_passthrough i
|
||||
local -a pos
|
||||
for ((i = 1; i <= $#; ++i)); do
|
||||
case $*[i] in
|
||||
--) (( ++i <= $# )) && pos+=({$i..$#}); break;;
|
||||
-[OG]) must_passthrough=1; ((++i));;
|
||||
-*) [[ bcDEeFIiJLlmOopQRSWw == *${${*[i]}[-1]}* ]] && ((++i));;
|
||||
*) pos+=($i);;
|
||||
esac
|
||||
done
|
||||
|
||||
local z4h_min_version
|
||||
z4h_min_version=${$(<$Z4H/zsh4humans/version)%$'\r'} || return
|
||||
if [[ $z4h_min_version != <1-> ]]; then
|
||||
print -Pru2 -- '%F{3}z4h%f: invalid file content: %F{1}%U$Z4H/zsh4humans/version%f%u'
|
||||
return 1
|
||||
fi
|
||||
local -r z4h_min_version
|
||||
|
||||
local -r z4h_ssh_client=${${(%):-%m}:-unknown}
|
||||
|
||||
local z4h_ssh_host
|
||||
if (( $#pos == 1 )); then
|
||||
local user_host=$*[pos[1]]
|
||||
z4h_ssh_host=${${user_host##*@}%%:*}
|
||||
fi
|
||||
local -r z4h_ssh_host
|
||||
|
||||
[[ -n $z4h_ssh_host ]] || must_passthrough=1
|
||||
|
||||
local -i z4h_ssh_enable=$(( !must_passthrough ))
|
||||
zstyle -t :z4h:ssh:$z4h_ssh_host enable || z4h_ssh_enable=0
|
||||
|
||||
local -i mkdir_control_master=0
|
||||
local default_ssh_command=(command ssh)
|
||||
if (( z4h_ssh_enable )); then
|
||||
mkdir_control_master=1
|
||||
default_ssh_command+=(
|
||||
-o ControlMaster=auto
|
||||
-o ControlPersist=5
|
||||
-o ControlPath='~/.ssh/s/%C')
|
||||
fi
|
||||
|
||||
local -a z4h_ssh_command
|
||||
if ! zstyle -a :z4h:ssh:$z4h_ssh_host ssh-command z4h_ssh_command; then
|
||||
z4h_ssh_command=($default_ssh_command)
|
||||
fi
|
||||
|
||||
local term
|
||||
zstyle -s :z4h:ssh:$z4h_ssh_host term term || term=${TERM:/tmux-256color/screen-256color}
|
||||
|
||||
local -A z4h_ssh_send_files z4h_ssh_retrieve_files
|
||||
local -a z4h_ssh_prelude z4h_ssh_setup z4h_ssh_run z4h_ssh_teardown
|
||||
local -aU z4h_retrieve_history
|
||||
|
||||
if (( !must_passthrough )); then
|
||||
z4h_ssh_prelude=(
|
||||
'"export" ZDOTDIR="$HOME"'
|
||||
'if command -v "locale" >"/dev/null" 2>&1; then
|
||||
"export" LC_ALL="C"
|
||||
fi')
|
||||
|
||||
z4h_ssh_send_files=(
|
||||
$ZDOTDIR/.zshenv '"$ZDOTDIR"/.zshenv'
|
||||
$ZDOTDIR/.zprofile '"$ZDOTDIR"/.zprofile'
|
||||
$ZDOTDIR/.zshrc '"$ZDOTDIR"/.zshrc'
|
||||
$ZDOTDIR/.zlogin '"$ZDOTDIR"/.zlogin'
|
||||
$ZDOTDIR/.zlogout '"$ZDOTDIR"/.zlogout')
|
||||
|
||||
local file
|
||||
for file in $ZDOTDIR/.p10k{,-ascii}{,-8color}.zsh(N) $ZDOTDIR/.zsh_history.*:$z4h_ssh_host(N); do
|
||||
z4h_ssh_send_files[$file]='"$ZDOTDIR"/'${(q)file:t}
|
||||
done
|
||||
|
||||
local -a extra_files
|
||||
if zstyle -a :z4h:ssh:$z4h_ssh_host send-extra-files extra_files; then
|
||||
local src dst
|
||||
for dst in $extra_files; do
|
||||
eval "src=$dst"
|
||||
z4h_ssh_send_files[$src]=$dst
|
||||
done
|
||||
fi
|
||||
|
||||
z4h_ssh_run=(
|
||||
'if "[" "-f" "$ZDOTDIR"/.zshenv "-a" "-r" "$ZDOTDIR"/.zshenv "]"; then
|
||||
"." "$ZDOTDIR"/.zshenv
|
||||
else
|
||||
>&2 "printf" "\\033[33mz4h\\033[0m: not a readable file: \\033[31m%s\033[0m\n" "$ZDOTDIR"/.zshenv
|
||||
"false"
|
||||
fi')
|
||||
|
||||
if zstyle -a :z4h:ssh:$z4h_ssh_host retrieve-extra-files extra_files; then
|
||||
local src dst
|
||||
for src in $extra_files; do
|
||||
eval "dst=$src"
|
||||
z4h_ssh_retrieve_files[$src]=$dst
|
||||
done
|
||||
fi
|
||||
|
||||
zstyle -a :z4h:ssh:$z4h_ssh_host retrieve-history z4h_retrieve_history || z4h_retrieve_history=()
|
||||
fi
|
||||
|
||||
local configure
|
||||
if zstyle -s :z4h:ssh:$z4h_ssh_host configure configure; then
|
||||
eval $configure || return
|
||||
elif (( $+functions[z4h-ssh-configure] )); then
|
||||
z4h-ssh-configure || return
|
||||
fi
|
||||
|
||||
if (( ! $#z4h_ssh_command )); then
|
||||
print -Pru2 -- '%F{3}z4h%f: empty %F{1}z4h_ssh_command%f'
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ $mkdir_control_master == 1 &&
|
||||
${(pj:\0:)z4h_ssh_command} == ${(pj:\0:)default_ssh_command} &&
|
||||
! -d ~/.ssh/s && -n ~(#qNU) ]]; then
|
||||
zf_mkdir -pm 700 ~/.ssh/s || return
|
||||
{
|
||||
>~/.ssh/s/README <<\END
|
||||
This directory has been created by `z4h ssh`. It stores control sockets
|
||||
for SSH connections. See ControlMaster, ControlPath and ControlPersist
|
||||
in `man ssh_config`. This directory must not be writable by anyone other
|
||||
than the current user.
|
||||
END
|
||||
} || return
|
||||
if [[ -e ~/.ssh/control-master/README ]]; then
|
||||
{
|
||||
>>~/.ssh/s/README <<\END
|
||||
|
||||
You might also have ~/.ssh/control-master with the same file in it. This
|
||||
is the old directory that was used by zsh4humans for the same purpose
|
||||
before 2021-11-14. If you don't reference that directory explicitly from
|
||||
~/.ssh/config, you can safely delete it.
|
||||
END
|
||||
} || return
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( must_passthrough || !z4h_ssh_enable )); then
|
||||
TERM=${term:-$TERM} "${z4h_ssh_command[@]}" "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
if (( $#z4h_retrieve_history )); then
|
||||
local local_hist_tmp=$Z4H/tmp/ssh-history.tmp.$sysparams[pid]
|
||||
z4h_ssh_retrieve_files[\$HISTFILE]=$local_hist_tmp
|
||||
zf_rm -f -- $local_hist_tmp || return
|
||||
else
|
||||
local local_hist_tmp=
|
||||
fi
|
||||
|
||||
local file
|
||||
for file in "${(@kv)z4h_ssh_send_files}"; do
|
||||
if [[ -z $file ]]; then
|
||||
print -Pru2 -- '%F{3}z4h%f: empty element(s) in %F{1}z4h_ssh_send_files%f'
|
||||
return 1
|
||||
fi
|
||||
if [[ $file == */ ]]; then
|
||||
print -Pru2 -- "%F{3}z4h%f: element(s) of %Bz4h_ssh_send_files%b end with %B/%b: %F{1}${file//\%/%%}%f"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
for file in "${(@kv)z4h_ssh_retrieve_files}"; do
|
||||
if [[ -z $file ]]; then
|
||||
print -Pru2 -- '%F{3}z4h%f: empty element(s) in %F{1}z4h_ssh_retrieve_files%f'
|
||||
return 1
|
||||
fi
|
||||
if [[ $file == */ ]]; then
|
||||
print -Pru2 -- "%F{3}z4h%f: element(s) of %Bz4h_ssh_retrieve_files%b end with %B/%b: %F{1}${file//\%/%%}%f"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
for file in "${(@)z4h_retrieve_history}"; do
|
||||
if [[ -z $file ]]; then
|
||||
print -Pru2 -- '%F{3}z4h%f: empty element(s) in %F{1}z4h_retrieve_history%f'
|
||||
return 1
|
||||
fi
|
||||
if [[ $file == */ ]]; then
|
||||
print -Pru2 -- "%F{3}z4h%f: element(s) of %Bz4h_retrieve_history%b end with %B/%b: %F{1}${file//\%/%%}%f"
|
||||
return 1
|
||||
fi
|
||||
if [[ -e $file ]]; then
|
||||
if [[ ! ( -f $file && -r $file && -w $file ) ]]; then
|
||||
print -Pru2 -- "%F{3}z4h%f: element of %Bz4h_retrieve_history%b is not a readable & writable file: %F{1}${file//\%/%%}%f"
|
||||
return 1
|
||||
fi
|
||||
elif [[ -d ${file:h} ]]; then
|
||||
if [[ ! -w ${file:h} ]]; then
|
||||
print -Pru2 -- "%F{3}z4h%f: element of %Bz4h_retrieve_history%b is in a non-writable directory: %F{1}${file//\%/%%}%f"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
zf_mkdir -p -- ${file:h} || return
|
||||
fi
|
||||
done
|
||||
|
||||
if (( $#z4h_ssh_retrieve_files && ! $+commands[base64] )); then
|
||||
print -Pru2 -- '%F{3}z4h%f: command not found: %F{1}base64%f'
|
||||
return 1
|
||||
fi
|
||||
|
||||
local tmpdir
|
||||
if (( $+commands[mktemp] )); then
|
||||
tmpdir=$(command mktemp -d -- $Z4H/tmp/ssh.XXXXXXXXXX) || return
|
||||
else
|
||||
tmpdir=$Z4H/tmp/ssh.tmp.$sysparams[pid]
|
||||
zf_rm -rf -- $tmpdir || return
|
||||
zf_mkdir -- $tmpdir || return
|
||||
fi
|
||||
|
||||
{
|
||||
local -i i=0
|
||||
local src dst
|
||||
local indices=() send_to=()
|
||||
for src dst in ${(kv)z4h_ssh_send_files}; do
|
||||
(( ++i ))
|
||||
send_to+=($dst)
|
||||
[[ -e $src ]] || continue
|
||||
local target=${src:A}
|
||||
if [[ -z $target(#qN.) && -z $target(#qN/) ]]; then
|
||||
print -Pru2 -- "%F{3}z4h%f: unsupported file type: %F{1}${src//\%/%%}%f"
|
||||
return 1
|
||||
fi
|
||||
if [[ ${tmpdir:A} == $target(|/*) ]]; then
|
||||
print -Pru2 -- "%F{3}z4h%f: cannot send file: %F{1}${src//\%/%%}%f"
|
||||
return 1
|
||||
fi
|
||||
zf_ln -s -- $target $tmpdir/$i || return
|
||||
indices+=($i)
|
||||
done
|
||||
|
||||
local -a retrieve_from retrieve_to
|
||||
local from to
|
||||
for from to in ${(kv)z4h_ssh_retrieve_files}; do
|
||||
retrieve_from+=($from)
|
||||
retrieve_to+=($to)
|
||||
done
|
||||
|
||||
local dump_marker=${(%):-%n}.$sysparams[pid].$EPOCHSECONDS.$RANDOM
|
||||
|
||||
local script
|
||||
script=${"$(<$Z4H/zsh4humans/sc/ssh-bootstrap)"//$'\r'} || return
|
||||
script=${script//'^TERM^'/${(q)term}}
|
||||
script=${script//'^MIN_VERSION^'/${(q)z4h_min_version}}
|
||||
script=${script//'^SSH_HOST^'/${(q)z4h_ssh_host}}
|
||||
script=${script//'^SSH_CLIENT^'/${(q)z4h_ssh_client}}
|
||||
script=${script//'^SSH_ARGS^'/${(q)${(j: :)@}}}
|
||||
script=${script//'^PRELUDE^'/${(F)z4h_ssh_prelude}}
|
||||
script=${script//'^SEND_TO^'/${(j: :)send_to}}
|
||||
script=${script//'^SETUP^'/${(F)z4h_ssh_setup}}
|
||||
script=${script//'^RUN^'/${(F)z4h_ssh_run}}
|
||||
script=${script//'^TEARDOWN^'/${(F)z4h_ssh_teardown}}
|
||||
if (( $#retrieve_from )); then
|
||||
script=${script//'^EMPTY_RETRIEVE_FROM^'/"'false'"}
|
||||
else
|
||||
script=${script//'^EMPTY_RETRIEVE_FROM^'/"'true'"}
|
||||
fi
|
||||
script=${script//'^RETRIEVE_FROM^'/${(j: :)retrieve_from}}
|
||||
script=${script//'^DUMP_MARKER^'/${(q)dump_marker}}
|
||||
script=${script//'^CAN_SAVE_RESTORE_SCREEN^'/${_z4h_can_save_restore_screen}}
|
||||
|
||||
script=${script//'^DUMP_POS^'/${(r:8:: :)${#script}}}
|
||||
|
||||
print -r -- $script >$tmpdir/script || return
|
||||
|
||||
local tar_v tar_c_opt tar_x_opt
|
||||
if tar_v=$(command tar --version 2>/dev/null) && [[ $tar_v == *'GNU tar'* ]]; then
|
||||
tar_c_opt=(--owner=0 --group=0)
|
||||
tar_x_opt=(--warning=no-unknown-keyword --warning=no-timestamp --no-same-owner)
|
||||
fi
|
||||
|
||||
if (( $#indices )); then
|
||||
command tar -C $tmpdir $tar_c_opt -czhf - -- $indices >>$tmpdir/script || return
|
||||
fi
|
||||
|
||||
local args=("$@")
|
||||
args[pos[1],pos[1]-1]=('-T')
|
||||
local remote_script=.z4h-ssh.${(%):-%n}.$sysparams[pid].$EPOCHSECONDS.$RANDOM
|
||||
|
||||
# Tricky corner cases where this command must work:
|
||||
#
|
||||
# 1. The remote shell is csh (default on FreeBSD).
|
||||
# 2. There is no /tmp on the remote host (e.g., Termux).
|
||||
# 3. TMPDIR is not set.
|
||||
# 4. TMPDIR has spaces in it.
|
||||
#
|
||||
# The next command (the one that invokes /bin/sh) must also work in these
|
||||
# cases. It should also propagate the exit status of /bin/sh.
|
||||
local cmd="test -w /tmp && cat >/tmp/$remote_script && echo 1 && exit"
|
||||
cmd+=" || "
|
||||
cmd+="test ! -e /tmp/$remote_script && cat >~/$remote_script && echo 2"
|
||||
local loc
|
||||
loc=$("${z4h_ssh_command[@]}" "${args[@]}" $cmd <$tmpdir/script) || return
|
||||
} always {
|
||||
zf_rm -rf -- $tmpdir
|
||||
}
|
||||
|
||||
case ${loc//[[:space:]]} in
|
||||
1) remote_script="/tmp/$remote_script";;
|
||||
2) remote_script="~/$remote_script";;
|
||||
*)
|
||||
print -Pru2 -- "%F{3}z4h%f: failed to upload bootstrap script"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
args[pos[1]]='-t'
|
||||
|
||||
local stty
|
||||
if [[ -v commands[stty] && -v _z4h_tty_fd ]]; then
|
||||
stty=$(command stty -g <&$_z4h_tty_fd 2>/dev/null) || stty=
|
||||
fi
|
||||
|
||||
{ ( # subshell to avoid TTOU
|
||||
|
||||
local -i bypass=0
|
||||
|
||||
local -i pid=$sysparams[pid]
|
||||
|
||||
{
|
||||
setopt no_multi_os
|
||||
"${z4h_ssh_command[@]}" "${args[@]}" "sh $remote_script" 2>&1 1>&3 |
|
||||
LC_ALL=C command grep -vxE '(Shared c|C)onnection to .* closed\.(.)?' >&2
|
||||
return $pipestatus[1]
|
||||
} 3>&1 | {
|
||||
if (( $+commands[mktemp] )); then
|
||||
tmpdir=$(command mktemp -d -- $Z4H/tmp/ssh.XXXXXXXXXX) || return
|
||||
else
|
||||
tmpdir=$Z4H/tmp/ssh.tmp.$sysparams[pid]
|
||||
zf_rm -rf -- $tmpdir || return
|
||||
zf_mkdir -- $tmpdir || return
|
||||
fi
|
||||
|
||||
unsetopt multibyte
|
||||
local LC_ALL=C
|
||||
|
||||
unset _z4h_saved_screen
|
||||
|
||||
{
|
||||
local buf=
|
||||
local mark=$'\001z4h.'$dump_marker
|
||||
while true; do
|
||||
[[ -n $buf ]] || sysread 'buf[$#buf+1]' || return $(( $? != 5 ))
|
||||
if [[ $buf != *$mark[1]* ]]; then
|
||||
print -rn -- $buf
|
||||
buf=
|
||||
continue
|
||||
fi
|
||||
while true; do
|
||||
print -rn -- ${buf%%$mark[1]*}
|
||||
buf=$mark[1]${buf#*$mark[1]}
|
||||
local -i prefix=$(($#buf < $#mark ? $#buf : $#mark))
|
||||
(( prefix )) || continue
|
||||
[[ ${buf:0:$prefix} == ${mark:0:$prefix} ]] && break
|
||||
print -rn -- $buf[1]
|
||||
buf[1]=""
|
||||
continue 2
|
||||
done
|
||||
while (( $#buf < $#mark )) && [[ $mark == $buf* ]]; do
|
||||
# What should we do if the output ends with a proper prefix of mark?
|
||||
# Print it or not? Return an error or not? We choose to not print and return
|
||||
# success iff we've reached eof.
|
||||
sysread -s $(($#mark - $#buf)) 'buf[$#buf+1]' && continue
|
||||
return $(( $? != 5 ))
|
||||
done
|
||||
if [[ $buf != $mark* ]]; then
|
||||
print -rn -- $buf[1]
|
||||
buf[1]=""
|
||||
continue
|
||||
fi
|
||||
buf[1,$#mark]=""
|
||||
while (( $#buf < 16 )); do
|
||||
sysread -s $((16 - $#buf)) 'buf[$#buf+1]' && continue
|
||||
return $(( $? != 5 ))
|
||||
done
|
||||
|
||||
{
|
||||
case ${buf[1,16]%% #} in
|
||||
bypass)
|
||||
bypass=1
|
||||
break
|
||||
;;
|
||||
save-screen)
|
||||
(( _z4h_can_save_restore_screen )) || return
|
||||
local _z4h_saved_screen=
|
||||
-z4h-save-screen || return
|
||||
_z4h_saved_screen+=x
|
||||
continue
|
||||
;;
|
||||
restore-screen)
|
||||
[[ -n $_z4h_saved_screen ]] || return
|
||||
_z4h_saved_screen[-1]=
|
||||
-z4h-restore-screen || return
|
||||
unset _z4h_saved_screen
|
||||
continue
|
||||
;;
|
||||
<->)
|
||||
local -i len=buf[1,16]
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
} always {
|
||||
buf=${buf:16}
|
||||
}
|
||||
|
||||
(( len )) || continue
|
||||
if [[ -d $tmpdir ]]; then
|
||||
local dump_file=$tmpdir/dump.base64
|
||||
else
|
||||
local dump_file=/dev/null
|
||||
fi
|
||||
{
|
||||
local -i n=$((len < $#buf ? len : $#buf))
|
||||
print -rn -- $buf[1,n] || return
|
||||
(( len -= n ))
|
||||
buf[1,n]=""
|
||||
while (( len )); do
|
||||
sysread -s $((len > 65636 ? 65636 : len)) -o 1 -c n || return $(( $? != 5 ))
|
||||
(( len -= n, 1 ))
|
||||
done
|
||||
} >$dump_file || return
|
||||
if [[ $dump_file != /dev/null ]]; then
|
||||
if base64 -d <<<'Cg==' &>/dev/null; then
|
||||
local base64_opt=-d
|
||||
else
|
||||
local base64_opt=-D
|
||||
fi
|
||||
<$tmpdir/dump.base64 command base64 $base64_opt |
|
||||
command tar -C $tmpdir $tar_x_opt -xzf - || return
|
||||
local -i i
|
||||
for i in {1..$#retrieve_to}; do
|
||||
local src=$tmpdir/$i
|
||||
local dst=$retrieve_to[i]
|
||||
[[ -e $src ]] || continue
|
||||
if [[ -e $dst ]]; then
|
||||
zf_rm -rf -- $dst || return
|
||||
fi
|
||||
if ! command mv -f -- $src $dst 2>/dev/null; then
|
||||
command cp -rf -- $src $dst || return
|
||||
fi
|
||||
done
|
||||
if [[ -s $local_hist_tmp ]]; then
|
||||
local local_hist
|
||||
for local_hist in $z4h_retrieve_history; do
|
||||
local TMPPREFIX=$local_hist
|
||||
() {
|
||||
() { fc -pa -- $1 $HISTSIZE $SAVEHIST } $1 && zf_mv -f -- $1 $local_hist
|
||||
} =(command cat -- $local_hist(N) $local_hist_tmp) || return
|
||||
done
|
||||
fi
|
||||
fi
|
||||
done
|
||||
} always {
|
||||
local -i err=$?
|
||||
zf_rm -rf -- $tmpdir $local_hist_tmp
|
||||
if (( err )); then
|
||||
kill -- -$pid 2>/dev/null
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
if (( bypass )); then
|
||||
setopt no_multi_os
|
||||
{
|
||||
TERM=${term:-$TERM} "${z4h_ssh_command[@]}" "${args[@]}" 2>&1 1>&3 |
|
||||
LC_ALL=C command grep -vxE '(Shared c|C)onnection to .* closed\.(.)?' >&2
|
||||
return $pipestatus[1]
|
||||
} 3>&1
|
||||
fi
|
||||
|
||||
) } always {
|
||||
[[ -n $stty ]] && command stty $stty <&$_z4h_tty_fd 2>/dev/null
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue