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)
|
||||
#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);
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_WILDIGN
|
||||
/*
|
||||
|
@@ -4490,8 +4490,25 @@ mch_system_c(char *cmd, int options UNUSED)
|
||||
{
|
||||
int ret;
|
||||
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);
|
||||
|
||||
if (wcmd == NULL)
|
||||
return -1;
|
||||
|
||||
|
@@ -574,11 +574,17 @@ func Test_set_shell()
|
||||
quit!
|
||||
[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 expected = '/bin/with\ space/sh'
|
||||
endif
|
||||
|
||||
if RunVimPiped([], after, '', '')
|
||||
let lines = readfile('Xtestout')
|
||||
" MS-Windows adds a space after the word
|
||||
call assert_equal('/bin/with\ space/sh', lines[0])
|
||||
call assert_equal(expected, lines[0])
|
||||
endif
|
||||
call delete('Xtestout')
|
||||
endfunc
|
||||
|
@@ -1,6 +1,7 @@
|
||||
" Tests for system() and systemlist()
|
||||
|
||||
source shared.vim
|
||||
source check.vim
|
||||
|
||||
func Test_System()
|
||||
if !has('win32')
|
||||
@@ -112,3 +113,53 @@ func Test_system_exmode()
|
||||
let a = system(GetVimCommand() . cmd)
|
||||
call assert_notequal(0, v:shell_error)
|
||||
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[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2115,
|
||||
/**/
|
||||
2114,
|
||||
/**/
|
||||
|
24
src/vimrun.c
24
src/vimrun.c
@@ -27,6 +27,8 @@
|
||||
main(void)
|
||||
{
|
||||
const wchar_t *p;
|
||||
wchar_t *cmd;
|
||||
size_t cmdlen;
|
||||
int retval;
|
||||
int inquote = 0;
|
||||
int silent = 0;
|
||||
@@ -63,16 +65,36 @@ main(void)
|
||||
++p;
|
||||
}
|
||||
|
||||
/* Print the command, including quotes and redirection. */
|
||||
// Print the command, including quotes and redirection.
|
||||
hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
WriteConsoleW(hstdout, p, wcslen(p), &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!
|
||||
*/
|
||||
retval = _wsystem(p);
|
||||
|
||||
if (cmd)
|
||||
free(cmd);
|
||||
|
||||
if (retval == -1)
|
||||
perror("vimrun system(): ");
|
||||
else if (retval != 0)
|
||||
|
Reference in New Issue
Block a user