diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-10-05 12:09:32 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-10-05 12:09:32 +0200 |
commit | 2efc44b3f0b6bd8307cb281af095e08e15ab1c24 (patch) | |
tree | 4245a8fef089e696e8eb6df87e02cafbc4d7806e | |
parent | fd00c042afc40539447e798aadbd0a2219fdbdc1 (diff) | |
download | vim-git-2efc44b3f0b6bd8307cb281af095e08e15ab1c24.tar.gz |
patch 8.1.2115: MS-Windows: shell commands fail if &shell contains a spacev8.1.2115
Problem: MS-Windows: shell commands fail if &shell contains a space.
Solution: Use quotes instead of escaping. (closes #4920)
-rw-r--r-- | src/option.c | 19 | ||||
-rw-r--r-- | src/os_win32.c | 19 | ||||
-rw-r--r-- | src/testdir/test_startup.vim | 12 | ||||
-rw-r--r-- | src/testdir/test_system.vim | 51 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vimrun.c | 24 |
6 files changed, 122 insertions, 5 deletions
diff --git a/src/option.c b/src/option.c index 3d408143e..75ff3cdb2 100644 --- a/src/option.c +++ b/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 /* diff --git a/src/os_win32.c b/src/os_win32.c index 26005b24f..ce035570d 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -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); - wcmd = enc_to_utf16((char_u *)cmd, NULL); if (wcmd == NULL) return -1; diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index ceee044ca..f10eabb79 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -574,11 +574,17 @@ func Test_set_shell() quit! [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, '', '') 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 diff --git a/src/testdir/test_system.vim b/src/testdir/test_system.vim index dfe368372..eabccfb37 100644 --- a/src/testdir/test_system.vim +++ b/src/testdir/test_system.vim @@ -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 diff --git a/src/version.c b/src/version.c index 0673d7e78..b1bccb4f6 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2115, +/**/ 2114, /**/ 2113, diff --git a/src/vimrun.c b/src/vimrun.c index ece20f839..26c4aa4c6 100644 --- a/src/vimrun.c +++ b/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) |