Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: 3.1.5 - PWD and OLDPWD aren't updated before chpwd runs



For ages I've had this csh compatibility function lurking in my .zshrc:

chpwd() { cwd=$PWD }

I don't know when this stopped working, but it does not work in 3.1.5.  My
guess is that making PWD non-special has broken it; $PWD has not yet been
changed when chpwd is invoked, so $cwd is always the same as $OLDPWD.

The code in cd_new_pwd() in builtin.c does some irrelevent replenv() foo on
PWD and OLDPWD just before chpwd() is called, but bin_cd() doesn't call
set_pwd_env() to update the actual PWD param until quite some while after
that, so there's no way to see the new value.

I think the call to set_pwd_env() should replace the replenv() stuff in
cd_new_pwd(), and not happen where it now does in bin_cd().  That change
corresponds exactly to the 3.0.5 behavior, except for the specialness of
PWD and OLDPWD.

Note that it makes no difference that this happens before the actual call
to chdir(), because zsh ignores any chdir() failure regardless.  This is
probably not a good thing, but it only fails in a race condition where the
directory is removed while zsh is in the process of changing to it.

The following patch shuffles the set_pwd_env() call accordingly.

Index: Src/builtin.c
===================================================================
--- builtin.c	1998/10/31 09:11:41	1.5
+++ builtin.c	1998/11/08 06:13:18
@@ -618,6 +618,8 @@
 {
     Param pm;
 
+    /* update the PWD and OLDPWD shell parameters */
+
     pm = (Param) paramtab->getnode(paramtab, "PWD");
     if (pm && PM_TYPE(pm->flags) != PM_SCALAR) {
 	pm->flags &= ~PM_READONLY;
@@ -704,7 +706,6 @@
 	    chdir(unmeta(pwd));
 	}
     }
-    set_pwd_env();
     return 0;
 }
 
@@ -981,13 +982,8 @@
     zsfree(oldpwd);
     oldpwd = pwd;
     pwd = new_pwd;
-    /* update the PWD and OLDPWD shell parameters */
-    if ((pm = (Param) paramtab->getnode(paramtab, "PWD")) &&
-	(pm->flags & PM_EXPORTED) && pm->env)
-	pm->env = replenv(pm->env, pwd);
-    if ((pm = (Param) paramtab->getnode(paramtab, "OLDPWD")) &&
-	(pm->flags & PM_EXPORTED) && pm->env)
-	pm->env = replenv(pm->env, oldpwd);
+    set_pwd_env();
+
     if (unset(PUSHDSILENT) && func != BIN_CD && isset(INTERACTIVE))
 	printdirstack();
     else if (doprintdir) {

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com



Messages sorted by: Reverse Date, Date, Thread, Author