diff options
author | cracauer <cracauer@FreeBSD.org> | 1999-12-20 13:42:59 +0000 |
---|---|---|
committer | cracauer <cracauer@FreeBSD.org> | 1999-12-20 13:42:59 +0000 |
commit | 6d35bd2d53c6a7ddb80ecae5e0148a58c23b73e6 (patch) | |
tree | 82531f32187fe6780dd6491e283a806a71a99d0d /bin/sh | |
parent | b4682bef656f35db2ebb8df88d935e6042aa97f0 (diff) | |
download | FreeBSD-src-6d35bd2d53c6a7ddb80ecae5e0148a58c23b73e6.zip FreeBSD-src-6d35bd2d53c6a7ddb80ecae5e0148a58c23b73e6.tar.gz |
Fix command hash handling on
PATH=... command
Noted by and fix works for Marcel Moolenaar <marcel@scc.nl>
Diffstat (limited to 'bin/sh')
-rw-r--r-- | bin/sh/eval.c | 28 | ||||
-rw-r--r-- | bin/sh/exec.c | 3 | ||||
-rw-r--r-- | bin/sh/exec.h | 1 |
3 files changed, 29 insertions, 3 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 4f20822..33dec0e 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -612,12 +612,14 @@ evalcommand(cmd, flags, backcmd) volatile int e; char *lastarg; int realstatus; + int do_clearcmdentry; #if __GNUC__ /* Avoid longjmp clobbering */ (void) &argv; (void) &argc; (void) &lastarg; (void) &flags; + (void) &do_clearcmdentry; #endif /* First expand the arguments. */ @@ -626,6 +628,7 @@ evalcommand(cmd, flags, backcmd) arglist.lastp = &arglist.list; varlist.lastp = &varlist.list; varflag = 1; + do_clearcmdentry = 0; oexitstatus = exitstatus; exitstatus = 0; for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { @@ -688,8 +691,29 @@ evalcommand(cmd, flags, backcmd) * is present */ for (sp = varlist.list ; sp ; sp = sp->next) - if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) + if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) { path = sp->text + sizeof(PATH) - 1; + /* + * On `PATH=... command`, we need to make + * sure that the command isn't using the + * non-updated hash table of the outer PATH + * setting and we need to make sure that + * the hash table isn't filled with items + * from the temporary setting. + * + * It would be better to forbit using and + * updating the table while this command + * runs, by the command finding mechanism + * is heavily integrated with hash handling, + * so we just delete the hash before and after + * the command runs. Partly deleting like + * changepatch() does doesn't seem worth the + * bookinging effort, since most such runs add + * diretories in front of the new PATH. + */ + clearcmdentry(0); + do_clearcmdentry = 1; + } find_command(argv[0], &cmdentry, 1, path); if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ @@ -887,6 +911,8 @@ parent: /* parent process gets here (if we forked) */ out: if (lastarg) setvar("_", lastarg, 0); + if (do_clearcmdentry) + clearcmdentry(0); popstackmark(&smark); } diff --git a/bin/sh/exec.c b/bin/sh/exec.c index 3bfdba5..67a858b 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -104,7 +104,6 @@ STATIC void tryexec __P((char *, char **, char **)); STATIC void execinterp __P((char **, char **)); #endif STATIC void printentry __P((struct tblentry *, int)); -STATIC void clearcmdentry __P((int)); STATIC struct tblentry *cmdlookup __P((char *, int)); STATIC void delete_cmd_entry __P((void)); @@ -640,7 +639,7 @@ changepath(newval) * PATH which has changed. */ -STATIC void +void clearcmdentry(firstchange) int firstchange; { diff --git a/bin/sh/exec.h b/bin/sh/exec.h index 5b8e5e4..bb593f0 100644 --- a/bin/sh/exec.h +++ b/bin/sh/exec.h @@ -69,3 +69,4 @@ void addcmdentry __P((char *, struct cmdentry *)); void defun __P((char *, union node *)); int unsetfunc __P((char *)); int typecmd __P((int, char **)); +void clearcmdentry __P((int)); |