diff --git a/go.mod b/go.mod index 083f1b5..da5744f 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/trzsz/go-arg v1.5.3 github.com/trzsz/iterm2 v0.1.2 github.com/trzsz/promptui v0.10.7 - github.com/trzsz/ssh_config v1.3.5 + github.com/trzsz/ssh_config v1.3.6 github.com/trzsz/trzsz-go v1.1.8-0.20240525015006-6424386a6738 golang.org/x/crypto v0.23.0 golang.org/x/sys v0.20.0 diff --git a/go.sum b/go.sum index 9b66946..c934de6 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,8 @@ github.com/trzsz/iterm2 v0.1.2 h1:VwfLzr2fKeaLf+p4tS0ms+kqdiQQxVLbTJUoyuQXmK8= github.com/trzsz/iterm2 v0.1.2/go.mod h1:PMI+3JcT7J9D0T6e3mOWv8ICYdrrNZwuge3Tm7zDLws= github.com/trzsz/promptui v0.10.7 h1:77uBrmsIPYYJS/9n+zwFRhwOz82EKXkkdjOiWSEUPpk= github.com/trzsz/promptui v0.10.7/go.mod h1:9dp59ixe32qBV9GjDxQ1PDWwbzHjTzveZenQwEoVHbg= -github.com/trzsz/ssh_config v1.3.5 h1:wSZT2PG/7IICvHTIGeDQF5xT5HMXwRfYdnC8IcM3Yk8= -github.com/trzsz/ssh_config v1.3.5/go.mod h1:Dl1okTjVVfsrtTA8nqkJ1OnjiCrZY6DUEI2DGT2/YoQ= +github.com/trzsz/ssh_config v1.3.6 h1:+LBCg2uzhAgw2s19yqeUdD4YwW2z4kvlsXtKB6zDjmQ= +github.com/trzsz/ssh_config v1.3.6/go.mod h1:uSVHpGOTpBwE1FwyUrtnanlFuxZKt4dvdKFVKe41h58= github.com/trzsz/trzsz-go v1.1.8-0.20240525015006-6424386a6738 h1:yPNjsEKiQAkBtbPBHWKg8sZcx2NhEvK1WmfmVMs3Moc= github.com/trzsz/trzsz-go v1.1.8-0.20240525015006-6424386a6738/go.mod h1:fBEGNZiKmGYodYENKATNuz/U3Wzt6MWWJs3ox0CzPhM= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= diff --git a/tssh/config.go b/tssh/config.go index 65a78ba..683a7fb 100644 --- a/tssh/config.go +++ b/tssh/config.go @@ -40,6 +40,7 @@ import ( "strings" "sync" + "github.com/google/shlex" "github.com/mitchellh/go-homedir" "github.com/trzsz/ssh_config" ) @@ -313,13 +314,19 @@ func getConfig(alias, key string) string { userConfig.doLoadConfig() if userConfig.config != nil { - if value, _ := userConfig.config.Get(alias, key); value != "" { + value, err := userConfig.config.Get(alias, key) + if err != nil { + warning("get user config [%s] for [%s] failed: %v", key, alias, err) + } else if value != "" { return value } } if userConfig.sysConfig != nil { - if value, _ := userConfig.sysConfig.Get(alias, key); value != "" { + value, err := userConfig.sysConfig.Get(alias, key) + if err != nil { + warning("get sys config [%s] for [%s] failed: %v", key, alias, err) + } else if value != "" { return value } } @@ -327,17 +334,56 @@ func getConfig(alias, key string) string { return ssh_config.Default(key) } +func getConfigSplits(alias, key string) []string { + userConfig.doLoadConfig() + + if userConfig.config != nil { + values, err := userConfig.config.GetSplits(alias, key) + if err != nil { + warning("get user config splits [%s] for [%s] failed: %v", key, alias, err) + } else if len(values) > 0 { + return values + } + } + + if userConfig.sysConfig != nil { + values, err := userConfig.sysConfig.GetSplits(alias, key) + if err != nil { + warning("get sys config splits [%s] for [%s] failed: %v", key, alias, err) + } else if len(values) > 0 { + return values + } + } + + if value := ssh_config.Default(key); value != "" { + values, err := shlex.Split(value) + if err != nil { + warning("split default [%s] value [%s] failed: %v", key, value, err) + } else if len(values) > 0 { + return values + } + } + + return nil +} + func getAllConfig(alias, key string) []string { userConfig.doLoadConfig() var values []string if userConfig.config != nil { - if vals, _ := userConfig.config.GetAll(alias, key); len(vals) > 0 { + vals, err := userConfig.config.GetAll(alias, key) + if err != nil { + warning("get all user config [%s] for [%s] failed: %v", key, alias, err) + } else if len(vals) > 0 { values = append(values, vals...) } } if userConfig.sysConfig != nil { - if vals, _ := userConfig.sysConfig.GetAll(alias, key); len(vals) > 0 { + vals, err := userConfig.sysConfig.GetAll(alias, key) + if err != nil { + warning("get all sys config [%s] for [%s] failed: %v", key, alias, err) + } else if len(vals) > 0 { values = append(values, vals...) } } @@ -345,8 +391,43 @@ func getAllConfig(alias, key string) []string { return values } - if d := ssh_config.Default(key); d != "" { - values = append(values, d) + if value := ssh_config.Default(key); value != "" { + values = append(values, value) + } + return values +} + +func getAllConfigSplits(alias, key string) []string { + userConfig.doLoadConfig() + + var values []string + if userConfig.config != nil { + vals, err := userConfig.config.GetAllSplits(alias, key) + if err != nil { + warning("get all user config splits [%s] for [%s] failed: %v", key, alias, err) + } else if len(vals) > 0 { + values = append(values, vals...) + } + } + if userConfig.sysConfig != nil { + vals, err := userConfig.sysConfig.GetAllSplits(alias, key) + if err != nil { + warning("get all sys config splits [%s] for [%s] failed: %v", key, alias, err) + } else if len(vals) > 0 { + values = append(values, vals...) + } + } + if len(values) > 0 { + return values + } + + if value := ssh_config.Default(key); value != "" { + vals, err := shlex.Split(value) + if err != nil { + warning("split default [%s] value [%s] failed: %v", key, value, err) + } else if len(vals) > 0 { + values = append(values, vals...) + } } return values } @@ -355,8 +436,10 @@ func getExConfig(alias, key string) string { userConfig.doLoadExConfig() if userConfig.exConfig != nil { - value, _ := userConfig.exConfig.Get(alias, key) - if value != "" { + value, err := userConfig.exConfig.Get(alias, key) + if err != nil { + warning("get extended config [%s] for [%s] failed: %v", key, alias, err) + } else if value != "" { debug("get extended config [%s] for [%s] success", key, alias) return value } @@ -376,7 +459,10 @@ func getAllExConfig(alias, key string) []string { var values []string if userConfig.exConfig != nil { - if vals, _ := userConfig.exConfig.GetAll(alias, key); len(vals) > 0 { + vals, err := userConfig.exConfig.GetAll(alias, key) + if err != nil { + warning("get all extended config [%s] for [%s] failed: %v", key, alias, err) + } else if len(vals) > 0 { values = append(values, vals...) } } @@ -477,10 +563,38 @@ func getOptionConfig(args *sshArgs, option string) string { return getConfig(args.Destination, option) } +func getOptionConfigSplits(args *sshArgs, option string) []string { + if value := args.Option.get(option); value != "" { + values, err := shlex.Split(value) + if err != nil { + warning("split option [%s] value [%s] failed: %v", option, value, err) + } + return values + } + return getConfigSplits(args.Destination, option) +} + func getAllOptionConfig(args *sshArgs, option string) []string { return append(args.Option.getAll(option), getAllConfig(args.Destination, option)...) } +func getAllOptionConfigSplits(args *sshArgs, option string) []string { + var all []string + for _, value := range args.Option.getAll(option) { + values, err := shlex.Split(value) + if err != nil { + warning("split option [%s] value [%s] failed: %v", option, value, err) + } else if len(values) > 0 { + all = append(all, values...) + } + } + values := getAllConfigSplits(args.Destination, option) + if len(values) > 0 { + all = append(all, values...) + } + return all +} + func getExOptionConfig(args *sshArgs, option string) string { if value := args.Option.get(option); value != "" { return value diff --git a/tssh/env.go b/tssh/env.go index f9c2a51..71a3157 100644 --- a/tssh/env.go +++ b/tssh/env.go @@ -30,7 +30,6 @@ import ( "regexp" "strings" - "github.com/google/shlex" "golang.org/x/crypto/ssh" ) @@ -41,11 +40,9 @@ type sshEnv struct { func getSendEnvs(args *sshArgs) ([]*sshEnv, error) { envSet := make(map[string]struct{}) - for _, envCfg := range getAllOptionConfig(args, "SendEnv") { - for _, env := range strings.Fields(envCfg) { - if len(env) > 0 { - envSet[env] = struct{}{} - } + for _, env := range getAllOptionConfigSplits(args, "SendEnv") { + if len(env) > 0 { + envSet[env] = struct{}{} } } if len(envSet) == 0 { @@ -103,23 +100,19 @@ func getSendEnvs(args *sshArgs) ([]*sshEnv, error) { } func getSetEnvs(args *sshArgs) ([]*sshEnv, error) { - envCfg := getOptionConfig(args, "SetEnv") - if envCfg == "" { + setEnvs := getOptionConfigSplits(args, "SetEnv") + if len(setEnvs) == 0 { return nil, nil } - tokens, err := shlex.Split(envCfg) - if err != nil { - return nil, fmt.Errorf("invalid SetEnv: %s", envCfg) - } var envs []*sshEnv - for _, token := range tokens { + for _, token := range setEnvs { pos := strings.IndexRune(token, '=') if pos < 0 { - return nil, fmt.Errorf("invalid SetEnv: %s", envCfg) + return nil, fmt.Errorf("invalid SetEnv: %s", token) } name := strings.TrimSpace(token[:pos]) if name == "" { - return nil, fmt.Errorf("invalid SetEnv: %s", envCfg) + return nil, fmt.Errorf("invalid SetEnv: %s", token) } value := strings.TrimSpace(token[pos+1:]) envs = append(envs, &sshEnv{name, value}) diff --git a/tssh/login.go b/tssh/login.go index 6a73b53..f1eed34 100644 --- a/tssh/login.go +++ b/tssh/login.go @@ -318,12 +318,16 @@ func getHostKeyCallback(args *sshArgs, param *sshParam) (ssh.HostKeyCallback, kn primaryPath := "" var files []string addKnownHostsFiles := func(key string, user bool) error { - knownHostsFiles := getOptionConfig(args, key) - if knownHostsFiles == "" || user && strings.ToLower(knownHostsFiles) == "none" { - debug("%s is empty or none", key) + knownHostsFiles := getOptionConfigSplits(args, key) + if len(knownHostsFiles) == 0 { + debug("%s is empty", key) return nil } - for _, path := range strings.Fields(knownHostsFiles) { + if len(knownHostsFiles) == 1 && strings.ToLower(knownHostsFiles[0]) == "none" { + debug("%s is none", key) + return nil + } + for _, path := range knownHostsFiles { var resolvedPath string if user { expandedPath, err := expandTokens(path, args, param, "%CdhijkLlnpru")