mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-03 08:30:09 +00:00
Fix invocation of commands whose file name includes extension (Bug#19817)
nt/cmdproxy.c (get_next_token): Don't make backslashes disappear without a trace when they are not followed by a quote. (search_dir): Support searching programs whose file name already has an arbitrary extension. (main): When passing a command line to the shell, use cmd.exe rules for quoting command-line tail.
This commit is contained in:
parent
87fc99fee1
commit
4b0b27d001
@ -1,3 +1,12 @@
|
||||
2015-02-10 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* cmdproxy.c (get_next_token): Don't make backslashes disappear
|
||||
without a trace when they are not followed by a quote.
|
||||
(search_dir): Support searching programs whose file name already
|
||||
has an arbitrary extension. (Bug#19817)
|
||||
(main): When passing a command line to the shell, use cmd.exe
|
||||
rules for quoting command-line tail.
|
||||
|
||||
2014-11-17 Oscar Fuentes <ofv@wanadoo.es>
|
||||
|
||||
* inc/ms-w32.h: Define MINGW_W64.
|
||||
|
@ -135,7 +135,10 @@ skip_nonspace (const char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
int escape_char = '\\';
|
||||
/* This value is never changed by the code. We keep the code that
|
||||
supports also the value of '"', but let's allow the compiler to
|
||||
optimize it out, until someone actually uses that. */
|
||||
const int escape_char = '\\';
|
||||
|
||||
/* Get next token from input, advancing pointer. */
|
||||
int
|
||||
@ -196,11 +199,31 @@ get_next_token (char * buf, const char ** pSrc)
|
||||
/* End of string, but no ending quote found. We might want to
|
||||
flag this as an error, but for now will consider the end as
|
||||
the end of the token. */
|
||||
if (escape_char == '\\')
|
||||
{
|
||||
/* Output literal backslashes. Note that if the
|
||||
token ends with an unpaired backslash, we eat it
|
||||
up here. But since this case invokes undefined
|
||||
behavior anyway, it's okay. */
|
||||
while (escape_char_run > 1)
|
||||
{
|
||||
*o++ = escape_char;
|
||||
escape_char_run -= 2;
|
||||
}
|
||||
}
|
||||
*o = '\0';
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (escape_char == '\\')
|
||||
{
|
||||
/* Output literal backslashes. Note that we don't
|
||||
treat a backslash as an escape character here,
|
||||
since it doesn't preceed a quote. */
|
||||
for ( ; escape_char_run > 0; escape_char_run--)
|
||||
*o++ = escape_char;
|
||||
}
|
||||
*o++ = *p++;
|
||||
}
|
||||
}
|
||||
@ -229,14 +252,45 @@ search_dir (const char *dir, const char *exec, int bufsize, char *buffer)
|
||||
int n_exts = sizeof (exts) / sizeof (char *);
|
||||
char *dummy;
|
||||
int i, rc;
|
||||
const char *pext = strrchr (exec, '\\');
|
||||
|
||||
/* Does EXEC already include an extension? */
|
||||
if (!pext)
|
||||
pext = exec;
|
||||
pext = strchr (pext, '.');
|
||||
|
||||
/* Search the directory for the program. */
|
||||
if (pext)
|
||||
{
|
||||
/* SearchPath will not append an extension if the file already
|
||||
has an extension, so we must append it ourselves. */
|
||||
char exec_ext[MAX_PATH], *p;
|
||||
|
||||
p = strcpy (exec_ext, exec) + strlen (exec);
|
||||
|
||||
/* Search first without any extension; if found, we are done. */
|
||||
rc = SearchPath (dir, exec_ext, NULL, bufsize, buffer, &dummy);
|
||||
if (rc > 0)
|
||||
return rc;
|
||||
|
||||
/* Try the known extensions. */
|
||||
for (i = 0; i < n_exts; i++)
|
||||
{
|
||||
strcpy (p, exts[i]);
|
||||
rc = SearchPath (dir, exec_ext, NULL, bufsize, buffer, &dummy);
|
||||
if (rc > 0)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < n_exts; i++)
|
||||
{
|
||||
rc = SearchPath (dir, exec, exts[i], bufsize, buffer, &dummy);
|
||||
if (rc > 0)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -769,7 +823,7 @@ main (int argc, char ** argv)
|
||||
quotes, since they are illegal in path names). */
|
||||
|
||||
remlen = maxlen =
|
||||
strlen (progname) + extra_arg_space + strlen (cmdline) + 16;
|
||||
strlen (progname) + extra_arg_space + strlen (cmdline) + 16 + 2;
|
||||
buf = p = alloca (maxlen + 1);
|
||||
|
||||
/* Quote progname in case it contains spaces. */
|
||||
@ -784,10 +838,16 @@ main (int argc, char ** argv)
|
||||
remlen = maxlen - (p - buf);
|
||||
}
|
||||
|
||||
/* Now that we know we will be invoking the shell, quote the
|
||||
command line after the "/c" switch as the shell expects:
|
||||
a single pair of quotes enclosing the entire command
|
||||
tail, no matter whether quotes are used in the command
|
||||
line, and how many of them are there. See the output of
|
||||
"cmd /?" for how cmd.exe treats quotes. */
|
||||
if (run_command_dot_com)
|
||||
_snprintf (p, remlen, " /e:%d /c %s", envsize, cmdline);
|
||||
_snprintf (p, remlen, " /e:%d /c \"%s\"", envsize, cmdline);
|
||||
else
|
||||
_snprintf (p, remlen, " /c %s", cmdline);
|
||||
_snprintf (p, remlen, " /c \"%s\"", cmdline);
|
||||
cmdline = buf;
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user