summaryrefslogtreecommitdiffstats
path: root/bin/sh
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2013-01-14 16:40:50 +0000
committerjilles <jilles@FreeBSD.org>2013-01-14 16:40:50 +0000
commit705fd8516acf0369c2f98c092137707eab99e0a9 (patch)
tree6c1022edf9abd2b90fae6d44c095e7a6a85a3f59 /bin/sh
parent7ed3ee172aa11cd143c08046767a78f1378e8cd6 (diff)
downloadFreeBSD-src-705fd8516acf0369c2f98c092137707eab99e0a9.zip
FreeBSD-src-705fd8516acf0369c2f98c092137707eab99e0a9.tar.gz
sh: Simplify cd-hash interaction.
Instead of rechecking relative paths for all hashed utilities after a cd, track if any utility in cmdtable depends on a relative path in PATH. If there is such a utility, cd clears the entire table. As a result, the '*' in hash no longer happens.
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/exec.c49
-rw-r--r--bin/sh/sh.16
2 files changed, 15 insertions, 40 deletions
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index eb32403..7a6dbae 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -86,12 +86,12 @@ struct tblentry {
union param param; /* definition of builtin function */
int special; /* flag for special builtin commands */
signed char cmdtype; /* index identifying command */
- char rehash; /* if set, cd done since entry created */
char cmdname[]; /* name of command */
};
static struct tblentry *cmdtable[CMDTABLESIZE];
+static int cmdtable_cd = 0; /* cmdtable contains cd-dependent entries */
int exerrno = 0; /* Last exec error */
@@ -305,8 +305,6 @@ printentry(struct tblentry *cmdp, int verbose)
error("internal error: cmdtype %d", cmdp->cmdtype);
#endif
}
- if (cmdp->rehash)
- out1c('*');
out1c('\n');
}
@@ -323,12 +321,12 @@ find_command(const char *name, struct cmdentry *entry, int act,
{
struct tblentry *cmdp, loc_cmd;
int idx;
- int prev;
char *fullname;
struct stat statb;
int e;
int i;
int spec;
+ int cd;
/* If name contains a slash, don't use the hash table */
if (strchr(name, '/') != NULL) {
@@ -337,8 +335,10 @@ find_command(const char *name, struct cmdentry *entry, int act,
return;
}
+ cd = 0;
+
/* If name is in the table, and not invalidated by cd, we're done */
- if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
+ if ((cmdp = cmdlookup(name, 0)) != NULL) {
if (cmdp->cmdtype == CMDFUNCTION && act & DO_NOFUNC)
cmdp = NULL;
else
@@ -359,13 +359,6 @@ find_command(const char *name, struct cmdentry *entry, int act,
}
/* We have to search path. */
- prev = -1; /* where to start */
- if (cmdp) { /* doing a rehash */
- if (cmdp->cmdtype == CMDBUILTIN)
- prev = -1;
- else
- prev = cmdp->param.index;
- }
e = ENOENT;
idx = -1;
@@ -380,13 +373,8 @@ loop:
goto loop; /* ignore unimplemented options */
}
}
- /* if rehash, don't redo absolute path names */
- if (fullname[0] == '/' && idx <= prev) {
- if (idx < prev)
- goto loop;
- TRACE(("searchexec \"%s\": no change\n", name));
- goto success;
- }
+ if (fullname[0] != '/')
+ cd = 1;
if (stat(fullname, &statb) < 0) {
if (errno != ENOENT && errno != ENOTDIR)
e = errno;
@@ -426,9 +414,6 @@ loop:
goto success;
}
- /* We failed. If there was an entry for this command, delete it */
- if (cmdp && cmdp->cmdtype != CMDFUNCTION)
- delete_cmd_entry();
if (act & DO_ERR) {
if (e == ENOENT || e == ENOTDIR)
outfmt(out2, "%s: not found\n", name);
@@ -440,7 +425,8 @@ loop:
return;
success:
- cmdp->rehash = 0;
+ if (cd)
+ cmdtable_cd = 1;
entry->cmdtype = cmdp->cmdtype;
entry->u = cmdp->param;
entry->special = cmdp->special;
@@ -469,22 +455,15 @@ find_builtin(const char *name, int *special)
/*
- * Called when a cd is done. Marks all commands so the next time they
- * are executed they will be rehashed.
+ * Called when a cd is done. If any entry in cmdtable depends on the current
+ * directory, simply clear cmdtable completely.
*/
void
hashcd(void)
{
- struct tblentry **pp;
- struct tblentry *cmdp;
-
- for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
- for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
- if (cmdp->cmdtype == CMDNORMAL)
- cmdp->rehash = 1;
- }
- }
+ if (cmdtable_cd)
+ clearcmdentry();
}
@@ -526,6 +505,7 @@ clearcmdentry(void)
}
}
}
+ cmdtable_cd = 0;
INTON;
}
@@ -566,7 +546,6 @@ cmdlookup(const char *name, int add)
+ strlen(name) + 1);
cmdp->next = NULL;
cmdp->cmdtype = CMDUNKNOWN;
- cmdp->rehash = 0;
strcpy(cmdp->cmdname, name);
INTON;
}
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 1750267..83cf7c2 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd July 15, 2012
+.Dd January 14, 2013
.Dt SH 1
.Os
.Sh NAME
@@ -2219,10 +2219,6 @@ The shell maintains a hash table which remembers the locations of commands.
With no arguments whatsoever, the
.Ic hash
command prints out the contents of this table.
-Entries which have not been looked at since the last
-.Ic cd
-command are marked with an asterisk;
-it is possible for these entries to be invalid.
.Pp
With arguments, the
.Ic hash
OpenPOWER on IntegriCloud