[BusyBox] "which" mostly rewritten
Pavel Roskin
pavel_roskin at geocities.com
Mon Jun 5 22:50:29 UTC 2000
Hello!
The current "which" is so buggy that it was easier for me to reimplement
it. Some notes:
Instead of scanning whole directories with readdir() I decided to use
stat(). This also gives us the possibility to ignore non-executable files.
The official "which" doesn't ignore directories, why should we bother?
"which" without arguments doesn't crash anymore.
If PATH is not defined we shouldn't fallback to a default. It's a problem
that should be reported. BTW, the official "which" crashes when run as
"env - which foo" (LinuxPPC 1999 Q3).
In order to process many arguments we should make a copy path_list,
otherwise it cannot be reused.
The official "which" stops processing arguments if it cannot find a file.
The error message is printed on stdout. The exit code is 1. All this is
now emulated.
I'll apply the patch myself with notes in Changelog. Ok?
Pavel Roskin
===================
diff -u -r1.1 which.c
--- which.c 2000/06/02 13:42:13 1.1
+++ which.c 2000/06/05 19:31:05
@@ -23,15 +23,18 @@
#include "internal.h"
#include <stdio.h>
-#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/param.h>
extern int which_main(int argc, char **argv)
{
- char *path_list, *test, *tmp;
- struct dirent *next;
+ char *path_list, *test, *tmp, *path_parsed;
+ char buf[PATH_MAX];
+ struct stat filestat;
+ int count = 0;
- if (**(argv + 1) == '-') {
+ if (argc <= 1 || **(argv + 1) == '-') {
usage("which [COMMAND ...]\n"
#ifndef BB_FEATURE_TRIVIAL_HELP
"\nLocates a COMMAND.\n"
@@ -42,23 +45,47 @@
path_list = getenv("PATH");
if (!path_list)
- path_list = "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin";
+ fatalError("which: PATH is not defined\n");
- while(argc-- > 0 && *(argv++) != '\0' && strlen(*argv)) {
- for( test=path_list; (tmp=strchr(test, ':')) && (tmp+1)!=NULL; test=++tmp) {
- DIR *dir;
- *tmp='\0';
- //printf("Checking directory '%s'\n", test);
- dir = opendir(test);
- if (!dir)
- continue;
- while ((next = readdir(dir)) != NULL) {
- //printf("Checking file '%s'\n", next->d_name);
- if ((strcmp(next->d_name, *argv) == 0)) {
- printf("%s/%s\n", test, next->d_name);
- exit(TRUE);
- }
+ path_parsed = malloc (strlen(path_list) + 1);
+ strcpy (path_parsed, path_list);
+
+ /* Parse path_parsed */
+ count = 1;
+ test = path_parsed;
+ while (1) {
+ tmp = strchr(test, ':');
+ if (tmp == NULL)
+ break;
+ *tmp = 0;
+ test = tmp + 1;
+ count++;
+ }
+
+
+ while(argc-- > 0) {
+ int i;
+ int found = FALSE;
+ test = path_parsed;
+ argv++;
+ for (i = 0; i < count; i++) {
+ strcpy (buf, test);
+ strcat (buf, "/");
+ strcat (buf, *argv);
+ if (stat (buf, &filestat) == 0
+ && filestat.st_mode & S_IXUSR)
+ {
+ found = TRUE;
+ break;
}
+ test += (strlen(test) + 1);
+ }
+ if (found == TRUE)
+ printf ("%s\n", buf);
+ else
+ {
+ printf ("which: no %s in (%s)\n", *argv, path_list);
+ exit (FALSE);
}
}
exit(TRUE);
===================
More information about the busybox
mailing list