diff options
Diffstat (limited to 'src')
| -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. | 
