diff options
Diffstat (limited to 'nt/cmdproxy.c')
| -rw-r--r-- | nt/cmdproxy.c | 72 |
1 files changed, 66 insertions, 6 deletions
diff --git a/nt/cmdproxy.c b/nt/cmdproxy.c index faef2f83496..3157a69c1b6 100644 --- a/nt/cmdproxy.c +++ b/nt/cmdproxy.c | |||
| @@ -135,7 +135,10 @@ skip_nonspace (const char *str) | |||
| 135 | return str; | 135 | return str; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | int escape_char = '\\'; | 138 | /* This value is never changed by the code. We keep the code that |
| 139 | supports also the value of '"', but let's allow the compiler to | ||
| 140 | optimize it out, until someone actually uses that. */ | ||
| 141 | const int escape_char = '\\'; | ||
| 139 | 142 | ||
| 140 | /* Get next token from input, advancing pointer. */ | 143 | /* Get next token from input, advancing pointer. */ |
| 141 | int | 144 | int |
| @@ -196,11 +199,31 @@ get_next_token (char * buf, const char ** pSrc) | |||
| 196 | /* End of string, but no ending quote found. We might want to | 199 | /* End of string, but no ending quote found. We might want to |
| 197 | flag this as an error, but for now will consider the end as | 200 | flag this as an error, but for now will consider the end as |
| 198 | the end of the token. */ | 201 | the end of the token. */ |
| 202 | if (escape_char == '\\') | ||
| 203 | { | ||
| 204 | /* Output literal backslashes. Note that if the | ||
| 205 | token ends with an unpaired backslash, we eat it | ||
| 206 | up here. But since this case invokes undefined | ||
| 207 | behavior anyway, it's okay. */ | ||
| 208 | while (escape_char_run > 1) | ||
| 209 | { | ||
| 210 | *o++ = escape_char; | ||
| 211 | escape_char_run -= 2; | ||
| 212 | } | ||
| 213 | } | ||
| 199 | *o = '\0'; | 214 | *o = '\0'; |
| 200 | break; | 215 | break; |
| 201 | } | 216 | } |
| 202 | else | 217 | else |
| 203 | { | 218 | { |
| 219 | if (escape_char == '\\') | ||
| 220 | { | ||
| 221 | /* Output literal backslashes. Note that we don't | ||
| 222 | treat a backslash as an escape character here, | ||
| 223 | since it doesn't preceed a quote. */ | ||
| 224 | for ( ; escape_char_run > 0; escape_char_run--) | ||
| 225 | *o++ = escape_char; | ||
| 226 | } | ||
| 204 | *o++ = *p++; | 227 | *o++ = *p++; |
| 205 | } | 228 | } |
| 206 | } | 229 | } |
| @@ -251,13 +274,44 @@ search_dir (const char *dir, const char *exec, int bufsize, char *buffer) | |||
| 251 | int n_exts = sizeof (exts) / sizeof (char *); | 274 | int n_exts = sizeof (exts) / sizeof (char *); |
| 252 | char *dummy; | 275 | char *dummy; |
| 253 | int i, rc; | 276 | int i, rc; |
| 277 | const char *pext = strrchr (exec, '\\'); | ||
| 278 | |||
| 279 | /* Does EXEC already include an extension? */ | ||
| 280 | if (!pext) | ||
| 281 | pext = exec; | ||
| 282 | pext = strchr (pext, '.'); | ||
| 254 | 283 | ||
| 255 | /* Search the directory for the program. */ | 284 | /* Search the directory for the program. */ |
| 256 | for (i = 0; i < n_exts; i++) | 285 | if (pext) |
| 257 | { | 286 | { |
| 258 | rc = SearchPath (dir, exec, exts[i], bufsize, buffer, &dummy); | 287 | /* SearchPath will not append an extension if the file already |
| 288 | has an extension, so we must append it ourselves. */ | ||
| 289 | char exec_ext[MAX_PATH], *p; | ||
| 290 | |||
| 291 | p = strcpy (exec_ext, exec) + strlen (exec); | ||
| 292 | |||
| 293 | /* Search first without any extension; if found, we are done. */ | ||
| 294 | rc = SearchPath (dir, exec_ext, NULL, bufsize, buffer, &dummy); | ||
| 259 | if (rc > 0) | 295 | if (rc > 0) |
| 260 | return rc; | 296 | return rc; |
| 297 | |||
| 298 | /* Try the known extensions. */ | ||
| 299 | for (i = 0; i < n_exts; i++) | ||
| 300 | { | ||
| 301 | strcpy (p, exts[i]); | ||
| 302 | rc = SearchPath (dir, exec_ext, NULL, bufsize, buffer, &dummy); | ||
| 303 | if (rc > 0) | ||
| 304 | return rc; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | else | ||
| 308 | { | ||
| 309 | for (i = 0; i < n_exts; i++) | ||
| 310 | { | ||
| 311 | rc = SearchPath (dir, exec, exts[i], bufsize, buffer, &dummy); | ||
| 312 | if (rc > 0) | ||
| 313 | return rc; | ||
| 314 | } | ||
| 261 | } | 315 | } |
| 262 | 316 | ||
| 263 | return 0; | 317 | return 0; |
| @@ -798,7 +852,7 @@ main (int argc, char ** argv) | |||
| 798 | quotes, since they are illegal in path names). */ | 852 | quotes, since they are illegal in path names). */ |
| 799 | 853 | ||
| 800 | remlen = maxlen = | 854 | remlen = maxlen = |
| 801 | strlen (progname) + extra_arg_space + strlen (cmdline) + 16; | 855 | strlen (progname) + extra_arg_space + strlen (cmdline) + 16 + 2; |
| 802 | buf = p = alloca (maxlen + 1); | 856 | buf = p = alloca (maxlen + 1); |
| 803 | 857 | ||
| 804 | /* Quote progname in case it contains spaces. */ | 858 | /* Quote progname in case it contains spaces. */ |
| @@ -813,10 +867,16 @@ main (int argc, char ** argv) | |||
| 813 | remlen = maxlen - (p - buf); | 867 | remlen = maxlen - (p - buf); |
| 814 | } | 868 | } |
| 815 | 869 | ||
| 870 | /* Now that we know we will be invoking the shell, quote the | ||
| 871 | command line after the "/c" switch as the shell expects: | ||
| 872 | a single pair of quotes enclosing the entire command | ||
| 873 | tail, no matter whether quotes are used in the command | ||
| 874 | line, and how many of them are there. See the output of | ||
| 875 | "cmd /?" for how cmd.exe treats quotes. */ | ||
| 816 | if (run_command_dot_com) | 876 | if (run_command_dot_com) |
| 817 | _snprintf (p, remlen, " /e:%d /c %s", envsize, cmdline); | 877 | _snprintf (p, remlen, " /e:%d /c \"%s\"", envsize, cmdline); |
| 818 | else | 878 | else |
| 819 | _snprintf (p, remlen, " /c %s", cmdline); | 879 | _snprintf (p, remlen, " /c \"%s\"", cmdline); |
| 820 | cmdline = buf; | 880 | cmdline = buf; |
| 821 | } | 881 | } |
| 822 | else | 882 | else |