diff --git a/src/nvim/channel.c b/src/nvim/channel.c index 569d3f5887..f9ce62dbd2 100644 --- a/src/nvim/channel.c +++ b/src/nvim/channel.c @@ -309,6 +309,7 @@ static void close_cb(Stream *stream, void *data) /// /// @param[in] argv Arguments vector specifying the command to run, /// NULL-terminated +/// @param[in] exepath The path to the executable. If NULL, use `argv[0]`. /// @param[in] on_stdout Callback to read the job's stdout /// @param[in] on_stderr Callback to read the job's stderr /// @param[in] on_exit Callback to receive the job's exit status @@ -330,10 +331,11 @@ static void close_cb(Stream *stream, void *data) /// < 0 if the job can't start /// /// @returns [allocated] channel -Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader on_stderr, - Callback on_exit, bool pty, bool rpc, bool overlapped, bool detach, - ChannelStdinMode stdin_mode, const char *cwd, uint16_t pty_width, - uint16_t pty_height, dict_T *env, varnumber_T *status_out) +Channel *channel_job_start(char **argv, const char *exepath, CallbackReader on_stdout, + CallbackReader on_stderr, Callback on_exit, bool pty, bool rpc, + bool overlapped, bool detach, ChannelStdinMode stdin_mode, + const char *cwd, uint16_t pty_width, uint16_t pty_height, dict_T *env, + varnumber_T *status_out) { Channel *chan = channel_alloc(kChannelStreamProc); chan->on_data = on_stdout; @@ -364,6 +366,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader Process *proc = &chan->stream.proc; proc->argv = argv; + proc->exepath = exepath; proc->cb = channel_process_exit_cb; proc->events = chan->events; proc->detach = detach; @@ -371,7 +374,7 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout, CallbackReader proc->env = env; proc->overlapped = overlapped; - char *cmd = xstrdup(proc->argv[0]); + char *cmd = xstrdup(process_get_exepath(proc)); bool has_out, has_err; if (proc->type == kProcessTypePty) { has_out = true; diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 7c3c5cc274..e823e131b1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4120,7 +4120,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) env = create_environment(job_env, clear_env, pty, term_name); - Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, pty, + Channel *chan = channel_job_start(argv, NULL, on_stdout, on_stderr, on_exit, pty, rpc, overlapped, detach, stdin_mode, cwd, width, height, env, &rettv->vval.v_number); if (chan) { @@ -6678,7 +6678,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // The last item of argv must be NULL argv[i] = NULL; - Channel *chan = channel_job_start(argv, CALLBACK_READER_INIT, + Channel *chan = channel_job_start(argv, NULL, CALLBACK_READER_INIT, CALLBACK_READER_INIT, CALLBACK_NONE, false, true, false, false, kChannelStdinPipe, NULL, 0, 0, NULL, @@ -8455,7 +8455,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const bool detach = false; ChannelStdinMode stdin_mode = kChannelStdinPipe; uint16_t term_width = (uint16_t)MAX(0, curwin->w_width_inner - win_col_off(curwin)); - Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, + Channel *chan = channel_job_start(argv, NULL, on_stdout, on_stderr, on_exit, pty, rpc, overlapped, detach, stdin_mode, cwd, term_width, (uint16_t)curwin->w_height_inner, env, &rettv->vval.v_number); diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c index e528d21a71..1bb0511f12 100644 --- a/src/nvim/event/libuv_process.c +++ b/src/nvim/event/libuv_process.c @@ -24,7 +24,7 @@ int libuv_process_spawn(LibuvProcess *uvproc) FUNC_ATTR_NONNULL_ALL { Process *proc = (Process *)uvproc; - uvproc->uvopts.file = proc->argv[0]; + uvproc->uvopts.file = process_get_exepath(proc); uvproc->uvopts.args = proc->argv; uvproc->uvopts.flags = UV_PROCESS_WINDOWS_HIDE; #ifdef MSWIN diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 1219566e9b..95bf4d1c3b 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -131,7 +131,7 @@ int process_spawn(Process *proc, bool in, bool out, bool err) proc->internal_close_cb = decref; proc->refcount++; kl_push(WatcherPtr, proc->loop->children, proc); - DLOG("new: pid=%d argv=[%s]", proc->pid, proc->argv[0]); + DLOG("new: pid=%d exepath=[%s]", proc->pid, process_get_exepath(proc)); return 0; } diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h index 39fed08c77..69fe229b0e 100644 --- a/src/nvim/event/process.h +++ b/src/nvim/event/process.h @@ -32,6 +32,7 @@ struct process { uint64_t stopped_time; // process_stop() timestamp const char *cwd; char **argv; + const char *exepath; dict_T *env; Stream in, out, err; /// Exit handler. If set, user must call process_free(). @@ -54,6 +55,7 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data) .stopped_time = 0, .cwd = NULL, .argv = NULL, + .exepath = NULL, .in = { .closed = false }, .out = { .closed = false }, .err = { .closed = false }, @@ -66,6 +68,12 @@ static inline Process process_init(Loop *loop, ProcessType type, void *data) }; } +/// Get the path to the executable of the process. +static inline const char *process_get_exepath(Process *proc) +{ + return proc->exepath != NULL ? proc->exepath : proc->argv[0]; +} + static inline bool process_is_stopped(Process *proc) { bool exited = (proc->status >= 0); diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index b5423c59d7..15a4ef6230 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -285,7 +285,7 @@ static void init_child(PtyProcess *ptyproc) return; } - char *prog = ptyproc->process.argv[0]; + const char *prog = process_get_exepath(proc); assert(proc->env); environ = tv_dict_to_env(proc->env); diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 0fc6d4936d..cc564f4777 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -53,8 +53,8 @@ uint64_t ui_client_start_server(int argc, char **argv) CallbackReader on_err = CALLBACK_READER_INIT; on_err.fwd_err = true; - Channel *channel = channel_job_start(args, CALLBACK_READER_INIT, - on_err, CALLBACK_NONE, + Channel *channel = channel_job_start(args, get_vim_var_str(VV_PROGPATH), + CALLBACK_READER_INIT, on_err, CALLBACK_NONE, false, true, true, false, kChannelStdinPipe, NULL, 0, 0, NULL, &exit_status);