diff options
| author | Noam Postavsky | 2014-10-25 12:12:01 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2014-10-25 12:12:01 +0300 |
| commit | a91ff4f4b1d835cc2c723429c06ddcb357f807c8 (patch) | |
| tree | f32ac836d8644b60cbd6408acd4de9967c70e53a | |
| parent | b5dc75aed71ecb2310a6689e2f7082243aa7e4ab (diff) | |
| download | emacs-a91ff4f4b1d835cc2c723429c06ddcb357f807c8.tar.gz emacs-a91ff4f4b1d835cc2c723429c06ddcb357f807c8.zip | |
Fix bug #18745 with invoking Windows batch files with embedded whitespace.
src/w32proc.c (create_child): If calling a quoted batch file,
pass NULL for exe.
nt/cmdproxy.c (batch_file_p): New function.
(spawn): If calling a quoted batch file pass NULL for progname.
test/automated/process-tests.el (process-test-quoted-batfile): New test.
| -rw-r--r-- | nt/ChangeLog | 6 | ||||
| -rw-r--r-- | nt/cmdproxy.c | 29 | ||||
| -rw-r--r-- | src/ChangeLog | 5 | ||||
| -rw-r--r-- | src/w32proc.c | 10 | ||||
| -rw-r--r-- | test/ChangeLog | 5 | ||||
| -rw-r--r-- | test/automated/process-tests.el | 22 |
6 files changed, 77 insertions, 0 deletions
diff --git a/nt/ChangeLog b/nt/ChangeLog index 632c3739493..c4e01a38c21 100644 --- a/nt/ChangeLog +++ b/nt/ChangeLog | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | 2014-10-22 Noam Postavsky <npostavs@users.sourceforget.net> | ||
| 2 | |||
| 3 | * nt/cmdproxy.c (batch_file_p): New function. | ||
| 4 | (spawn): If calling a quoted batch file pass NULL for progname. | ||
| 5 | (Bug#18745) | ||
| 6 | |||
| 1 | 2014-10-20 Glenn Morris <rgm@gnu.org> | 7 | 2014-10-20 Glenn Morris <rgm@gnu.org> |
| 2 | 8 | ||
| 3 | * Merge in all changes up to 24.4 release. | 9 | * Merge in all changes up to 24.4 release. |
diff --git a/nt/cmdproxy.c b/nt/cmdproxy.c index e48ca63a257..d8f7ae3c41e 100644 --- a/nt/cmdproxy.c +++ b/nt/cmdproxy.c | |||
| @@ -220,6 +220,28 @@ get_next_token (char * buf, const char ** pSrc) | |||
| 220 | return o - buf; | 220 | return o - buf; |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | /* Return TRUE if PROGNAME is a batch file. */ | ||
| 224 | BOOL | ||
| 225 | batch_file_p (const char *progname) | ||
| 226 | { | ||
| 227 | const char *exts[] = {".bat", ".cmd"}; | ||
| 228 | int n_exts = sizeof (exts) / sizeof (char *); | ||
| 229 | int i; | ||
| 230 | |||
| 231 | const char *ext = strrchr (progname, '.'); | ||
| 232 | |||
| 233 | if (ext) | ||
| 234 | { | ||
| 235 | for (i = 0; i < n_exts; i++) | ||
| 236 | { | ||
| 237 | if (stricmp (ext, exts[i]) == 0) | ||
| 238 | return TRUE; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | return FALSE; | ||
| 243 | } | ||
| 244 | |||
| 223 | /* Search for EXEC file in DIR. If EXEC does not have an extension, | 245 | /* Search for EXEC file in DIR. If EXEC does not have an extension, |
| 224 | DIR is searched for EXEC with the standard extensions appended. */ | 246 | DIR is searched for EXEC with the standard extensions appended. */ |
| 225 | int | 247 | int |
| @@ -470,6 +492,13 @@ spawn (const char *progname, char *cmdline, const char *dir, int *retcode) | |||
| 470 | memset (&start, 0, sizeof (start)); | 492 | memset (&start, 0, sizeof (start)); |
| 471 | start.cb = sizeof (start); | 493 | start.cb = sizeof (start); |
| 472 | 494 | ||
| 495 | /* CreateProcess handles batch files as progname specially. This | ||
| 496 | special handling fails when both the batch file and arguments are | ||
| 497 | quoted. We pass NULL as progname to avoid the special | ||
| 498 | handling. */ | ||
| 499 | if (progname != NULL && cmdline[0] == '"' && batch_file_p (progname)) | ||
| 500 | progname = NULL; | ||
| 501 | |||
| 473 | if (CreateProcess (progname, cmdline, &sec_attrs, NULL, TRUE, | 502 | if (CreateProcess (progname, cmdline, &sec_attrs, NULL, TRUE, |
| 474 | 0, envblock, dir, &start, &child)) | 503 | 0, envblock, dir, &start, &child)) |
| 475 | { | 504 | { |
diff --git a/src/ChangeLog b/src/ChangeLog index a1b70b63755..fb724fb583f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2014-10-25 Noam Postavsky <npostavs@users.sourceforget.net> | ||
| 2 | |||
| 3 | * src/w32proc.c (create_child): If calling a quoted batch file, | ||
| 4 | pass NULL for exe. (Bug#18745) | ||
| 5 | |||
| 1 | 2014-10-24 Eli Zaretskii <eliz@gnu.org> | 6 | 2014-10-24 Eli Zaretskii <eliz@gnu.org> |
| 2 | 7 | ||
| 3 | * bidi.c (bidi_resolve_explicit, bidi_find_bracket_pairs) | 8 | * bidi.c (bidi_resolve_explicit, bidi_find_bracket_pairs) |
diff --git a/src/w32proc.c b/src/w32proc.c index 38452917add..09e0c0530a4 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -1078,6 +1078,7 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app, | |||
| 1078 | DWORD flags; | 1078 | DWORD flags; |
| 1079 | char dir[ MAX_PATH ]; | 1079 | char dir[ MAX_PATH ]; |
| 1080 | char *p; | 1080 | char *p; |
| 1081 | const char *ext; | ||
| 1081 | 1082 | ||
| 1082 | if (cp == NULL) emacs_abort (); | 1083 | if (cp == NULL) emacs_abort (); |
| 1083 | 1084 | ||
| @@ -1116,6 +1117,15 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app, | |||
| 1116 | if (*p == '/') | 1117 | if (*p == '/') |
| 1117 | *p = '\\'; | 1118 | *p = '\\'; |
| 1118 | 1119 | ||
| 1120 | /* CreateProcess handles batch files as exe specially. This special | ||
| 1121 | handling fails when both the batch file and arguments are quoted. | ||
| 1122 | We pass NULL as exe to avoid the special handling. */ | ||
| 1123 | if (exe && cmdline[0] == '"' && | ||
| 1124 | (ext = strrchr (exe, '.')) && | ||
| 1125 | (xstrcasecmp (ext, ".bat") == 0 | ||
| 1126 | || xstrcasecmp (ext, ".cmd") == 0)) | ||
| 1127 | exe = NULL; | ||
| 1128 | |||
| 1119 | flags = (!NILP (Vw32_start_process_share_console) | 1129 | flags = (!NILP (Vw32_start_process_share_console) |
| 1120 | ? CREATE_NEW_PROCESS_GROUP | 1130 | ? CREATE_NEW_PROCESS_GROUP |
| 1121 | : CREATE_NEW_CONSOLE); | 1131 | : CREATE_NEW_CONSOLE); |
diff --git a/test/ChangeLog b/test/ChangeLog index bb4b2fbdc49..fb19252cd34 100644 --- a/test/ChangeLog +++ b/test/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2014-10-22 Noam Postavsky <npostavs@users.sourceforget.net> | ||
| 2 | |||
| 3 | * test/automated/process-tests.el (process-test-quoted-batfile): | ||
| 4 | New test. | ||
| 5 | |||
| 1 | 2014-10-20 Glenn Morris <rgm@gnu.org> | 6 | 2014-10-20 Glenn Morris <rgm@gnu.org> |
| 2 | 7 | ||
| 3 | * Merge in all changes up to 24.4 release. | 8 | * Merge in all changes up to 24.4 release. |
diff --git a/test/automated/process-tests.el b/test/automated/process-tests.el index cd209bacaa6..6783a61d595 100644 --- a/test/automated/process-tests.el +++ b/test/automated/process-tests.el | |||
| @@ -50,4 +50,26 @@ | |||
| 50 | (should | 50 | (should |
| 51 | (process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t))))) | 51 | (process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t))))) |
| 52 | 52 | ||
| 53 | (when (eq system-type 'windows-nt) | ||
| 54 | (ert-deftest process-test-quoted-batfile () | ||
| 55 | "Check that Emacs hides CreateProcess deficiency (bug#18745)." | ||
| 56 | (let (batfile) | ||
| 57 | (unwind-protect | ||
| 58 | (progn | ||
| 59 | ;; CreateProcess will fail when both the bat file and 1st | ||
| 60 | ;; argument are quoted, so include spaces in both of those | ||
| 61 | ;; to force quoting. | ||
| 62 | (setq batfile (make-temp-file "echo args" nil ".bat")) | ||
| 63 | (with-temp-file batfile | ||
| 64 | (insert "@echo arg1 = %1, arg2 = %2\n")) | ||
| 65 | (with-temp-buffer | ||
| 66 | (call-process batfile nil '(t t) t "x &y") | ||
| 67 | (should (string= (buffer-string) "arg1 = \"x &y\", arg2 = \n"))) | ||
| 68 | (with-temp-buffer | ||
| 69 | (call-process-shell-command | ||
| 70 | (mapconcat #'shell-quote-argument (list batfile "x &y") " ") | ||
| 71 | nil '(t t) t) | ||
| 72 | (should (string= (buffer-string) "arg1 = \"x &y\", arg2 = \n")))) | ||
| 73 | (when batfile (delete-file batfile)))))) | ||
| 74 | |||
| 53 | (provide 'process-tests) | 75 | (provide 'process-tests) |