summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-10-05 12:09:32 +0200
committerBram Moolenaar <Bram@vim.org>2019-10-05 12:09:32 +0200
commit2efc44b3f0b6bd8307cb281af095e08e15ab1c24 (patch)
tree4245a8fef089e696e8eb6df87e02cafbc4d7806e
parentfd00c042afc40539447e798aadbd0a2219fdbdc1 (diff)
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.c19
-rw-r--r--src/os_win32.c19
-rw-r--r--src/testdir/test_startup.vim12
-rw-r--r--src/testdir/test_system.vim51
-rw-r--r--src/version.c2
-rw-r--r--src/vimrun.c24
6 files changed, 122 insertions, 5 deletions
diff --git a/src/option.c b/src/option.c
index 3d408143e9..75ff3cdb29 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 26005b24fc..ce035570db 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 ceee044ca3..f10eabb798 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 dfe3683723..eabccfb371 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 0673d7e787..b1bccb4f6b 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 ece20f8392..26c4aa4c64 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)