diff options
Diffstat (limited to 'src/nvim/channel.c')
-rw-r--r-- | src/nvim/channel.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 37cbfb968b..22eb31513d 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -161,7 +161,7 @@ void channel_init(void) /// /// Channel is allocated with refcount 1, which should be decreased /// when the underlying stream closes. -static Channel *channel_alloc(ChannelStreamType type) +Channel *channel_alloc(ChannelStreamType type) { Channel *chan = xcalloc(1, sizeof(*chan)); if (type == kChannelStreamStdio) { @@ -292,7 +292,6 @@ static void close_cb(Stream *stream, void *data) /// directory if `cwd` is NULL /// @param[in] pty_width Width of the pty, ignored if `pty` is false /// @param[in] pty_height Height of the pty, ignored if `pty` is false -/// @param[in] term_name `$TERM` for the pty /// @param[in] env Nvim's configured environment is used if this is NULL, /// otherwise defines all environment variables /// @param[out] status_out 0 for invalid arguments, > 0 for the channel id, @@ -304,7 +303,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, bool pty, bool rpc, bool overlapped, bool detach, const char *cwd, uint16_t pty_width, uint16_t pty_height, - char *term_name, char **env, varnumber_T *status_out) + dict_T *env, varnumber_T *status_out) { assert(cwd == NULL || os_isdir_executable(cwd)); @@ -317,7 +316,9 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, if (detach) { EMSG2(_(e_invarg2), "terminal/pty job cannot be detached"); shell_free_argv(argv); - xfree(term_name); + if (env) { + tv_dict_free(env); + } channel_destroy_early(chan); *status_out = 0; return NULL; @@ -329,9 +330,6 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, if (pty_height > 0) { chan->stream.pty.height = pty_height; } - if (term_name) { - chan->stream.pty.term_name = term_name; - } } else { chan->stream.uv = libuv_process_init(&main_loop, chan); } @@ -358,17 +356,17 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, if (status) { EMSG3(_(e_jobspawn), os_strerror(status), cmd); xfree(cmd); - os_free_fullenv(proc->env); - if (proc->type == kProcessTypePty) { - xfree(chan->stream.pty.term_name); + if (proc->env) { + tv_dict_free(proc->env); } channel_destroy_early(chan); *status_out = proc->status; return NULL; } xfree(cmd); - os_free_fullenv(proc->env); - + if (proc->env) { + tv_dict_free(proc->env); + } wstream_init(&proc->in, 0); if (has_out) { @@ -501,43 +499,54 @@ uint64_t channel_from_stdio(bool rpc, CallbackReader on_output, } /// @param data will be consumed -size_t channel_send(uint64_t id, char *data, size_t len, const char **error) +size_t channel_send(uint64_t id, char *data, size_t len, + bool data_owned, const char **error) { Channel *chan = find_channel(id); + size_t written = 0; if (!chan) { - EMSG(_(e_invchan)); - goto err; + *error = _(e_invchan); + goto retfree; } if (chan->streamtype == kChannelStreamStderr) { if (chan->stream.err.closed) { *error = _("Can't send data to closed stream"); - goto err; + goto retfree; } // unbuffered write - size_t written = fwrite(data, len, 1, stderr); - xfree(data); - return len * written; + written = len * fwrite(data, len, 1, stderr); + goto retfree; + } + + if (chan->streamtype == kChannelStreamInternal && chan->term) { + terminal_receive(chan->term, data, len); + written = len; + goto retfree; } Stream *in = channel_instream(chan); if (in->closed) { *error = _("Can't send data to closed stream"); - goto err; + goto retfree; } if (chan->is_rpc) { *error = _("Can't send raw data to rpc channel"); - goto err; + goto retfree; } - WBuffer *buf = wstream_new_buffer(data, len, 1, xfree); + // write can be delayed indefinitely, so always use an allocated buffer + WBuffer *buf = wstream_new_buffer(data_owned ? data : xmemdup(data, len), + len, 1, xfree); return wstream_write(in, buf) ? len : 0; -err: - xfree(data); - return 0; +retfree: + if (data_owned) { + xfree(data); + } + return written; } /// Convert binary byte array to a readfile()-style list @@ -726,8 +735,8 @@ static void channel_callback_call(Channel *chan, CallbackReader *reader) /// Open terminal for channel /// /// Channel `chan` is assumed to be an open pty channel, -/// and curbuf is assumed to be a new, unmodified buffer. -void channel_terminal_open(Channel *chan) +/// and `buf` is assumed to be a new, unmodified buffer. +void channel_terminal_open(buf_T *buf, Channel *chan) { TerminalOptions topts; topts.data = chan; @@ -736,8 +745,8 @@ void channel_terminal_open(Channel *chan) topts.write_cb = term_write; topts.resize_cb = term_resize; topts.close_cb = term_close; - curbuf->b_p_channel = (long)chan->id; // 'channel' option - Terminal *term = terminal_open(topts); + buf->b_p_channel = (long)chan->id; // 'channel' option + Terminal *term = terminal_open(buf, topts); chan->term = term; channel_incref(chan); } |