about summary refs log tree commit diff
path: root/Src/builtin.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/builtin.c')
-rw-r--r--Src/builtin.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/Src/builtin.c b/Src/builtin.c
index ae608cc39..e159c1e85 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -572,8 +572,28 @@ bin_pwd(char *name, char **argv, char *ops, int func)
     if (ops['r'] || ops['P'] || (isset(CHASELINKS) && !ops['L']))
 	printf("%s\n", zgetcwd());
     else {
-	zputs(pwd, stdout);
-	putchar('\n');
+	struct stat stdot, stpwd;
+	char *tmppwd;
+	/*
+	 * We could print nothing and return status 1 if we can't
+	 * stat ., but that's incompatible with both ksh and what
+	 * we used to do.
+	 */
+	if (stat(".", &stdot) < 0 ||
+	    stat(pwd, &stpwd) >= 0 && stpwd.st_ino == stdot.st_ino) {
+	    zputs(pwd, stdout);
+	    putchar('\n');
+	} else {
+	    /*
+	     * The directory has changed without us noticing it.  We
+	     * need to change pwd, since directory changing commands
+	     * are liable to fail otherwise.
+	     */
+	    zsfree(pwd);
+	    printf("%s\n", tmppwd = zgetcwd());
+	    pwd = metafy(tmppwd, -1, META_DUP);
+	    set_pwd_env();
+	}
     }
     return 0;
 }