From 99581b6eda314ad01e14f6d04fdf3fb63746a978 Mon Sep 17 00:00:00 2001 From: harsxv Date: Wed, 19 Mar 2025 14:31:35 +0800 Subject: [PATCH] feat: SetEnv --- AUTHORS | 1 + contrib/completion/bash_autocomplete | 41 ++++++++++++++++------------ contrib/completion/zsh_autocomplete | 4 +-- pkg/config/host.go | 28 ++++++++++++++++--- 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/AUTHORS b/AUTHORS index cb113f624..c74bf21a3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -5,6 +5,7 @@ Aaron Bach adasauce <60991921+adasauce@users.noreply.github.com> ahh Alen Masic +Alexander Proschek Anthony Cruz Ash Matadeen Ashish SHUKLA diff --git a/contrib/completion/bash_autocomplete b/contrib/completion/bash_autocomplete index b7096afeb..6ea09683f 100644 --- a/contrib/completion/bash_autocomplete +++ b/contrib/completion/bash_autocomplete @@ -2,7 +2,7 @@ __assh_debug() { - if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then + if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then echo "$*" >> "${BASH_COMP_DEBUG_FILE}" fi } @@ -112,7 +112,7 @@ __assh_handle_go_custom_completion() $filteringCmd elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then # File completion for directories only - local subDir + local subdir # Use printf to strip any trailing newline subdir=$(printf "%s" "${out[0]}") if [ -n "$subdir" ]; then @@ -165,13 +165,19 @@ __assh_handle_reply() PREFIX="" cur="${cur#*=}" ${flags_completion[${index}]} - if [ -n "${ZSH_VERSION}" ]; then + if [ -n "${ZSH_VERSION:-}" ]; then # zsh completion needs --flag= prefix eval "COMPREPLY=( \"\${COMPREPLY[@]/#/${flag}=}\" )" fi fi fi - return 0; + + if [[ -z "${flag_parsing_disabled}" ]]; then + # If flag parsing is enabled, we have completed the flags and can return. + # If flag parsing is disabled, we may not know all (or any) of the flags, so we fallthrough + # to possibly call handle_go_custom_completion. + return 0; + fi ;; esac @@ -210,13 +216,13 @@ __assh_handle_reply() fi if [[ ${#COMPREPLY[@]} -eq 0 ]]; then - if declare -F __assh_custom_func >/dev/null; then - # try command name qualified custom func - __assh_custom_func - else - # otherwise fall back to unqualified for compatibility - declare -F __custom_func >/dev/null && __custom_func - fi + if declare -F __assh_custom_func >/dev/null; then + # try command name qualified custom func + __assh_custom_func + else + # otherwise fall back to unqualified for compatibility + declare -F __custom_func >/dev/null && __custom_func + fi fi # available in bash-completion >= 2, not always present on macOS @@ -250,7 +256,7 @@ __assh_handle_flag() # if a command required a flag, and we found it, unset must_have_one_flag() local flagname=${words[c]} - local flagvalue + local flagvalue="" # if the word contained an = if [[ ${words[c]} == *"="* ]]; then flagvalue=${flagname#*=} # take in as flagvalue after the = @@ -269,7 +275,7 @@ __assh_handle_flag() # keep flag value with flagname as flaghash # flaghash variable is an associative array which is only supported in bash > 3. - if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then if [ -n "${flagvalue}" ] ; then flaghash[${flagname}]=${flagvalue} elif [ -n "${words[ $((c+1)) ]}" ] ; then @@ -281,7 +287,7 @@ __assh_handle_flag() # skip the argument to a two word flag if [[ ${words[c]} != *"="* ]] && __assh_contains_word "${words[c]}" "${two_word_flags[@]}"; then - __assh_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument" + __assh_debug "${FUNCNAME[0]}: found a flag ${words[c]}, skip the next argument" c=$((c+1)) # if we are looking for a flags value, don't show commands if [[ $c -eq $cword ]]; then @@ -341,7 +347,7 @@ __assh_handle_word() __assh_handle_command elif __assh_contains_word "${words[c]}" "${command_aliases[@]}"; then # aliashash variable is an associative array which is only supported in bash > 3. - if [[ -z "${BASH_VERSION}" || "${BASH_VERSINFO[0]}" -gt 3 ]]; then + if [[ -z "${BASH_VERSION:-}" || "${BASH_VERSINFO[0]:-}" -gt 3 ]]; then words[c]=${aliashash[${words[c]}]} __assh_handle_command else @@ -671,6 +677,7 @@ __start_assh() fi local c=0 + local flag_parsing_disabled= local flags=() local two_word_flags=() local local_nonpersistent_flags=() @@ -680,8 +687,8 @@ __start_assh() local command_aliases=() local must_have_one_flag=() local must_have_one_noun=() - local has_completion_function - local last_command + local has_completion_function="" + local last_command="" local nouns=() local noun_aliases=() diff --git a/contrib/completion/zsh_autocomplete b/contrib/completion/zsh_autocomplete index f37fcdf3b..b29d2c6f6 100644 --- a/contrib/completion/zsh_autocomplete +++ b/contrib/completion/zsh_autocomplete @@ -125,7 +125,7 @@ _assh() _arguments '*:filename:'"$filteringCmd" elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then # File completion for directories only - local subDir + local subdir subdir="${completions[1]}" if [ -n "$subdir" ]; then __assh_debug "Listing directories in $subdir" @@ -173,5 +173,5 @@ _assh() # don't run the completion function when being source-ed or eval-ed if [ "$funcstack[1]" = "_assh" ]; then - _assh + _assh fi diff --git a/pkg/config/host.go b/pkg/config/host.go index ee0fa5ef6..1573055fc 100644 --- a/pkg/config/host.go +++ b/pkg/config/host.go @@ -96,6 +96,7 @@ type Host struct { RhostsRSAAuthentication string `yaml:"rhostsrsaauthentication,omitempty,flow" json:"RhostsRSAAuthentication,omitempty"` RSAAuthentication string `yaml:"rsaauthentication,omitempty,flow" json:"RSAAuthentication,omitempty"` SendEnv composeyaml.Stringorslice `yaml:"sendenv,omitempty,flow" json:"SendEnv,omitempty"` + SetEnv composeyaml.Stringorslice `yaml:"setenv,omitempty,flow" json:"SetEnv,omitempty"` ServerAliveCountMax int `yaml:"serveralivecountmax,omitempty,flow" json:"ServerAliveCountMax,omitempty"` ServerAliveInterval int `yaml:"serveraliveinterval,omitempty,flow" json:"ServerAliveInterval,omitempty"` StreamLocalBindMask string `yaml:"streamlocalbindmask,omitempty,flow" json:"StreamLocalBindMask,omitempty"` @@ -480,8 +481,15 @@ func (h *Host) Options() OptionsList { if h.RSAAuthentication != "" { options = append(options, Option{Name: "RSAAuthentication", Value: h.RSAAuthentication}) } - for _, entry := range h.SendEnv { - options = append(options, Option{Name: "SendEnv", Value: entry}) + if len(h.SendEnv) > 0 { + for _, env := range h.SendEnv { + options = append(options, Option{Name: "SendEnv", Value: env}) + } + } + if len(h.SetEnv) > 0 { + for _, env := range h.SetEnv { + options = append(options, Option{Name: "SetEnv", Value: env}) + } } if h.ServerAliveCountMax != 0 { options = append(options, Option{Name: "ServerAliveCountMax", Value: fmt.Sprintf("%d", h.ServerAliveCountMax)}) @@ -991,6 +999,11 @@ func (h *Host) ApplyDefaults(defaults *Host) { } h.SendEnv = utils.ExpandSliceField(h.SendEnv) + if len(h.SetEnv) == 0 { + h.SetEnv = defaults.SetEnv + } + h.SetEnv = utils.ExpandSliceField(h.SetEnv) + if h.ServerAliveCountMax == 0 { h.ServerAliveCountMax = defaults.ServerAliveCountMax } @@ -1403,8 +1416,15 @@ func (h *Host) WriteSSHConfigTo(w io.Writer) error { if h.RSAAuthentication != "" { _, _ = fmt.Fprintf(w, " RSAAuthentication %s\n", h.RSAAuthentication) } - for _, entry := range h.SendEnv { - _, _ = fmt.Fprintf(w, " SendEnv %s\n", entry) + if len(h.SendEnv) > 0 { + for _, env := range h.SendEnv { + _, _ = fmt.Fprintf(w, " SendEnv %s\n", env) + } + } + if len(h.SetEnv) > 0 { + for _, env := range h.SetEnv { + _, _ = fmt.Fprintf(w, " SetEnv %s\n", env) + } } if h.ServerAliveCountMax != 0 { _, _ = fmt.Fprintf(w, " ServerAliveCountMax %d\n", h.ServerAliveCountMax)