hush: fix a bug in argv restoration after sourcing a file
[oweals/busybox.git] / debianutils / which.c
index 41a864cfa52a41ef8cb30c7bd35e47828ed09578..c0f897809825a9ad725b88e09b5b5af113e7ed42 100644 (file)
@@ -1,90 +1,72 @@
 /* vi: set sw=4 ts=4: */
 /*
- * Which implementation for busybox
- *
  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  * Copyright (C) 2006 Gabriel Somlo <somlo at cmu.edu>
  *
- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
- *
- * Based on which from debianutils
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
+//config:config WHICH
+//config:      bool "which"
+//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(which, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_WHICH) += which.o
+
+//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"
 
 #include "libbb.h"
 
 int which_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int which_main(int argc ATTRIBUTE_UNUSED, char **argv)
+int which_main(int argc UNUSED_PARAM, char **argv)
 {
-       USE_DESKTOP(int opt;)
-       int status = EXIT_SUCCESS;
-       char *path;
-       char *p;
+       const char *env_path;
+       int status = 0;
+
+       env_path = getenv("PATH");
+       if (!env_path)
+               env_path = bb_default_root_path;
 
        opt_complementary = "-1"; /* at least one argument */
-       USE_DESKTOP(opt =) getopt32(argv, "a");
+       getopt32(argv, "a");
        argv += optind;
 
-       /* This matches what is seen on e.g. ubuntu.
-        * "which" there is a shell script. */
-       path = getenv("PATH");
-       if (!path) {
-               path = (char*)bb_PATH_root_path;
-               putenv(path);
-               path += 5; /* skip "PATH=" */
-       }
-
        do {
-#if ENABLE_DESKTOP
-/* Much bloat just to support -a */
-               if (strchr(*argv, '/')) {
-                       if (execable_file(*argv)) {
-                               puts(*argv);
-                               continue;
-                       }
-                       status = EXIT_FAILURE;
-               } else {
-                       char *path2 = xstrdup(path);
-                       char *tmp = path2;
+               int missing = 1;
 
-                       p = find_execable(*argv, &tmp);
-                       if (!p)
-                               status = EXIT_FAILURE;
-                       else {
- print:
-                               puts(p);
-                               free(p);
-                               if (opt) {
-                                       /* -a: show matches in all PATH components */
-                                       if (tmp) {
-                                               p = find_execable(*argv, &tmp);
-                                               if (p)
-                                                       goto print;
-                                       }
-                               }
-                       }
-                       free(path2);
-               }
-#else
-/* Just ignoring -a */
+               /* If file contains a slash don't use PATH */
                if (strchr(*argv, '/')) {
-                       if (execable_file(*argv)) {
+                       if (file_is_executable(*argv)) {
+                               missing = 0;
                                puts(*argv);
-                               continue;
                        }
                } else {
-                       char *path2 = xstrdup(path);
-                       char *tmp = path2;
-                       p = find_execable(*argv, &tmp);
-                       free(path2);
-                       if (p) {
+                       char *path;
+                       char *tmp;
+                       char *p;
+
+                       path = tmp = xstrdup(env_path);
+                       while ((p = find_executable(*argv, &tmp)) != NULL) {
+                               missing = 0;
                                puts(p);
                                free(p);
-                               continue;
+                               if (!option_mask32) /* -a not set */
+                                       break;
                        }
+                       free(path);
                }
-               status = EXIT_FAILURE;
-#endif
-       } while (*(++argv) != NULL);
+               status |= missing;
+       } while (*++argv);
 
-       fflush_stdout_and_exit(status);
+       return status;
 }