httpd: require "HTTP/xyz" at the end of request line
[oweals/busybox.git] / debianutils / which.c
index fbcfb371bc9e1aa8eab65083ccd7e2d451aaa78a..98876521f80906730f8b2906f7689d1ba8c10774 100644 (file)
@@ -1,81 +1,73 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Which implementation for busybox
- *
- * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
- * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ * Copyright (C) 2006 Gabriel Somlo <somlo at cmu.edu>
  *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
+//config:config WHICH
+//config:      bool "which (3.8 kb)"
+//config:      default y
+//config:      help
+//config:      which is used to find programs in your PATH and
+//config:      print out their pathnames.
+
+//applet:IF_WHICH(APPLET_NOFORK(which, which, BB_DIR_USR_BIN, BB_SUID_DROP, which))
+
+//kbuild:lib-$(CONFIG_WHICH) += which.o
 
-/* getopt not needed */
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "busybox.h"
+//usage:#define which_trivial_usage
+//usage:       "[COMMAND]..."
+//usage:#define which_full_usage "\n\n"
+//usage:       "Locate a COMMAND"
+//usage:
+//usage:#define which_example_usage
+//usage:       "$ which login\n"
+//usage:       "/bin/login\n"
 
-extern int which_main(int argc, char **argv)
+#include "libbb.h"
+
+int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int which_main(int argc UNUSED_PARAM, char **argv)
 {
-       char *path_list, *path_n;
-       struct stat filestat;
-       int i, count=1, found, status = EXIT_SUCCESS;
+       char *env_path;
+       int status = 0;
+       /* This sizeof(): bb_default_root_path is shorter than BB_PATH_ROOT_PATH */
+       char buf[sizeof(BB_PATH_ROOT_PATH)];
+
+       env_path = getenv("PATH");
+       if (!env_path)
+               /* env_path must be writable, and must not alloc, so... */
+               env_path = strcpy(buf, bb_default_root_path);
+
+       getopt32(argv, "^" "a" "\0" "-1"/*at least one arg*/);
+       argv += optind;
 
-       if (argc <= 1 || **(argv + 1) == '-')
-               bb_show_usage();
-       argc--;
+       do {
+               int missing = 1;
 
-       path_list = getenv("PATH");
-       if (path_list != NULL) {
-               for(i=strlen(path_list); i > 0; i--)
-                       if (path_list[i]==':') {
-                               path_list[i]=0;
-                               count++;
+               /* If file contains a slash don't use PATH */
+               if (strchr(*argv, '/')) {
+                       if (file_is_executable(*argv)) {
+                               missing = 0;
+                               puts(*argv);
                        }
-       } else {
-               path_list = "/bin\0/sbin\0/usr/bin\0/usr/sbin\0/usr/local/bin";
-               count = 5;
-       }
+               } else {
+                       char *path;
+                       char *p;
 
-       while(argc-- > 0) { 
-               path_n = path_list;
-               argv++;
-               found = 0;
-               for (i = 0; i < count; i++) {
-                       char *buf;
-                       buf = concat_path_file(path_n, *argv);
-                       if (stat (buf, &filestat) == 0
-                           && filestat.st_mode & S_IXUSR)
-                       {
-                               puts(buf);
-                               found = 1;
-                               break;
+                       path = env_path;
+                       /* NOFORK NB: xmalloc inside find_executable(), must have no allocs above! */
+                       while ((p = find_executable(*argv, &path)) != NULL) {
+                               missing = 0;
+                               puts(p);
+                               free(p);
+                               if (!option_mask32) /* -a not set */
+                                       break;
                        }
-                       free(buf);
-                       path_n += (strlen(path_n) + 1);
                }
-               if (!found)
-                       status = EXIT_FAILURE;
-       }
+               status |= missing;
+       } while (*++argv);
+
        return status;
 }
-
-/*
-Local Variables:
-c-file-style: "linux"
-c-basic-offset: 4
-tab-width: 4
-End:
-*/