svn commit: r245426 - head/bin/sh

Jilles Tjoelker jilles at FreeBSD.org
Mon Jan 14 16:40:51 UTC 2013


Author: jilles
Date: Mon Jan 14 16:40:50 2013
New Revision: 245426
URL: http://svnweb.freebsd.org/changeset/base/245426

Log:
  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.

Modified:
  head/bin/sh/exec.c
  head/bin/sh/sh.1

Modified: head/bin/sh/exec.c
==============================================================================
--- head/bin/sh/exec.c	Mon Jan 14 16:38:43 2013	(r245425)
+++ head/bin/sh/exec.c	Mon Jan 14 16:40:50 2013	(r245426)
@@ -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 ve
 		error("internal error: cmdtype %d", cmdp->cmdtype);
 #endif
 	}
-	if (cmdp->rehash)
-		out1c('*');
 	out1c('\n');
 }
 
@@ -323,12 +321,12 @@ find_command(const char *name, struct cm
 {
 	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 cm
 		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 cm
 	}
 
 	/* 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 *spec
 
 
 /*
- * 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;
 	}

Modified: head/bin/sh/sh.1
==============================================================================
--- head/bin/sh/sh.1	Mon Jan 14 16:38:43 2013	(r245425)
+++ head/bin/sh/sh.1	Mon Jan 14 16:40:50 2013	(r245426)
@@ -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 r
 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


More information about the svn-src-all mailing list