To: vim_dev@googlegroups.com Subject: Patch 8.1.2115 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2115 Problem: MS-Windows: shell commands fail if &shell contains a space. Solution: Use quotes instead of escaping. (closes #4920) Files: src/option.c, src/os_win32.c, src/testdir/test_startup.vim, src/testdir/test_system.vim, src/vimrun.c, *** ../vim-8.1.2114/src/option.c 2019-10-01 17:01:56.346282798 +0200 --- src/option.c 2019-10-05 12:06:18.371723592 +0200 *************** *** 102,108 **** --- 102,127 ---- || ((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 /* *** ../vim-8.1.2114/src/os_win32.c 2019-10-04 21:29:01.744385935 +0200 --- src/os_win32.c 2019-10-05 12:07:14.799436544 +0200 *************** *** 4490,4497 **** { int ret; WCHAR *wcmd; - wcmd = enc_to_utf16((char_u *)cmd, NULL); if (wcmd == NULL) return -1; --- 4490,4514 ---- { 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; *** ../vim-8.1.2114/src/testdir/test_startup.vim 2019-08-07 23:07:03.960858821 +0200 --- src/testdir/test_startup.vim 2019-10-05 12:02:29.716858348 +0200 *************** *** 574,584 **** quit! [CODE] ! let $SHELL = '/bin/with space/sh' if RunVimPiped([], after, '', '') let lines = readfile('Xtestout') ! " MS-Windows adds a space after the word ! call assert_equal('/bin/with\ space/sh', lines[0]) endif call delete('Xtestout') endfunc --- 574,590 ---- 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') ! call assert_equal(expected, lines[0]) endif call delete('Xtestout') endfunc *** ../vim-8.1.2114/src/testdir/test_system.vim 2019-09-28 16:24:56.429236536 +0200 --- src/testdir/test_system.vim 2019-10-05 12:02:29.716858348 +0200 *************** *** 1,6 **** --- 1,7 ---- " Tests for system() and systemlist() source shared.vim + source check.vim func Test_System() if !has('win32') *************** *** 112,114 **** --- 113,165 ---- 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 *** ../vim-8.1.2114/src/vimrun.c 2019-05-09 15:12:45.180723879 +0200 --- src/vimrun.c 2019-10-05 12:07:58.655211857 +0200 *************** *** 27,32 **** --- 27,34 ---- main(void) { const wchar_t *p; + wchar_t *cmd; + size_t cmdlen; int retval; int inquote = 0; int silent = 0; *************** *** 63,78 **** ++p; } ! /* 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); /* * Do it! */ retval = _wsystem(p); if (retval == -1) perror("vimrun system(): "); else if (retval != 0) --- 65,100 ---- ++p; } ! // 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) *** ../vim-8.1.2114/src/version.c 2019-10-05 11:56:49.670415784 +0200 --- src/version.c 2019-10-05 12:04:54.880143732 +0200 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 2115, /**/ -- TALL KNIGHT: We are now no longer the Knights Who Say Ni! ONE KNIGHT: Ni! OTHERS: Sh! ONE KNIGHT: (whispers) Sorry. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///