10f66f451Sopenharmony_ci/* which.c - Find executable files in $PATH. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2006 Rob landley <rob@landley.net> 40f66f451Sopenharmony_ci 50f66f451Sopenharmony_ciUSE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN)) 60f66f451Sopenharmony_ci 70f66f451Sopenharmony_ciconfig WHICH 80f66f451Sopenharmony_ci bool "which" 90f66f451Sopenharmony_ci default y 100f66f451Sopenharmony_ci help 110f66f451Sopenharmony_ci usage: which [-a] filename ... 120f66f451Sopenharmony_ci 130f66f451Sopenharmony_ci Search $PATH for executable files matching filename(s). 140f66f451Sopenharmony_ci 150f66f451Sopenharmony_ci -a Show all matches 160f66f451Sopenharmony_ci*/ 170f66f451Sopenharmony_ci#include "toys.h" 180f66f451Sopenharmony_ci 190f66f451Sopenharmony_ci// Find an exectuable file either at a path with a slash in it (absolute or 200f66f451Sopenharmony_ci// relative to current directory), or in $PATH. Returns absolute path to file, 210f66f451Sopenharmony_ci// or NULL if not found. 220f66f451Sopenharmony_ci 230f66f451Sopenharmony_cistatic int which_in_path(char *filename) 240f66f451Sopenharmony_ci{ 250f66f451Sopenharmony_ci struct string_list *list; 260f66f451Sopenharmony_ci 270f66f451Sopenharmony_ci // If they gave us a path, don't worry about $PATH or -a 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ci if (strchr(filename, '/')) { 300f66f451Sopenharmony_ci // Confirm it has the executable bit set, and it's not a directory. 310f66f451Sopenharmony_ci if (!access(filename, X_OK)) { 320f66f451Sopenharmony_ci struct stat st; 330f66f451Sopenharmony_ci 340f66f451Sopenharmony_ci if (!stat(filename, &st) && S_ISREG(st.st_mode)) { 350f66f451Sopenharmony_ci puts(filename); 360f66f451Sopenharmony_ci return 0; 370f66f451Sopenharmony_ci } 380f66f451Sopenharmony_ci return 1; 390f66f451Sopenharmony_ci } 400f66f451Sopenharmony_ci } 410f66f451Sopenharmony_ci 420f66f451Sopenharmony_ci // Search $PATH for matches. 430f66f451Sopenharmony_ci list = find_in_path(getenv("PATH"), filename); 440f66f451Sopenharmony_ci if (!list) return 1; 450f66f451Sopenharmony_ci 460f66f451Sopenharmony_ci // Print out matches 470f66f451Sopenharmony_ci while (list) { 480f66f451Sopenharmony_ci if (!access(list->str, X_OK)) { 490f66f451Sopenharmony_ci puts(list->str); 500f66f451Sopenharmony_ci // If we should stop at one match, do so 510f66f451Sopenharmony_ci if (!toys.optflags) { 520f66f451Sopenharmony_ci llist_traverse(list, free); 530f66f451Sopenharmony_ci break; 540f66f451Sopenharmony_ci } 550f66f451Sopenharmony_ci } 560f66f451Sopenharmony_ci free(llist_pop(&list)); 570f66f451Sopenharmony_ci } 580f66f451Sopenharmony_ci 590f66f451Sopenharmony_ci return 0; 600f66f451Sopenharmony_ci} 610f66f451Sopenharmony_ci 620f66f451Sopenharmony_civoid which_main(void) 630f66f451Sopenharmony_ci{ 640f66f451Sopenharmony_ci int i; 650f66f451Sopenharmony_ci 660f66f451Sopenharmony_ci for (i=0; toys.optargs[i]; i++) 670f66f451Sopenharmony_ci toys.exitval |= which_in_path(toys.optargs[i]); 680f66f451Sopenharmony_ci} 69