mirror of
https://github.com/tmate-io/tmate.git
synced 2024-12-23 07:09:10 +01:00
Infrastructure and commands to manage the environment for processes started
within tmux. There is a global environment, copied from the external environment when the server is started and each sesssion has an (initially empty) session environment which overrides it. New commands set-environment and show-environment manipulate or display the environments. A new session option, update-environment, is a space-separated list of variables which are updated from the external environment into the session environment every time a new session is created - the default is DISPLAY.
This commit is contained in:
parent
e985629440
commit
6491274f60
3
Makefile
3
Makefile
@ -25,8 +25,9 @@ SRCS= attributes.c buffer-poll.c buffer.c cfg.c client-fn.c \
|
|||||||
cmd-split-window.c cmd-start-server.c cmd-string.c cmd-if-shell.c \
|
cmd-split-window.c cmd-start-server.c cmd-string.c cmd-if-shell.c \
|
||||||
cmd-suspend-client.c cmd-swap-pane.c cmd-swap-window.c \
|
cmd-suspend-client.c cmd-swap-pane.c cmd-swap-window.c \
|
||||||
cmd-switch-client.c cmd-unbind-key.c cmd-unlink-window.c \
|
cmd-switch-client.c cmd-unbind-key.c cmd-unlink-window.c \
|
||||||
|
cmd-set-environment.c cmd-show-environment.c \
|
||||||
cmd-up-pane.c cmd-display-message.c cmd.c \
|
cmd-up-pane.c cmd-display-message.c cmd.c \
|
||||||
colour.c grid-view.c grid.c input-keys.c \
|
colour.c environ.c grid-view.c grid.c input-keys.c \
|
||||||
input.c key-bindings.c key-string.c layout-set.c layout.c log.c \
|
input.c key-bindings.c key-string.c layout-set.c layout.c log.c \
|
||||||
mode-key.c names.c options-cmd.c options.c paste.c procname.c \
|
mode-key.c names.c options-cmd.c options.c paste.c procname.c \
|
||||||
resize.c screen-redraw.c screen-write.c screen.c server-fn.c \
|
resize.c screen-redraw.c screen-write.c screen.c server-fn.c \
|
||||||
|
18
client.c
18
client.c
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
|
void client_send_environ(struct client_ctx *);
|
||||||
void client_handle_winch(struct client_ctx *);
|
void client_handle_winch(struct client_ctx *);
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -95,6 +96,8 @@ server_started:
|
|||||||
cctx->srv_in = buffer_create(BUFSIZ);
|
cctx->srv_in = buffer_create(BUFSIZ);
|
||||||
cctx->srv_out = buffer_create(BUFSIZ);
|
cctx->srv_out = buffer_create(BUFSIZ);
|
||||||
|
|
||||||
|
if (cmdflags & CMD_SENDENVIRON)
|
||||||
|
client_send_environ(cctx);
|
||||||
if (isatty(STDIN_FILENO)) {
|
if (isatty(STDIN_FILENO)) {
|
||||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
|
||||||
fatal("ioctl(TIOCGWINSZ)");
|
fatal("ioctl(TIOCGWINSZ)");
|
||||||
@ -133,6 +136,19 @@ not_found:
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
client_send_environ(struct client_ctx *cctx)
|
||||||
|
{
|
||||||
|
char **var;
|
||||||
|
struct msg_environ_data data;
|
||||||
|
|
||||||
|
for (var = environ; *var != NULL; var++) {
|
||||||
|
if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
|
||||||
|
continue;
|
||||||
|
client_write_server(cctx, MSG_ENVIRON, &data, sizeof data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
client_main(struct client_ctx *cctx)
|
client_main(struct client_ctx *cctx)
|
||||||
{
|
{
|
||||||
@ -242,8 +258,8 @@ client_msg_dispatch(struct client_ctx *cctx)
|
|||||||
if (hdr.size != sizeof printdata)
|
if (hdr.size != sizeof printdata)
|
||||||
fatalx("bad MSG_PRINT size");
|
fatalx("bad MSG_PRINT size");
|
||||||
buffer_read(cctx->srv_in, &printdata, sizeof printdata);
|
buffer_read(cctx->srv_in, &printdata, sizeof printdata);
|
||||||
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
|
|
||||||
|
|
||||||
|
printdata.msg[(sizeof printdata.msg) - 1] = '\0';
|
||||||
cctx->errstr = xstrdup(printdata.msg);
|
cctx->errstr = xstrdup(printdata.msg);
|
||||||
return (-1);
|
return (-1);
|
||||||
case MSG_EXIT:
|
case MSG_EXIT:
|
||||||
|
@ -29,7 +29,7 @@ int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
|
|||||||
const struct cmd_entry cmd_attach_session_entry = {
|
const struct cmd_entry cmd_attach_session_entry = {
|
||||||
"attach-session", "attach",
|
"attach-session", "attach",
|
||||||
"[-d] " CMD_TARGET_SESSION_USAGE,
|
"[-d] " CMD_TARGET_SESSION_USAGE,
|
||||||
CMD_CANTNEST|CMD_STARTSERVER, CMD_CHFLAG('d'),
|
CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, CMD_CHFLAG('d'),
|
||||||
cmd_target_init,
|
cmd_target_init,
|
||||||
cmd_target_parse,
|
cmd_target_parse,
|
||||||
cmd_attach_session_exec,
|
cmd_attach_session_exec,
|
||||||
@ -43,6 +43,7 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct cmd_target_data *data = self->data;
|
struct cmd_target_data *data = self->data;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
const char *update;
|
||||||
char *overrides, *cause;
|
char *overrides, *cause;
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
@ -93,6 +94,10 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
|
|
||||||
ctx->cmdclient->session = s;
|
ctx->cmdclient->session = s;
|
||||||
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
|
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
|
||||||
|
|
||||||
|
update = options_get_string(&s->options, "update-environment");
|
||||||
|
environ_update(update, &ctx->cmdclient->environ, &s->environ);
|
||||||
|
|
||||||
server_redraw_client(ctx->cmdclient);
|
server_redraw_client(ctx->cmdclient);
|
||||||
}
|
}
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
@ -40,7 +40,7 @@ struct cmd_new_session_data {
|
|||||||
const struct cmd_entry cmd_new_session_entry = {
|
const struct cmd_entry cmd_new_session_entry = {
|
||||||
"new-session", "new",
|
"new-session", "new",
|
||||||
"[-d] [-n window-name] [-s session-name] [command]",
|
"[-d] [-n window-name] [-s session-name] [command]",
|
||||||
CMD_STARTSERVER|CMD_CANTNEST, 0,
|
CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON, 0,
|
||||||
cmd_new_session_init,
|
cmd_new_session_init,
|
||||||
cmd_new_session_parse,
|
cmd_new_session_parse,
|
||||||
cmd_new_session_exec,
|
cmd_new_session_exec,
|
||||||
@ -108,6 +108,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
{
|
{
|
||||||
struct cmd_new_session_data *data = self->data;
|
struct cmd_new_session_data *data = self->data;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
struct environ env;
|
||||||
|
const char *update;
|
||||||
char *overrides, *cmd, *cwd, *cause;
|
char *overrides, *cmd, *cwd, *cause;
|
||||||
int detached;
|
int detached;
|
||||||
u_int sx, sy;
|
u_int sx, sy;
|
||||||
@ -184,13 +186,20 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
else
|
else
|
||||||
cmd = options_get_string(&global_s_options, "default-command");
|
cmd = options_get_string(&global_s_options, "default-command");
|
||||||
|
|
||||||
|
/* Construct the environment. */
|
||||||
|
environ_init(&env);
|
||||||
|
update = options_get_string(&global_s_options, "update-environment");
|
||||||
|
if (ctx->cmdclient != NULL)
|
||||||
|
environ_update(update, &ctx->cmdclient->environ, &env);
|
||||||
|
|
||||||
/* Create the new session. */
|
/* Create the new session. */
|
||||||
s = session_create(data->newname, cmd, cwd, sx, sy, &cause);
|
s = session_create(data->newname, cmd, cwd, &env, sx, sy, &cause);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
ctx->error(ctx, "create session failed: %s", cause);
|
ctx->error(ctx, "create session failed: %s", cause);
|
||||||
xfree(cause);
|
xfree(cause);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
environ_free(&env);
|
||||||
|
|
||||||
if (data->winname != NULL) {
|
if (data->winname != NULL) {
|
||||||
xfree(s->curw->window->name);
|
xfree(s->curw->window->name);
|
||||||
|
@ -47,7 +47,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct window *w;
|
struct window *w;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
const char **env;
|
struct environ env;
|
||||||
char *cause;
|
char *cause;
|
||||||
|
|
||||||
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
|
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
|
||||||
@ -64,7 +64,10 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
env = server_fill_environ(s);
|
environ_init(&env);
|
||||||
|
environ_copy(&global_environ, &env);
|
||||||
|
environ_copy(&s->environ, &env);
|
||||||
|
server_fill_environ(s, &env);
|
||||||
|
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
TAILQ_REMOVE(&w->panes, wp, entry);
|
TAILQ_REMOVE(&w->panes, wp, entry);
|
||||||
@ -72,9 +75,10 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
window_destroy_panes(w);
|
window_destroy_panes(w);
|
||||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||||
window_pane_resize(wp, w->sx, w->sy);
|
window_pane_resize(wp, w->sx, w->sy);
|
||||||
if (window_pane_spawn(wp, data->arg, NULL, env, &cause) != 0) {
|
if (window_pane_spawn(wp, data->arg, NULL, &env, &cause) != 0) {
|
||||||
ctx->error(ctx, "respawn window failed: %s", cause);
|
ctx->error(ctx, "respawn window failed: %s", cause);
|
||||||
xfree(cause);
|
xfree(cause);
|
||||||
|
environ_free(&env);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
layout_init(w);
|
layout_init(w);
|
||||||
@ -84,5 +88,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
|
|
||||||
|
environ_free(&env);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
88
cmd-set-environment.c
Normal file
88
cmd-set-environment.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set an environment variable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int cmd_set_environment_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_set_environment_entry = {
|
||||||
|
"set-environment", "setenv",
|
||||||
|
"[-gru] " CMD_OPTION_SESSION_USAGE,
|
||||||
|
0, CMD_CHFLAG('g')|CMD_CHFLAG('r')|CMD_CHFLAG('u'),
|
||||||
|
NULL,
|
||||||
|
cmd_option_parse,
|
||||||
|
cmd_set_environment_exec,
|
||||||
|
cmd_option_free,
|
||||||
|
cmd_option_print
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct cmd_option_data *data = self->data;
|
||||||
|
struct session *s;
|
||||||
|
struct environ *env;
|
||||||
|
|
||||||
|
if (*data->option == '\0') {
|
||||||
|
ctx->error(ctx, "empty variable name");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (strchr(data->option, '=') != NULL) {
|
||||||
|
ctx->error(ctx, "variable name contains =");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->chflags & CMD_CHFLAG('g'))
|
||||||
|
env = &global_environ;
|
||||||
|
else {
|
||||||
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
|
return (-1);
|
||||||
|
env = &s->environ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->chflags & CMD_CHFLAG('u')) {
|
||||||
|
if (data->value != NULL) {
|
||||||
|
ctx->error(ctx, "can't specify a value with -u");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
environ_unset(env, data->option);
|
||||||
|
} else if (data->chflags & CMD_CHFLAG('r')) {
|
||||||
|
if (data->value != NULL) {
|
||||||
|
ctx->error(ctx, "can't specify a value with -r");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
environ_set(env, data->option, NULL);
|
||||||
|
} else {
|
||||||
|
if (data->value == NULL) {
|
||||||
|
ctx->error(ctx, "no value specified");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
environ_set(env, data->option, data->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
@ -85,6 +85,7 @@ const struct set_option_entry set_option_table[] = {
|
|||||||
{ "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
|
{ "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
|
||||||
{ "status-utf8", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "status-utf8", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "terminal-overrides", SET_OPTION_STRING, 0, 0, NULL },
|
{ "terminal-overrides", SET_OPTION_STRING, 0, 0, NULL },
|
||||||
|
{ "update-environment", SET_OPTION_STRING, 0, 0, NULL },
|
||||||
{ "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
{ "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
|
{ "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
|
||||||
|
67
cmd-show-environment.c
Normal file
67
cmd-show-environment.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show environment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int cmd_show_environment_exec(struct cmd *, struct cmd_ctx *);
|
||||||
|
|
||||||
|
const struct cmd_entry cmd_show_environment_entry = {
|
||||||
|
"show-environment", "showenv",
|
||||||
|
"[-g] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
0, CMD_CHFLAG('g'),
|
||||||
|
cmd_target_init,
|
||||||
|
cmd_target_parse,
|
||||||
|
cmd_show_environment_exec,
|
||||||
|
cmd_target_free,
|
||||||
|
cmd_target_print
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||||
|
{
|
||||||
|
struct cmd_target_data *data = self->data;
|
||||||
|
struct session *s;
|
||||||
|
struct environ *env;
|
||||||
|
struct environ_entry *envent;
|
||||||
|
|
||||||
|
if (data->chflags & CMD_CHFLAG('g'))
|
||||||
|
env = &global_environ;
|
||||||
|
else {
|
||||||
|
if ((s = cmd_find_session(ctx, data->target)) == NULL)
|
||||||
|
return (-1);
|
||||||
|
env = &s->environ;
|
||||||
|
}
|
||||||
|
|
||||||
|
RB_FOREACH(envent, environ, env) {
|
||||||
|
if (envent->value != NULL)
|
||||||
|
ctx->print(ctx, "%s=%s", envent->name, envent->value);
|
||||||
|
else
|
||||||
|
ctx->print(ctx, "-%s", envent->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
@ -149,7 +149,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
const char **env;
|
struct environ env;
|
||||||
char *cmd, *cwd, *cause;
|
char *cmd, *cwd, *cause;
|
||||||
u_int hlimit;
|
u_int hlimit;
|
||||||
int size;
|
int size;
|
||||||
@ -159,7 +159,10 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
return (-1);
|
return (-1);
|
||||||
w = wl->window;
|
w = wl->window;
|
||||||
|
|
||||||
env = server_fill_environ(s);
|
environ_init(&env);
|
||||||
|
environ_copy(&global_environ, &env);
|
||||||
|
environ_copy(&s->environ, &env);
|
||||||
|
server_fill_environ(s, &env);
|
||||||
|
|
||||||
cmd = data->cmd;
|
cmd = data->cmd;
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
@ -181,7 +184,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
type = LAYOUT_LEFTRIGHT;
|
type = LAYOUT_LEFTRIGHT;
|
||||||
|
|
||||||
wp = window_add_pane(w, hlimit);
|
wp = window_add_pane(w, hlimit);
|
||||||
if (window_pane_spawn(wp, cmd, cwd, env, &cause) != 0)
|
if (window_pane_spawn(wp, cmd, cwd, &env, &cause) != 0)
|
||||||
goto error;
|
goto error;
|
||||||
if (layout_split_pane(w->active, type, size, wp) != 0) {
|
if (layout_split_pane(w->active, type, size, wp) != 0) {
|
||||||
cause = xstrdup("pane too small");
|
cause = xstrdup("pane too small");
|
||||||
@ -197,9 +200,11 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
|||||||
} else
|
} else
|
||||||
server_status_session(s);
|
server_status_session(s);
|
||||||
|
|
||||||
|
environ_free(&env);
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
environ_free(&env);
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
window_remove_pane(w, wp);
|
window_remove_pane(w, wp);
|
||||||
ctx->error(ctx, "create pane failed: %s", cause);
|
ctx->error(ctx, "create pane failed: %s", cause);
|
||||||
|
28
cmd-string.c
28
cmd-string.c
@ -59,21 +59,11 @@ int
|
|||||||
cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
|
cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
|
||||||
{
|
{
|
||||||
size_t p;
|
size_t p;
|
||||||
int ch, argc, rval, have_arg;
|
int ch, i, argc, rval, have_arg;
|
||||||
char **argv, *buf, *t, *u;
|
char **argv, *buf, *t;
|
||||||
|
const char *whitespace, *equals;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if ((t = strchr(s, ' ')) == NULL && (t = strchr(s, '\t')) == NULL)
|
|
||||||
t = strchr(s, '\0');
|
|
||||||
if ((u = strchr(s, '=')) != NULL && u < t) {
|
|
||||||
if (putenv(xstrdup(s)) != 0) {
|
|
||||||
xasprintf(cause, "assignment failed: %s", s);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
*cmdlist = NULL;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
argv = NULL;
|
argv = NULL;
|
||||||
argc = 0;
|
argc = 0;
|
||||||
|
|
||||||
@ -147,6 +137,18 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
|
|||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
equals = strchr(argv[i], '=');
|
||||||
|
whitespace = argv[i] + strcspn(argv[i], " \t");
|
||||||
|
if (equals == NULL || equals > whitespace)
|
||||||
|
break;
|
||||||
|
environ_put(&global_environ, argv[i]);
|
||||||
|
memmove(&argv[i], &argv[i + 1], argc - i - 1);
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
if (argc == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
*cmdlist = cmd_list_parse(argc, argv, cause);
|
*cmdlist = cmd_list_parse(argc, argv, cause);
|
||||||
if (*cmdlist == NULL)
|
if (*cmdlist == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
2
cmd.c
2
cmd.c
@ -84,10 +84,12 @@ const struct cmd_entry *cmd_table[] = {
|
|||||||
&cmd_send_prefix_entry,
|
&cmd_send_prefix_entry,
|
||||||
&cmd_server_info_entry,
|
&cmd_server_info_entry,
|
||||||
&cmd_set_buffer_entry,
|
&cmd_set_buffer_entry,
|
||||||
|
&cmd_set_environment_entry,
|
||||||
&cmd_set_option_entry,
|
&cmd_set_option_entry,
|
||||||
&cmd_set_password_entry,
|
&cmd_set_password_entry,
|
||||||
&cmd_set_window_option_entry,
|
&cmd_set_window_option_entry,
|
||||||
&cmd_show_buffer_entry,
|
&cmd_show_buffer_entry,
|
||||||
|
&cmd_show_environment_entry,
|
||||||
&cmd_show_options_entry,
|
&cmd_show_options_entry,
|
||||||
&cmd_show_window_options_entry,
|
&cmd_show_window_options_entry,
|
||||||
&cmd_source_file_entry,
|
&cmd_source_file_entry,
|
||||||
|
147
environ.c
Normal file
147
environ.c
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/* $OpenBSD$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tmux.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Environment - manipulate a set of environment variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
RB_GENERATE(environ, environ_entry, entry, environ_cmp);
|
||||||
|
|
||||||
|
void environ_set1(struct environ *, char *, char *);
|
||||||
|
|
||||||
|
int
|
||||||
|
environ_cmp(struct environ_entry *envent1, struct environ_entry *envent2)
|
||||||
|
{
|
||||||
|
return (strcmp(envent1->name, envent2->name));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
environ_init(struct environ *env)
|
||||||
|
{
|
||||||
|
RB_INIT(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
environ_free(struct environ *env)
|
||||||
|
{
|
||||||
|
struct environ_entry *envent;
|
||||||
|
|
||||||
|
while (!RB_EMPTY(env)) {
|
||||||
|
envent = RB_ROOT(env);
|
||||||
|
RB_REMOVE(environ, env, envent);
|
||||||
|
xfree(envent->name);
|
||||||
|
if (envent->value != NULL)
|
||||||
|
xfree(envent->value);
|
||||||
|
xfree(envent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
environ_copy(struct environ *srcenv, struct environ *dstenv)
|
||||||
|
{
|
||||||
|
struct environ_entry *envent;
|
||||||
|
|
||||||
|
RB_FOREACH(envent, environ, srcenv)
|
||||||
|
environ_set(dstenv, envent->name, envent->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct environ_entry *
|
||||||
|
environ_find(struct environ *env, const char *name)
|
||||||
|
{
|
||||||
|
struct environ_entry envent;
|
||||||
|
|
||||||
|
envent.name = (char *) name;
|
||||||
|
return (RB_FIND(environ, env, &envent));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
environ_set(struct environ *env, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
struct environ_entry *envent;
|
||||||
|
|
||||||
|
if ((envent = environ_find(env, name)) != NULL) {
|
||||||
|
if (envent->value != NULL)
|
||||||
|
xfree(envent->value);
|
||||||
|
if (value != NULL)
|
||||||
|
envent->value = xstrdup(value);
|
||||||
|
else
|
||||||
|
envent->value = NULL;
|
||||||
|
} else {
|
||||||
|
envent = xmalloc(sizeof *envent);
|
||||||
|
envent->name = xstrdup(name);
|
||||||
|
if (value != NULL)
|
||||||
|
envent->value = xstrdup(value);
|
||||||
|
else
|
||||||
|
envent->value = NULL;
|
||||||
|
RB_INSERT(environ, env, envent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
environ_put(struct environ *env, const char *var)
|
||||||
|
{
|
||||||
|
char *name, *value;
|
||||||
|
|
||||||
|
value = strchr(var, '=');
|
||||||
|
if (value == NULL)
|
||||||
|
return;
|
||||||
|
value++;
|
||||||
|
|
||||||
|
name = xstrdup(var);
|
||||||
|
name[strcspn(name, "=")] = '\0';
|
||||||
|
|
||||||
|
environ_set(env, name, value);
|
||||||
|
xfree(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
environ_unset(struct environ *env, const char *name)
|
||||||
|
{
|
||||||
|
struct environ_entry *envent;
|
||||||
|
|
||||||
|
if ((envent = environ_find(env, name)) == NULL)
|
||||||
|
return;
|
||||||
|
RB_REMOVE(environ, env, envent);
|
||||||
|
xfree(envent->name);
|
||||||
|
if (envent->value != NULL)
|
||||||
|
xfree(envent->value);
|
||||||
|
xfree(envent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
environ_update(const char *vars, struct environ *srcenv, struct environ *dstenv)
|
||||||
|
{
|
||||||
|
struct environ_entry *envent;
|
||||||
|
char *var, *next;
|
||||||
|
|
||||||
|
vars = next = xstrdup(vars);
|
||||||
|
while ((var = strsep(&next, " ")) != NULL) {
|
||||||
|
if ((envent = environ_find(srcenv, var)) == NULL)
|
||||||
|
environ_set(dstenv, var, NULL);
|
||||||
|
else
|
||||||
|
environ_set(dstenv, envent->name, envent->value);
|
||||||
|
}
|
||||||
|
xfree(vars);
|
||||||
|
}
|
19
server-fn.c
19
server-fn.c
@ -26,25 +26,20 @@
|
|||||||
|
|
||||||
int server_lock_callback(void *, const char *);
|
int server_lock_callback(void *, const char *);
|
||||||
|
|
||||||
const char **
|
void
|
||||||
server_fill_environ(struct session *s)
|
server_fill_environ(struct session *s, struct environ *env)
|
||||||
{
|
{
|
||||||
static const char *env[] = { NULL /* TMUX= */, NULL /* TERM */, NULL };
|
char tmuxvar[MAXPATHLEN], *term;
|
||||||
static char tmuxvar[MAXPATHLEN + 256], termvar[256];
|
|
||||||
u_int idx;
|
u_int idx;
|
||||||
|
|
||||||
if (session_index(s, &idx) != 0)
|
if (session_index(s, &idx) != 0)
|
||||||
fatalx("session not found");
|
fatalx("session not found");
|
||||||
|
|
||||||
xsnprintf(tmuxvar, sizeof tmuxvar,
|
xsnprintf(tmuxvar, sizeof tmuxvar,
|
||||||
"TMUX=%s,%ld,%u", socket_path, (long) getpid(), idx);
|
"%s,%ld,%u", socket_path, (long) getpid(), idx);
|
||||||
env[0] = tmuxvar;
|
environ_set(env, "TMUX", tmuxvar);
|
||||||
|
|
||||||
xsnprintf(termvar, sizeof termvar,
|
term = options_get_string(&s->options, "default-terminal");
|
||||||
"TERM=%s", options_get_string(&s->options, "default-terminal"));
|
environ_set(env, "TERM", term);
|
||||||
env[1] = termvar;
|
|
||||||
|
|
||||||
return (env);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
10
server-msg.c
10
server-msg.c
@ -42,6 +42,7 @@ server_msg_dispatch(struct client *c)
|
|||||||
struct msg_identify_data identifydata;
|
struct msg_identify_data identifydata;
|
||||||
struct msg_resize_data resizedata;
|
struct msg_resize_data resizedata;
|
||||||
struct msg_unlock_data unlockdata;
|
struct msg_unlock_data unlockdata;
|
||||||
|
struct msg_environ_data environdata;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (BUFFER_USED(c->in) < sizeof hdr)
|
if (BUFFER_USED(c->in) < sizeof hdr)
|
||||||
@ -100,6 +101,15 @@ server_msg_dispatch(struct client *c)
|
|||||||
tty_start_tty(&c->tty);
|
tty_start_tty(&c->tty);
|
||||||
server_redraw_client(c);
|
server_redraw_client(c);
|
||||||
break;
|
break;
|
||||||
|
case MSG_ENVIRON:
|
||||||
|
if (hdr.size != sizeof environdata)
|
||||||
|
fatalx("bad MSG_ENVIRON size");
|
||||||
|
buffer_read(c->in, &environdata, sizeof environdata);
|
||||||
|
|
||||||
|
environdata.var[(sizeof environdata.var) - 1] = '\0';
|
||||||
|
if (strchr(environdata.var, '=') != NULL)
|
||||||
|
environ_put(&c->environ, environdata.var);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fatalx("unexpected message");
|
fatalx("unexpected message");
|
||||||
}
|
}
|
||||||
|
22
session.c
22
session.c
@ -112,8 +112,8 @@ session_find(const char *name)
|
|||||||
|
|
||||||
/* Create a new session. */
|
/* Create a new session. */
|
||||||
struct session *
|
struct session *
|
||||||
session_create(const char *name,
|
session_create(const char *name, const char *cmd, const char *cwd,
|
||||||
const char *cmd, const char *cwd, u_int sx, u_int sy, char **cause)
|
struct environ *env, u_int sx, u_int sy, char **cause)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
u_int i;
|
u_int i;
|
||||||
@ -128,6 +128,9 @@ session_create(const char *name,
|
|||||||
SLIST_INIT(&s->alerts);
|
SLIST_INIT(&s->alerts);
|
||||||
paste_init_stack(&s->buffers);
|
paste_init_stack(&s->buffers);
|
||||||
options_init(&s->options, &global_s_options);
|
options_init(&s->options, &global_s_options);
|
||||||
|
environ_init(&s->environ);
|
||||||
|
if (env != NULL)
|
||||||
|
environ_copy(env, &s->environ);
|
||||||
|
|
||||||
s->sx = sx;
|
s->sx = sx;
|
||||||
s->sy = sy;
|
s->sy = sy;
|
||||||
@ -171,6 +174,7 @@ session_destroy(struct session *s)
|
|||||||
ARRAY_TRUNC(&sessions, 1);
|
ARRAY_TRUNC(&sessions, 1);
|
||||||
|
|
||||||
session_alert_cancel(s, NULL);
|
session_alert_cancel(s, NULL);
|
||||||
|
environ_free(&s->environ);
|
||||||
options_free(&s->options);
|
options_free(&s->options);
|
||||||
paste_free_stack(&s->buffers);
|
paste_free_stack(&s->buffers);
|
||||||
|
|
||||||
@ -200,15 +204,21 @@ session_new(struct session *s,
|
|||||||
const char *name, const char *cmd, const char *cwd, int idx, char **cause)
|
const char *name, const char *cmd, const char *cwd, int idx, char **cause)
|
||||||
{
|
{
|
||||||
struct window *w;
|
struct window *w;
|
||||||
const char **env;
|
struct environ env;
|
||||||
u_int hlimit;
|
u_int hlimit;
|
||||||
|
|
||||||
env = server_fill_environ(s);
|
environ_init(&env);
|
||||||
|
environ_copy(&global_environ, &env);
|
||||||
|
environ_copy(&s->environ, &env);
|
||||||
|
server_fill_environ(s, &env);
|
||||||
|
|
||||||
hlimit = options_get_number(&s->options, "history-limit");
|
hlimit = options_get_number(&s->options, "history-limit");
|
||||||
w = window_create(name, cmd, cwd, env, s->sx, s->sy, hlimit, cause);
|
w = window_create(name, cmd, cwd, &env, s->sx, s->sy, hlimit, cause);
|
||||||
if (w == NULL)
|
if (w == NULL) {
|
||||||
|
environ_free(&env);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
}
|
||||||
|
environ_free(&env);
|
||||||
|
|
||||||
if (options_get_number(&s->options, "set-remain-on-exit"))
|
if (options_get_number(&s->options, "set-remain-on-exit"))
|
||||||
options_set_number(&w->options, "remain-on-exit", 1);
|
options_set_number(&w->options, "remain-on-exit", 1);
|
||||||
|
66
tmux.1
66
tmux.1
@ -1321,6 +1321,18 @@ entry for terminals which support 88 or 256 colours:
|
|||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
"*88col*:colors=88,*256col*:colors=256"
|
"*88col*:colors=88,*256col*:colors=256"
|
||||||
.Ed
|
.Ed
|
||||||
|
.It Ic update-environment Ar variables
|
||||||
|
Set a space-separated string containing a list of environment variables to be
|
||||||
|
copied into the session environment when a new session is created or an
|
||||||
|
existing session is attached.
|
||||||
|
Any variables that do not exist in the source environment are set to be
|
||||||
|
removed from the session environment (as if
|
||||||
|
.Fl r
|
||||||
|
was given to the
|
||||||
|
.Ic set-environment
|
||||||
|
command).
|
||||||
|
The default is
|
||||||
|
.Ev DISPLAY .
|
||||||
.It Xo Ic visual-activity
|
.It Xo Ic visual-activity
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
@ -1525,6 +1537,60 @@ or the global window options if
|
|||||||
.Fl g
|
.Fl g
|
||||||
is used.
|
is used.
|
||||||
.El
|
.El
|
||||||
|
.Sh ENVIRONMENT
|
||||||
|
When the server is started,
|
||||||
|
.Nm
|
||||||
|
copies the environment into the
|
||||||
|
.Em global environment ;
|
||||||
|
in addition, each session has a
|
||||||
|
.Em session environment .
|
||||||
|
When a window is created, the session and global environments are merged with
|
||||||
|
the session environment overriding any variable present in both.
|
||||||
|
This is the initial environment passed to the new process.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Ic update-environment
|
||||||
|
session option may be used to update the session environment from the client
|
||||||
|
when a new session is created or an old reattached.
|
||||||
|
.Nm
|
||||||
|
also initialises the
|
||||||
|
.Ev TMUX
|
||||||
|
variable with some internal information to allow commands to be executed
|
||||||
|
from inside, and the
|
||||||
|
.Ev TERM
|
||||||
|
variable with the correct terminal setting of
|
||||||
|
.Ql screen .
|
||||||
|
.Pp
|
||||||
|
Commands to alter and view the environment are:
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Xo Ic set-environment
|
||||||
|
.Op Fl gru
|
||||||
|
.Op Fl t Ar target-session
|
||||||
|
.Ar name Op Ar value
|
||||||
|
.Xc
|
||||||
|
Set or unset an environment variable.
|
||||||
|
If
|
||||||
|
.Fl g
|
||||||
|
is used, the change is made in the global environment; otherwise, it is applied
|
||||||
|
to the session environment for
|
||||||
|
.Ar target-session .
|
||||||
|
The
|
||||||
|
.Fl u
|
||||||
|
flag unsets a variable.
|
||||||
|
.Fl r
|
||||||
|
indicates the variable is to be removed from the environment before starting a
|
||||||
|
new process.
|
||||||
|
.It Xo Ic show-environment
|
||||||
|
.Op Fl g
|
||||||
|
.Op Fl t Ar target-session
|
||||||
|
.Xc
|
||||||
|
Display the environment for
|
||||||
|
.Ar target-session
|
||||||
|
or the global environment with
|
||||||
|
.Fl g .
|
||||||
|
Variables removed from the environment are prefixed with
|
||||||
|
.Ql - .
|
||||||
|
.El
|
||||||
.Sh STATUS LINE
|
.Sh STATUS LINE
|
||||||
.Nm
|
.Nm
|
||||||
includes an optional status line which is displayed in the bottom line of each
|
includes an optional status line which is displayed in the bottom line of each
|
||||||
|
14
tmux.c
14
tmux.c
@ -44,6 +44,7 @@ volatile sig_atomic_t sigusr2;
|
|||||||
char *cfg_file;
|
char *cfg_file;
|
||||||
struct options global_s_options; /* session options */
|
struct options global_s_options; /* session options */
|
||||||
struct options global_w_options; /* window options */
|
struct options global_w_options; /* window options */
|
||||||
|
struct environ global_environ;
|
||||||
|
|
||||||
int server_locked;
|
int server_locked;
|
||||||
u_int password_failures;
|
u_int password_failures;
|
||||||
@ -262,7 +263,7 @@ main(int argc, char **argv)
|
|||||||
struct hdr hdr;
|
struct hdr hdr;
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct msg_print_data printdata;
|
struct msg_print_data printdata;
|
||||||
char *s, *path, *label, *home, *cause;
|
char *s, *path, *label, *home, *cause, **var;
|
||||||
char cwd[MAXPATHLEN];
|
char cwd[MAXPATHLEN];
|
||||||
void *buf;
|
void *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -320,6 +321,10 @@ main(int argc, char **argv)
|
|||||||
log_open_tty(debug_level);
|
log_open_tty(debug_level);
|
||||||
siginit();
|
siginit();
|
||||||
|
|
||||||
|
environ_init(&global_environ);
|
||||||
|
for (var = environ; *var != NULL; var++)
|
||||||
|
environ_put(&global_environ, *var);
|
||||||
|
|
||||||
if (!(flags & IDENTIFY_UTF8)) {
|
if (!(flags & IDENTIFY_UTF8)) {
|
||||||
/*
|
/*
|
||||||
* If the user has set whichever of LC_ALL, LC_CTYPE or LANG
|
* If the user has set whichever of LC_ALL, LC_CTYPE or LANG
|
||||||
@ -376,6 +381,7 @@ main(int argc, char **argv)
|
|||||||
options_set_number(&global_s_options, "status-utf8", 0);
|
options_set_number(&global_s_options, "status-utf8", 0);
|
||||||
options_set_string(&global_s_options,
|
options_set_string(&global_s_options,
|
||||||
"terminal-overrides", "*88col*:colors=88,*256col*:colors=256");
|
"terminal-overrides", "*88col*:colors=88,*256col*:colors=256");
|
||||||
|
options_set_string(&global_s_options, "update-environment", "DISPLAY");
|
||||||
options_set_number(&global_s_options, "visual-activity", 0);
|
options_set_number(&global_s_options, "visual-activity", 0);
|
||||||
options_set_number(&global_s_options, "visual-bell", 0);
|
options_set_number(&global_s_options, "visual-bell", 0);
|
||||||
options_set_number(&global_s_options, "visual-content", 0);
|
options_set_number(&global_s_options, "visual-content", 0);
|
||||||
@ -469,10 +475,10 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
cmdflags &= ~CMD_STARTSERVER;
|
cmdflags &= ~CMD_STARTSERVER;
|
||||||
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
TAILQ_FOREACH(cmd, cmdlist, qentry) {
|
||||||
if (cmd->entry->flags & CMD_STARTSERVER) {
|
if (cmd->entry->flags & CMD_STARTSERVER)
|
||||||
cmdflags |= CMD_STARTSERVER;
|
cmdflags |= CMD_STARTSERVER;
|
||||||
break;
|
if (cmd->entry->flags & CMD_SENDENVIRON)
|
||||||
}
|
cmdflags |= CMD_SENDENVIRON;
|
||||||
}
|
}
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
}
|
}
|
||||||
|
46
tmux.h
46
tmux.h
@ -39,6 +39,7 @@
|
|||||||
#include "array.h"
|
#include "array.h"
|
||||||
|
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
/* Default configuration files. */
|
/* Default configuration files. */
|
||||||
#define DEFAULT_CFG ".tmux.conf"
|
#define DEFAULT_CFG ".tmux.conf"
|
||||||
@ -69,6 +70,7 @@ extern char *__progname;
|
|||||||
#define COMMAND_LENGTH 2048 /* packed argv size */
|
#define COMMAND_LENGTH 2048 /* packed argv size */
|
||||||
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
|
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
|
||||||
#define PRINT_LENGTH 512 /* printed error/message size */
|
#define PRINT_LENGTH 512 /* printed error/message size */
|
||||||
|
#define ENVIRON_LENGTH 1024 /* environment variable length */
|
||||||
|
|
||||||
/* Fatal errors. */
|
/* Fatal errors. */
|
||||||
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
|
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
|
||||||
@ -302,6 +304,7 @@ enum msgtype {
|
|||||||
MSG_SUSPEND,
|
MSG_SUSPEND,
|
||||||
MSG_UNLOCK,
|
MSG_UNLOCK,
|
||||||
MSG_WAKEUP,
|
MSG_WAKEUP,
|
||||||
|
MSG_ENVIRON
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -356,6 +359,10 @@ struct msg_unlock_data {
|
|||||||
char pass[PASS_MAX];
|
char pass[PASS_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct msg_environ_data {
|
||||||
|
char var[ENVIRON_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
/* Mode key commands. */
|
/* Mode key commands. */
|
||||||
enum mode_key_cmd {
|
enum mode_key_cmd {
|
||||||
MODEKEY_NONE,
|
MODEKEY_NONE,
|
||||||
@ -765,6 +772,15 @@ struct paste_buffer {
|
|||||||
};
|
};
|
||||||
ARRAY_DECL(paste_stack, struct paste_buffer *);
|
ARRAY_DECL(paste_stack, struct paste_buffer *);
|
||||||
|
|
||||||
|
/* Environment variable. */
|
||||||
|
struct environ_entry {
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
RB_ENTRY(environ_entry) entry;
|
||||||
|
};
|
||||||
|
RB_HEAD(environ, environ_entry);
|
||||||
|
|
||||||
/* Client session. */
|
/* Client session. */
|
||||||
struct session_alert {
|
struct session_alert {
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
@ -792,6 +808,8 @@ struct session {
|
|||||||
|
|
||||||
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */
|
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
struct environ environ;
|
||||||
};
|
};
|
||||||
ARRAY_DECL(sessions, struct session *);
|
ARRAY_DECL(sessions, struct session *);
|
||||||
|
|
||||||
@ -894,6 +912,8 @@ struct client {
|
|||||||
struct buffer *in;
|
struct buffer *in;
|
||||||
struct buffer *out;
|
struct buffer *out;
|
||||||
|
|
||||||
|
struct environ environ;
|
||||||
|
|
||||||
char *title;
|
char *title;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
|
|
||||||
@ -992,6 +1012,7 @@ struct cmd_entry {
|
|||||||
#define CMD_CANTNEST 0x2
|
#define CMD_CANTNEST 0x2
|
||||||
#define CMD_ARG1 0x4
|
#define CMD_ARG1 0x4
|
||||||
#define CMD_ARG01 0x8
|
#define CMD_ARG01 0x8
|
||||||
|
#define CMD_SENDENVIRON 0x10
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
#define CMD_CHFLAG(flag) \
|
#define CMD_CHFLAG(flag) \
|
||||||
@ -1074,6 +1095,7 @@ extern volatile sig_atomic_t sigusr1;
|
|||||||
extern volatile sig_atomic_t sigusr2;
|
extern volatile sig_atomic_t sigusr2;
|
||||||
extern struct options global_s_options;
|
extern struct options global_s_options;
|
||||||
extern struct options global_w_options;
|
extern struct options global_w_options;
|
||||||
|
extern struct environ global_environ;
|
||||||
extern char *cfg_file;
|
extern char *cfg_file;
|
||||||
extern int server_locked;
|
extern int server_locked;
|
||||||
extern u_int password_failures;
|
extern u_int password_failures;
|
||||||
@ -1123,6 +1145,18 @@ char *options_get_string(struct options *, const char *);
|
|||||||
void options_set_number(struct options *, const char *, long long);
|
void options_set_number(struct options *, const char *, long long);
|
||||||
long long options_get_number(struct options *, const char *);
|
long long options_get_number(struct options *, const char *);
|
||||||
|
|
||||||
|
/* environ.c */
|
||||||
|
int environ_cmp(struct environ_entry *, struct environ_entry *);
|
||||||
|
RB_PROTOTYPE(environ, environ_entry, entry, environ_cmp);
|
||||||
|
void environ_init(struct environ *);
|
||||||
|
void environ_free(struct environ *);
|
||||||
|
void environ_copy(struct environ *, struct environ *);
|
||||||
|
struct environ_entry *environ_find(struct environ *, const char *);
|
||||||
|
void environ_set(struct environ *, const char *, const char *);
|
||||||
|
void environ_put(struct environ *, const char *);
|
||||||
|
void environ_unset(struct environ *, const char *);
|
||||||
|
void environ_update(const char *, struct environ *, struct environ *);
|
||||||
|
|
||||||
/* tty.c */
|
/* tty.c */
|
||||||
u_char tty_get_acs(struct tty *, u_char);
|
u_char tty_get_acs(struct tty *, u_char);
|
||||||
void tty_reset(struct tty *);
|
void tty_reset(struct tty *);
|
||||||
@ -1285,10 +1319,12 @@ extern const struct cmd_entry cmd_send_keys_entry;
|
|||||||
extern const struct cmd_entry cmd_send_prefix_entry;
|
extern const struct cmd_entry cmd_send_prefix_entry;
|
||||||
extern const struct cmd_entry cmd_server_info_entry;
|
extern const struct cmd_entry cmd_server_info_entry;
|
||||||
extern const struct cmd_entry cmd_set_buffer_entry;
|
extern const struct cmd_entry cmd_set_buffer_entry;
|
||||||
|
extern const struct cmd_entry cmd_set_environment_entry;
|
||||||
extern const struct cmd_entry cmd_set_option_entry;
|
extern const struct cmd_entry cmd_set_option_entry;
|
||||||
extern const struct cmd_entry cmd_set_password_entry;
|
extern const struct cmd_entry cmd_set_password_entry;
|
||||||
extern const struct cmd_entry cmd_set_window_option_entry;
|
extern const struct cmd_entry cmd_set_window_option_entry;
|
||||||
extern const struct cmd_entry cmd_show_buffer_entry;
|
extern const struct cmd_entry cmd_show_buffer_entry;
|
||||||
|
extern const struct cmd_entry cmd_show_environment_entry;
|
||||||
extern const struct cmd_entry cmd_show_options_entry;
|
extern const struct cmd_entry cmd_show_options_entry;
|
||||||
extern const struct cmd_entry cmd_show_window_options_entry;
|
extern const struct cmd_entry cmd_show_window_options_entry;
|
||||||
extern const struct cmd_entry cmd_source_file_entry;
|
extern const struct cmd_entry cmd_source_file_entry;
|
||||||
@ -1384,7 +1420,7 @@ int server_start(char *);
|
|||||||
int server_msg_dispatch(struct client *);
|
int server_msg_dispatch(struct client *);
|
||||||
|
|
||||||
/* server-fn.c */
|
/* server-fn.c */
|
||||||
const char **server_fill_environ(struct session *);
|
void server_fill_environ(struct session *, struct environ *);
|
||||||
void server_write_error(struct client *, const char *);
|
void server_write_error(struct client *, const char *);
|
||||||
void server_write_client(
|
void server_write_client(
|
||||||
struct client *, enum msgtype, const void *, size_t);
|
struct client *, enum msgtype, const void *, size_t);
|
||||||
@ -1554,8 +1590,8 @@ void winlink_stack_push(struct winlink_stack *, struct winlink *);
|
|||||||
void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
||||||
int window_index(struct window *, u_int *);
|
int window_index(struct window *, u_int *);
|
||||||
struct window *window_create1(u_int, u_int);
|
struct window *window_create1(u_int, u_int);
|
||||||
struct window *window_create(const char *, const char *,
|
struct window *window_create(const char *, const char *, const char *,
|
||||||
const char *, const char **, u_int, u_int, u_int, char **);
|
struct environ *, u_int, u_int, u_int, char **);
|
||||||
void window_destroy(struct window *);
|
void window_destroy(struct window *);
|
||||||
void window_set_active_pane(struct window *, struct window_pane *);
|
void window_set_active_pane(struct window *, struct window_pane *);
|
||||||
struct window_pane *window_add_pane(struct window *, u_int);
|
struct window_pane *window_add_pane(struct window *, u_int);
|
||||||
@ -1568,7 +1604,7 @@ void window_destroy_panes(struct window *);
|
|||||||
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
|
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
|
||||||
void window_pane_destroy(struct window_pane *);
|
void window_pane_destroy(struct window_pane *);
|
||||||
int window_pane_spawn(struct window_pane *,
|
int window_pane_spawn(struct window_pane *,
|
||||||
const char *, const char *, const char **, char **);
|
const char *, const char *, struct environ *, char **);
|
||||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||||
int window_pane_set_mode(
|
int window_pane_set_mode(
|
||||||
struct window_pane *, const struct window_mode *);
|
struct window_pane *, const struct window_mode *);
|
||||||
@ -1648,7 +1684,7 @@ int session_alert_has(struct session *, struct winlink *, int);
|
|||||||
int session_alert_has_window(struct session *, struct window *, int);
|
int session_alert_has_window(struct session *, struct window *, int);
|
||||||
struct session *session_find(const char *);
|
struct session *session_find(const char *);
|
||||||
struct session *session_create(const char *, const char *,
|
struct session *session_create(const char *, const char *,
|
||||||
const char *, u_int, u_int, char **);
|
const char *, struct environ *, u_int, u_int, char **);
|
||||||
void session_destroy(struct session *);
|
void session_destroy(struct session *);
|
||||||
int session_index(struct session *, u_int *);
|
int session_index(struct session *, u_int *);
|
||||||
struct winlink *session_new(struct session *,
|
struct winlink *session_new(struct session *,
|
||||||
|
31
window.c
31
window.c
@ -254,7 +254,7 @@ window_create1(u_int sx, u_int sy)
|
|||||||
|
|
||||||
struct window *
|
struct window *
|
||||||
window_create(const char *name, const char *cmd, const char *cwd,
|
window_create(const char *name, const char *cmd, const char *cwd,
|
||||||
const char **envp, u_int sx, u_int sy, u_int hlimit, char **cause)
|
struct environ *env, u_int sx, u_int sy, u_int hlimit, char **cause)
|
||||||
{
|
{
|
||||||
struct window *w;
|
struct window *w;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
@ -262,7 +262,7 @@ window_create(const char *name, const char *cmd, const char *cwd,
|
|||||||
w = window_create1(sx, sy);
|
w = window_create1(sx, sy);
|
||||||
wp = window_add_pane(w, hlimit);
|
wp = window_add_pane(w, hlimit);
|
||||||
layout_init(w);
|
layout_init(w);
|
||||||
if (window_pane_spawn(wp, cmd, cwd, envp, cause) != 0) {
|
if (window_pane_spawn(wp, cmd, cwd, env, cause) != 0) {
|
||||||
window_destroy(w);
|
window_destroy(w);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -456,13 +456,16 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
|
|
||||||
int
|
int
|
||||||
window_pane_spawn(struct window_pane *wp,
|
window_pane_spawn(struct window_pane *wp,
|
||||||
const char *cmd, const char *cwd, const char **envp, char **cause)
|
const char *cmd, const char *cwd, struct environ *env, char **cause)
|
||||||
{
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
int mode;
|
int mode;
|
||||||
const char **envq, *ptr;
|
char *argv0, **varp, *var;
|
||||||
char *argv0;
|
ARRAY_DECL(, char *) varlist;
|
||||||
|
struct environ_entry *envent;
|
||||||
|
const char *ptr;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
u_int i;
|
||||||
|
|
||||||
if (wp->fd != -1)
|
if (wp->fd != -1)
|
||||||
close(wp->fd);
|
close(wp->fd);
|
||||||
@ -495,10 +498,22 @@ window_pane_spawn(struct window_pane *wp,
|
|||||||
case 0:
|
case 0:
|
||||||
if (chdir(wp->cwd) != 0)
|
if (chdir(wp->cwd) != 0)
|
||||||
chdir("/");
|
chdir("/");
|
||||||
for (envq = envp; *envq != NULL; envq++) {
|
|
||||||
if (putenv(xstrdup(*envq)) != 0)
|
ARRAY_INIT(&varlist);
|
||||||
fatal("putenv failed");
|
for (varp = environ; *varp != NULL; varp++) {
|
||||||
|
var = xstrdup(*varp);
|
||||||
|
var[strcspn(var, "=")] = '\0';
|
||||||
|
ARRAY_ADD(&varlist, var);
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < ARRAY_LENGTH(&varlist); i++) {
|
||||||
|
var = ARRAY_ITEM(&varlist, i);
|
||||||
|
unsetenv(var);
|
||||||
|
}
|
||||||
|
RB_FOREACH(envent, environ, env) {
|
||||||
|
if (envent->value != NULL)
|
||||||
|
setenv(envent->name, envent->value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
sigreset();
|
sigreset();
|
||||||
log_close();
|
log_close();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user