To: vim_dev@googlegroups.com Subject: Patch 7.3.447 Fcc: outbox From: Bram Moolenaar 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 ///