| 331 | } |
| 332 | |
| 333 | func (Args) writeQuoted(dst *strings.Builder, str string) { |
| 334 | needsQuote := strings.ContainsAny(str, ";\"'()$|&><` \t\r\n\\#{~*?[=") |
| 335 | if !needsQuote { |
| 336 | dst.WriteString(str) |
| 337 | return |
| 338 | } |
| 339 | |
| 340 | canSingleQuote := !strings.Contains(str, "'") |
| 341 | if canSingleQuote { |
| 342 | dst.WriteByte('\'') |
| 343 | dst.WriteString(str) |
| 344 | dst.WriteByte('\'') |
| 345 | return |
| 346 | } |
| 347 | |
| 348 | dst.WriteByte('"') |
| 349 | for _, r := range str { |
| 350 | switch r { |
| 351 | // Special characters inside double quotes: |
| 352 | // https://pubs.opengroup.org/onlinepubs/009604499/utilities/xcu_chap02.html#tag_02_02_03 |
| 353 | case '$', '`', '"', '\\': |
| 354 | dst.WriteRune('\\') |
| 355 | } |
| 356 | dst.WriteRune(r) |
| 357 | } |
| 358 | dst.WriteByte('"') |
| 359 | } |
| 360 | |
| 361 | type cmdError struct { |
| 362 | msg string |