sh: On startup of the shell, use PWD from the environment if it is valid.

Unset PWD if it is incorrect and no value for it can be determined.
This preserves the logical current directory across shell invocations.

Example (assuming /home is a symlink):
$ cd
$ pwd
/home/foo
$ sh
$ pwd
/home/foo

Formerly the second pwd would show the physical path (symlinks resolved).
This commit is contained in:
Jilles Tjoelker 2010-04-17 14:35:46 +00:00
parent 37f144eb5d
commit 8eac1f9477
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=206759
4 changed files with 48 additions and 10 deletions

View File

@ -70,6 +70,7 @@ STATIC int docd(char *, int, int);
STATIC char *getcomponent(void);
STATIC char *findcwd(char *);
STATIC void updatepwd(char *);
STATIC char *getpwd(void);
STATIC char *getpwd2(void);
STATIC char *curdir = NULL; /* current working directory */
@ -351,7 +352,7 @@ pwdcmd(int argc, char **argv)
/*
* Get the current directory and cache the result in curdir.
*/
char *
STATIC char *
getpwd(void)
{
char *p;
@ -374,7 +375,6 @@ getpwd(void)
STATIC char *
getpwd2(void)
{
struct stat stdot, stpwd;
char *pwd;
int i;
@ -387,12 +387,29 @@ getpwd2(void)
break;
}
pwd = getenv("PWD");
return NULL;
}
/*
* Initialize PWD in a new shell.
* If the shell is interactive, we need to warn if this fails.
*/
void
pwd_init(int warn)
{
char *pwd;
struct stat stdot, stpwd;
pwd = lookupvar("PWD");
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
stat(pwd, &stpwd) != -1 &&
stdot.st_dev == stpwd.st_dev &&
stdot.st_ino == stpwd.st_ino) {
return pwd;
if (curdir)
ckfree(curdir);
curdir = savestr(pwd);
}
return NULL;
if (getpwd() == NULL && warn)
out2fmt_flush("sh: cannot determine working directory\n");
setvar("PWD", curdir, VEXPORT);
}

View File

@ -29,6 +29,6 @@
* $FreeBSD$
*/
char *getpwd(void);
void pwd_init(int);
int cdcmd (int, char **);
int pwdcmd(int, char **);

View File

@ -153,10 +153,7 @@ main(int argc, char *argv[])
init();
setstackmark(&smark);
procargs(argc, argv);
if (getpwd() == NULL && iflag)
out2fmt_flush("sh: cannot determine working directory\n");
if (getpwd() != NULL)
setvar ("PWD", getpwd(), VEXPORT);
pwd_init(iflag);
if (iflag)
chkmail(1);
if (argv[0] && argv[0][0] == '-') {

View File

@ -0,0 +1,24 @@
# $FreeBSD$
# Check that PWD is exported and accepted from the environment.
set -e
T=$(mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX)
trap 'rm -rf $T' 0
cd -P $T
TP=$(pwd)
mkdir test1
ln -s test1 link
cd link
[ "$PWD" = "$TP/link" ]
[ "$(pwd)" = "$TP/link" ]
[ "$(pwd -P)" = "$TP/test1" ]
[ "$(sh -c pwd)" = "$TP/link" ]
[ "$(sh -c pwd\ -P)" = "$TP/test1" ]
cd ..
[ "$(pwd)" = "$TP" ]
cd -P link
[ "$PWD" = "$TP/test1" ]
[ "$(pwd)" = "$TP/test1" ]
[ "$(pwd -P)" = "$TP/test1" ]
[ "$(sh -c pwd)" = "$TP/test1" ]
[ "$(sh -c pwd\ -P)" = "$TP/test1" ]