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.
This commit is contained in:
Noam Postavsky 2014-10-25 12:12:01 +03:00 committed by Eli Zaretskii
parent b5dc75aed7
commit a91ff4f4b1
6 changed files with 77 additions and 0 deletions

View file

@ -1,3 +1,9 @@
2014-10-22 Noam Postavsky <npostavs@users.sourceforget.net>
* nt/cmdproxy.c (batch_file_p): New function.
(spawn): If calling a quoted batch file pass NULL for progname.
(Bug#18745)
2014-10-20 Glenn Morris <rgm@gnu.org>
* Merge in all changes up to 24.4 release.

View file

@ -220,6 +220,28 @@ get_next_token (char * buf, const char ** pSrc)
return o - buf;
}
/* Return TRUE if PROGNAME is a batch file. */
BOOL
batch_file_p (const char *progname)
{
const char *exts[] = {".bat", ".cmd"};
int n_exts = sizeof (exts) / sizeof (char *);
int i;
const char *ext = strrchr (progname, '.');
if (ext)
{
for (i = 0; i < n_exts; i++)
{
if (stricmp (ext, exts[i]) == 0)
return TRUE;
}
}
return FALSE;
}
/* Search for EXEC file in DIR. If EXEC does not have an extension,
DIR is searched for EXEC with the standard extensions appended. */
int
@ -470,6 +492,13 @@ spawn (const char *progname, char *cmdline, const char *dir, int *retcode)
memset (&start, 0, sizeof (start));
start.cb = sizeof (start);
/* CreateProcess handles batch files as progname specially. This
special handling fails when both the batch file and arguments are
quoted. We pass NULL as progname to avoid the special
handling. */
if (progname != NULL && cmdline[0] == '"' && batch_file_p (progname))
progname = NULL;
if (CreateProcess (progname, cmdline, &sec_attrs, NULL, TRUE,
0, envblock, dir, &start, &child))
{

View file

@ -1,3 +1,8 @@
2014-10-25 Noam Postavsky <npostavs@users.sourceforget.net>
* src/w32proc.c (create_child): If calling a quoted batch file,
pass NULL for exe. (Bug#18745)
2014-10-24 Eli Zaretskii <eliz@gnu.org>
* bidi.c (bidi_resolve_explicit, bidi_find_bracket_pairs)

View file

@ -1078,6 +1078,7 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
DWORD flags;
char dir[ MAX_PATH ];
char *p;
const char *ext;
if (cp == NULL) emacs_abort ();
@ -1116,6 +1117,15 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
if (*p == '/')
*p = '\\';
/* CreateProcess handles batch files as exe specially. This special
handling fails when both the batch file and arguments are quoted.
We pass NULL as exe to avoid the special handling. */
if (exe && cmdline[0] == '"' &&
(ext = strrchr (exe, '.')) &&
(xstrcasecmp (ext, ".bat") == 0
|| xstrcasecmp (ext, ".cmd") == 0))
exe = NULL;
flags = (!NILP (Vw32_start_process_share_console)
? CREATE_NEW_PROCESS_GROUP
: CREATE_NEW_CONSOLE);

View file

@ -1,3 +1,8 @@
2014-10-22 Noam Postavsky <npostavs@users.sourceforget.net>
* test/automated/process-tests.el (process-test-quoted-batfile):
New test.
2014-10-20 Glenn Morris <rgm@gnu.org>
* Merge in all changes up to 24.4 release.

View file

@ -50,4 +50,26 @@
(should
(process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t)))))
(when (eq system-type 'windows-nt)
(ert-deftest process-test-quoted-batfile ()
"Check that Emacs hides CreateProcess deficiency (bug#18745)."
(let (batfile)
(unwind-protect
(progn
;; CreateProcess will fail when both the bat file and 1st
;; argument are quoted, so include spaces in both of those
;; to force quoting.
(setq batfile (make-temp-file "echo args" nil ".bat"))
(with-temp-file batfile
(insert "@echo arg1 = %1, arg2 = %2\n"))
(with-temp-buffer
(call-process batfile nil '(t t) t "x &y")
(should (string= (buffer-string) "arg1 = \"x &y\", arg2 = \n")))
(with-temp-buffer
(call-process-shell-command
(mapconcat #'shell-quote-argument (list batfile "x &y") " ")
nil '(t t) t)
(should (string= (buffer-string) "arg1 = \"x &y\", arg2 = \n"))))
(when batfile (delete-file batfile))))))
(provide 'process-tests)