int type, const char **paths) { size_t i; DBG(STATIC, ul_debugobj(*ls, "construct %s dirlist from static array", whereis_type_to_name(type))); for (i = 0; paths[i]; i++) { if (!strchr(paths[i], '*')) dirlist_add_dir(ls, type, paths[i]); else dirlist_add_subdir(ls, type, paths[i]); } return; } static void free_dirlist(struct wh_dirlist **ls0, int type) { struct wh_dirlist *prev = NULL, *next, *ls = *ls0; *ls0 = NULL; DBG(LIST, ul_debugobj(*ls0, "free dirlist")); while (ls) { if (ls->type & type) { next = ls->next; DBG(LIST, ul_debugobj(*ls0, " free: %s", ls->path)); free(ls->path); free(ls); ls = next; if (prev) prev->next = ls; } else { if (!prev) *ls0 = ls;/* first unremoved */ prev = ls; ls = ls->next; } } return; } static int filename_equal(const char *cp, const char *dp) { int i = strlen(dp); DBG(SEARCH, ul_debug("compare '%s' and '%s'", cp, dp)); if (dp[0] == 's' && dp[1] == '.' && filename_equal(cp, dp + 2)) return 1; if (!strcmp(dp + i - 2, ".Z")) i -= 2; else if (!strcmp(dp + i - 3, ".gz")) i -= 3; else if (!strcmp(dp + i - 3, ".xz")) i -= 3; else if (!strcmp(dp + i - 4, ".bz2")) i -= 4; while (*cp && *dp && *cp == *dp) cp++, dp++, i--; if (*cp == 0 && *dp == 0) return 1; while (isdigit(*dp)) dp++; if (*cp == 0 && *dp++ == '.') { --i; while (i > 0 && *dp) if (--i, *dp++ == '.') return (*dp++ == 'C' && *dp++ == 0); return 1; } return 0; } static void findin(const char *dir, const char *pattern, int *count, char **wait) { DIR *dirp; struct dirent *dp; dirp = opendir(dir); if (dirp == NULL) return; DBG(SEARCH, ul_debug("find '%s' in '%s'", pattern, dir)); while ((dp = readdir(dirp)) != NULL) { if (!filename_equal(pattern, dp->d_name)) continue; if (uflag && *count == 0) xasprintf(wait, "%s/%s", dir, dp->d_name); else if (uflag && *count == 1 && *wait) { printf("%s: %s %s/%s", pattern, *wait, dir, dp->d_name); free(*wait); *wait = NULL; } else printf(" %s/%s", dir, dp->d_name); ++(*count); } closedir(dirp); return; } static void lookup(const char *pattern, struct wh_dirlist *ls, int want) { char patbuf[PATH_MAX]; int count = 0; char *wait = NULL, *p; /* canonicalize pattern -- remove path suffix etc. */ p = strrchr(pattern, '/'); p = p ? p + 1 : (char *) pattern; strncpy(patbuf, p, PATH_MAX); patbuf[PATH_MAX - 1] = '\0'; DBG(SEARCH, ul_debug("lookup dirs for '%s' (%s), want: %s %s %s", patbuf, pattern, want & BIN_DIR ? "bin" : "", want & MAN_DIR ? "min" : "", want & SRC_DIR ? "src" : "")); p = strrchr(patbuf, '.'); if (p) *p = '\0'; if (!uflag) /* if -u not specifIEd then we always print the pattern */ printf("%s:", patbuf); for (; ls; ls = ls->next) { if ((ls->type & want) && ls->path) findin(ls->path, patbuf, &count, &wait); } free(wait); if (!uflag || (uflag && count > 1)) putchar('\n'); return; } static void list_dirlist(struct wh_dirlist *ls) { while (ls) { if (ls->path) { switch (ls->type) { case BIN_DIR: printf("bin: "); break; case MAN_DIR: printf("man: "); break; case SRC_DIR: printf("src: "); break; default: abort(); } printf("%s\n", ls->path); } ls = ls->next; } } int main(int argc, char **argv) { struct wh_dirlist *ls = NULL; int want = ALL_DIRS; int i, want_resetable = 0; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); if (argc == 1) usage(stderr); whereis_init_debug(); construct_dirlist(&ls, BIN_DIR, bindirs); construct_dirlist_from_env("PATH", &ls, BIN_DIR); construct_dirlist(&ls, MAN_DIR, mandirs); construct_dirlist_from_env("MANPATH", &ls, MAN_DIR); construct_dirlist(&ls, SRC_DIR, srcdirs); for (i = 1; i < argc; i++) { const char *arg = argv[i]; int arg_i = i; DBG(ARGV, ul_debug("argv[%d]: %s", i, arg)); |