From 0b9664f5240be4d9e9d6882fcd398970fd3a9532 Mon Sep 17 00:00:00 2001 From: Enan Ajmain <3nan.ajmain@gmail.com> Date: Tue, 9 Nov 2021 20:22:21 +0600 Subject: fix: make_filter_cmd for :! powershell #15913 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Nvim fails to create tempfile "…/nvim6UJx04/7" when 'shell' is set to pwsh (PowerShell Core). This breaks filtered shell commands ":{range}!". With shell set to cmd, it works. Solution: PowerShell doesn't use "<" for stdin redirection. Instead, use "-RedirectStandardInput". Closes #15913 --- src/nvim/ex_cmds.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'src/nvim') diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index a1f0a123b1..0f351d8af6 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1573,14 +1573,18 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) #else false; #endif + bool is_pwsh = STRNCMP(invocation_path_tail(p_sh, NULL), "pwsh", 4) == 0 + || STRNCMP(invocation_path_tail(p_sh, NULL), "powershell", 10) == 0; size_t len = STRLEN(cmd) + 1; // At least enough space for cmd + NULL. len += is_fish_shell ? sizeof("begin; " "; end") - 1 - : sizeof("(" ")") - 1; + : is_pwsh ? STRLEN("Start-Process ") + : sizeof("(" ")") - 1; if (itmp != NULL) { - len += STRLEN(itmp) + sizeof(" { " " < " " } ") - 1; + len += is_pwsh ? STRLEN(itmp) + STRLEN(" -RedirectStandardInput ") + : STRLEN(itmp) + sizeof(" { " " < " " } ") - 1; } if (otmp != NULL) { len += STRLEN(otmp) + STRLEN(p_srr) + 2; // two extra spaces (" "), @@ -1590,7 +1594,10 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) #if defined(UNIX) // Put delimiters around the command (for concatenated commands) when // redirecting input and/or output. - if (itmp != NULL || otmp != NULL) { + if (is_pwsh) { + xstrlcpy(buf, "Start-Process ", len); + xstrlcat(buf, (char *)cmd, len); + } else if (itmp != NULL || otmp != NULL) { char *fmt = is_fish_shell ? "begin; %s; end" : "(%s)"; vim_snprintf(buf, len, fmt, cmd); @@ -1599,13 +1606,22 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) } if (itmp != NULL) { - xstrlcat(buf, " < ", len - 1); + if (is_pwsh) { + xstrlcat(buf, " -RedirectStandardInput ", len - 1); + } else { + xstrlcat(buf, " < ", len - 1); + } xstrlcat(buf, (const char *)itmp, len - 1); } #else // For shells that don't understand braces around commands, at least allow // the use of commands in a pipe. - xstrlcpy(buf, (char *)cmd, len); + if (is_pwsh) { + xstrlcpy(buf, "Start-Process ", len); + xstrlcat(buf, (char *)cmd, len); + } else { + xstrlcpy(buf, (char *)cmd, len); + } if (itmp != NULL) { // If there is a pipe, we have to put the '<' in front of it. // Don't do this when 'shellquote' is not empty, otherwise the @@ -1616,7 +1632,11 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) *p = NUL; } } - xstrlcat(buf, " < ", len); + if (is_pwsh) { + xstrlcat(buf, " -RedirectStandardInput ", len); + } else { + xstrlcat(buf, " < ", len); + } xstrlcat(buf, (const char *)itmp, len); if (*p_shq == NUL) { const char *const p = find_pipe((const char *)cmd); -- cgit From f977f9445f7689fc32a136108ff92b3c2137968c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 22 Jun 2022 05:51:52 -0700 Subject: refactor(tests): introduce testprg() Also: - Add a describe('shell :!') section to system_spec. - Make the test for #16271 work on systems without powershell. --- src/nvim/ex_cmds.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/nvim') diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 0f351d8af6..bd8c099579 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1579,11 +1579,11 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) size_t len = STRLEN(cmd) + 1; // At least enough space for cmd + NULL. len += is_fish_shell ? sizeof("begin; " "; end") - 1 - : is_pwsh ? STRLEN("Start-Process ") + : is_pwsh ? sizeof("Start-Process ") : sizeof("(" ")") - 1; if (itmp != NULL) { - len += is_pwsh ? STRLEN(itmp) + STRLEN(" -RedirectStandardInput ") + len += is_pwsh ? STRLEN(itmp) + sizeof(" -RedirectStandardInput ") : STRLEN(itmp) + sizeof(" { " " < " " } ") - 1; } if (otmp != NULL) { @@ -1596,7 +1596,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) // redirecting input and/or output. if (is_pwsh) { xstrlcpy(buf, "Start-Process ", len); - xstrlcat(buf, (char *)cmd, len); + xstrlcat(buf, cmd, len); } else if (itmp != NULL || otmp != NULL) { char *fmt = is_fish_shell ? "begin; %s; end" : "(%s)"; @@ -1611,16 +1611,16 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) } else { xstrlcat(buf, " < ", len - 1); } - xstrlcat(buf, (const char *)itmp, len - 1); + xstrlcat(buf, itmp, len - 1); } #else // For shells that don't understand braces around commands, at least allow // the use of commands in a pipe. if (is_pwsh) { xstrlcpy(buf, "Start-Process ", len); - xstrlcat(buf, (char *)cmd, len); + xstrlcat(buf, cmd, len); } else { - xstrlcpy(buf, (char *)cmd, len); + xstrlcpy(buf, cmd, len); } if (itmp != NULL) { // If there is a pipe, we have to put the '<' in front of it. @@ -1637,9 +1637,9 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp) } else { xstrlcat(buf, " < ", len); } - xstrlcat(buf, (const char *)itmp, len); + xstrlcat(buf, itmp, len); if (*p_shq == NUL) { - const char *const p = find_pipe((const char *)cmd); + const char *const p = find_pipe(cmd); if (p != NULL) { xstrlcat(buf, " ", len - 1); // Insert a space before the '|' for DOS xstrlcat(buf, p, len - 1); -- cgit