0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

updated for version 7.3.447

Problem:    Win32: External commands with "start" do not work.
Solution:   Unescape part of the command. (Yasuhiro Matsumoto)
This commit is contained in:
Bram Moolenaar
2012-02-21 21:22:44 +01:00
parent f66b3fcf6c
commit 6b707b4b82
2 changed files with 144 additions and 112 deletions

View File

@@ -258,6 +258,29 @@ get_exe_name(void)
}
}
/*
* Unescape characters in "p" that appear in "escaped".
*/
static void
unescape_shellxquote(char_u *p, char_u *escaped)
{
int l = STRLEN(p);
int n;
while (*p != NUL)
{
if (*p == '^' && vim_strchr(escaped, p[1]) != NULL)
mch_memmove(p, p + 1, l--);
#ifdef FEAT_MBYTE
n = (*mb_ptr2len)(p);
#else
n = 1;
#endif
p += n;
l -= n;
}
}
/*
* Load library "name".
*/
@@ -3559,6 +3582,7 @@ mch_system_piped(char *cmd, int options)
garray_T ga;
int delay = 1;
DWORD buffer_off = 0; /* valid bytes in buffer[] */
char *p = NULL;
SECURITY_ATTRIBUTES saAttr;
@@ -3599,9 +3623,18 @@ mch_system_piped(char *cmd, int options)
if (options & SHELL_READ)
ga_init2(&ga, 1, BUFLEN);
if (cmd != NULL)
{
p = (char *)vim_strsave((char_u *)cmd);
if (p != NULL)
unescape_shellxquote((char_u *)p, p_sxe);
else
p = cmd;
}
/* Now, run the command */
CreateProcess(NULL, /* Executable name */
cmd, /* Command to execute */
p, /* Command to execute */
NULL, /* Process security attributes */
NULL, /* Thread security attributes */
@@ -3616,6 +3649,8 @@ mch_system_piped(char *cmd, int options)
&si, /* Startup information */
&pi); /* Process information */
if (p != cmd)
vim_free(p);
/* Close our unused side of the pipes */
CloseHandle(g_hChildStd_IN_Rd);
@@ -3898,121 +3933,116 @@ mch_call_shell(
else
{
/* we use "command" or "cmd" to start the shell; slow but easy */
char_u *newcmd;
long_u cmdlen = (
char_u *cmdbase = cmd;
/* Skip a leading ", ( and "(. */
if (*cmdbase == '"' )
++cmdbase;
if (*cmdbase == '(')
++cmdbase;
if ((STRNICMP(cmdbase, "start", 5) == 0) && vim_iswhite(cmdbase[5]))
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD flags = CREATE_NEW_CONSOLE;
char_u *p;
si.cb = sizeof(si);
si.lpReserved = NULL;
si.lpDesktop = NULL;
si.lpTitle = NULL;
si.dwFlags = 0;
si.cbReserved2 = 0;
si.lpReserved2 = NULL;
cmdbase = skipwhite(cmdbase + 5);
if ((STRNICMP(cmdbase, "/min", 4) == 0)
&& vim_iswhite(cmdbase[4]))
{
cmdbase = skipwhite(cmdbase + 4);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWMINNOACTIVE;
}
else if ((STRNICMP(cmdbase, "/b", 2) == 0)
&& vim_iswhite(cmdbase[2]))
{
cmdbase = skipwhite(cmdbase + 2);
flags = CREATE_NO_WINDOW;
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = CreateFile("\\\\.\\NUL", // File name
GENERIC_READ, // Access flags
0, // Share flags
NULL, // Security att.
OPEN_EXISTING, // Open flags
FILE_ATTRIBUTE_NORMAL, // File att.
NULL); // Temp file
si.hStdOutput = si.hStdInput;
si.hStdError = si.hStdInput;
}
/* Remove a trailing ", ) and )" if they have a match
* at the start of the command. */
if (cmdbase > cmd)
{
p = cmdbase + STRLEN(cmdbase);
if (p > cmdbase && p[-1] == '"' && *cmd == '"')
*--p = NUL;
if (p > cmdbase && p[-1] == ')'
&& (*cmd =='(' || cmd[1] == '('))
*--p = NUL;
}
/*
* Unescape characters in shellxescape. This is workaround for
* /b option. Only redirect character should be unescaped.
*/
unescape_shellxquote(cmdbase,
(flags & CREATE_NEW_CONSOLE) ? p_sxe : "<>");
/*
* Now, start the command as a process, so that it doesn't
* inherit our handles which causes unpleasant dangling swap
* files if we exit before the spawned process
*/
if (CreateProcess(NULL, // Executable name
cmdbase, // Command to execute
NULL, // Process security attributes
NULL, // Thread security attributes
FALSE, // Inherit handles
flags, // Creation flags
NULL, // Environment
NULL, // Current directory
&si, // Startup information
&pi)) // Process information
x = 0;
else
{
x = -1;
#ifdef FEAT_GUI_W32
EMSG(_("E371: Command not found"));
#endif
}
if (si.hStdInput != NULL)
{
/* Close the handle to \\.\NUL */
CloseHandle(si.hStdInput);
}
/* Close the handles to the subprocess, so that it goes away */
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
else
{
char_u *newcmd;
long_u cmdlen = (
#ifdef FEAT_GUI_W32
(allowPiping && !p_stmp ? 0 : STRLEN(vimrun_path)) +
#endif
STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10);
newcmd = lalloc(cmdlen, TRUE);
if (newcmd != NULL)
{
char_u *cmdbase = cmd;
/* Skip a leading ", ( and "(. */
if (*cmdbase == '"' )
++cmdbase;
if (*cmdbase == '(')
++cmdbase;
if ((STRNICMP(cmdbase, "start", 5) == 0) && vim_iswhite(cmdbase[5]))
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD flags = CREATE_NEW_CONSOLE;
si.cb = sizeof(si);
si.lpReserved = NULL;
si.lpDesktop = NULL;
si.lpTitle = NULL;
si.dwFlags = 0;
si.cbReserved2 = 0;
si.lpReserved2 = NULL;
cmdbase = skipwhite(cmdbase + 5);
if ((STRNICMP(cmdbase, "/min", 4) == 0)
&& vim_iswhite(cmdbase[4]))
{
cmdbase = skipwhite(cmdbase + 4);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWMINNOACTIVE;
}
else if ((STRNICMP(cmdbase, "/b", 2) == 0)
&& vim_iswhite(cmdbase[2]))
{
cmdbase = skipwhite(cmdbase + 2);
flags = CREATE_NO_WINDOW;
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = CreateFile("\\\\.\\NUL", // File name
GENERIC_READ, // Access flags
0, // Share flags
NULL, // Security att.
OPEN_EXISTING, // Open flags
FILE_ATTRIBUTE_NORMAL, // File att.
NULL); // Temp file
si.hStdOutput = si.hStdInput;
si.hStdError = si.hStdInput;
}
/* When the command is in double quotes, but 'shellxquote' is
* empty, keep the double quotes around the command.
* Otherwise remove the double quotes, they aren't needed
* here, because we don't use a shell to run the command. */
if (cmdbase > cmd)
{
if (STRNCMP(cmd, p_sxq, cmd - cmdbase) != 0)
{
STRCPY(newcmd, cmd);
}
else
{
char_u *p;
STRCPY(newcmd, cmdbase);
/* Remove a trailing ", ) and )" if they have a match
* at the start of the command. */
p = newcmd + STRLEN(newcmd);
if (p > newcmd && p[-1] == '"' && *cmd == '"')
*--p = NUL;
if (p > newcmd && p[-1] == ')'
&& (*cmd =='(' || cmd[1] == '('))
*--p = NUL;
}
}
/*
* Now, start the command as a process, so that it doesn't
* inherit our handles which causes unpleasant dangling swap
* files if we exit before the spawned process
*/
if (CreateProcess(NULL, // Executable name
newcmd, // Command to execute
NULL, // Process security attributes
NULL, // Thread security attributes
FALSE, // Inherit handles
flags, // Creation flags
NULL, // Environment
NULL, // Current directory
&si, // Startup information
&pi)) // Process information
x = 0;
else
{
x = -1;
#ifdef FEAT_GUI_W32
EMSG(_("E371: Command not found"));
#endif
}
if (si.hStdInput != NULL)
{
/* Close the handle to \\.\NUL */
CloseHandle(si.hStdInput);
}
/* Close the handles to the subprocess, so that it goes away */
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
else
newcmd = lalloc(cmdlen, TRUE);
if (newcmd != NULL)
{
#if defined(FEAT_GUI_W32)
if (need_vimrun_warning)
@@ -4038,8 +4068,8 @@ mch_call_shell(
vim_snprintf((char *)newcmd, cmdlen, "%s %s %s",
p_sh, p_shcf, cmd);
x = mch_system((char *)newcmd, options);
vim_free(newcmd);
}
vim_free(newcmd);
}
}