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