which.c revision 55928b1e0a08d84a5cbc50020f0a8c1024f5b6ce
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
955928b1e0a08d84a5cbc50020f0a8c1024f5b6ceRob LandleyUSE_WHICH(NEWTOY(which, "a", 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#define OPT_a   1
240a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
250a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley// Find an exectuable file either at a path with a slash in it (absolute or
260a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley// relative to current directory), or in $PATH.  Returns absolute path to file,
270a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley// or NULL if not found.
280a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
290a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landleystatic int which_in_path(char *filename)
300a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley{
310a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	struct string_list *list;
320a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
330a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	// If they gave us a path, don't worry about $PATH or -a
340a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
350a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	if (index(filename, '/')) {
360a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		// Confirm it has the executable bit set, and it's not a directory.
370a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		if (!access(filename, X_OK)) {
380a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			struct stat st;
390a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
400a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			if (!stat(filename, &st) && S_ISREG(st.st_mode)) {
410a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley				puts(filename);
420a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley				return 0;
430a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			}
440a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			return 1;
450a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		}
460a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	}
470a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
480a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	// Search $PATH for matches.
490a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	list = find_in_path(getenv("PATH"), filename);
500a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	if (!list) return 1;
510a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
520a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	// Print out matches
530a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	while (list) {
540a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		if (!access(list->str, X_OK)) {
550a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			puts(list->str);
560a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			// If we should stop at one match, do so
570a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			if (toys.optflags & OPT_a) {
580a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley				llist_free(list, NULL);
590a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley				break;
600a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley			}
610a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		}
620a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		free(llist_pop(&list));
630a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	}
640a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
650a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	return 0;
660a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley}
670a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley
68efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landleyvoid which_main(void)
690a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley{
70efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landley	if (!*toys.optargs) toys.exitval++;
710a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	else {
720a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley		int i;
73efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landley		for (i=0; toys.optargs[i]; i++)
74efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landley			toys.exitval |= which_in_path(toys.optargs[i]);
750a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley	}
760a04b3ef850cd3d6f06b3c8d0036993adc9ba7b2Rob Landley}
77