This changes the way environment variables are handled:
- a new session populates the local environment from the current
  client/session/server process (in case the config creates a session)
- the global environment is empty by default
- variables in the global environment override variables in the local
  environment

---

I'm not sure what all the existing use cases are and which ones may
break from this change.

One thing I can think of is the config file parsing wrt to environment
variable expansion. I guess we could use the environment variables the
server inherited when it was started?

---
 cfg.c                |    2 +-
 cmd-command-prompt.c |    3 ++-
 cmd-confirm-before.c |    3 ++-
 cmd-if-shell.c       |    3 ++-
 cmd-new-session.c    |   15 ++++++++++-----
 cmd-respawn-pane.c   |    2 +-
 cmd-respawn-window.c |    2 +-
 cmd-split-window.c   |    2 +-
 cmd-string.c         |   30 +++++++++++++++++-------------
 control.c            |    3 ++-
 job.c                |    2 +-
 session.c            |    2 +-
 tmux.c               |    4 ----
 tmux.h               |    4 ++--
 window-choose.c      |    3 ++-
 15 files changed, 45 insertions(+), 35 deletions(-)

diff --git a/cfg.c b/cfg.c
index 1153de6..34a49e2 100644
--- a/cfg.c
+++ b/cfg.c
@@ -91,7 +91,7 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
                }
 
                /* Parse and run the command. */
-               if (cmd_string_parse(buf, &cmdlist, path, n, &cause1) != 0) {
+               if (cmd_string_parse(NULL, buf, &cmdlist, path, n, &cause1) != 
0) {
                        free(copy);
                        if (cause1 == NULL)
                                continue;
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 759d578..8c1393c 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -172,7 +172,8 @@ cmd_command_prompt_callback(void *data, const char *s)
                return (1);
        }
 
-       if (cmd_string_parse(new_template, &cmdlist, NULL, 0, &cause) != 0) {
+       if (cmd_string_parse(&c->session->environ, new_template, &cmdlist,
+               NULL, 0, &cause) != 0) {
                if (cause != NULL) {
                        *cause = toupper((u_char) *cause);
                        status_message_set(c, "%s", cause);
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index 9266721..691810f 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -115,7 +115,8 @@ cmd_confirm_before_callback(void *data, const char *s)
        if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
                return (0);
 
-       if (cmd_string_parse(cdata->cmd, &cmdlist, NULL, 0, &cause) != 0) {
+       if (cmd_string_parse(&c->session->environ, cdata->cmd, &cmdlist, NULL,
+               0, &cause) != 0) {
                if (cause != NULL) {
                        cmdq_error(c->cmdq, "%s", cause);
                        free(cause);
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index 9b6dcf3..e79c0c4 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -123,7 +123,8 @@ cmd_if_shell_callback(struct job *job)
        if (cmd == NULL)
                return;
 
-       if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
+       if (cmd_string_parse(&cmdq->client->session->environ, cmd, &cmdlist,
+               NULL, 0, &cause) != 0) {
                if (cause != NULL) {
                        cmdq_error(cmdq, "%s", cause);
                        free(cause);
diff --git a/cmd-new-session.c b/cmd-new-session.c
index ad083a4..b0a5bd2 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -54,8 +54,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
        struct window           *w;
        struct environ           env;
        struct termios           tio, *tiop;
-       const char              *newname, *target, *update, *errstr, *template;
-       char                    *cmd, *cause, *cp;
+       const char              *newname, *target, *errstr, *template;
+       char                    *cmd, *cause, *cp, **var;
        int                      detached, already_attached, idx, cwd, fd = -1;
        u_int                    sx, sy;
        struct format_tree      *ft;
@@ -188,9 +188,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 
        /* Construct the environment. */
        environ_init(&env);
-       update = options_get_string(&global_s_options, "update-environment");
-       if (c != NULL)
-               environ_update(update, &c->environ, &env);
+       if (c != NULL && c->session == NULL)
+               environ_copy(&c->environ, &env);
+       else if ((c0 = cmd_current_client(cmdq)) != NULL)
+               environ_copy(&c0->environ, &env);
+       else {
+               for (var = environ; *var != NULL; var++)
+                       environ_put(&env, *var);
+       }
 
        /* Create the new session. */
        idx = -1 - options_get_number(&global_s_options, "base-index");
diff --git a/cmd-respawn-pane.c b/cmd-respawn-pane.c
index bcde275..f92fbe6 100644
--- a/cmd-respawn-pane.c
+++ b/cmd-respawn-pane.c
@@ -65,8 +65,8 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
        }
 
        environ_init(&env);
-       environ_copy(&global_environ, &env);
        environ_copy(&s->environ, &env);
+       environ_copy(&global_environ, &env);
        server_fill_environ(s, &env);
 
        window_pane_reset_mode(wp);
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index e6d913c..3f0d7be 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -65,8 +65,8 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
        }
 
        environ_init(&env);
-       environ_copy(&global_environ, &env);
        environ_copy(&s->environ, &env);
+       environ_copy(&global_environ, &env);
        server_fill_environ(s, &env);
 
        wp = TAILQ_FIRST(&w->panes);
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 4bb069f..31b5e09 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -75,8 +75,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
        server_unzoom_window(w);
 
        environ_init(&env);
-       environ_copy(&global_environ, &env);
        environ_copy(&s->environ, &env);
+       environ_copy(&global_environ, &env);
        server_fill_environ(s, &env);
 
        if (args->argc == 0)
diff --git a/cmd-string.c b/cmd-string.c
index e793ea0..98077d5 100644
--- a/cmd-string.c
+++ b/cmd-string.c
@@ -34,9 +34,9 @@
 int     cmd_string_getc(const char *, size_t *);
 void    cmd_string_ungetc(size_t *);
 void    cmd_string_copy(char **, char *, size_t *);
-char   *cmd_string_string(const char *, size_t *, char, int);
-char   *cmd_string_variable(const char *, size_t *);
-char   *cmd_string_expand_tilde(const char *, size_t *);
+char   *cmd_string_string(struct environ *, const char *, size_t *, char, int);
+char   *cmd_string_variable(struct environ *, const char *, size_t *);
+char   *cmd_string_expand_tilde(struct environ *, const char *, size_t *);
 
 int
 cmd_string_getc(const char *s, size_t *p)
@@ -59,8 +59,8 @@ cmd_string_ungetc(size_t *p)
  * string, or NULL for empty command.
  */
 int
-cmd_string_parse(const char *s, struct cmd_list **cmdlist, const char *file,
-    u_int line, char **cause)
+cmd_string_parse(struct environ* environ, const char *s,
+    struct cmd_list **cmdlist, const char *file, u_int line, char **cause)
 {
        size_t          p;
        int             ch, i, argc, rval;
@@ -84,17 +84,17 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, 
const char *file,
                ch = cmd_string_getc(s, &p);
                switch (ch) {
                case '\'':
-                       if ((t = cmd_string_string(s, &p, '\'', 0)) == NULL)
+                       if ((t = cmd_string_string(environ, s, &p, '\'', 0)) == 
NULL)
                                goto error;
                        cmd_string_copy(&buf, t, &len);
                        break;
                case '"':
-                       if ((t = cmd_string_string(s, &p, '"', 1)) == NULL)
+                       if ((t = cmd_string_string(environ, s, &p, '"', 1)) == 
NULL)
                                goto error;
                        cmd_string_copy(&buf, t, &len);
                        break;
                case '$':
-                       if ((t = cmd_string_variable(s, &p)) == NULL)
+                       if ((t = cmd_string_variable(environ, s, &p)) == NULL)
                                goto error;
                        cmd_string_copy(&buf, t, &len);
                        break;
@@ -140,7 +140,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, 
const char *file,
                        goto out;
                case '~':
                        if (buf == NULL) {
-                               t = cmd_string_expand_tilde(s, &p);
+                               t = cmd_string_expand_tilde(environ, s, &p);
                                if (t == NULL)
                                        goto error;
                                cmd_string_copy(&buf, t, &len);
@@ -187,7 +187,7 @@ cmd_string_copy(char **dst, char *src, size_t *len)
 }
 
 char *
-cmd_string_string(const char *s, size_t *p, char endch, int esc)
+cmd_string_string(struct environ *environ, const char *s, size_t *p, char 
endch, int esc)
 {
        int     ch;
        char   *buf, *t;
@@ -223,7 +223,7 @@ cmd_string_string(const char *s, size_t *p, char endch, int 
esc)
                case '$':
                        if (!esc)
                                break;
-                       if ((t = cmd_string_variable(s, p)) == NULL)
+                       if ((t = cmd_string_variable(environ, s, p)) == NULL)
                                goto error;
                        cmd_string_copy(&buf, t, &len);
                        continue;
@@ -245,7 +245,7 @@ error:
 }
 
 char *
-cmd_string_variable(const char *s, size_t *p)
+cmd_string_variable(struct environ *environ, const char *s, size_t *p)
 {
        int                     ch, fch;
        char                   *buf, *t;
@@ -303,6 +303,8 @@ cmd_string_variable(const char *s, size_t *p)
        buf[len] = '\0';
 
        envent = environ_find(&global_environ, buf);
+       if (envent == NULL && environ)
+               envent = environ_find(environ, buf);
        free(buf);
        if (envent == NULL)
                return (xstrdup(""));
@@ -314,7 +316,7 @@ error:
 }
 
 char *
-cmd_string_expand_tilde(const char *s, size_t *p)
+cmd_string_expand_tilde(struct environ *environ, const char *s, size_t *p)
 {
        struct passwd           *pw;
        struct environ_entry    *envent;
@@ -326,6 +328,8 @@ cmd_string_expand_tilde(const char *s, size_t *p)
        last = cmd_string_getc(s, p);
        if (last == EOF || last == '/' || last == ' '|| last == '\t') {
                envent = environ_find(&global_environ, "HOME");
+               if (envent == NULL && environ)
+                       envent = environ_find(environ, "HOME");
                if (envent != NULL && *envent->value != '\0')
                        home = envent->value;
                else if ((pw = getpwuid(getuid())) != NULL)
diff --git a/control.c b/control.c
index 52fdb52..4b5df7b 100644
--- a/control.c
+++ b/control.c
@@ -69,7 +69,8 @@ control_callback(struct client *c, int closed, unused void 
*data)
                        break;
                }
 
-               if (cmd_string_parse(line, &cmdlist, NULL, 0, &cause) != 0) {
+               if (cmd_string_parse(&c->session->environ, line, &cmdlist,
+                       NULL, 0, &cause) != 0) {
                        c->cmdq->time = time(NULL);
                        c->cmdq->number++;
 
diff --git a/job.c b/job.c
index d7bd852..494d901 100644
--- a/job.c
+++ b/job.c
@@ -51,9 +51,9 @@ job_run(const char *cmd, struct session *s,
                return (NULL);
 
        environ_init(&env);
-       environ_copy(&global_environ, &env);
        if (s != NULL)
                environ_copy(&s->environ, &env);
+       environ_copy(&global_environ, &env);
        server_fill_environ(s, &env);
 
        switch (pid = fork()) {
diff --git a/session.c b/session.c
index 66a52bc..eb51595 100644
--- a/session.c
+++ b/session.c
@@ -240,8 +240,8 @@ session_new(struct session *s, const char *name, const char 
*cmd, int cwd,
        }
 
        environ_init(&env);
-       environ_copy(&global_environ, &env);
        environ_copy(&s->environ, &env);
+       environ_copy(&global_environ, &env);
        server_fill_environ(s, &env);
 
        shell = options_get_string(&s->options, "default-shell");
diff --git a/tmux.c b/tmux.c
index 1e6edd9..90a97be 100644
--- a/tmux.c
+++ b/tmux.c
@@ -289,10 +289,6 @@ main(int argc, char **argv)
        }
 
        environ_init(&global_environ);
-       for (var = environ; *var != NULL; var++)
-               environ_put(&global_environ, *var);
-       if (getcwd(tmp, sizeof tmp) != NULL)
-               environ_set(&global_environ, "PWD", tmp);
 
        options_init(&global_options, NULL);
        options_table_populate_tree(server_options_table, &global_options);
diff --git a/tmux.h b/tmux.h
index 84ad164..deff813 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1841,8 +1841,8 @@ int                cmdq_continue(struct cmd_q *);
 void            cmdq_flush(struct cmd_q *);
 
 /* cmd-string.c */
-int    cmd_string_parse(const char *, struct cmd_list **, const char *,
-           u_int, char **);
+int    cmd_string_parse(struct environ *, const char *, struct cmd_list **,
+           const char *, u_int, char **);
 
 /* client.c */
 int    client_main(int, char **, int);
diff --git a/window-choose.c b/window-choose.c
index 572581a..bc10b7e 100644
--- a/window-choose.c
+++ b/window-choose.c
@@ -228,7 +228,8 @@ window_choose_data_run(struct window_choose_data *cdata)
        if (cdata->command == NULL)
                return;
 
-       if (cmd_string_parse(cdata->command, &cmdlist, NULL, 0, &cause) != 0) {
+       if (cmd_string_parse(&cdata->start_session->environ, cdata->command,
+               &cmdlist, NULL, 0, &cause) != 0) {
                if (cause != NULL) {
                        *cause = toupper((u_char) *cause);
                        status_message_set(cdata->start_client, "%s", cause);
-- 
1.7.10.4


------------------------------------------------------------------------------
Sponsored by Intel(R) XDK 
Develop, test and display web and hybrid apps with a single code base.
Download it for free now!
http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to