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:
19
src/option.c
19
src/option.c
@@ -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
|
||||||
/*
|
/*
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -574,11 +574,17 @@ func Test_set_shell()
|
|||||||
quit!
|
quit!
|
||||||
[CODE]
|
[CODE]
|
||||||
|
|
||||||
let $SHELL = '/bin/with space/sh'
|
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 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
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
24
src/vimrun.c
24
src/vimrun.c
@@ -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)
|
||||||
|
Reference in New Issue
Block a user