Son of 'which'
Jeffrey Jongeward
jeff at ssc-vax.UUCP
Thu Aug 29 04:59:45 AEST 1985
> A week or so I posted a quick C version of the UCB shell script
> "which". It takes as arguments command names and searches your path
> for instances of them. The version I posted had some cute bugs: it
> didn't work if you didn't have a path or if there were a null
> component in the path (Thanks to Tom Truscott). To the folks with v8
> shell: wish I had it, sounds like it make a lot of utilities, like
> this one, useless.
>
> Here is a fancified version of the original one.
>
> ..!uw-beaver!teltone!larry
>
Larry's "which" clone is a big win because it results in about a 3X
speed improvement over the sh-coded version. However, in the 4.2BSD environment
(at least) there is 1 bug, and 3 incompatibilities with the standard
version. In addition, the standard version embodies (at least one) bug of
it's own.
The Bugs:
Access(2) will return return 0 if a file is a directory and searchable,
but not executable (since X_OK only checks only the execute bit); so a
stat(2) is required in addition to check that the file is not a
directory. In addition, access(... X_OK) is truly worthless
if the user is 'su' - since every existing file will return 0
regardless of it's mode.
The 4.2BSD original embodies the 'su' problem as will; it will incorrectly
identify a non-executable in the search path. The diffs posted below "fix"
that problem too - the price for this is to perform a somewhat pointless
access(2) call for the 'su'ed user, and to perform a worthless check
that some execute bit is set (since it duplicates the check in access)
for the non-su user.
The Incompatibilities:
1. The program should bail out after the first found occurrence.
2. The path should be printed delimited with ' ', not ':' when not found.
3. the leading 'No' should be 'no' when not found.
Here are the diffs:
1a2,4
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <sys/file.h>
4a8
> struct stat sb;
18a23
>
39,41c44,49
< if (access(buf, 1) == 0) {
< printf("%s\n", buf);
< found++;
---
> if ( access(buf, 1) == 0 && !stat(buf,&sb) ) {
> if((sb.st_mode&S_IFDIR) == 0 && sb.st_mode&0111) {
> printf("%s\n", buf);
> found++;
> break;
> }
44,45c52,62
< if (!found)
< printf("No %s in %s\n", *av, origpath);
---
> if (!found) {
> char *optr = origpath;
> char *oend = optr+strlen(origpath);
>
> while(optr < oend) {
> if(*optr == ':')
> *optr = ' ';
> optr++;
> }
> printf("no %s in %s\n", *av, origpath);
> }
More information about the Comp.sources.unix
mailing list