char * which (const char *name) { const char *path_list = getenv ("PATH"); char *full_path = NULL; char *result = NULL; if (!name || !*name) return NULL; get_current_working_directory (); if (path_list && *path_list != '\0') { int path_index = 0; result = find_command_in_path (name, path_list, &path_index); if (result) { full_path = path_clean_up (result); free (result); return xstrdup (full_path); } else { return NULL; } } return NULL; }
int main(int argc, char *argv[]) { const char *path_list = getenv("PATH"); int short_option, long_option, fail_count = 0, path_index; int show_dot = 0, show_tilde = 0, tty_only = 0; struct option longopts[] = { {"version", 0, &long_option, opt_version}, {"skip-dot", 0, &long_option, opt_skip_dot}, {"skip-tilde", 0, &long_option, opt_skip_tilde}, {"show-dot", 0, &long_option, opt_show_dot}, {"show-tilde", 0, &long_option, opt_show_tilde}, {"tty-only", 0, &long_option, opt_tty_only}, {"all", 0, NULL, 'a'}, {NULL, 0, NULL, 0} }; progname = argv[0]; while ((short_option = getopt_long(argc, argv, "avV", longopts, NULL)) != -1) { switch (short_option) { case 0: switch (long_option) { case opt_version: print_version(); return 0; case opt_skip_dot: skip_dot = !tty_only; break; case opt_skip_tilde: skip_tilde = !tty_only; break; case opt_show_dot: show_dot = !tty_only; break; #ifndef WIN32 case opt_show_tilde: show_tilde = (!tty_only && geteuid() != 0); break; #endif case opt_tty_only: tty_only = !isatty(1); break; } break; case 'a': show_all = 1; break; case 'v': case 'V': print_version(); return 0; } } if (show_dot) get_current_working_directory(); if (show_tilde || skip_tilde) { const char *h; if (!(h = getenv("HOME"))) { fprintf(stderr, "%s: ", progname); if (show_tilde) fprintf(stderr, "--show-tilde"); else fprintf(stderr, "--skip-tilde"); fprintf(stderr, ": Environment variable HOME not set\n"); show_tilde = skip_tilde = 0; } else { strncpy(home, h, sizeof(home)); home[sizeof(home) - 1] = 0; homelen = strlen(home); if (home[homelen - 1] != DIRSEP && homelen < sizeof(home) - 1) { strcat(home, "/"); ++homelen; } } } argv += optind; if (!*argv) { print_usage(); return -1; } for (; *argv; ++argv) { char *result = NULL; int found_something = 0; if (path_list && *path_list != '\0') { int next; path_index = 0; do { next = show_all; result = find_command_in_path(*argv, path_list, &path_index); if (result) { const char *full_path = path_clean_up(result); int in_home = (show_tilde || skip_tilde) && !strncmp(full_path, home, homelen); if (!(skip_tilde && in_home) && show_dot && found_path_starts_with_dot && !strncmp(full_path, cwd, cwdlen)) { full_path += cwdlen; fprintf(stdout, "./"); } else if (in_home) { if (skip_tilde) { next = 1; continue; } if (show_tilde) { full_path += homelen; fprintf(stdout, "~/"); } } fprintf(stdout, "%s\n", full_path); free(result); found_something = 1; } else break; } while(next); } if (!found_something) { print_fail(absolute_path_given ? strrchr(*argv, DIRSEP) + 1 : *argv, absolute_path_given ? abs_path : path_list); ++fail_count; } } return fail_count; }