aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/event/libuv_process.c8
-rw-r--r--src/nvim/memory.c7
-rw-r--r--src/nvim/misc1.c6
-rw-r--r--src/nvim/options.lua6
-rw-r--r--src/nvim/os/env.c22
-rw-r--r--src/nvim/os/shell.c2
-rw-r--r--src/nvim/strings.c36
7 files changed, 73 insertions, 14 deletions
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index 3da0c386b4..f5a41d151b 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -8,6 +8,7 @@
#include "nvim/event/process.h"
#include "nvim/event/libuv_process.h"
#include "nvim/log.h"
+#include "nvim/os/os.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/libuv_process.c.generated.h"
@@ -24,6 +25,13 @@ int libuv_process_spawn(LibuvProcess *uvproc)
if (proc->detach) {
uvproc->uvopts.flags |= UV_PROCESS_DETACHED;
}
+#ifdef WIN32
+ // libuv collapses the argv to a CommandLineToArgvW()-style string. cmd.exe
+ // expects a different syntax (must be prepared by the caller before now).
+ if (os_shell_is_cmdexe(proc->argv[0])) {
+ uvproc->uvopts.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
+ }
+#endif
uvproc->uvopts.exit_cb = exit_cb;
uvproc->uvopts.cwd = proc->cwd;
uvproc->uvopts.env = NULL;
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index b4fdd86a6d..85ec916ba0 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -495,6 +495,13 @@ bool strequal(const char *a, const char *b)
return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0);
}
+/// Case-insensitive `strequal`.
+bool striequal(const char *a, const char *b)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return (a == NULL && b == NULL) || (a && b && STRICMP(a, b) == 0);
+}
+
/*
* Avoid repeating the error message many times (they take 1 second each).
* Did_outofmem_msg is reset when a character is read.
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index 0b74b4437e..8d93505be3 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -2678,7 +2678,8 @@ void fast_breakcheck(void)
}
}
-// Call shell. Calls os_call_shell, with 'shellxquote' added.
+// os_call_shell wrapper. Handles 'verbose', :profile, and v:shell_error.
+// Invalidates cached tags.
int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
{
int retval;
@@ -2686,8 +2687,7 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
if (p_verbose > 3) {
verbose_enter();
- smsg(_("Calling shell to execute: \"%s\""),
- cmd == NULL ? p_sh : cmd);
+ smsg(_("Calling shell to execute: \"%s\""), cmd == NULL ? p_sh : cmd);
ui_putc('\n');
verbose_leave();
}
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 4ca63f2efe..4e7be63b63 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2051,7 +2051,11 @@ return {
secure=true,
vi_def=true,
varname='p_srr',
- defaults={if_true={vi=">"}}
+ defaults={
+ condition='WIN32',
+ if_true={vi=">%s 2>&1"},
+ if_false={vi=">"}
+ }
},
{
full_name='shellslash', abbreviation='ssl',
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 12c2da6152..ad51e598c1 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -1,11 +1,8 @@
-// env.c -- environment variable access
+// Environment inspection
#include <assert.h>
-
#include <uv.h>
-// vim.h must be included before charset.h (and possibly others) or things
-// blow up
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/charset.h"
@@ -919,3 +916,20 @@ bool os_term_is_nice(void)
|| NULL != os_getenv("KONSOLE_DBUS_SESSION");
#endif
}
+
+/// Returns true if `sh` looks like it resolves to "cmd.exe".
+bool os_shell_is_cmdexe(const char *sh)
+ FUNC_ATTR_NONNULL_ALL
+{
+ if (*sh == NUL) {
+ return false;
+ }
+ if (striequal(sh, "$COMSPEC")) {
+ const char *comspec = os_getenv("COMSPEC");
+ return striequal("cmd.exe", (char *)path_tail((char_u *)comspec));
+ }
+ if (striequal(sh, "cmd.exe") || striequal(sh, "cmd")) {
+ return true;
+ }
+ return striequal("cmd.exe", (char *)path_tail((char_u *)sh));
+}
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index b449cc3d5a..5cc9d4b79b 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -124,11 +124,9 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args)
}
size_t nread;
-
int exitcode = do_os_system(shell_build_argv((char *)cmd, (char *)extra_args),
input.data, input.len, output_ptr, &nread,
emsg_silent, forward_output);
-
xfree(input.data);
if (output) {
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 87e066d80a..8a1a3beddd 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -198,8 +198,16 @@ char_u *vim_strsave_shellescape(const char_u *string,
/* First count the number of extra bytes required. */
size_t length = STRLEN(string) + 3; // two quotes and a trailing NUL
for (const char_u *p = string; *p != NUL; mb_ptr_adv(p)) {
- if (*p == '\'')
- length += 3; /* ' => '\'' */
+#ifdef WIN32
+ if (!p_ssl) {
+ if (*p == '"') {
+ length++; // " -> ""
+ }
+ } else
+#endif
+ if (*p == '\'') {
+ length += 3; // ' => '\''
+ }
if ((*p == '\n' && (csh_like || do_newline))
|| (*p == '!' && (csh_like || do_special))) {
++length; /* insert backslash */
@@ -216,10 +224,25 @@ char_u *vim_strsave_shellescape(const char_u *string,
escaped_string = xmalloc(length);
d = escaped_string;
- /* add opening quote */
+ // add opening quote
+#ifdef WIN32
+ if (!p_ssl) {
+ *d++ = '"';
+ } else
+#endif
*d++ = '\'';
for (const char_u *p = string; *p != NUL; ) {
+#ifdef WIN32
+ if (!p_ssl) {
+ if (*p == '"') {
+ *d++ = '"';
+ *d++ = '"';
+ p++;
+ continue;
+ }
+ } else
+#endif
if (*p == '\'') {
*d++ = '\'';
*d++ = '\\';
@@ -246,7 +269,12 @@ char_u *vim_strsave_shellescape(const char_u *string,
MB_COPY_CHAR(p, d);
}
- /* add terminating quote and finish with a NUL */
+ // add terminating quote and finish with a NUL
+# ifdef WIN32
+ if (!p_ssl) {
+ *d++ = '"';
+ } else
+# endif
*d++ = '\'';
*d = NUL;