1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Make PATH properly survive a shared-state ${ comsub; }

Reproducer:

$ ksh -c 'v=${ PATH=/dev/null; }; echo $PATH; whence ls'
/dev/null
/bin/ls

The PATH=/dev/null assignment should survive the shared-state
command substitution, and does, yet 'ls' is still found.
The variable became inconsistent with the internal pathlist.

This bugfix is from the 93v- beta.

src/cmd/ksh93/sh/subshell.c: sh_subshell():
- Do not save and restore pathlist for a subshare.
- A few other subshell tweaks from 93v- that made sense:
  . reset shp->subdup (bitmask for dups of 1) after saving it
  . use e_dot instead of "." for consistency
  . retry close(1) if it was interrupted

src/cmd/ksh93/tests/path.sh:
- Add test for this bug.
This commit is contained in:
Martijn Dekker 2021-02-23 21:35:26 +00:00
parent e3882fe71b
commit caf7ab6c71
2 changed files with 26 additions and 7 deletions

View file

@ -549,14 +549,14 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
sp->options = shp->options; sp->options = shp->options;
sp->jobs = job_subsave(); sp->jobs = job_subsave();
sp->subdup = shp->subdup; sp->subdup = shp->subdup;
shp->subdup = 0;
/* make sure initialization has occurred */ /* make sure initialization has occurred */
if(!shp->pathlist) if(!shp->pathlist)
{ {
shp->pathinit = 1; shp->pathinit = 1;
path_get(shp,"."); path_get(shp,e_dot);
shp->pathinit = 0; shp->pathinit = 0;
} }
sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
#if _lib_fchdir #if _lib_fchdir
sp->pwdfd = -1; sp->pwdfd = -1;
#endif /* _lib_fchdir */ #endif /* _lib_fchdir */
@ -570,6 +570,8 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
sp->subshare = shp->subshare; sp->subshare = shp->subshare;
sp->comsub = shp->comsub; sp->comsub = shp->comsub;
shp->subshare = comsub==2; shp->subshare = comsub==2;
if(!shp->subshare)
sp->pathlist = path_dup((Pathcomp_t*)shp->pathlist);
if(comsub) if(comsub)
{ {
shp->comsub = comsub; shp->comsub = comsub;
@ -590,7 +592,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
} }
if(sp->pwdfd<0) if(sp->pwdfd<0)
{ {
int n = open(".",O_SEARCH); int n = open(e_dot,O_SEARCH);
if(n>=0) if(n>=0)
{ {
sp->pwdfd = n; sp->pwdfd = n;
@ -759,11 +761,16 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
} }
sfset(iop,SF_READ,1); sfset(iop,SF_READ,1);
} }
sfswap(sp->saveout,sfstdout); if(sp->saveout)
sfswap(sp->saveout,sfstdout);
else
sfstdout = &_Sfstdout;
/* check if standard output was preserved */ /* check if standard output was preserved */
if(sp->tmpfd>=0) if(sp->tmpfd>=0)
{ {
close(1); int err=errno;
while(close(1)<0 && errno==EINTR)
errno = err;
if (fcntl(sp->tmpfd,F_DUPFD,1) != 1) if (fcntl(sp->tmpfd,F_DUPFD,1) != 1)
{ {
saveerrno = errno; saveerrno = errno;
@ -773,8 +780,11 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
} }
shp->fdstatus[1] = sp->fdstatus; shp->fdstatus[1] = sp->fdstatus;
} }
path_delete((Pathcomp_t*)shp->pathlist); if(!shp->subshare)
shp->pathlist = (void*)sp->pathlist; {
path_delete((Pathcomp_t*)shp->pathlist);
shp->pathlist = (void*)sp->pathlist;
}
job_subrestore(sp->jobs); job_subrestore(sp->jobs);
shp->curenv = shp->jobenv = savecurenv; shp->curenv = shp->jobenv = savecurenv;
job.curpgid = savejobpgid; job.curpgid = savejobpgid;

View file

@ -731,6 +731,15 @@ got=$({ FPATH=$tmp/fun.$$ "$SHELL" -c self; } 2>&1)
(((e = $?) == 126)) || err_exit 'Function autoload recursion loop:' \ (((e = $?) == 126)) || err_exit 'Function autoload recursion loop:' \
"got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got")" "got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got")"
# ======
# If a shared-state ${ command substitution; } changed the value of $PATH, the variable
# would change but the internal pathlist would not, making path searches inconsistent.
savePATH=$PATH
got=${ PATH=/dev/null; }
got=$(whence ls)
PATH=$savePATH
[[ -z $got ]] || err_exit "PATH search inconsistent after changing PATH in subshare (got $(printf %q "$got"))"
# ====== # ======
exit $((Errors<125?Errors:125)) exit $((Errors<125?Errors:125))