aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/shell.c
diff options
context:
space:
mode:
authorZhaosheng Pan <brglng@gmail.com>2015-06-03 19:01:17 +0800
committerJustin M. Keyes <justinkz@gmail.com>2016-09-10 22:21:40 +0200
commit0991041ae72e866add2a820a6b0401d21b9a8fab (patch)
tree830b721746e9734b221210d7dbaac32c5186a399 /src/nvim/os/shell.c
parentbccb49bedb9b5fe0a3635e2be4aa2d168c5d3051 (diff)
downloadrneovim-0991041ae72e866add2a820a6b0401d21b9a8fab.tar.gz
rneovim-0991041ae72e866add2a820a6b0401d21b9a8fab.tar.bz2
rneovim-0991041ae72e866add2a820a6b0401d21b9a8fab.zip
system(): Respect 'sxe' and 'sxq' #2789
Fixes #2773
Diffstat (limited to 'src/nvim/os/shell.c')
-rw-r--r--src/nvim/os/shell.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index ba52b9f661..5cc15e5a2e 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -37,6 +37,51 @@ 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).
///
@@ -59,7 +104,8 @@ char **shell_build_argv(const char *cmd, const char *extra_args)
if (cmd) {
i += tokenize(p_shcf, rv + i); // Split 'shellcmdflag'
- rv[i++] = xstrdup(cmd); // Push a copy of the command.
+ rv[i++] = shell_escape(cmd); // Process command string with
+ // 'shellxescape' and 'shellxquote'
}
rv[i] = NULL;