blob: db28f78032976443a3508db97fd219e1321c8aa4 [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 *
Bernhard Reutner-Fischer7fee0c42006-09-13 16:39:19 +00007 * Licensed under the GPL v2 or later, 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
Bernhard Reutner-Fischere15d7572006-06-02 20:56:16 +000012#include "busybox.h"
Eric Andersened3ef502001-01-27 08:24:39 +000013#include <string.h>
Erik Andersen330fd2b2000-05-19 05:35:19 +000014#include <stdio.h>
Eric Andersened3ef502001-01-27 08:24:39 +000015#include <stdlib.h>
Glenn L McGrathe84152e2004-03-01 08:32:49 +000016#include <unistd.h>
Paul Foxdb485cf2005-09-14 14:08:38 +000017#include <sys/stat.h>
Erik Andersen330fd2b2000-05-19 05:35:19 +000018
Bernhard Reutner-Fischer66e3a222006-06-14 16:17:50 +000019
Rob Landleyf86a5ba2006-07-19 21:45:30 +000020static int is_executable_file(char *a, struct stat *b)
Bernhard Reutner-Fischer66e3a222006-06-14 16:17:50 +000021{
22 return (!access(a,X_OK) && !stat(a, b) && S_ISREG(b->st_mode));
23}
24
Rob Landleydfba7412006-03-06 20:47:33 +000025int which_main(int argc, char **argv)
Erik Andersen330fd2b2000-05-19 05:35:19 +000026{
Bernhard Reutner-Fischer66e3a222006-06-14 16:17:50 +000027 int status;
Paul Foxdb485cf2005-09-14 14:08:38 +000028 size_t i, count;
Glenn L McGrathe84152e2004-03-01 08:32:49 +000029 char *path_list;
Erik Andersen330fd2b2000-05-19 05:35:19 +000030
Glenn L McGrathe84152e2004-03-01 08:32:49 +000031 if (argc <= 1 || **(argv + 1) == '-') {
Manuel Novoa III cad53642003-03-19 09:13:01 +000032 bb_show_usage();
Glenn L McGrathe84152e2004-03-01 08:32:49 +000033 }
Erik Andersen330fd2b2000-05-19 05:35:19 +000034 argc--;
35
36 path_list = getenv("PATH");
Matt Kraaia3181dd2002-01-14 18:30:10 +000037 if (path_list != NULL) {
Rob Landleya3896512006-05-07 20:20:34 +000038 size_t path_len = strlen(path_list);
Paul Foxdb485cf2005-09-14 14:08:38 +000039 char *new_list = NULL;
40 count = 1;
41
42 for (i = 0; i <= path_len; i++) {
43 char *this_i = &path_list[i];
44 if (*this_i == ':') {
45 /* ^::[^:] == \.: */
46 if (!i && (*(this_i + 1) == ':')) {
47 *this_i = '.';
48 continue;
49 }
50 *this_i = 0;
Matt Kraaia3181dd2002-01-14 18:30:10 +000051 count++;
Paul Foxdb485cf2005-09-14 14:08:38 +000052 /* ^:[^:] == \.0 and [^:]::[^:] == 0\.0 and [^:]:$ == 0\.0 */
53 if (!i || (*(this_i + 1) == ':') || (i == path_len-1)) {
54 new_list = xrealloc(new_list, path_len += 1);
55 if (i) {
56 memmove(&new_list[i+2], &path_list[i+1], path_len-i);
57 new_list[i+1] = '.';
58 memmove(new_list, path_list, i);
59 } else {
60 memmove(&new_list[i+1], &path_list[i], path_len-i);
61 new_list[i] = '.';
62 }
63 path_list = new_list;
64 }
Matt Kraaia3181dd2002-01-14 18:30:10 +000065 }
Glenn L McGrathe84152e2004-03-01 08:32:49 +000066 }
Matt Kraaia3181dd2002-01-14 18:30:10 +000067 } else {
68 path_list = "/bin\0/sbin\0/usr/bin\0/usr/sbin\0/usr/local/bin";
69 count = 5;
70 }
Pavel Roskinc389d912000-06-05 23:41:27 +000071
Bernhard Reutner-Fischer66e3a222006-06-14 16:17:50 +000072 status = EXIT_SUCCESS;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000073 while (argc-- > 0) {
Paul Foxdb485cf2005-09-14 14:08:38 +000074 struct stat stat_b;
Eric Andersene78fe242003-10-22 11:36:55 +000075 char *buf;
Glenn L McGrathe84152e2004-03-01 08:32:49 +000076 char *path_n;
Bernhard Reutner-Fischer66e3a222006-06-14 16:17:50 +000077 int found = 0;
Eric Andersen514633b2003-10-22 10:38:22 +000078
Paul Foxdb485cf2005-09-14 14:08:38 +000079 argv++;
Glenn L McGrathe84152e2004-03-01 08:32:49 +000080 path_n = path_list;
Eric Andersen514633b2003-10-22 10:38:22 +000081 buf = *argv;
Paul Foxdb485cf2005-09-14 14:08:38 +000082
83 /* if filename is either absolute or contains slashes,
84 * stat it */
Bernhard Reutner-Fischer66e3a222006-06-14 16:17:50 +000085 if (strchr(buf, '/') != NULL && is_executable_file(buf, &stat_b)) {
86 found++;
Eric Andersen514633b2003-10-22 10:38:22 +000087 } else {
Paul Foxdb485cf2005-09-14 14:08:38 +000088 /* Couldn't access file and file doesn't contain slashes */
Eric Andersen514633b2003-10-22 10:38:22 +000089 for (i = 0; i < count; i++) {
90 buf = concat_path_file(path_n, *argv);
Bernhard Reutner-Fischer66e3a222006-06-14 16:17:50 +000091 if (is_executable_file(buf, &stat_b)) {
92 found++;
Eric Andersen514633b2003-10-22 10:38:22 +000093 break;
94 }
95 free(buf);
Rob Landleya3896512006-05-07 20:20:34 +000096 path_n += (strlen(path_n) + 1);
Erik Andersen330fd2b2000-05-19 05:35:19 +000097 }
Erik Andersen330fd2b2000-05-19 05:35:19 +000098 }
Glenn L McGrathe84152e2004-03-01 08:32:49 +000099 if (found) {
100 puts(buf);
101 } else {
Matt Kraai768a2342000-11-18 01:16:43 +0000102 status = EXIT_FAILURE;
Glenn L McGrathe84152e2004-03-01 08:32:49 +0000103 }
Erik Andersen330fd2b2000-05-19 05:35:19 +0000104 }
Paul Foxdb485cf2005-09-14 14:08:38 +0000105 bb_fflush_stdout_and_exit(status);
Erik Andersen330fd2b2000-05-19 05:35:19 +0000106}