diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/os/shell.c | 88 |
1 files changed, 39 insertions, 49 deletions
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 5cc15e5a2e..99ae3af221 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -37,51 +37,6 @@ typedef struct { # include "os/shell.c.generated.h" #endif -/// Process command string with 'shellxescape' (p_sxe) and 'shellxquote' -/// (p_sxq) -/// -/// @param cmd Command string -/// @return NULL if `cmd` is NULL. Otherwise, a newly allocated command string. -/// It must be freed with `xfree` when no longer needed. -static char *shell_escape(const char *cmd) - FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT -{ - char *ncmd; - - if (cmd == NULL) { - ncmd = NULL; - } else if (*p_sxq == NUL) { - ncmd = xstrdup(cmd); - } else { - const char *ecmd; - size_t ncmd_size; - - if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0) { - ecmd = (char *)vim_strsave_escaped_ext((char_u *)cmd, p_sxe, '^', false); - } else { - ecmd = cmd; - } - ncmd_size = strlen(ecmd) + STRLEN(p_sxq) * 2 + 1; - ncmd = xmalloc(ncmd_size); - - // When 'shellxquote' is '(', append ')'. - // When 'shellxquote' is '"(', append ')"'. - if (STRCMP(p_sxq, "(") == 0) { - vim_snprintf(ncmd, ncmd_size, "(%s)", ecmd); - } else if (STRCMP(p_sxq, "\"(") == 0) { - vim_snprintf(ncmd, ncmd_size, "\"(%s)\"", ecmd); - } else { - vim_snprintf(ncmd, ncmd_size, "%s%s%s", p_sxq, ecmd, p_sxq); - } - - if (ecmd != (const char *)cmd) { - xfree((void *)ecmd); - } - } - - return ncmd; -} - /// Builds the argument vector for running the user-configured 'shell' (p_sh) /// with an optional command prefixed by 'shellcmdflag' (p_shcf). /// @@ -99,13 +54,12 @@ char **shell_build_argv(const char *cmd, const char *extra_args) size_t i = tokenize(p_sh, rv); if (extra_args) { - rv[i++] = xstrdup(extra_args); // Push a copy of `extra_args` + rv[i++] = xstrdup(extra_args); // Push a copy of `extra_args` } if (cmd) { - i += tokenize(p_shcf, rv + i); // Split 'shellcmdflag' - rv[i++] = shell_escape(cmd); // Process command string with - // 'shellxescape' and 'shellxquote' + i += tokenize(p_shcf, rv + i); // Split 'shellcmdflag' + rv[i++] = shell_xescape_xquote(cmd); // Copy (and escape) `cmd`. } rv[i] = NULL; @@ -594,3 +548,39 @@ static void shell_write_cb(Stream *stream, void *data, int status) { stream_close(stream, NULL, NULL); } + +/// Applies 'shellxescape' (p_sxe) and 'shellxquote' (p_sxq) to a command. +/// +/// @param cmd Command string +/// @return Escaped/quoted command string (allocated). +static char *shell_xescape_xquote(const char *cmd) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (*p_sxq == NUL) { + return xstrdup(cmd); + } + + const char *ecmd = cmd; + if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0) { + ecmd = (char *)vim_strsave_escaped_ext((char_u *)cmd, p_sxe, '^', false); + } + size_t ncmd_size = strlen(ecmd) + STRLEN(p_sxq) * 2 + 1; + char *ncmd = xmalloc(ncmd_size); + + // When 'shellxquote' is ( append ). + // When 'shellxquote' is "( append )". + if (STRCMP(p_sxq, "(") == 0) { + vim_snprintf(ncmd, ncmd_size, "(%s)", ecmd); + } else if (STRCMP(p_sxq, "\"(") == 0) { + vim_snprintf(ncmd, ncmd_size, "\"(%s)\"", ecmd); + } else { + vim_snprintf(ncmd, ncmd_size, "%s%s%s", p_sxq, ecmd, p_sxq); + } + + if (ecmd != cmd) { + xfree((void *)ecmd); + } + + return ncmd; +} + |