which.c revision 2896480c4918f2accccb8301bec457a7bff7377e
12896480c4918f2accccb8301bec457a7bff7377eRob Landley/* vi: set sw=4 ts=4:
22896480c4918f2accccb8301bec457a7bff7377eRob Landley *
32c4f3cb6b3d79a1025288fb54ec30994efee1890Charlie Shepherd * which.c - Find executable files in $PATH.
40a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley *
50a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley * Copyright 2006 Rob landley <rob@landley.net>
6fece5cb6d796119eccb1ae0074e5b3aaccbb74eeRob Landley *
7fece5cb6d796119eccb1ae0074e5b3aaccbb74eeRob Landley * Not in SUSv3.
80a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
92896480c4918f2accccb8301bec457a7bff7377eRob Landleyconfig WHICH
102896480c4918f2accccb8301bec457a7bff7377eRob Landley	bool "which"
112896480c4918f2accccb8301bec457a7bff7377eRob Landley	default y
122896480c4918f2accccb8301bec457a7bff7377eRob Landley	help
132896480c4918f2accccb8301bec457a7bff7377eRob Landley	  usage: which [-a] filename ...
142896480c4918f2accccb8301bec457a7bff7377eRob Landley
152896480c4918f2accccb8301bec457a7bff7377eRob Landley	  Search $PATH for executable files matching filename(s).
162896480c4918f2accccb8301bec457a7bff7377eRob Landley
172896480c4918f2accccb8301bec457a7bff7377eRob Landley	  -a	Show all matches
182896480c4918f2accccb8301bec457a7bff7377eRob Landley*/
190a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley#include "toys.h"
200a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
210a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley#define OPT_a   1
220a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
230a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley// Find an exectuable file either at a path with a slash in it (absolute or
240a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley// relative to current directory), or in $PATH.  Returns absolute path to file,
250a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley// or NULL if not found.
260a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
270a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landleystatic int which_in_path(char *filename)
280a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley{
290a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	struct string_list *list;
300a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
310a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	// If they gave us a path, don't worry about $PATH or -a
320a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
330a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	if (index(filename, '/')) {
340a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		// Confirm it has the executable bit set, and it's not a directory.
350a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		if (!access(filename, X_OK)) {
360a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			struct stat st;
370a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
380a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			if (!stat(filename, &st) && S_ISREG(st.st_mode)) {
390a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley				puts(filename);
400a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley				return 0;
410a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			}
420a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			return 1;
430a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		}
440a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	}
450a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
460a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	// Search $PATH for matches.
470a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	list = find_in_path(getenv("PATH"), filename);
480a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	if (!list) return 1;
490a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
500a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	// Print out matches
510a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	while (list) {
520a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		if (!access(list->str, X_OK)) {
530a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			puts(list->str);
540a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			// If we should stop at one match, do so
550a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			if (toys.optflags & OPT_a) {
560a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley				llist_free(list, NULL);
570a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley				break;
580a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			}
590a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		}
600a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		free(llist_pop(&list));
610a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	}
620a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
630a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	return 0;
640a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley}
650a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
66efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landleyvoid which_main(void)
670a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley{
68efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landley	if (!*toys.optargs) toys.exitval++;
690a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	else {
700a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		int i;
71efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landley		for (i=0; toys.optargs[i]; i++)
72efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landley			toys.exitval |= which_in_path(toys.optargs[i]);
730a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	}
740a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley}
75