diff --git a/NEWS b/NEWS index 4883f6124e5b..0fa8aabfac2b 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,14 @@ For full details, see the git log at: Any uppercase BUG_* names are modernish shell bug IDs. +2020-05-31: + +- Fix a bug in autoloading functions. Directories in the path search list + which should be skipped (e.g. because they don't exist) did not interact + correctly with autoloaded functions, so that a function to autoload was + not always found correctly. + Details: https://github.com/att/ast/issues/1454 + 2020-05-30: - Fix POSIX compliance of 'test'/'[' exit status on error. The command now diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index abaf5ea16808..ffbb19f8215d 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -17,4 +17,4 @@ * David Korn * * * ***********************************************************************/ -#define SH_RELEASE "93u+m 2020-05-30" +#define SH_RELEASE "93u+m 2020-05-31" diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c index 0eca9fc0e857..157fb4312ba3 100644 --- a/src/cmd/ksh93/sh/path.c +++ b/src/cmd/ksh93/sh/path.c @@ -508,7 +508,8 @@ static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp, { register int fd= -1; struct stat statb; - Pathcomp_t *oldpp; + Pathcomp_t *nextpp; + if(!pp && !shp->pathlist) path_init(shp); if(!fun && strchr(name,'/')) @@ -516,12 +517,15 @@ static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp, if(sh_isoption(SH_RESTRICTED)) errormsg(SH_DICT,ERROR_exit(1),e_restricted,name); } + + nextpp = pp; do { - pp = path_nextcomp(shp,oldpp=pp,name,0); - while(oldpp && (oldpp->flags&PATH_SKIP)) - oldpp = oldpp->next; - if(fun && (!oldpp || !(oldpp->flags&PATH_FPATH))) + pp = nextpp; + nextpp = path_nextcomp(shp,pp,name,0); + if(pp && (pp->flags&PATH_SKIP)) + continue; + if(fun && (!pp || !(pp->flags&PATH_FPATH))) continue; if((fd = sh_open(path_relative(shp,stakptr(PATH_OFFSET)),O_RDONLY,0)) >= 0) { @@ -533,7 +537,8 @@ static int path_opentype(Shell_t *shp,const char *name, register Pathcomp_t *pp, } } } - while( fd<0 && pp); + while(fd<0 && nextpp); + if(fd>=0 && (fd = sh_iomovefd(fd)) > 0) { fcntl(fd,F_SETFD,FD_CLOEXEC); diff --git a/src/cmd/ksh93/tests/functions.sh b/src/cmd/ksh93/tests/functions.sh index f6f322e8dfcd..06e94e5c0070 100755 --- a/src/cmd/ksh93/tests/functions.sh +++ b/src/cmd/ksh93/tests/functions.sh @@ -1213,4 +1213,33 @@ rc=$? exp=$((256+$(kill -l TERM) )) [[ $rc == "$exp" ]] || err_exit "expected exitval $exp got $rc" +# ====== +# Verify that directories in the path search list which should be skipped +# (e.g. because they don't exist) interact correctly with autoloaded functions. +# See https://github.com/att/ast/issues/1454 +expect="Func cd called with |$tmp/usr| +$tmp/usr" +actual=$( + set -- wrong args passed + mkdir -p "$tmp/usr/bin" + print 'echo "wrong file executed ($*)"' >"$tmp/usr/bin/cd" + prefix=$tmp/ksh.$$ + + FPATH=$prefix/bad:$prefix/functions + mkdir -p "$prefix/functions" + print 'function cd { echo "Func cd called with |$*|"; command cd "$@"; }' >"$prefix/functions/cd" + typeset -fu cd + + PATH=$tmp/arglebargle:$PATH:$tmp/usr/bin:$tmp/bin + cd "$tmp/usr" + pwd +) +actual_status=$? +expect_status=0 +[[ $actual_status == "$expect_status" ]] || + err_exit "autoload function skipped dir test wrong status (expected $expect_status, got $actual_status)" +[[ $actual == "$expect" ]] || + err_exit "autoload function skipped dir test wrong output (expected $(printf %q "$expect"), got $(printf %q "$actual"))" + +# ====== exit $((Errors<125?Errors:125))