diff options
-rw-r--r-- | src/os/shell.c | 61 | ||||
-rw-r--r-- | src/os/shell.h | 2 | ||||
-rw-r--r-- | src/os_unix.c | 45 |
3 files changed, 66 insertions, 42 deletions
diff --git a/src/os/shell.c b/src/os/shell.c index cbedf72a9c..2f3f2f6095 100644 --- a/src/os/shell.c +++ b/src/os/shell.c @@ -1,9 +1,12 @@ +#include <string.h> #include <stdbool.h> #include "os/shell.h" #include "types.h" #include "vim.h" #include "ascii.h" +#include "misc2.h" +#include "option_defs.h" #include "charset.h" @@ -54,4 +57,60 @@ int shell_count_argc(char_u **ptr) return rv; } -char ** shell_build_argv(char_u **ptr, int argc); +char ** shell_build_argv(int argc, char_u *cmd, + char_u *extra_shell_arg, char_u **ptr, char_u **p_shcf_copy_ptr) +{ + char **argv; + char_u *p_shcf_copy = *p_shcf_copy_ptr; + char_u *p = *ptr; + // Allocate argv memory + argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *))); + if (argv == NULL) // out of memory + return NULL; + + // Build argv[] + argc = 0; + while (true) { + argv[argc] = (char *)p; + ++argc; + shell_skip_word(&p); + if (*p == NUL) + break; + // Terminate the word + *p++ = NUL; + p = skipwhite(p); + } + if (cmd != NULL) { + char_u *s; + + if (extra_shell_arg != NULL) + argv[argc++] = (char *)extra_shell_arg; + + // Break 'shellcmdflag' into white separated parts. This doesn't + // handle quoted strings, they are very unlikely to appear. + p_shcf_copy = alloc((unsigned)STRLEN(p_shcf) + 1); + if (p_shcf_copy == NULL) { + // out of memory + free(argv); + return NULL; + } + + s = p_shcf_copy; + p = p_shcf; + while (*p != NUL) { + argv[argc++] = (char *)s; + while (*p && *p != ' ' && *p != TAB) + *s++ = *p++; + *s++ = NUL; + p = skipwhite(p); + } + + argv[argc++] = (char *)cmd; + } + + argv[argc] = NULL; + *ptr = p; + *p_shcf_copy_ptr = p_shcf_copy; + + return argv; +} diff --git a/src/os/shell.h b/src/os/shell.h index 754f27df37..981171e787 100644 --- a/src/os/shell.h +++ b/src/os/shell.h @@ -7,6 +7,8 @@ void shell_skip_word(char_u **ptr); int shell_count_argc(char_u **ptr); +char ** shell_build_argv(int argc, char_u *cmd, + char_u *extra_shell_arg, char_u **ptr, char_u **p_shcf_copy_ptr); #endif // NEOVIM_OS_SHELL_H diff --git a/src/os_unix.c b/src/os_unix.c index d53ddac830..eb960cef00 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1721,51 +1721,14 @@ int mch_call_shell(char_u *cmd, int options, char_u *extra_shell_arg) // Count the number of arguments for the shell p = newcmd; argc = shell_count_argc(&p); - - // Allocate argv memory - argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *))); - if (argv == NULL) // out of memory - goto error; - - // Build argv[] p = newcmd; - argc = 0; - while (true) { - argv[argc] = (char *)p; - ++argc; - shell_skip_word(&p); - if (*p == NUL) - break; - // Terminate the word - *p++ = NUL; - p = skipwhite(p); - } - if (cmd != NULL) { - char_u *s; - - if (extra_shell_arg != NULL) - argv[argc++] = (char *)extra_shell_arg; - - /* Break 'shellcmdflag' into white separated parts. This doesn't - * handle quoted strings, they are very unlikely to appear. */ - p_shcf_copy = alloc((unsigned)STRLEN(p_shcf) + 1); - if (p_shcf_copy == NULL) /* out of memory */ - goto error; - s = p_shcf_copy; - p = p_shcf; - while (*p != NUL) { - argv[argc++] = (char *)s; - while (*p && *p != ' ' && *p != TAB) - *s++ = *p++; - *s++ = NUL; - p = skipwhite(p); - } + argv = shell_build_argv(argc, cmd, extra_shell_arg, &p, &p_shcf_copy); - argv[argc++] = (char *)cmd; + if (argv == NULL) { + goto error; } - argv[argc] = NULL; - /* + /* * For the GUI, when writing the output into the buffer and when reading * input from the buffer: Try using a pseudo-tty to get the stdin/stdout * of the executed command into the Vim window. Or use a pipe. |