blob: 4d206ab294bc5b85cb08f7e6fa93c3379ed5781d [file] [log] [blame]
Erik Andersen330fd2b2000-05-19 05:35:19 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Which implementation for busybox
4 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Erik Andersen330fd2b2000-05-19 05:35:19 +00006 *
Paul Foxdb485cf2005-09-14 14:08:38 +00007 * Licensed under the GPL v2, see the file LICENSE in this tarball.
Erik Andersen330fd2b2000-05-19 05:35:19 +00008 *
Glenn L McGrathe84152e2004-03-01 08:32:49 +00009 * Based on which from debianutils
Erik Andersen330fd2b2000-05-19 05:35:19 +000010 */
11
Eric Andersened3ef502001-01-27 08:24:39 +000012#include <string.h>
Erik Andersen330fd2b2000-05-19 05:35:19 +000013#include <stdio.h>
Eric Andersened3ef502001-01-27 08:24:39 +000014#include <stdlib.h>
Glenn L McGrathe84152e2004-03-01 08:32:49 +000015#include <unistd.h>
Paul Foxdb485cf2005-09-14 14:08:38 +000016#include <sys/stat.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000017#include "busybox.h"
Erik Andersen330fd2b2000-05-19 05:35:19 +000018
Rob Landleydfba7412006-03-06 20:47:33 +000019int which_main(int argc, char **argv)
Erik Andersen330fd2b2000-05-19 05:35:19 +000020{
Paul Foxdb485cf2005-09-14 14:08:38 +000021 int status = EXIT_SUCCESS;
22 size_t i, count;
Glenn L McGrathe84152e2004-03-01 08:32:49 +000023 char *path_list;
Erik Andersen330fd2b2000-05-19 05:35:19 +000024
Glenn L McGrathe84152e2004-03-01 08:32:49 +000025 if (argc <= 1 || **(argv + 1) == '-') {
Manuel Novoa III cad53642003-03-19 09:13:01 +000026 bb_show_usage();
Glenn L McGrathe84152e2004-03-01 08:32:49 +000027 }
Erik Andersen330fd2b2000-05-19 05:35:19 +000028 argc--;
29
30 path_list = getenv("PATH");
Matt Kraaia3181dd2002-01-14 18:30:10 +000031 if (path_list != NULL) {
Paul Foxdb485cf2005-09-14 14:08:38 +000032 size_t path_len = bb_strlen(path_list);
33 char *new_list = NULL;
34 count = 1;
35
36 for (i = 0; i <= path_len; i++) {
37 char *this_i = &path_list[i];
38 if (*this_i == ':') {
39 /* ^::[^:] == \.: */
40 if (!i && (*(this_i + 1) == ':')) {
41 *this_i = '.';
42 continue;
43 }
44 *this_i = 0;
Matt Kraaia3181dd2002-01-14 18:30:10 +000045 count++;
Paul Foxdb485cf2005-09-14 14:08:38 +000046 /* ^:[^:] == \.0 and [^:]::[^:] == 0\.0 and [^:]:$ == 0\.0 */
47 if (!i || (*(this_i + 1) == ':') || (i == path_len-1)) {
48 new_list = xrealloc(new_list, path_len += 1);
49 if (i) {
50 memmove(&new_list[i+2], &path_list[i+1], path_len-i);
51 new_list[i+1] = '.';
52 memmove(new_list, path_list, i);
53 } else {
54 memmove(&new_list[i+1], &path_list[i], path_len-i);
55 new_list[i] = '.';
56 }
57 path_list = new_list;
58 }
Matt Kraaia3181dd2002-01-14 18:30:10 +000059 }
Glenn L McGrathe84152e2004-03-01 08:32:49 +000060 }
Matt Kraaia3181dd2002-01-14 18:30:10 +000061 } else {
62 path_list = "/bin\0/sbin\0/usr/bin\0/usr/sbin\0/usr/local/bin";
63 count = 5;
64 }
Pavel Roskinc389d912000-06-05 23:41:27 +000065
Eric Andersenc7bda1c2004-03-15 08:29:22 +000066 while (argc-- > 0) {
Paul Foxdb485cf2005-09-14 14:08:38 +000067 struct stat stat_b;
Eric Andersene78fe242003-10-22 11:36:55 +000068 char *buf;
Glenn L McGrathe84152e2004-03-01 08:32:49 +000069 char *path_n;
Glenn L McGrathe84152e2004-03-01 08:32:49 +000070 char found = 0;
Paul Foxdb485cf2005-09-14 14:08:38 +000071#define is_executable_file(a, b) (!access(a,X_OK) && !stat(a, &b) && \
72 S_ISREG(b.st_mode))
Eric Andersen514633b2003-10-22 10:38:22 +000073
Paul Foxdb485cf2005-09-14 14:08:38 +000074 argv++;
Glenn L McGrathe84152e2004-03-01 08:32:49 +000075 path_n = path_list;
Eric Andersen514633b2003-10-22 10:38:22 +000076 buf = *argv;
Paul Foxdb485cf2005-09-14 14:08:38 +000077
78 /* if filename is either absolute or contains slashes,
79 * stat it */
80 if (strchr(buf, '/') != NULL && is_executable_file(buf, stat_b)) {
Eric Andersen514633b2003-10-22 10:38:22 +000081 found = 1;
82 } else {
Paul Foxdb485cf2005-09-14 14:08:38 +000083 /* Couldn't access file and file doesn't contain slashes */
Eric Andersen514633b2003-10-22 10:38:22 +000084 for (i = 0; i < count; i++) {
85 buf = concat_path_file(path_n, *argv);
Paul Foxdb485cf2005-09-14 14:08:38 +000086 if (is_executable_file(buf, stat_b)) {
Eric Andersen514633b2003-10-22 10:38:22 +000087 found = 1;
88 break;
89 }
90 free(buf);
Paul Foxdb485cf2005-09-14 14:08:38 +000091 path_n += (bb_strlen(path_n) + 1);
Erik Andersen330fd2b2000-05-19 05:35:19 +000092 }
Erik Andersen330fd2b2000-05-19 05:35:19 +000093 }
Glenn L McGrathe84152e2004-03-01 08:32:49 +000094 if (found) {
95 puts(buf);
96 } else {
Matt Kraai768a2342000-11-18 01:16:43 +000097 status = EXIT_FAILURE;
Glenn L McGrathe84152e2004-03-01 08:32:49 +000098 }
Erik Andersen330fd2b2000-05-19 05:35:19 +000099 }
Paul Foxdb485cf2005-09-14 14:08:38 +0000100 bb_fflush_stdout_and_exit(status);
Erik Andersen330fd2b2000-05-19 05:35:19 +0000101}
102
103/*
104Local Variables:
105c-file-style: "linux"
106c-basic-offset: 4
107tab-width: 4
108End:
109*/