diff options
Diffstat (limited to 'src/nvim/os/shell.c')
-rw-r--r-- | src/nvim/os/shell.c | 60 |
1 files changed, 31 insertions, 29 deletions
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 9514936ad0..32e9a70e57 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <string.h> #include <assert.h> #include <stdbool.h> @@ -39,14 +42,15 @@ typedef struct { #endif /// Builds the argument vector for running the user-configured 'shell' (p_sh) -/// with an optional command prefixed by 'shellcmdflag' (p_shcf). +/// with an optional command prefixed by 'shellcmdflag' (p_shcf). E.g.: +/// +/// ["shell", "-extra_args", "-shellcmdflag", "command with spaces"] /// /// @param cmd Command string, or NULL to run an interactive shell. /// @param extra_args Extra arguments to the shell, or NULL. -/// @return A newly allocated argument vector. It must be freed with -/// `shell_free_argv` when no longer needed. +/// @return Newly allocated argument vector. Must be freed with shell_free_argv. char **shell_build_argv(const char *cmd, const char *extra_args) - FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC + FUNC_ATTR_NONNULL_RET { size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0); char **rv = xmalloc((argc + 4) * sizeof(*rv)); @@ -123,15 +127,9 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) } size_t nread; - - int status = do_os_system(shell_build_argv((char *)cmd, (char *)extra_args), - input.data, - input.len, - output_ptr, - &nread, - emsg_silent, - forward_output); - + 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) { @@ -139,16 +137,16 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) xfree(output); } - if (!emsg_silent && status != 0 && !(opts & kShellOptSilent)) { + if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) { MSG_PUTS(_("\nshell returned ")); - msg_outnum(status); + msg_outnum(exitcode); msg_putchar('\n'); } State = current_state; signal_accept_deadly(); - return status; + return exitcode; } /// os_system - synchronously execute a command in the shell @@ -157,7 +155,7 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) /// char *output = NULL; /// size_t nread = 0; /// char *argv[] = {"ls", "-la", NULL}; -/// int status = os_sytem(argv, NULL, 0, &output, &nread); +/// int exitcode = os_sytem(argv, NULL, 0, &output, &nread); /// /// @param argv The commandline arguments to be passed to the shell. `argv` /// will be consumed. @@ -218,11 +216,14 @@ static int do_os_system(char **argv, proc->in = input != NULL ? &in : NULL; proc->out = &out; proc->err = &err; - if (!process_spawn(proc)) { + int status = process_spawn(proc); + if (status) { loop_poll_events(&main_loop, 0); - // Failed, probably due to 'sh' not being executable + // Failed, probably 'shell' is not executable. if (!silent) { - MSG_PUTS(_("\nCannot execute ")); + MSG_PUTS(_("\nshell failed to start: ")); + msg_outtrans((char_u *)os_strerror(status)); + MSG_PUTS(": "); msg_outtrans((char_u *)prog); msg_putchar('\n'); } @@ -262,7 +263,7 @@ static int do_os_system(char **argv, // busy state. ui_busy_start(); ui_flush(); - int status = process_wait(proc, -1, NULL); + int exitcode = process_wait(proc, -1, NULL); if (!got_int && out_data_decide_throttle(0)) { // Last chunk of output was skipped; display it now. out_data_ring(NULL, SIZE_MAX); @@ -289,7 +290,7 @@ static int do_os_system(char **argv, assert(multiqueue_empty(events)); multiqueue_free(events); - return status; + return exitcode; } /// - ensures at least `desired` bytes in buffer @@ -321,7 +322,7 @@ static void system_data_cb(Stream *stream, RBuffer *buf, size_t count, /// Tracks output received for the current executing shell command, and displays /// a pulsing "..." when output should be skipped. Tracking depends on the /// synchronous/blocking nature of ":!". -// +/// /// Purpose: /// 1. CTRL-C is more responsive. #1234 #5396 /// 2. Improves performance of :! (UI, esp. TUI, is the bottleneck). @@ -446,7 +447,7 @@ static void out_data_append_to_screen(char *output, size_t remaining, size_t off = 0; int last_row = (int)Rows - 1; - while (off < remaining) { + while (output != NULL && off < remaining) { // Found end of line? if (output[off] == NL) { // Can we start a new line or do we need to continue the last one? @@ -463,15 +464,16 @@ static void out_data_append_to_screen(char *output, size_t remaining, continue; } - // Translate NUL to SOH - if (output[off] == NUL) { - output[off] = 1; + // TODO(bfredl): using msg_puts would be better until + // terminal emulation is implemented. + if (output[off] < 0x20) { + output[off] = ' '; } off++; } - if (remaining) { + if (output != NULL && remaining) { if (last_col == 0) { screen_del_lines(0, 0, 1, (int)Rows, NULL); } @@ -683,7 +685,7 @@ static void shell_write_cb(Stream *stream, void *data, int status) uv_err_name(status)); } if (stream->closed) { // Process may have exited before this write. - ELOG("stream was already closed"); + WLOG("stream was already closed"); return; } stream_close(stream, NULL, NULL); |