0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.1.2115: MS-Windows: shell commands fail if &shell contains a space

Problem:    MS-Windows: shell commands fail if &shell contains a space.
Solution:   Use quotes instead of escaping. (closes #4920)
This commit is contained in:
Bram Moolenaar
2019-10-05 12:09:32 +02:00
parent fd00c042af
commit 2efc44b3f0
6 changed files with 122 additions and 5 deletions

View File

@@ -102,7 +102,26 @@ set_init_1(int clean_arg)
|| ((p = (char_u *)default_shell()) != NULL && *p != NUL) || ((p = (char_u *)default_shell()) != NULL && *p != NUL)
#endif #endif
) )
#if defined(MSWIN)
{
// For MS-Windows put the path in quotes instead of escaping spaces.
char_u *cmd;
size_t len;
if (vim_strchr(p, ' ') != NULL)
{
len = STRLEN(p) + 3; // two quotes and a trailing NUL
cmd = alloc(len);
vim_snprintf((char *)cmd, len, "\"%s\"", p);
set_string_default("sh", cmd);
vim_free(cmd);
}
else
set_string_default("sh", p);
}
#else
set_string_default_esc("sh", p, TRUE); set_string_default_esc("sh", p, TRUE);
#endif
#ifdef FEAT_WILDIGN #ifdef FEAT_WILDIGN
/* /*

View File

@@ -4490,8 +4490,25 @@ mch_system_c(char *cmd, int options UNUSED)
{ {
int ret; int ret;
WCHAR *wcmd; WCHAR *wcmd;
char_u *buf;
size_t len;
// If the command starts and ends with double quotes, enclose the command
// in parentheses.
len = STRLEN(cmd);
if (len >= 2 && cmd[0] == '"' && cmd[len - 1] == '"')
{
len += 3;
buf = alloc(len);
if (buf == NULL)
return -1;
vim_snprintf((char *)buf, len, "(%s)", cmd);
wcmd = enc_to_utf16(buf, NULL);
free(buf);
}
else
wcmd = enc_to_utf16((char_u *)cmd, NULL); wcmd = enc_to_utf16((char_u *)cmd, NULL);
if (wcmd == NULL) if (wcmd == NULL)
return -1; return -1;

View File

@@ -574,11 +574,17 @@ func Test_set_shell()
quit! quit!
[CODE] [CODE]
if has('win32')
let $SHELL = 'C:\with space\cmd.exe'
let expected = '"C:\with space\cmd.exe"'
else
let $SHELL = '/bin/with space/sh' let $SHELL = '/bin/with space/sh'
let expected = '/bin/with\ space/sh'
endif
if RunVimPiped([], after, '', '') if RunVimPiped([], after, '', '')
let lines = readfile('Xtestout') let lines = readfile('Xtestout')
" MS-Windows adds a space after the word call assert_equal(expected, lines[0])
call assert_equal('/bin/with\ space/sh', lines[0])
endif endif
call delete('Xtestout') call delete('Xtestout')
endfunc endfunc

View File

@@ -1,6 +1,7 @@
" Tests for system() and systemlist() " Tests for system() and systemlist()
source shared.vim source shared.vim
source check.vim
func Test_System() func Test_System()
if !has('win32') if !has('win32')
@@ -112,3 +113,53 @@ func Test_system_exmode()
let a = system(GetVimCommand() . cmd) let a = system(GetVimCommand() . cmd)
call assert_notequal(0, v:shell_error) call assert_notequal(0, v:shell_error)
endfunc endfunc
func Test_system_with_shell_quote()
CheckMSWindows
call mkdir('Xdir with spaces', 'p')
call system('copy "%COMSPEC%" "Xdir with spaces\cmd.exe"')
let shell_save = &shell
let shellxquote_save = &shellxquote
try
" Set 'shell' always needs noshellslash.
let shellslash_save = &shellslash
set noshellslash
let shell_tests = [
\ expand('$COMSPEC'),
\ '"' . fnamemodify('Xdir with spaces\cmd.exe', ':p') . '"',
\]
let &shellslash = shellslash_save
let sxq_tests = ['', '(', '"']
" Matrix tests: 'shell' * 'shellxquote'
for shell in shell_tests
let &shell = shell
for sxq in sxq_tests
let &shellxquote = sxq
let msg = printf('shell=%s shellxquote=%s', &shell, &shellxquote)
try
let out = 'echo 123'->system()
catch
call assert_report(printf('%s: %s', msg, v:exception))
continue
endtry
" On Windows we may get a trailing space and CR.
if out != "123 \n"
call assert_equal("123\n", out, msg)
endif
endfor
endfor
finally
let &shell = shell_save
let &shellxquote = shellxquote_save
call delete('Xdir with spaces', 'rf')
endtry
endfunc

View File

@@ -753,6 +753,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2115,
/**/ /**/
2114, 2114,
/**/ /**/

View File

@@ -27,6 +27,8 @@
main(void) main(void)
{ {
const wchar_t *p; const wchar_t *p;
wchar_t *cmd;
size_t cmdlen;
int retval; int retval;
int inquote = 0; int inquote = 0;
int silent = 0; int silent = 0;
@@ -63,16 +65,36 @@ main(void)
++p; ++p;
} }
/* Print the command, including quotes and redirection. */ // Print the command, including quotes and redirection.
hstdout = GetStdHandle(STD_OUTPUT_HANDLE); hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsoleW(hstdout, p, wcslen(p), &written, NULL); WriteConsoleW(hstdout, p, wcslen(p), &written, NULL);
WriteConsoleW(hstdout, L"\r\n", 2, &written, NULL); WriteConsoleW(hstdout, L"\r\n", 2, &written, NULL);
// If the command starts and ends with double quotes,
// Enclose the command in parentheses.
cmd = NULL;
cmdlen = wcslen(p);
if (cmdlen >= 2 && p[0] == L'"' && p[cmdlen - 1] == L'"')
{
cmdlen += 3;
cmd = (wchar_t *)malloc(cmdlen * sizeof(wchar_t));
if (cmd == NULL)
{
perror("vimrun malloc(): ");
return -1;
}
_snwprintf(cmd, cmdlen, L"(%s)", p);
p = cmd;
}
/* /*
* Do it! * Do it!
*/ */
retval = _wsystem(p); retval = _wsystem(p);
if (cmd)
free(cmd);
if (retval == -1) if (retval == -1)
perror("vimrun system(): "); perror("vimrun system(): ");
else if (retval != 0) else if (retval != 0)