* Do backslash quoting of any weird chars in "arg", append the resulting * string to the end of the "opt" (which gets a "=" appended if it is not * an empty or NULL string), and return the (perhaps malloced) result. * If opt is NULL, arg is considered a filename arg that allows wildcards. * If it is "" or any other value, it is considered an option. **/
| 2537 | * If it is "" or any other value, it is considered an option. |
| 2538 | **/ |
| 2539 | char *safe_arg(const char *opt, const char *arg) |
| 2540 | { |
| 2541 | #define SHELL_CHARS "!#$&;|<>(){}\"'` \t\\" |
| 2542 | #define WILD_CHARS "*?[]" /* We don't allow remote brace expansion */ |
| 2543 | BOOL is_filename_arg = !opt; |
| 2544 | char *escapes = is_filename_arg ? SHELL_CHARS : WILD_CHARS SHELL_CHARS; |
| 2545 | BOOL escape_leading_dash = is_filename_arg && *arg == '-'; |
| 2546 | BOOL escape_leading_tilde = 0; |
| 2547 | int len1 = opt && *opt ? strlen(opt) + 1 : 0; |
| 2548 | int len2 = strlen(arg); |
| 2549 | int extras = escape_leading_dash ? 2 : 0; |
| 2550 | char *ret; |
| 2551 | if (!protect_args && old_style_args < 2 && (!old_style_args || (!is_filename_arg && opt != SPLIT_ARG_WHEN_OLD))) { |
| 2552 | const char *f; |
| 2553 | if (*arg == '~' && is_filename_arg && !am_sender && !trust_sender_args |
| 2554 | && ((relative_paths && !strstr(arg, "/./")) |
| 2555 | || !strchr(arg, '/'))) { |
| 2556 | extras++; |
| 2557 | escape_leading_tilde = 1; |
| 2558 | } |
| 2559 | for (f = arg; *f; f++) { |
| 2560 | if (strchr(escapes, *f)) |
| 2561 | extras++; |
| 2562 | } |
| 2563 | } |
| 2564 | if (!len1 && !extras) |
| 2565 | return (char*)arg; |
| 2566 | ret = new_array(char, len1 + len2 + extras + 1); |
| 2567 | if (len1) { |
| 2568 | memcpy(ret, opt, len1-1); |
| 2569 | ret[len1-1] = '='; |
| 2570 | } |
| 2571 | if (escape_leading_dash) { |
| 2572 | ret[len1++] = '.'; |
| 2573 | ret[len1++] = '/'; |
| 2574 | extras -= 2; |
| 2575 | } |
| 2576 | if (!extras) |
| 2577 | memcpy(ret + len1, arg, len2); |
| 2578 | else { |
| 2579 | const char *f = arg; |
| 2580 | char *t = ret + len1; |
| 2581 | if (escape_leading_tilde) |
| 2582 | *t++ = '\\'; |
| 2583 | while (*f) { |
| 2584 | if (*f == '\\') { |
| 2585 | if (!is_filename_arg || !strchr(WILD_CHARS, f[1])) |
| 2586 | *t++ = '\\'; |
| 2587 | } else if (strchr(escapes, *f)) |
| 2588 | *t++ = '\\'; |
| 2589 | *t++ = *f++; |
| 2590 | } |
| 2591 | } |
| 2592 | ret[len1+len2+extras] = '\0'; |
| 2593 | return ret; |
| 2594 | } |
| 2595 | |
| 2596 |
no outgoing calls
no test coverage detected