To: vim_dev@googlegroups.com
Subject: Patch 7.3.447
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------
Patch 7.3.447 (after 7.3.446)
Problem: Win32: External commands with "start" do not work.
Solution: Unescape part of the command. (Yasuhiro Matsumoto)
Files: src/os_win32.c
*** ../vim-7.3.446/src/os_win32.c 2012-02-19 18:19:24.000000000 +0100
--- src/os_win32.c 2012-02-21 20:56:51.000000000 +0100
***************
*** 259,264 ****
--- 259,287 ----
}
/*
+ * 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".
*/
HINSTANCE
***************
*** 3559,3564 ****
--- 3582,3588 ----
garray_T ga;
int delay = 1;
DWORD buffer_off = 0; /* valid bytes in buffer[] */
+ char *p = NULL;
SECURITY_ATTRIBUTES saAttr;
***************
*** 3599,3607 ****
if (options & SHELL_READ)
ga_init2(&ga, 1, BUFLEN);
/* Now, run the command */
CreateProcess(NULL, /* Executable name */
! cmd, /* Command to execute */
NULL, /* Process security attributes */
NULL, /* Thread security attributes */
--- 3623,3640 ----
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 */
! p, /* Command to execute */
NULL, /* Process security attributes */
NULL, /* Thread security attributes */
***************
*** 3616,3621 ****
--- 3649,3656 ----
&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,4018 ****
else
{
/* we use "command" or "cmd" to start the shell; slow but easy */
! 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
{
#if defined(FEAT_GUI_W32)
if (need_vimrun_warning)
--- 3933,4048 ----
else
{
/* we use "command" or "cmd" to start the shell; slow but easy */
! 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)
{
#if defined(FEAT_GUI_W32)
if (need_vimrun_warning)
***************
*** 4038,4045 ****
vim_snprintf((char *)newcmd, cmdlen, "%s %s %s",
p_sh, p_shcf, cmd);
x = mch_system((char *)newcmd, options);
}
- vim_free(newcmd);
}
}
--- 4068,4075 ----
vim_snprintf((char *)newcmd, cmdlen, "%s %s %s",
p_sh, p_shcf, cmd);
x = mch_system((char *)newcmd, options);
+ vim_free(newcmd);
}
}
}
*** ../vim-7.3.446/src/version.c 2012-02-20 22:18:23.000000000 +0100
--- src/version.c 2012-02-21 21:20:05.000000000 +0100
***************
*** 716,717 ****
--- 716,719 ----
{ /* Add new patch number below this line */
+ /**/
+ 447,
/**/
--
From "know your smileys":
:----} You lie like Pinocchio
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///