1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
https://github.com/tmux/tmux/issues/4719
https://github.com/tmux/tmux/commit/f58b8d0d6abb2477b584547a4e72cc362ecbbcdb
https://github.com/tmux/tmux/issues/4719#issuecomment-3623649061 (so it applies to the portable version)
--- a/spawn.c
+++ b/spawn.c
@@ -211,7 +211,8 @@ spawn_pane(struct spawn_context *sc, char **cause)
struct environ *child;
struct environ_entry *ee;
char **argv, *cp, **argvp, *argv0, *cwd, *new_cwd;
- const char *cmd, *tmp;
+ char path[PATH_MAX];
+ const char *cmd, *tmp, *home = find_home(), *actual_cwd = NULL;
int argc;
u_int idx;
struct termios now;
@@ -366,6 +367,16 @@ spawn_pane(struct spawn_context *sc, char **cause)
goto complete;
}
+ /* Store current working directory and change to new one. */
+ if (getcwd(path, sizeof path) != NULL) {
+ if (chdir(new_wp->cwd) == 0)
+ actual_cwd = new_wp->cwd;
+ else if (home != NULL && chdir(home) == 0)
+ actual_cwd = home;
+ else if (chdir("/") == 0)
+ actual_cwd = "/";
+ }
+
/* Fork the new process. */
new_wp->pid = fdforkpty(ptm_fd, &new_wp->fd, new_wp->tty, NULL, &ws);
if (new_wp->pid == -1) {
@@ -383,8 +394,12 @@ spawn_pane(struct spawn_context *sc, char **cause)
/* In the parent process, everything is done now. */
if (new_wp->pid != 0) {
+ if (actual_cwd != NULL &&
+ chdir(path) != 0 &&
+ (home == NULL || chdir(home) != 0))
+ chdir("/");
goto complete;
- }
+ }
#if defined(HAVE_SYSTEMD) && defined(ENABLE_CGROUPS)
/*
@@ -396,18 +411,12 @@ spawn_pane(struct spawn_context *sc, char **cause)
free (*cause);
}
#endif
+
/*
- * Child process. Change to the working directory or home if that
- * fails.
+ * Child process. Set PWD to the working directory.
*/
- if (chdir(new_wp->cwd) == 0)
- environ_set(child, "PWD", 0, "%s", new_wp->cwd);
- else if ((tmp = find_home()) != NULL && chdir(tmp) == 0)
- environ_set(child, "PWD", 0, "%s", tmp);
- else if (chdir("/") == 0)
- environ_set(child, "PWD", 0, "/");
- else
- fatal("chdir failed");
+ if (actual_cwd != NULL)
+ environ_set(child, "PWD", 0, "%s", actual_cwd);
/*
* Update terminal escape characters from the session if available and
|