Package: tmux
Version: 2.8-1
Severity: normal

Dear Maintainer,

tmux 2.8 contains a change in behaviour compared to previous versions when
the current directory differs from the contents of the PWD environment
variable:

Consider running the following at a shell prompt in a tmux session:

 cd /
 PWD=/etc tmux split-window

With tmux 2.3 (Debian 9) the shell in the new split ends up with its
current directory set to /, whereas with tmux 2.8 the shell in the new
split ends up with its current directory set to /etc.

Unfortunately, this breaks processes (such as openembedded's terminal.py)
which change the current directory but don't change PWD.

I reported the problem upstream at https://github.com/tmux/tmux/issues/1549
and it has been fixed, but I'm worried that there won't be a new release
prior to the Buster freeze.

Please can you consider applying the attached patch taken from
https://github.com/tmux/tmux/commit/3a7b9d57355c4b2b521f05049a5c6f5eb2939b5d
?

Thanks.

Mike.


-- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.18.0-2-amd64 (SMP w/8 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_GB:en (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages tmux depends on:
ii  libc6           2.27-8
ii  libevent-2.1-6  2.1.8-stable-4
ii  libtinfo6       6.1+20181013-1
ii  libutempter0    1.1.6-3

tmux recommends no packages.

tmux suggests no packages.

-- no debconf information
>From 3a7b9d57355c4b2b521f05049a5c6f5eb2939b5d Mon Sep 17 00:00:00 2001
From: nicm <nicm>
Date: Thu, 22 Nov 2018 10:36:40 +0000
Subject: [PATCH] Do not use PWD unless it actually matches the real working
 directory.

---
 client.c |  6 ++----
 tmux.c   | 29 ++++++++++++++++++++++++++---
 tmux.h   |  1 +
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/client.c b/client.c
index 7e8bd734..1054ccae 100644
--- a/client.c
+++ b/client.c
@@ -222,7 +222,7 @@ client_main(struct event_base *base, int argc, char **argv, 
int flags)
        const char              *ttynam, *cwd;
        pid_t                    ppid;
        enum msgtype             msg;
-       char                    *cause, path[PATH_MAX];
+       char                    *cause;
        struct termios           tio, saved_tio;
        size_t                   size;
 
@@ -277,9 +277,7 @@ client_main(struct event_base *base, int argc, char **argv, 
int flags)
        client_peer = proc_add_peer(client_proc, fd, client_dispatch, NULL);
 
        /* Save these before pledge(). */
-       if ((cwd = getenv("PWD")) == NULL &&
-           (cwd = getcwd(path, sizeof path)) == NULL &&
-           (cwd = find_home()) == NULL)
+       if ((cwd = find_cwd()) == NULL && (cwd = find_home()) == NULL)
                cwd = "/";
        if ((ttynam = ttyname(STDIN_FILENO)) == NULL)
                ttynam = "";
diff --git a/tmux.c b/tmux.c
index dd986783..d7f8ab53 100644
--- a/tmux.c
+++ b/tmux.c
@@ -166,6 +166,31 @@ setblocking(int fd, int state)
        }
 }
 
+const char *
+find_cwd(void)
+{
+       char             resolved1[PATH_MAX], resolved2[PATH_MAX];
+       static char      cwd[PATH_MAX];
+       const char      *pwd;
+
+       if (getcwd(cwd, sizeof cwd) == NULL)
+               return (NULL);
+       if ((pwd = getenv("PWD")) == NULL || *pwd == '\0')
+               return (cwd);
+
+       /*
+        * We want to use PWD so that symbolic links are maintained,
+        * but only if it matches the actual working directory.
+        */
+       if (realpath(pwd, resolved1) == NULL)
+               return (cwd);
+       if (realpath(cwd, resolved2) == NULL)
+               return (cwd);
+       if (strcmp(resolved1, resolved2) != 0)
+               return (cwd);
+       return (pwd);
+}
+
 const char *
 find_home(void)
 {
@@ -191,7 +216,6 @@ int
 main(int argc, char **argv)
 {
        char                                    *path, *label, *cause, **var;
-       char                                     tmp[PATH_MAX];
        const char                              *s, *shell, *cwd;
        int                                      opt, flags, keys;
        const struct options_table_entry        *oe;
@@ -293,8 +317,7 @@ main(int argc, char **argv)
        global_environ = environ_create();
        for (var = environ; *var != NULL; var++)
                environ_put(global_environ, *var);
-       if ((cwd = getenv("PWD")) == NULL &&
-           (cwd = getcwd(tmp, sizeof tmp)) != NULL)
+       if ((cwd = find_cwd()) != NULL)
                environ_set(global_environ, "PWD", "%s", cwd);
 
        global_options = options_create(NULL);
diff --git a/tmux.h b/tmux.h
index 8b41a785..b76d15e8 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1506,6 +1506,7 @@ extern int                 ptm_fd;
 extern const char      *shell_command;
 int             areshell(const char *);
 void            setblocking(int, int);
+const char     *find_cwd(void);
 const char     *find_home(void);
 
 /* proc.c */
-- 
2.19.2

Reply via email to