diff options
author | stefanf <stefanf@FreeBSD.org> | 2008-02-24 16:50:55 +0000 |
---|---|---|
committer | stefanf <stefanf@FreeBSD.org> | 2008-02-24 16:50:55 +0000 |
commit | fe9202bf0f56d3e502455e35dcc4eb1a964fba78 (patch) | |
tree | 86a21737db7034296635cfc37c975e23bd215315 | |
parent | 0d54671a48443b15ac601a80e192bc4c8faed7f9 (diff) | |
download | FreeBSD-src-fe9202bf0f56d3e502455e35dcc4eb1a964fba78.zip FreeBSD-src-fe9202bf0f56d3e502455e35dcc4eb1a964fba78.tar.gz |
Split updatepwd() into two smaller functions. The first one, findpwd(),
computes the new path and the second one, updatepwd(), updates the variables
PWD, OLDPWD and the path used for the pwd builtin according to the new
directory. For a logical directory change, chdir() is now called between
those two functions, no longer causing wrong values to be stored in PWD etc. if
it fails.
PR: 64990, 101316, 120571
-rw-r--r-- | bin/sh/cd.c | 83 |
1 files changed, 45 insertions, 38 deletions
diff --git a/bin/sh/cd.c b/bin/sh/cd.c index d52c9b8..4abe91e 100644 --- a/bin/sh/cd.c +++ b/bin/sh/cd.c @@ -68,7 +68,9 @@ STATIC int cdlogical(char *); STATIC int cdphysical(char *); STATIC int docd(char *, int, int); STATIC char *getcomponent(void); -STATIC int updatepwd(char *); +STATIC char *findcwd(char *); +STATIC void updatepwd(char *); +STATIC char *getpwd2(char *, size_t); STATIC char *curdir = NULL; /* current working directory */ STATIC char *prevdir; /* previous working directory */ @@ -201,10 +203,11 @@ cdlogical(char *dest) } INTOFF; - if (updatepwd(badstat ? NULL : dest) < 0 || chdir(curdir) < 0) { + if ((p = findcwd(badstat ? NULL : dest)) == NULL || chdir(p) < 0) { INTON; return (-1); } + updatepwd(p); INTON; return (0); } @@ -212,12 +215,14 @@ cdlogical(char *dest) STATIC int cdphysical(char *dest) { + char *p; INTOFF; - if (chdir(dest) < 0 || updatepwd(NULL) < 0) { + if (chdir(dest) < 0 || (p = findcwd(NULL)) == NULL) { INTON; return (-1); } + updatepwd(p); INTON; return (0); } @@ -247,38 +252,20 @@ getcomponent(void) } -/* - * Update curdir (the name of the current directory) in response to a - * cd command. We also call hashcd to let the routines in exec.c know - * that the current directory has changed. - */ -STATIC int -updatepwd(char *dir) +STATIC char * +findcwd(char *dir) { char *new; char *p; - hashcd(); /* update command hash table */ - /* * If our argument is NULL, we don't know the current directory * any more because we traversed a symbolic link or something * we couldn't stat(). */ if (dir == NULL || curdir == NULL) { - if (prevdir) - ckfree(prevdir); - INTOFF; - prevdir = curdir; - curdir = NULL; - if (getpwd() == NULL) { - INTON; - return (-1); - } - setvar("PWD", curdir, VEXPORT); - setvar("OLDPWD", prevdir, VEXPORT); - INTON; - return (0); + p = stalloc(PATH_MAX); + return getpwd2(p, PATH_MAX); } cdcomppath = stalloc(strlen(dir) + 1); scopy(dir, cdcomppath); @@ -302,16 +289,25 @@ updatepwd(char *dir) if (new == stackblock()) STPUTC('/', new); STACKSTRNUL(new); - INTOFF; + return stackblock(); +} + +/* + * Update curdir (the name of the current directory) in response to a + * cd command. We also call hashcd to let the routines in exec.c know + * that the current directory has changed. + */ +STATIC void +updatepwd(char *dir) +{ + hashcd(); /* update command hash table */ + if (prevdir) ckfree(prevdir); prevdir = curdir; - curdir = savestr(stackblock()); + curdir = savestr(dir); setvar("PWD", curdir, VEXPORT); setvar("OLDPWD", prevdir, VEXPORT); - INTON; - - return (0); } int @@ -355,17 +351,31 @@ pwdcmd(int argc, char **argv) } /* - * Find out what the current directory is. If we already know the current - * directory, this routine returns immediately. + * Get the current directory and cache the result in curdir. */ char * getpwd(void) { char buf[PATH_MAX]; + char *p; if (curdir) return curdir; - if (getcwd(buf, sizeof(buf)) == NULL) { + + p = getpwd2(buf, sizeof(buf)); + if (p != NULL) + curdir = savestr(p); + + return curdir; +} + +/* + * Return the current directory. + */ +STATIC char * +getpwd2(char *buf, size_t size) +{ + if (getcwd(buf, size) == NULL) { char *pwd = getenv("PWD"); struct stat stdot, stpwd; @@ -373,12 +383,9 @@ getpwd(void) stat(pwd, &stpwd) != -1 && stdot.st_dev == stpwd.st_dev && stdot.st_ino == stpwd.st_ino) { - curdir = savestr(pwd); - return curdir; + return pwd; } return NULL; } - curdir = savestr(buf); - - return curdir; + return buf; } |