larry@tikal.UUCP (Larry J. Barello) (08/26/85)
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
-------- cut here (duh) -------
#include <stdio.h>
char *getenv();
char *index();
int
main(ac,av)
char **av;
{
char *origpath, *path, *cp;
char buf[200];
char patbuf[512];
int quit, found;
if (ac < 2) {
fprintf(stderr, "Usage: %s cmd [cmd, ..]\n", *av);
exit(1);
}
if ((origpath = getenv("PATH")) == 0)
origpath = ".";
av[ac] = 0;
for(av++ ; *av; av++) {
strcpy(patbuf, origpath);
cp = path = patbuf;
quit = found = 0;
while(!quit) {
cp = index(path, ':');
if (cp == NULL)
quit++;
else
*cp = '\0';
sprintf(buf, "%s/%s", (*path ? path:"."), *av);
path = ++cp;
if (access(buf, 1) == 0) {
printf("%s\n", buf);
found++;
}
}
if (!found)
printf("No %s in %s\n", *av, origpath);
}
exit(0);
}
------------------jeff@ssc-vax.UUCP (Jeffrey Jongeward) (08/28/85)
> 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); > }
robert@smcvax (09/02/85)
> >Here is a fancified version of the original one. > > ..!uw-beaver!teltone!larry > >-------- cut here (duh) ------- > >#include <stdio.h> > >char *getenv(); >char *index(); >... >... > while(!quit) { > cp = index(path, ':'); > if (cp == NULL) > quit++; For those of you without "index()", the intent of which is to return a pointer to the first occurrence of str2 in str1 (or NULL if no match), replace then name "index" with "strchr". Robert Wallace infoswx!smcvax!robert