summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2009-08-08 21:52:44 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2009-08-08 21:52:44 +0000
commite25abe44e01289aa01c6c4f199ce053d873f56db (patch)
treea52f7db2acdacf6382b139452ee240ba4e506af9
parentafc7a7f90fe800edd4702c36311f0362cff98bb9 (diff)
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.
-rw-r--r--usr.bin/tmux/Makefile5
-rw-r--r--usr.bin/tmux/client.c20
-rw-r--r--usr.bin/tmux/cmd-attach-session.c9
-rw-r--r--usr.bin/tmux/cmd-new-session.c15
-rw-r--r--usr.bin/tmux/cmd-respawn-window.c13
-rw-r--r--usr.bin/tmux/cmd-set-environment.c88
-rw-r--r--usr.bin/tmux/cmd-set-option.c3
-rw-r--r--usr.bin/tmux/cmd-show-environment.c67
-rw-r--r--usr.bin/tmux/cmd-split-window.c13
-rw-r--r--usr.bin/tmux/cmd-string.c30
-rw-r--r--usr.bin/tmux/cmd.c4
-rw-r--r--usr.bin/tmux/environ.c147
-rw-r--r--usr.bin/tmux/server-fn.c23
-rw-r--r--usr.bin/tmux/server-msg.c12
-rw-r--r--usr.bin/tmux/session.c24
-rw-r--r--usr.bin/tmux/tmux.168
-rw-r--r--usr.bin/tmux/tmux.c16
-rw-r--r--usr.bin/tmux/tmux.h48
-rw-r--r--usr.bin/tmux/window.c39
19 files changed, 565 insertions, 79 deletions
diff --git a/usr.bin/tmux/Makefile b/usr.bin/tmux/Makefile
index f6712aab1ae..7de4a7cc2f1 100644
--- a/usr.bin/tmux/Makefile
+++ b/usr.bin/tmux/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.11 2009/07/30 16:32:12 nicm Exp $
+# $OpenBSD: Makefile,v 1.12 2009/08/08 21:52:43 nicm Exp $
PROG= tmux
SRCS= attributes.c buffer-poll.c buffer.c cfg.c client-fn.c \
@@ -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-suspend-client.c cmd-swap-pane.c cmd-swap-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 \
- 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 \
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 \
diff --git a/usr.bin/tmux/client.c b/usr.bin/tmux/client.c
index dbe96613bd7..295e9b02ac7 100644
--- a/usr.bin/tmux/client.c
+++ b/usr.bin/tmux/client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: client.c,v 1.10 2009/08/08 21:18:23 nicm Exp $ */
+/* $OpenBSD: client.c,v 1.11 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,6 +33,7 @@
#include "tmux.h"
+void client_send_environ(struct client_ctx *);
void client_handle_winch(struct client_ctx *);
int
@@ -95,6 +96,8 @@ server_started:
cctx->srv_in = buffer_create(BUFSIZ);
cctx->srv_out = buffer_create(BUFSIZ);
+ if (cmdflags & CMD_SENDENVIRON)
+ client_send_environ(cctx);
if (isatty(STDIN_FILENO)) {
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
fatal("ioctl(TIOCGWINSZ)");
@@ -133,6 +136,19 @@ not_found:
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
client_main(struct client_ctx *cctx)
{
@@ -242,8 +258,8 @@ client_msg_dispatch(struct client_ctx *cctx)
if (hdr.size != sizeof printdata)
fatalx("bad MSG_PRINT size");
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);
return (-1);
case MSG_EXIT:
diff --git a/usr.bin/tmux/cmd-attach-session.c b/usr.bin/tmux/cmd-attach-session.c
index 08aec80bec7..9c867737d0d 100644
--- a/usr.bin/tmux/cmd-attach-session.c
+++ b/usr.bin/tmux/cmd-attach-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-attach-session.c,v 1.7 2009/08/03 14:10:54 nicm Exp $ */
+/* $OpenBSD: cmd-attach-session.c,v 1.8 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,7 +29,7 @@ int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach",
"[-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_parse,
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 session *s;
struct client *c;
+ const char *update;
char *overrides, *cause;
u_int i;
@@ -93,6 +94,10 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
ctx->cmdclient->session = s;
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);
}
recalculate_sizes();
diff --git a/usr.bin/tmux/cmd-new-session.c b/usr.bin/tmux/cmd-new-session.c
index 38f9038b9d8..b2ecc6767e5 100644
--- a/usr.bin/tmux/cmd-new-session.c
+++ b/usr.bin/tmux/cmd-new-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-new-session.c,v 1.9 2009/08/03 14:10:54 nicm Exp $ */
+/* $OpenBSD: cmd-new-session.c,v 1.10 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -40,7 +40,7 @@ struct cmd_new_session_data {
const struct cmd_entry cmd_new_session_entry = {
"new-session", "new",
"[-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_parse,
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 session *s;
+ struct environ env;
+ const char *update;
char *overrides, *cmd, *cwd, *cause;
int detached;
u_int sx, sy;
@@ -184,13 +186,20 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
else
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. */
- s = session_create(data->newname, cmd, cwd, sx, sy, &cause);
+ s = session_create(data->newname, cmd, cwd, &env, sx, sy, &cause);
if (s == NULL) {
ctx->error(ctx, "create session failed: %s", cause);
xfree(cause);
return (-1);
}
+ environ_free(&env);
if (data->winname != NULL) {
xfree(s->curw->window->name);
diff --git a/usr.bin/tmux/cmd-respawn-window.c b/usr.bin/tmux/cmd-respawn-window.c
index e9ac69d01c8..71d82cc63d4 100644
--- a/usr.bin/tmux/cmd-respawn-window.c
+++ b/usr.bin/tmux/cmd-respawn-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-respawn-window.c,v 1.5 2009/07/26 12:58:44 nicm Exp $ */
+/* $OpenBSD: cmd-respawn-window.c,v 1.6 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -47,7 +47,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window *w;
struct window_pane *wp;
struct session *s;
- const char **env;
+ struct environ env;
char *cause;
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);
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);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
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);
xfree(cause);
+ environ_free(&env);
return (-1);
}
layout_init(w);
@@ -84,5 +88,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
recalculate_sizes();
server_redraw_window(w);
+ environ_free(&env);
return (0);
}
diff --git a/usr.bin/tmux/cmd-set-environment.c b/usr.bin/tmux/cmd-set-environment.c
new file mode 100644
index 00000000000..374887f5ae3
--- /dev/null
+++ b/usr.bin/tmux/cmd-set-environment.c
@@ -0,0 +1,88 @@
+/* $OpenBSD: cmd-set-environment.c,v 1.1 2009/08/08 21:52:43 nicm Exp $ */
+
+/*
+ * 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);
+}
diff --git a/usr.bin/tmux/cmd-set-option.c b/usr.bin/tmux/cmd-set-option.c
index b0e52c39b56..50825fb3997 100644
--- a/usr.bin/tmux/cmd-set-option.c
+++ b/usr.bin/tmux/cmd-set-option.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-set-option.c,v 1.12 2009/08/08 20:36:42 nicm Exp $ */
+/* $OpenBSD: cmd-set-option.c,v 1.13 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -85,6 +85,7 @@ const struct set_option_entry set_option_table[] = {
{ "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "status-utf8", SET_OPTION_FLAG, 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-bell", SET_OPTION_FLAG, 0, 0, NULL },
{ "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
diff --git a/usr.bin/tmux/cmd-show-environment.c b/usr.bin/tmux/cmd-show-environment.c
new file mode 100644
index 00000000000..8efd0144a36
--- /dev/null
+++ b/usr.bin/tmux/cmd-show-environment.c
@@ -0,0 +1,67 @@
+/* $OpenBSD: cmd-show-environment.c,v 1.1 2009/08/08 21:52:43 nicm Exp $ */
+
+/*
+ * 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);
+}
diff --git a/usr.bin/tmux/cmd-split-window.c b/usr.bin/tmux/cmd-split-window.c
index 2585b1f15d4..4907af86deb 100644
--- a/usr.bin/tmux/cmd-split-window.c
+++ b/usr.bin/tmux/cmd-split-window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-split-window.c,v 1.7 2009/07/26 12:58:44 nicm Exp $ */
+/* $OpenBSD: cmd-split-window.c,v 1.8 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -149,7 +149,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct winlink *wl;
struct window *w;
struct window_pane *wp;
- const char **env;
+ struct environ env;
char *cmd, *cwd, *cause;
u_int hlimit;
int size;
@@ -159,7 +159,10 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1);
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;
if (cmd == NULL)
@@ -181,7 +184,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
type = LAYOUT_LEFTRIGHT;
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;
if (layout_split_pane(w->active, type, size, wp) != 0) {
cause = xstrdup("pane too small");
@@ -197,9 +200,11 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} else
server_status_session(s);
+ environ_free(&env);
return (0);
error:
+ environ_free(&env);
if (wp != NULL)
window_remove_pane(w, wp);
ctx->error(ctx, "create pane failed: %s", cause);
diff --git a/usr.bin/tmux/cmd-string.c b/usr.bin/tmux/cmd-string.c
index 2094d35b9c6..450279b1c4c 100644
--- a/usr.bin/tmux/cmd-string.c
+++ b/usr.bin/tmux/cmd-string.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-string.c,v 1.5 2009/08/03 14:10:54 nicm Exp $ */
+/* $OpenBSD: cmd-string.c,v 1.6 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -59,21 +59,11 @@ int
cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
{
size_t p;
- int ch, argc, rval, have_arg;
- char **argv, *buf, *t, *u;
+ int ch, i, argc, rval, have_arg;
+ char **argv, *buf, *t;
+ const char *whitespace, *equals;
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;
argc = 0;
@@ -147,6 +137,18 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
if (argc == 0)
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);
if (*cmdlist == NULL)
goto out;
diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c
index 6e172d70ae2..b2e8203a02e 100644
--- a/usr.bin/tmux/cmd.c
+++ b/usr.bin/tmux/cmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.12 2009/07/30 13:45:56 nicm Exp $ */
+/* $OpenBSD: cmd.c,v 1.13 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -84,10 +84,12 @@ const struct cmd_entry *cmd_table[] = {
&cmd_send_prefix_entry,
&cmd_server_info_entry,
&cmd_set_buffer_entry,
+ &cmd_set_environment_entry,
&cmd_set_option_entry,
&cmd_set_password_entry,
&cmd_set_window_option_entry,
&cmd_show_buffer_entry,
+ &cmd_show_environment_entry,
&cmd_show_options_entry,
&cmd_show_window_options_entry,
&cmd_source_file_entry,
diff --git a/usr.bin/tmux/environ.c b/usr.bin/tmux/environ.c
new file mode 100644
index 00000000000..b62bf6d1cff
--- /dev/null
+++ b/usr.bin/tmux/environ.c
@@ -0,0 +1,147 @@
+/* $OpenBSD: environ.c,v 1.1 2009/08/08 21:52:43 nicm Exp $ */
+
+/*
+ * 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);
+}
diff --git a/usr.bin/tmux/server-fn.c b/usr.bin/tmux/server-fn.c
index 761d137d518..85be4a4ddfe 100644
--- a/usr.bin/tmux/server-fn.c
+++ b/usr.bin/tmux/server-fn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-fn.c,v 1.12 2009/08/07 15:39:10 nicm Exp $ */
+/* $OpenBSD: server-fn.c,v 1.13 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,25 +26,20 @@
int server_lock_callback(void *, const char *);
-const char **
-server_fill_environ(struct session *s)
+void
+server_fill_environ(struct session *s, struct environ *env)
{
- static const char *env[] = { NULL /* TMUX= */, NULL /* TERM */, NULL };
- static char tmuxvar[MAXPATHLEN + 256], termvar[256];
- u_int idx;
+ char tmuxvar[MAXPATHLEN], *term;
+ u_int idx;
if (session_index(s, &idx) != 0)
fatalx("session not found");
-
xsnprintf(tmuxvar, sizeof tmuxvar,
- "TMUX=%s,%ld,%u", socket_path, (long) getpid(), idx);
- env[0] = tmuxvar;
-
- xsnprintf(termvar, sizeof termvar,
- "TERM=%s", options_get_string(&s->options, "default-terminal"));
- env[1] = termvar;
+ "%s,%ld,%u", socket_path, (long) getpid(), idx);
+ environ_set(env, "TMUX", tmuxvar);
- return (env);
+ term = options_get_string(&s->options, "default-terminal");
+ environ_set(env, "TERM", term);
}
void
diff --git a/usr.bin/tmux/server-msg.c b/usr.bin/tmux/server-msg.c
index 7471323cf45..fd4d8a8ecaa 100644
--- a/usr.bin/tmux/server-msg.c
+++ b/usr.bin/tmux/server-msg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-msg.c,v 1.9 2009/07/30 16:40:12 nicm Exp $ */
+/* $OpenBSD: server-msg.c,v 1.10 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -42,6 +42,7 @@ server_msg_dispatch(struct client *c)
struct msg_identify_data identifydata;
struct msg_resize_data resizedata;
struct msg_unlock_data unlockdata;
+ struct msg_environ_data environdata;
for (;;) {
if (BUFFER_USED(c->in) < sizeof hdr)
@@ -100,6 +101,15 @@ server_msg_dispatch(struct client *c)
tty_start_tty(&c->tty);
server_redraw_client(c);
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:
fatalx("unexpected message");
}
diff --git a/usr.bin/tmux/session.c b/usr.bin/tmux/session.c
index 0ce96dac295..7691c29a2b1 100644
--- a/usr.bin/tmux/session.c
+++ b/usr.bin/tmux/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.2 2009/07/07 19:49:19 nicm Exp $ */
+/* $OpenBSD: session.c,v 1.3 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -112,8 +112,8 @@ session_find(const char *name)
/* Create a new session. */
struct session *
-session_create(const char *name,
- const char *cmd, const char *cwd, u_int sx, u_int sy, char **cause)
+session_create(const char *name, const char *cmd, const char *cwd,
+ struct environ *env, u_int sx, u_int sy, char **cause)
{
struct session *s;
u_int i;
@@ -128,6 +128,9 @@ session_create(const char *name,
SLIST_INIT(&s->alerts);
paste_init_stack(&s->buffers);
options_init(&s->options, &global_s_options);
+ environ_init(&s->environ);
+ if (env != NULL)
+ environ_copy(env, &s->environ);
s->sx = sx;
s->sy = sy;
@@ -171,6 +174,7 @@ session_destroy(struct session *s)
ARRAY_TRUNC(&sessions, 1);
session_alert_cancel(s, NULL);
+ environ_free(&s->environ);
options_free(&s->options);
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)
{
struct window *w;
- const char **env;
+ struct environ env;
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");
- w = window_create(name, cmd, cwd, env, s->sx, s->sy, hlimit, cause);
- if (w == NULL)
+ w = window_create(name, cmd, cwd, &env, s->sx, s->sy, hlimit, cause);
+ if (w == NULL) {
+ environ_free(&env);
return (NULL);
+ }
+ environ_free(&env);
if (options_get_number(&s->options, "set-remain-on-exit"))
options_set_number(&w->options, "remain-on-exit", 1);
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index c7d341af824..81378eae95f 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.62 2009/08/08 20:36:42 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.63 2009/08/08 21:52:43 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\"
@@ -1321,6 +1321,18 @@ entry for terminals which support 88 or 256 colours:
.Bd -literal -offset indent
"*88col*:colors=88,*256col*:colors=256"
.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
.Op Ic on | off
.Xc
@@ -1525,6 +1537,60 @@ or the global window options if
.Fl g
is used.
.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
.Nm
includes an optional status line which is displayed in the bottom line of each
diff --git a/usr.bin/tmux/tmux.c b/usr.bin/tmux/tmux.c
index 6959b4662f0..1beb777d275 100644
--- a/usr.bin/tmux/tmux.c
+++ b/usr.bin/tmux/tmux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.c,v 1.28 2009/08/08 20:36:42 nicm Exp $ */
+/* $OpenBSD: tmux.c,v 1.29 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -44,6 +44,7 @@ volatile sig_atomic_t sigusr2;
char *cfg_file;
struct options global_s_options; /* session options */
struct options global_w_options; /* window options */
+struct environ global_environ;
int server_locked;
u_int password_failures;
@@ -262,7 +263,7 @@ main(int argc, char **argv)
struct hdr hdr;
struct passwd *pw;
struct msg_print_data printdata;
- char *s, *path, *label, *home, *cause;
+ char *s, *path, *label, *home, *cause, **var;
char cwd[MAXPATHLEN];
void *buf;
size_t len;
@@ -320,6 +321,10 @@ main(int argc, char **argv)
log_open_tty(debug_level);
siginit();
+ environ_init(&global_environ);
+ for (var = environ; *var != NULL; var++)
+ environ_put(&global_environ, *var);
+
if (!(flags & IDENTIFY_UTF8)) {
/*
* 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_string(&global_s_options,
"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-bell", 0);
options_set_number(&global_s_options, "visual-content", 0);
@@ -469,10 +475,10 @@ main(int argc, char **argv)
}
cmdflags &= ~CMD_STARTSERVER;
TAILQ_FOREACH(cmd, cmdlist, qentry) {
- if (cmd->entry->flags & CMD_STARTSERVER) {
+ if (cmd->entry->flags & CMD_STARTSERVER)
cmdflags |= CMD_STARTSERVER;
- break;
- }
+ if (cmd->entry->flags & CMD_SENDENVIRON)
+ cmdflags |= CMD_SENDENVIRON;
}
cmd_list_free(cmdlist);
}
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index 622b537f0f4..01af8f6aee0 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.72 2009/08/08 15:57:49 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.73 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -39,6 +39,7 @@
#include "array.h"
extern char *__progname;
+extern char **environ;
/* Default configuration files. */
#define DEFAULT_CFG ".tmux.conf"
@@ -69,6 +70,7 @@ extern char *__progname;
#define COMMAND_LENGTH 2048 /* packed argv size */
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
#define PRINT_LENGTH 512 /* printed error/message size */
+#define ENVIRON_LENGTH 1024 /* environment variable length */
/* Fatal errors. */
#define fatal(msg) log_fatal("%s: %s", __func__, msg);
@@ -302,6 +304,7 @@ enum msgtype {
MSG_SUSPEND,
MSG_UNLOCK,
MSG_WAKEUP,
+ MSG_ENVIRON
};
/*
@@ -356,6 +359,10 @@ struct msg_unlock_data {
char pass[PASS_MAX];
};
+struct msg_environ_data {
+ char var[ENVIRON_LENGTH];
+};
+
/* Mode key commands. */
enum mode_key_cmd {
MODEKEY_NONE,
@@ -765,6 +772,15 @@ 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. */
struct session_alert {
struct winlink *wl;
@@ -792,6 +808,8 @@ struct session {
#define SESSION_UNATTACHED 0x1 /* not attached to any clients */
int flags;
+
+ struct environ environ;
};
ARRAY_DECL(sessions, struct session *);
@@ -894,6 +912,8 @@ struct client {
struct buffer *in;
struct buffer *out;
+ struct environ environ;
+
char *title;
char *cwd;
@@ -992,6 +1012,7 @@ struct cmd_entry {
#define CMD_CANTNEST 0x2
#define CMD_ARG1 0x4
#define CMD_ARG01 0x8
+#define CMD_SENDENVIRON 0x10
int flags;
#define CMD_CHFLAG(flag) \
@@ -1074,6 +1095,7 @@ extern volatile sig_atomic_t sigusr1;
extern volatile sig_atomic_t sigusr2;
extern struct options global_s_options;
extern struct options global_w_options;
+extern struct environ global_environ;
extern char *cfg_file;
extern int server_locked;
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);
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 */
u_char tty_get_acs(struct tty *, u_char);
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_server_info_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_password_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_environment_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_source_file_entry;
@@ -1384,7 +1420,7 @@ int server_start(char *);
int server_msg_dispatch(struct client *);
/* 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_client(
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 *);
int window_index(struct window *, u_int *);
struct window *window_create1(u_int, u_int);
-struct window *window_create(const char *, const char *,
- const char *, const char **, u_int, u_int, u_int, char **);
+struct window *window_create(const char *, const char *, const char *,
+ struct environ *, u_int, u_int, u_int, char **);
void window_destroy(struct window *);
void window_set_active_pane(struct window *, struct window_pane *);
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);
void window_pane_destroy(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);
int window_pane_set_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);
struct session *session_find(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 *);
int session_index(struct session *, u_int *);
struct winlink *session_new(struct session *,
diff --git a/usr.bin/tmux/window.c b/usr.bin/tmux/window.c
index df914543055..6fc13cec4db 100644
--- a/usr.bin/tmux/window.c
+++ b/usr.bin/tmux/window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window.c,v 1.17 2009/07/28 06:48:44 nicm Exp $ */
+/* $OpenBSD: window.c,v 1.18 2009/08/08 21:52:43 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -254,7 +254,7 @@ window_create1(u_int sx, u_int sy)
struct window *
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_pane *wp;
@@ -262,7 +262,7 @@ window_create(const char *name, const char *cmd, const char *cwd,
w = window_create1(sx, sy);
wp = window_add_pane(w, hlimit);
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);
return (NULL);
}
@@ -456,13 +456,16 @@ window_pane_destroy(struct window_pane *wp)
int
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;
- int mode;
- const char **envq, *ptr;
- char *argv0;
- struct timeval tv;
+ struct winsize ws;
+ int mode;
+ char *argv0, **varp, *var;
+ ARRAY_DECL(, char *) varlist;
+ struct environ_entry *envent;
+ const char *ptr;
+ struct timeval tv;
+ u_int i;
if (wp->fd != -1)
close(wp->fd);
@@ -495,10 +498,22 @@ window_pane_spawn(struct window_pane *wp,
case 0:
if (chdir(wp->cwd) != 0)
chdir("/");
- for (envq = envp; *envq != NULL; envq++) {
- if (putenv(xstrdup(*envq)) != 0)
- fatal("putenv failed");
+
+ ARRAY_INIT(&varlist);
+ 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();
log_close();