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 -- [email protected] -- 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    ///

-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

Raspunde prin e-mail lui