Karsten Hopp 2f1054
To: vim_dev@googlegroups.com
Karsten Hopp 2f1054
Subject: Patch 7.3.447
Karsten Hopp 2f1054
Fcc: outbox
Karsten Hopp 2f1054
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp 2f1054
Mime-Version: 1.0
Karsten Hopp 2f1054
Content-Type: text/plain; charset=UTF-8
Karsten Hopp 2f1054
Content-Transfer-Encoding: 8bit
Karsten Hopp 2f1054
------------
Karsten Hopp 2f1054
Karsten Hopp 2f1054
Patch 7.3.447 (after 7.3.446)
Karsten Hopp 2f1054
Problem:    Win32: External commands with "start" do not work.
Karsten Hopp 2f1054
Solution:   Unescape part of the command. (Yasuhiro Matsumoto)
Karsten Hopp 2f1054
Files:	    src/os_win32.c
Karsten Hopp 2f1054
Karsten Hopp 2f1054
Karsten Hopp 2f1054
*** ../vim-7.3.446/src/os_win32.c	2012-02-19 18:19:24.000000000 +0100
Karsten Hopp 2f1054
--- src/os_win32.c	2012-02-21 20:56:51.000000000 +0100
Karsten Hopp 2f1054
***************
Karsten Hopp 2f1054
*** 259,264 ****
Karsten Hopp 2f1054
--- 259,287 ----
Karsten Hopp 2f1054
  }
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
  /*
Karsten Hopp 2f1054
+  * Unescape characters in "p" that appear in "escaped".
Karsten Hopp 2f1054
+  */
Karsten Hopp 2f1054
+     static void
Karsten Hopp 2f1054
+ unescape_shellxquote(char_u *p, char_u *escaped)
Karsten Hopp 2f1054
+ {
Karsten Hopp 2f1054
+     int	    l = STRLEN(p);
Karsten Hopp 2f1054
+     int	    n;
Karsten Hopp 2f1054
+ 
Karsten Hopp 2f1054
+     while (*p != NUL)
Karsten Hopp 2f1054
+     {
Karsten Hopp 2f1054
+ 	if (*p == '^' && vim_strchr(escaped, p[1]) != NULL)
Karsten Hopp 2f1054
+ 	    mch_memmove(p, p + 1, l--);
Karsten Hopp 2f1054
+ #ifdef FEAT_MBYTE
Karsten Hopp 2f1054
+ 	n = (*mb_ptr2len)(p);
Karsten Hopp 2f1054
+ #else
Karsten Hopp 2f1054
+ 	n = 1;
Karsten Hopp 2f1054
+ #endif
Karsten Hopp 2f1054
+ 	p += n;
Karsten Hopp 2f1054
+ 	l -= n;
Karsten Hopp 2f1054
+     }
Karsten Hopp 2f1054
+ }
Karsten Hopp 2f1054
+ 
Karsten Hopp 2f1054
+ /*
Karsten Hopp 2f1054
   * Load library "name".
Karsten Hopp 2f1054
   */
Karsten Hopp 2f1054
      HINSTANCE
Karsten Hopp 2f1054
***************
Karsten Hopp 2f1054
*** 3559,3564 ****
Karsten Hopp 2f1054
--- 3582,3588 ----
Karsten Hopp 2f1054
      garray_T	ga;
Karsten Hopp 2f1054
      int	    delay = 1;
Karsten Hopp 2f1054
      DWORD	buffer_off = 0;	/* valid bytes in buffer[] */
Karsten Hopp 2f1054
+     char	*p = NULL;
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
      SECURITY_ATTRIBUTES saAttr;
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
***************
Karsten Hopp 2f1054
*** 3599,3607 ****
Karsten Hopp 2f1054
      if (options & SHELL_READ)
Karsten Hopp 2f1054
  	ga_init2(&ga, 1, BUFLEN);
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
      /* Now, run the command */
Karsten Hopp 2f1054
      CreateProcess(NULL,			/* Executable name */
Karsten Hopp 2f1054
! 		  cmd,			/* Command to execute */
Karsten Hopp 2f1054
  		  NULL,			/* Process security attributes */
Karsten Hopp 2f1054
  		  NULL,			/* Thread security attributes */
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
--- 3623,3640 ----
Karsten Hopp 2f1054
      if (options & SHELL_READ)
Karsten Hopp 2f1054
  	ga_init2(&ga, 1, BUFLEN);
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
+     if (cmd != NULL)
Karsten Hopp 2f1054
+     {
Karsten Hopp 2f1054
+ 	p = (char *)vim_strsave((char_u *)cmd);
Karsten Hopp 2f1054
+ 	if (p != NULL)
Karsten Hopp 2f1054
+ 	    unescape_shellxquote((char_u *)p, p_sxe);
Karsten Hopp 2f1054
+ 	else
Karsten Hopp 2f1054
+ 	    p = cmd;
Karsten Hopp 2f1054
+     }
Karsten Hopp 2f1054
+ 
Karsten Hopp 2f1054
      /* Now, run the command */
Karsten Hopp 2f1054
      CreateProcess(NULL,			/* Executable name */
Karsten Hopp 2f1054
! 		  p,			/* Command to execute */
Karsten Hopp 2f1054
  		  NULL,			/* Process security attributes */
Karsten Hopp 2f1054
  		  NULL,			/* Thread security attributes */
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
***************
Karsten Hopp 2f1054
*** 3616,3621 ****
Karsten Hopp 2f1054
--- 3649,3656 ----
Karsten Hopp 2f1054
  		  &si,			/* Startup information */
Karsten Hopp 2f1054
  		  &pi);			/* Process information */
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
+     if (p != cmd)
Karsten Hopp 2f1054
+ 	vim_free(p);
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
      /* Close our unused side of the pipes */
Karsten Hopp 2f1054
      CloseHandle(g_hChildStd_IN_Rd);
Karsten Hopp 2f1054
***************
Karsten Hopp 2f1054
*** 3898,4018 ****
Karsten Hopp 2f1054
      else
Karsten Hopp 2f1054
      {
Karsten Hopp 2f1054
  	/* we use "command" or "cmd" to start the shell; slow but easy */
Karsten Hopp 2f1054
! 	char_u *newcmd;
Karsten Hopp 2f1054
! 	long_u cmdlen =  (
Karsten Hopp 2f1054
! #ifdef FEAT_GUI_W32
Karsten Hopp 2f1054
! 		(allowPiping && !p_stmp ? 0 : STRLEN(vimrun_path)) +
Karsten Hopp 2f1054
! #endif
Karsten Hopp 2f1054
! 		STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10);
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 	newcmd = lalloc(cmdlen, TRUE);
Karsten Hopp 2f1054
! 	if (newcmd != NULL)
Karsten Hopp 2f1054
! 	{
Karsten Hopp 2f1054
! 	    char_u *cmdbase = cmd;
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 	    /* Skip a leading ", ( and "(. */
Karsten Hopp 2f1054
! 	    if (*cmdbase == '"' )
Karsten Hopp 2f1054
! 		++cmdbase;
Karsten Hopp 2f1054
! 	    if (*cmdbase == '(')
Karsten Hopp 2f1054
! 		++cmdbase;
Karsten Hopp 2f1054
! 	    if ((STRNICMP(cmdbase, "start", 5) == 0) && vim_iswhite(cmdbase[5]))
Karsten Hopp 2f1054
! 	    {
Karsten Hopp 2f1054
! 		STARTUPINFO		si;
Karsten Hopp 2f1054
! 		PROCESS_INFORMATION	pi;
Karsten Hopp 2f1054
! 		DWORD			flags = CREATE_NEW_CONSOLE;
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 		si.cb = sizeof(si);
Karsten Hopp 2f1054
! 		si.lpReserved = NULL;
Karsten Hopp 2f1054
! 		si.lpDesktop = NULL;
Karsten Hopp 2f1054
! 		si.lpTitle = NULL;
Karsten Hopp 2f1054
! 		si.dwFlags = 0;
Karsten Hopp 2f1054
! 		si.cbReserved2 = 0;
Karsten Hopp 2f1054
! 		si.lpReserved2 = NULL;
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 		cmdbase = skipwhite(cmdbase + 5);
Karsten Hopp 2f1054
! 		if ((STRNICMP(cmdbase, "/min", 4) == 0)
Karsten Hopp 2f1054
! 			&& vim_iswhite(cmdbase[4]))
Karsten Hopp 2f1054
! 		{
Karsten Hopp 2f1054
! 		    cmdbase = skipwhite(cmdbase + 4);
Karsten Hopp 2f1054
! 		    si.dwFlags = STARTF_USESHOWWINDOW;
Karsten Hopp 2f1054
! 		    si.wShowWindow = SW_SHOWMINNOACTIVE;
Karsten Hopp 2f1054
! 		}
Karsten Hopp 2f1054
! 		else if ((STRNICMP(cmdbase, "/b", 2) == 0)
Karsten Hopp 2f1054
! 			&& vim_iswhite(cmdbase[2]))
Karsten Hopp 2f1054
! 		{
Karsten Hopp 2f1054
! 		    cmdbase = skipwhite(cmdbase + 2);
Karsten Hopp 2f1054
! 		    flags = CREATE_NO_WINDOW;
Karsten Hopp 2f1054
! 		    si.dwFlags = STARTF_USESTDHANDLES;
Karsten Hopp 2f1054
! 		    si.hStdInput = CreateFile("\\\\.\\NUL",	// File name
Karsten Hopp 2f1054
! 			GENERIC_READ,				// Access flags
Karsten Hopp 2f1054
! 			0,					// Share flags
Karsten Hopp 2f1054
! 			NULL,					// Security att.
Karsten Hopp 2f1054
! 			OPEN_EXISTING,				// Open flags
Karsten Hopp 2f1054
! 			FILE_ATTRIBUTE_NORMAL,			// File att.
Karsten Hopp 2f1054
! 			NULL);					// Temp file
Karsten Hopp 2f1054
! 		    si.hStdOutput = si.hStdInput;
Karsten Hopp 2f1054
! 		    si.hStdError = si.hStdInput;
Karsten Hopp 2f1054
! 		}
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
! 		/* When the command is in double quotes, but 'shellxquote' is
Karsten Hopp 2f1054
! 		 * empty, keep the double quotes around the command.
Karsten Hopp 2f1054
! 		 * Otherwise remove the double quotes, they aren't needed
Karsten Hopp 2f1054
! 		 * here, because we don't use a shell to run the command. */
Karsten Hopp 2f1054
! 		if (cmdbase > cmd)
Karsten Hopp 2f1054
! 		{
Karsten Hopp 2f1054
! 		    if (STRNCMP(cmd, p_sxq, cmd - cmdbase) != 0)
Karsten Hopp 2f1054
! 		    {
Karsten Hopp 2f1054
! 			STRCPY(newcmd, cmd);
Karsten Hopp 2f1054
! 		    }
Karsten Hopp 2f1054
! 		    else
Karsten Hopp 2f1054
! 		    {
Karsten Hopp 2f1054
! 			char_u *p;
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
! 			STRCPY(newcmd, cmdbase);
Karsten Hopp 2f1054
! 			/* Remove a trailing ", ) and )" if they have a match
Karsten Hopp 2f1054
! 			 * at the start of the command. */
Karsten Hopp 2f1054
! 			p = newcmd + STRLEN(newcmd);
Karsten Hopp 2f1054
! 			if (p > newcmd && p[-1] == '"' && *cmd == '"')
Karsten Hopp 2f1054
! 			    *--p = NUL;
Karsten Hopp 2f1054
! 			if (p > newcmd && p[-1] == ')'
Karsten Hopp 2f1054
! 					     && (*cmd =='(' || cmd[1] == '('))
Karsten Hopp 2f1054
! 			    *--p = NUL;
Karsten Hopp 2f1054
! 		    }
Karsten Hopp 2f1054
! 		}
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
! 		/*
Karsten Hopp 2f1054
! 		 * Now, start the command as a process, so that it doesn't
Karsten Hopp 2f1054
! 		 * inherit our handles which causes unpleasant dangling swap
Karsten Hopp 2f1054
! 		 * files if we exit before the spawned process
Karsten Hopp 2f1054
! 		 */
Karsten Hopp 2f1054
! 		if (CreateProcess(NULL,		// Executable name
Karsten Hopp 2f1054
! 			newcmd,			// Command to execute
Karsten Hopp 2f1054
! 			NULL,			// Process security attributes
Karsten Hopp 2f1054
! 			NULL,			// Thread security attributes
Karsten Hopp 2f1054
! 			FALSE,			// Inherit handles
Karsten Hopp 2f1054
! 			flags,			// Creation flags
Karsten Hopp 2f1054
! 			NULL,			// Environment
Karsten Hopp 2f1054
! 			NULL,			// Current directory
Karsten Hopp 2f1054
! 			&si,			// Startup information
Karsten Hopp 2f1054
! 			&pi))			// Process information
Karsten Hopp 2f1054
! 		    x = 0;
Karsten Hopp 2f1054
! 		else
Karsten Hopp 2f1054
! 		{
Karsten Hopp 2f1054
! 		    x = -1;
Karsten Hopp 2f1054
  #ifdef FEAT_GUI_W32
Karsten Hopp 2f1054
! 		    EMSG(_("E371: Command not found"));
Karsten Hopp 2f1054
  #endif
Karsten Hopp 2f1054
- 		}
Karsten Hopp 2f1054
- 		if (si.hStdInput != NULL)
Karsten Hopp 2f1054
- 		{
Karsten Hopp 2f1054
- 		    /* Close the handle to \\.\NUL */
Karsten Hopp 2f1054
- 		    CloseHandle(si.hStdInput);
Karsten Hopp 2f1054
- 		}
Karsten Hopp 2f1054
- 		/* Close the handles to the subprocess, so that it goes away */
Karsten Hopp 2f1054
- 		CloseHandle(pi.hThread);
Karsten Hopp 2f1054
- 		CloseHandle(pi.hProcess);
Karsten Hopp 2f1054
  	    }
Karsten Hopp 2f1054
! 	    else
Karsten Hopp 2f1054
  	    {
Karsten Hopp 2f1054
  #if defined(FEAT_GUI_W32)
Karsten Hopp 2f1054
  		if (need_vimrun_warning)
Karsten Hopp 2f1054
--- 3933,4048 ----
Karsten Hopp 2f1054
      else
Karsten Hopp 2f1054
      {
Karsten Hopp 2f1054
  	/* we use "command" or "cmd" to start the shell; slow but easy */
Karsten Hopp 2f1054
! 	char_u *cmdbase = cmd;
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
! 	/* Skip a leading ", ( and "(. */
Karsten Hopp 2f1054
! 	if (*cmdbase == '"' )
Karsten Hopp 2f1054
! 	    ++cmdbase;
Karsten Hopp 2f1054
! 	if (*cmdbase == '(')
Karsten Hopp 2f1054
! 	    ++cmdbase;
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 	if ((STRNICMP(cmdbase, "start", 5) == 0) && vim_iswhite(cmdbase[5]))
Karsten Hopp 2f1054
! 	{
Karsten Hopp 2f1054
! 	    STARTUPINFO		si;
Karsten Hopp 2f1054
! 	    PROCESS_INFORMATION	pi;
Karsten Hopp 2f1054
! 	    DWORD		flags = CREATE_NEW_CONSOLE;
Karsten Hopp 2f1054
! 	    char_u		*p;
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 	    si.cb = sizeof(si);
Karsten Hopp 2f1054
! 	    si.lpReserved = NULL;
Karsten Hopp 2f1054
! 	    si.lpDesktop = NULL;
Karsten Hopp 2f1054
! 	    si.lpTitle = NULL;
Karsten Hopp 2f1054
! 	    si.dwFlags = 0;
Karsten Hopp 2f1054
! 	    si.cbReserved2 = 0;
Karsten Hopp 2f1054
! 	    si.lpReserved2 = NULL;
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 	    cmdbase = skipwhite(cmdbase + 5);
Karsten Hopp 2f1054
! 	    if ((STRNICMP(cmdbase, "/min", 4) == 0)
Karsten Hopp 2f1054
! 		    && vim_iswhite(cmdbase[4]))
Karsten Hopp 2f1054
! 	    {
Karsten Hopp 2f1054
! 		cmdbase = skipwhite(cmdbase + 4);
Karsten Hopp 2f1054
! 		si.dwFlags = STARTF_USESHOWWINDOW;
Karsten Hopp 2f1054
! 		si.wShowWindow = SW_SHOWMINNOACTIVE;
Karsten Hopp 2f1054
! 	    }
Karsten Hopp 2f1054
! 	    else if ((STRNICMP(cmdbase, "/b", 2) == 0)
Karsten Hopp 2f1054
! 		    && vim_iswhite(cmdbase[2]))
Karsten Hopp 2f1054
! 	    {
Karsten Hopp 2f1054
! 		cmdbase = skipwhite(cmdbase + 2);
Karsten Hopp 2f1054
! 		flags = CREATE_NO_WINDOW;
Karsten Hopp 2f1054
! 		si.dwFlags = STARTF_USESTDHANDLES;
Karsten Hopp 2f1054
! 		si.hStdInput = CreateFile("\\\\.\\NUL",	// File name
Karsten Hopp 2f1054
! 		    GENERIC_READ,				// Access flags
Karsten Hopp 2f1054
! 		    0,					// Share flags
Karsten Hopp 2f1054
! 		    NULL,					// Security att.
Karsten Hopp 2f1054
! 		    OPEN_EXISTING,				// Open flags
Karsten Hopp 2f1054
! 		    FILE_ATTRIBUTE_NORMAL,			// File att.
Karsten Hopp 2f1054
! 		    NULL);					// Temp file
Karsten Hopp 2f1054
! 		si.hStdOutput = si.hStdInput;
Karsten Hopp 2f1054
! 		si.hStdError = si.hStdInput;
Karsten Hopp 2f1054
! 	    }
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 	    /* Remove a trailing ", ) and )" if they have a match
Karsten Hopp 2f1054
! 	     * at the start of the command. */
Karsten Hopp 2f1054
! 	    if (cmdbase > cmd)
Karsten Hopp 2f1054
! 	    {
Karsten Hopp 2f1054
! 		p = cmdbase + STRLEN(cmdbase);
Karsten Hopp 2f1054
! 		if (p > cmdbase && p[-1] == '"' && *cmd == '"')
Karsten Hopp 2f1054
! 		    *--p = NUL;
Karsten Hopp 2f1054
! 		if (p > cmdbase && p[-1] == ')'
Karsten Hopp 2f1054
! 			&& (*cmd =='(' || cmd[1] == '('))
Karsten Hopp 2f1054
! 		    *--p = NUL;
Karsten Hopp 2f1054
! 	    }
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
! 	    /*
Karsten Hopp 2f1054
! 	     * Unescape characters in shellxescape. This is workaround for
Karsten Hopp 2f1054
! 	     * /b option. Only redirect character should be unescaped.
Karsten Hopp 2f1054
! 	     */
Karsten Hopp 2f1054
! 	    unescape_shellxquote(cmdbase,
Karsten Hopp 2f1054
! 			(flags & CREATE_NEW_CONSOLE) ? p_sxe : "<>");
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
! 	    /*
Karsten Hopp 2f1054
! 	     * Now, start the command as a process, so that it doesn't
Karsten Hopp 2f1054
! 	     * inherit our handles which causes unpleasant dangling swap
Karsten Hopp 2f1054
! 	     * files if we exit before the spawned process
Karsten Hopp 2f1054
! 	     */
Karsten Hopp 2f1054
! 	    if (CreateProcess(NULL,		// Executable name
Karsten Hopp 2f1054
! 		    cmdbase,			// Command to execute
Karsten Hopp 2f1054
! 		    NULL,			// Process security attributes
Karsten Hopp 2f1054
! 		    NULL,			// Thread security attributes
Karsten Hopp 2f1054
! 		    FALSE,			// Inherit handles
Karsten Hopp 2f1054
! 		    flags,			// Creation flags
Karsten Hopp 2f1054
! 		    NULL,			// Environment
Karsten Hopp 2f1054
! 		    NULL,			// Current directory
Karsten Hopp 2f1054
! 		    &si,			// Startup information
Karsten Hopp 2f1054
! 		    &pi))			// Process information
Karsten Hopp 2f1054
! 		x = 0;
Karsten Hopp 2f1054
! 	    else
Karsten Hopp 2f1054
! 	    {
Karsten Hopp 2f1054
! 		x = -1;
Karsten Hopp 2f1054
  #ifdef FEAT_GUI_W32
Karsten Hopp 2f1054
! 		EMSG(_("E371: Command not found"));
Karsten Hopp 2f1054
  #endif
Karsten Hopp 2f1054
  	    }
Karsten Hopp 2f1054
! 	    if (si.hStdInput != NULL)
Karsten Hopp 2f1054
! 	    {
Karsten Hopp 2f1054
! 		/* Close the handle to \\.\NUL */
Karsten Hopp 2f1054
! 		CloseHandle(si.hStdInput);
Karsten Hopp 2f1054
! 	    }
Karsten Hopp 2f1054
! 	    /* Close the handles to the subprocess, so that it goes away */
Karsten Hopp 2f1054
! 	    CloseHandle(pi.hThread);
Karsten Hopp 2f1054
! 	    CloseHandle(pi.hProcess);
Karsten Hopp 2f1054
! 	}
Karsten Hopp 2f1054
! 	else
Karsten Hopp 2f1054
! 	{
Karsten Hopp 2f1054
! 	    char_u *newcmd;
Karsten Hopp 2f1054
! 	    long_u cmdlen =  (
Karsten Hopp 2f1054
! #ifdef FEAT_GUI_W32
Karsten Hopp 2f1054
! 		(allowPiping && !p_stmp ? 0 : STRLEN(vimrun_path)) +
Karsten Hopp 2f1054
! #endif
Karsten Hopp 2f1054
! 		STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10);
Karsten Hopp 2f1054
! 
Karsten Hopp 2f1054
! 	    newcmd = lalloc(cmdlen, TRUE);
Karsten Hopp 2f1054
! 	    if (newcmd != NULL)
Karsten Hopp 2f1054
  	    {
Karsten Hopp 2f1054
  #if defined(FEAT_GUI_W32)
Karsten Hopp 2f1054
  		if (need_vimrun_warning)
Karsten Hopp 2f1054
***************
Karsten Hopp 2f1054
*** 4038,4045 ****
Karsten Hopp 2f1054
  		    vim_snprintf((char *)newcmd, cmdlen, "%s %s %s",
Karsten Hopp 2f1054
  							   p_sh, p_shcf, cmd);
Karsten Hopp 2f1054
  		x = mch_system((char *)newcmd, options);
Karsten Hopp 2f1054
  	    }
Karsten Hopp 2f1054
- 	    vim_free(newcmd);
Karsten Hopp 2f1054
  	}
Karsten Hopp 2f1054
      }
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
--- 4068,4075 ----
Karsten Hopp 2f1054
  		    vim_snprintf((char *)newcmd, cmdlen, "%s %s %s",
Karsten Hopp 2f1054
  							   p_sh, p_shcf, cmd);
Karsten Hopp 2f1054
  		x = mch_system((char *)newcmd, options);
Karsten Hopp 2f1054
+ 		vim_free(newcmd);
Karsten Hopp 2f1054
  	    }
Karsten Hopp 2f1054
  	}
Karsten Hopp 2f1054
      }
Karsten Hopp 2f1054
  
Karsten Hopp 2f1054
*** ../vim-7.3.446/src/version.c	2012-02-20 22:18:23.000000000 +0100
Karsten Hopp 2f1054
--- src/version.c	2012-02-21 21:20:05.000000000 +0100
Karsten Hopp 2f1054
***************
Karsten Hopp 2f1054
*** 716,717 ****
Karsten Hopp 2f1054
--- 716,719 ----
Karsten Hopp 2f1054
  {   /* Add new patch number below this line */
Karsten Hopp 2f1054
+ /**/
Karsten Hopp 2f1054
+     447,
Karsten Hopp 2f1054
  /**/
Karsten Hopp 2f1054
Karsten Hopp 2f1054
-- 
Karsten Hopp 2f1054
From "know your smileys":
Karsten Hopp 2f1054
 :----}  You lie like Pinocchio
Karsten Hopp 2f1054
Karsten Hopp 2f1054
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp 2f1054
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp 2f1054
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
Karsten Hopp 2f1054
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///