which.c revision 59f490cb4e18960e7ddd003f9a66005eccc5ebd7
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
959f490cb4e18960e7ddd003f9a66005eccc5ebd7Rob LandleyUSE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
1055928b1e0a08d84a5cbc50020f0a8c1024f5b6ceRob Landley
112896480c4918f2accccb8301bec457a7bff7377eRob Landleyconfig WHICH
122896480c4918f2accccb8301bec457a7bff7377eRob Landley	bool "which"
132896480c4918f2accccb8301bec457a7bff7377eRob Landley	default y
142896480c4918f2accccb8301bec457a7bff7377eRob Landley	help
152896480c4918f2accccb8301bec457a7bff7377eRob Landley	  usage: which [-a] filename ...
162896480c4918f2accccb8301bec457a7bff7377eRob Landley
172896480c4918f2accccb8301bec457a7bff7377eRob Landley	  Search $PATH for executable files matching filename(s).
182896480c4918f2accccb8301bec457a7bff7377eRob Landley
192896480c4918f2accccb8301bec457a7bff7377eRob Landley	  -a	Show all matches
202896480c4918f2accccb8301bec457a7bff7377eRob Landley*/
210a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley#include "toys.h"
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
5559f490cb4e18960e7ddd003f9a66005eccc5ebd7Rob Landley			if (!toys.optflags) {
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{
6859f490cb4e18960e7ddd003f9a66005eccc5ebd7Rob Landley	int i;
6959f490cb4e18960e7ddd003f9a66005eccc5ebd7Rob Landley	for (i=0; toys.optargs[i]; i++)
7059f490cb4e18960e7ddd003f9a66005eccc5ebd7Rob Landley		toys.exitval |= which_in_path(toys.optargs[i]);
710a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley}
72