diff --git a/cmd-display-menu.c b/cmd-display-menu.c index 5df01c7a..87871f68 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -53,10 +53,10 @@ const struct cmd_entry cmd_display_popup_entry = { .name = "display-popup", .alias = "popup", - .args = { "BCc:d:Eh:t:w:x:y:", 0, -1, NULL }, - .usage = "[-BCE] [-c target-client] [-d start-directory] [-h height] " - CMD_TARGET_PANE_USAGE " [-w width] " - "[-x position] [-y position] [shell-command]", + .args = { "BCc:d:e:Eh:t:w:x:y:", 0, -1, NULL }, + .usage = "[-BCE] [-c target-client] [-d start-directory] " + "[-e environment] [-h height] " CMD_TARGET_PANE_USAGE " " + "[-w width] [-x position] [-y position] [shell-command]", .target = { 't', CMD_FIND_PANE, 0 }, @@ -357,6 +357,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) char *cwd, *cause, **argv = NULL; int flags = 0, argc = 0; u_int px, py, w, h, count = args_count(args); + struct args_value *av; + struct environ *env = NULL; if (args_has(args, 'C')) { server_client_clear_overlay(tc); @@ -410,17 +412,30 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) } else args_to_vector(args, &argc, &argv); + if (args_has(args, 'e') >= 1) { + env = environ_create(); + av = args_first_value(args, 'e'); + while (av != NULL) { + environ_put(env, av->string, 0); + av = args_next_value(av); + } + } + if (args_has(args, 'E') > 1) flags |= POPUP_CLOSEEXITZERO; else if (args_has(args, 'E')) flags |= POPUP_CLOSEEXIT; if (args_has(args, 'B')) flags |= POPUP_NOBORDER; - if (popup_display(flags, item, px, py, w, h, shellcmd, argc, argv, cwd, - tc, s, NULL, NULL) != 0) { + if (popup_display(flags, item, px, py, w, h, env, shellcmd, argc, argv, + cwd, tc, s, NULL, NULL) != 0) { cmd_free_argv(argc, argv); + if (env != NULL) + environ_free(env); return (CMD_RETURN_NORMAL); } + if (env != NULL) + environ_free(env); cmd_free_argv(argc, argv); return (CMD_RETURN_WAIT); } diff --git a/cmd-if-shell.c b/cmd-if-shell.c index 211e08d6..205a8ce1 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -118,7 +118,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) if (cdata->client != NULL) cdata->client->references++; - if (job_run(shellcmd, 0, NULL, s, + if (job_run(shellcmd, 0, NULL, NULL, s, server_client_get_cwd(cmdq_get_client(item), s), NULL, cmd_if_shell_callback, cmd_if_shell_free, cdata, 0, -1, -1) == NULL) { diff --git a/cmd-run-shell.c b/cmd-run-shell.c index bf43d313..5e914e65 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -188,7 +188,7 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg) cmd_run_shell_free(cdata); return; } - if (job_run(cmd, 0, NULL, cdata->s, cdata->cwd, NULL, + if (job_run(cmd, 0, NULL, NULL, cdata->s, cdata->cwd, NULL, cmd_run_shell_callback, cmd_run_shell_free, cdata, cdata->flags, -1, -1) == NULL) cmd_run_shell_free(cdata); diff --git a/format.c b/format.c index 37b9123b..f5d2c5f6 100644 --- a/format.c +++ b/format.c @@ -390,7 +390,7 @@ format_job_get(struct format_expand_state *es, const char *cmd) if (force && fj->job != NULL) job_free(fj->job); if (force || (fj->job == NULL && fj->last != t)) { - fj->job = job_run(expanded, 0, NULL, NULL, + fj->job = job_run(expanded, 0, NULL, NULL, NULL, server_client_get_cwd(ft->client, NULL), format_job_update, format_job_complete, NULL, fj, JOB_NOWAIT, -1, -1); if (fj->job == NULL) { diff --git a/job.c b/job.c index 66a25557..4c13f943 100644 --- a/job.c +++ b/job.c @@ -71,7 +71,7 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs); /* Start a job running. */ struct job * -job_run(const char *cmd, int argc, char **argv, struct session *s, +job_run(const char *cmd, int argc, char **argv, struct environ *e, struct session *s, const char *cwd, job_update_cb updatecb, job_complete_cb completecb, job_free_cb freecb, void *data, int flags, int sx, int sy) { @@ -89,6 +89,9 @@ job_run(const char *cmd, int argc, char **argv, struct session *s, * if-shell to decide on default-terminal based on outside TERM. */ env = environ_for_session(s, !cfg_finished); + if (e != NULL) { + environ_copy(e, env); + } sigfillset(&set); sigprocmask(SIG_BLOCK, &set, &oldset); diff --git a/popup.c b/popup.c index d4fc3833..635559fa 100644 --- a/popup.c +++ b/popup.c @@ -590,8 +590,9 @@ popup_job_complete_cb(struct job *job) int popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, - u_int sy, const char *shellcmd, int argc, char **argv, const char *cwd, - struct client *c, struct session *s, popup_close_cb cb, void *arg) + u_int sy, struct environ *env, const char *shellcmd, int argc, char **argv, + const char *cwd, struct client *c, struct session *s, popup_close_cb cb, + void *arg) { struct popup_data *pd; u_int jx, jy; @@ -635,7 +636,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, pd->psx = sx; pd->psy = sy; - pd->job = job_run(shellcmd, argc, argv, s, cwd, + pd->job = job_run(shellcmd, argc, argv, env, s, cwd, popup_job_update_cb, popup_job_complete_cb, NULL, pd, JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy); pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette); @@ -725,7 +726,7 @@ popup_editor(struct client *c, const char *buf, size_t len, xasprintf(&cmd, "%s %s", editor, path); if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, NULL, px, py, sx, sy, - cmd, 0, NULL, _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) { + NULL, cmd, 0, NULL, _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) { popup_editor_free(pe); free(cmd); return (-1); diff --git a/tmux.1 b/tmux.1 index 027db664..14556ba3 100644 --- a/tmux.1 +++ b/tmux.1 @@ -5753,6 +5753,7 @@ forwards any input read from stdin to the empty pane given by .Op Fl BCE .Op Fl c Ar target-client .Op Fl d Ar start-directory +.Op Fl e Ar environment .Op Fl h Ar height .Op Fl t Ar target-pane .Op Fl w Ar width @@ -5793,6 +5794,12 @@ If omitted, half of the terminal size is used. .Fl B does not surround the popup by a border. .Pp +.Fl e +takes the form +.Ql VARIABLE=value +and sets an environment variable for the popup; it may be specified multiple +times. +.Pp The .Fl C flag closes any popup on the client. diff --git a/tmux.h b/tmux.h index 29a532aa..57d3c909 100644 --- a/tmux.h +++ b/tmux.h @@ -2073,9 +2073,9 @@ typedef void (*job_free_cb) (void *); #define JOB_NOWAIT 0x1 #define JOB_KEEPWRITE 0x2 #define JOB_PTY 0x4 -struct job *job_run(const char *, int, char **, struct session *, - const char *, job_update_cb, job_complete_cb, job_free_cb, - void *, int, int, int); +struct job *job_run(const char *, int, char **, struct environ *, + struct session *, const char *, job_update_cb, + job_complete_cb, job_free_cb, void *, int, int, int); void job_free(struct job *); int job_transfer(struct job *, pid_t *, char *, size_t); void job_resize(struct job *, u_int, u_int); @@ -3105,8 +3105,9 @@ int menu_key_cb(struct client *, void *, struct key_event *); typedef void (*popup_close_cb)(int, void *); typedef void (*popup_finish_edit_cb)(char *, size_t, void *); int popup_display(int, struct cmdq_item *, u_int, u_int, u_int, - u_int, const char *, int, char **, const char *, - struct client *, struct session *, popup_close_cb, void *); + u_int, struct environ *, const char *, int, char **, + const char *, struct client *, struct session *, + popup_close_cb, void *); int popup_editor(struct client *, const char *, size_t, popup_finish_edit_cb, void *); diff --git a/window-copy.c b/window-copy.c index c1a31b48..ec6a2f4e 100644 --- a/window-copy.c +++ b/window-copy.c @@ -4531,8 +4531,8 @@ window_copy_pipe_run(struct window_mode_entry *wme, struct session *s, if (cmd == NULL || *cmd == '\0') cmd = options_get_string(global_options, "copy-command"); if (cmd != NULL && *cmd != '\0') { - job = job_run(cmd, 0, NULL, s, NULL, NULL, NULL, NULL, NULL, - JOB_NOWAIT, -1, -1); + job = job_run(cmd, 0, NULL, NULL, s, NULL, NULL, NULL, NULL, + NULL, JOB_NOWAIT, -1, -1); bufferevent_write(job_get_event(job), buf, *len); } return (buf);