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