summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Src/hashtable.c43
2 files changed, 43 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index d51b6d12e..4a477ad8a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2009-09-21 Peter Stephenson <pws@csr.com>
+
+ * users/14411: Src/hashtable.c: only hash stat-able executable
+ regular files in the command table.
+
2009-09-19 Peter Stephenson <p.w.stephenson@ntlworld.com>
* Darel Henman: users/14412: Doc/Zsh/builtins.yo: fix confusions
@@ -12192,5 +12197,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4783 $
+* $Revision: 1.4784 $
*****************************************************
diff --git a/Src/hashtable.c b/Src/hashtable.c
index 2eb70c3b0..6d7179412 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -630,20 +630,50 @@ hashdir(char **dirp)
{
Cmdnam cn;
DIR *dir;
- char *fn;
+ char *fn, *unmetadir, *pathbuf, *pathptr;
+ int dirlen;
#if defined(_WIN32) || defined(__CYGWIN__)
char *exe;
#endif /* _WIN32 || _CYGWIN__ */
- if (isrelative(*dirp) || !(dir = opendir(unmeta(*dirp))))
+ if (isrelative(*dirp))
return;
+ unmetadir = unmeta(*dirp);
+ if (!(dir = opendir(unmetadir)))
+ return;
+
+ dirlen = strlen(unmetadir);
+ pathbuf = (char *)zalloc(dirlen + PATH_MAX + 2);
+ sprintf(pathbuf, "%s/", unmetadir);
+ pathptr = pathbuf + dirlen + 1;
while ((fn = zreaddir(dir, 1))) {
if (!cmdnamtab->getnode(cmdnamtab, fn)) {
- cn = (Cmdnam) zshcalloc(sizeof *cn);
- cn->node.flags = 0;
- cn->u.name = dirp;
- cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
+ char *fname = ztrdup(fn);
+ struct stat statbuf;
+ int add = 0, dummylen;
+
+ unmetafy(fn, &dummylen);
+ if (strlen(fn) > PATH_MAX) {
+ /* Too heavy to do all the allocation */
+ add = 1;
+ } else {
+ strcpy(pathptr, fn);
+ /*
+ * This is the same test as for the glob qualifier for
+ * executable plain files.
+ */
+ if (stat(pathbuf, &statbuf) == 0 &&
+ S_ISREG(statbuf.st_mode) && (statbuf.st_mode & S_IXUGO))
+ add = 1;
+ }
+ if (add) {
+ cn = (Cmdnam) zshcalloc(sizeof *cn);
+ cn->node.flags = 0;
+ cn->u.name = dirp;
+ cmdnamtab->addnode(cmdnamtab, fname, cn);
+ } else
+ zsfree(fname);
}
#if defined(_WIN32) || defined(__CYGWIN__)
/* Hash foo.exe as foo, since when no real foo exists, foo.exe
@@ -664,6 +694,7 @@ hashdir(char **dirp)
#endif /* _WIN32 || __CYGWIN__ */
}
closedir(dir);
+ zfree(pathbuf, dirlen + PATH_MAX + 2);
}
/* Go through user's PATH and add everything to *