# HG changeset patch # User Bram Moolenaar # Date 1329671970 -3600 # Node ID 397e7e49bb0b831f7260d3ad70f6b07175c44a0c # Parent b37888de599c8292023dd290c4a7fabb9937a207 updated for version 7.3.445 Problem: Can't properly escape commands for cmd.exe. Solution: Default 'shellxquote' to '('. Append ')' to make '(command)'. No need to use "/s" for 'shellcmdflag'. diff --git a/src/misc2.c b/src/misc2.c --- a/src/misc2.c +++ b/src/misc2.c @@ -3230,7 +3230,11 @@ call_shell(cmd, opt) { STRCPY(ncmd, p_sxq); STRCAT(ncmd, cmd); - STRCAT(ncmd, p_sxq); + /* When 'shellxquote' is ( append ). + * When 'shellxquote' is "( append )". */ + STRCAT(ncmd, STRCMP(p_sxq, "(") == 0 ? (char_u *)")" + : STRCMP(p_sxq, "\"(") == 0 ? (char_u *)")\"" + : p_sxq); retval = mch_call_shell(ncmd, opt); vim_free(ncmd); } diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -3933,27 +3933,22 @@ set_init_3() * my path/to/echo" "my args to echo * when executed. * - * To avoid this, use the /s argument in addition to /c to force the - * stripping behavior, and also set shellxquote to automatically - * surround the entire command in quotes (which get stripped as - * noted). + * To avoid this, set shellxquote to surround the command in + * parenthesis. This appears to make most commands work, without + * breaking commands that worked previously, such as + * '"path with spaces/cmd" "a&b"'. */ - - /* Set shellxquote default to add the quotes to be stripped. */ idx3 = findoption((char_u *)"sxq"); if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET)) { - p_sxq = (char_u *)"\""; + p_sxq = (char_u *)"("; options[idx3].def_val[VI_DEFAULT] = p_sxq; } - /* Set shellcmdflag default to always strip the quotes, note the order - * between /s and /c is important or cmd.exe will treat the /s as part - * of the command to be executed. */ idx3 = findoption((char_u *)"shcf"); if (idx3 >= 0 && !(options[idx3].flags & P_WAS_SET)) { - p_shcf = (char_u *)"/s /c"; + p_shcf = (char_u *)"/c"; options[idx3].def_val[VI_DEFAULT] = p_shcf; } } diff --git a/src/os_win32.c b/src/os_win32.c --- a/src/os_win32.c +++ b/src/os_win32.c @@ -3908,8 +3908,13 @@ mch_call_shell( newcmd = lalloc(cmdlen, TRUE); if (newcmd != NULL) { - char_u *cmdbase = (*cmd == '"' ? cmd + 1 : cmd); - + 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; @@ -3953,16 +3958,26 @@ mch_call_shell( * 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 (*cmd == '"' && *p_sxq == NUL) + if (cmdbase > cmd) { - newcmd[0] = '"'; - STRCPY(newcmd + 1, cmdbase); - } - else - { - STRCPY(newcmd, cmdbase); - if (*cmd == '"' && *newcmd != NUL) - newcmd[STRLEN(newcmd) - 1] = NUL; + 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; + } } /* @@ -3970,7 +3985,7 @@ mch_call_shell( * inherit our handles which causes unpleasant dangling swap * files if we exit before the spawned process */ - if (CreateProcess (NULL, // Executable name + if (CreateProcess(NULL, // Executable name newcmd, // Command to execute NULL, // Process security attributes NULL, // Thread security attributes diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -715,6 +715,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 445, +/**/ 444, /**/ 443,