| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- package cli
- import (
- "fmt"
- "strings"
- "unicode"
- )
- // splitCommand supports quoted arguments without invoking a system shell.
- // Backslashes outside quotes remain literal, preserving passwords and keys.
- func splitCommand(input string) ([]string, error) {
- var args []string
- var word strings.Builder
- var quote rune
- started := false
- runes := []rune(input)
- for i := 0; i < len(runes); i++ {
- ch := runes[i]
- if quote != 0 {
- if ch == quote {
- quote = 0
- } else if ch == '\\' && quote == '"' && i+1 < len(runes) && (runes[i+1] == '"' || runes[i+1] == '\\') {
- i++
- word.WriteRune(runes[i])
- } else {
- word.WriteRune(ch)
- }
- } else if ch == '\'' || ch == '"' {
- quote = ch
- started = true
- } else if unicode.IsSpace(ch) {
- if started {
- args = append(args, word.String())
- word.Reset()
- started = false
- }
- } else {
- word.WriteRune(ch)
- started = true
- }
- }
- if quote != 0 {
- return nil, fmt.Errorf("unterminated quote")
- }
- if started {
- args = append(args, word.String())
- }
- return args, nil
- }
- // Existing command handlers mark failures red. Keep interactive rendering while
- // supplying an exit status for SSH automation.
- func commandExitStatus(output string) uint32 {
- if strings.HasPrefix(strings.TrimSpace(output), ColorRed) {
- return 1
- }
- return 0
- }
|