mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-23 07:19:15 +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>
|
2014-11-17 Oscar Fuentes <ofv@wanadoo.es>
|
||||||
|
|
||||||
* inc/ms-w32.h: Define MINGW_W64.
|
* inc/ms-w32.h: Define MINGW_W64.
|
||||||
|
@ -135,7 +135,10 @@ skip_nonspace (const char *str)
|
|||||||
return 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. */
|
/* Get next token from input, advancing pointer. */
|
||||||
int
|
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
|
/* 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
|
flag this as an error, but for now will consider the end as
|
||||||
the end of the token. */
|
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';
|
*o = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
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++;
|
*o++ = *p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,13 +252,44 @@ search_dir (const char *dir, const char *exec, int bufsize, char *buffer)
|
|||||||
int n_exts = sizeof (exts) / sizeof (char *);
|
int n_exts = sizeof (exts) / sizeof (char *);
|
||||||
char *dummy;
|
char *dummy;
|
||||||
int i, rc;
|
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. */
|
/* Search the directory for the program. */
|
||||||
for (i = 0; i < n_exts; i++)
|
if (pext)
|
||||||
{
|
{
|
||||||
rc = SearchPath (dir, exec, exts[i], bufsize, buffer, &dummy);
|
/* 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)
|
if (rc > 0)
|
||||||
return rc;
|
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;
|
return 0;
|
||||||
@ -769,7 +823,7 @@ main (int argc, char ** argv)
|
|||||||
quotes, since they are illegal in path names). */
|
quotes, since they are illegal in path names). */
|
||||||
|
|
||||||
remlen = maxlen =
|
remlen = maxlen =
|
||||||
strlen (progname) + extra_arg_space + strlen (cmdline) + 16;
|
strlen (progname) + extra_arg_space + strlen (cmdline) + 16 + 2;
|
||||||
buf = p = alloca (maxlen + 1);
|
buf = p = alloca (maxlen + 1);
|
||||||
|
|
||||||
/* Quote progname in case it contains spaces. */
|
/* Quote progname in case it contains spaces. */
|
||||||
@ -784,10 +838,16 @@ main (int argc, char ** argv)
|
|||||||
remlen = maxlen - (p - buf);
|
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)
|
if (run_command_dot_com)
|
||||||
_snprintf (p, remlen, " /e:%d /c %s", envsize, cmdline);
|
_snprintf (p, remlen, " /e:%d /c \"%s\"", envsize, cmdline);
|
||||||
else
|
else
|
||||||
_snprintf (p, remlen, " /c %s", cmdline);
|
_snprintf (p, remlen, " /c \"%s\"", cmdline);
|
||||||
cmdline = buf;
|
cmdline = buf;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user