Files
ssh-netbox-wrapper/internal/ssh/args.go
T
Sebastian Unterschütz 8ef4bbec16
Release / release (push) Failing after 51s
Add core modules (SSH args parser, cache, resolver, NetBox client) with tests
2026-05-23 12:38:41 +02:00

110 lines
2.5 KiB
Go

package ssh
import "strings"
// flagsWithArg lists all SSH flags that consume the following argument.
var flagsWithArg = map[byte]bool{
'b': true, 'c': true, 'D': true, 'E': true, 'e': true,
'F': true, 'I': true, 'i': true, 'J': true, 'L': true,
'l': true, 'm': true, 'o': true, 'O': true, 'p': true,
'Q': true, 'R': true, 'S': true, 'w': true, 'W': true,
}
// ParsedArgs holds the result of parsing SSH arguments.
type ParsedArgs struct {
Host string // hostname without the user@ prefix
User string // empty if not specified
DestIdx int // index in Args where [user@]host sits
Args []string
}
// Parse scans SSH arguments and extracts the destination ([user@]host).
// Returns nil if no destination is found.
func Parse(args []string) *ParsedArgs {
i := 0
for i < len(args) {
arg := args[i]
// "--" ends option processing
if arg == "--" {
i++
break
}
if strings.HasPrefix(arg, "-") && len(arg) > 1 {
flag := arg[1]
if flagsWithArg[flag] {
if len(arg) > 2 {
// argument is attached, e.g. -p2222
i++
} else {
// argument is the next element, e.g. -p 2222
i += 2
}
} else {
i++
}
continue
}
// first non-flag argument is the destination
host, user := splitUserHost(arg)
return &ParsedArgs{
Host: host,
User: user,
DestIdx: i,
Args: args,
}
}
// handle arguments after "--"
if i < len(args) {
host, user := splitUserHost(args[i])
return &ParsedArgs{
Host: host,
User: user,
DestIdx: i,
Args: args,
}
}
return nil
}
// ReplaceHost returns a copy of args with the destination replaced by newHost,
// preserving any user@ prefix.
func ReplaceHost(args []string, destIdx int, newHost string) []string {
result := make([]string, len(args))
copy(result, args)
original := args[destIdx]
if at := strings.Index(original, "@"); at != -1 {
result[destIdx] = original[:at+1] + newHost
} else {
result[destIdx] = newHost
}
return result
}
// HasUserFlag reports whether a user was specified via -l in args.
// Used to avoid overriding an explicit -l with the configured default user.
func HasUserFlag(args []string) bool {
for i, a := range args {
if a == "-l" && i+1 < len(args) {
return true
}
// handle attached form: -lroot
if len(a) > 2 && a[0] == '-' && a[1] == 'l' {
return true
}
}
return false
}
func splitUserHost(dest string) (host, user string) {
if at := strings.Index(dest, "@"); at != -1 {
return dest[at+1:], dest[:at]
}
return dest, ""
}