/* * Scan options passed to program. * * Note that the -B/-M/-S options expect a list of directory * names that must be terminated with -f. */ void scanopts(int argc, char **argv) { int c, i; ccharp **dirlist; while ((c = getopt(argc, argv, "BMSabfmqsux")) != -1) switch (c) { case 'B': dirlist = &bindirs; goto dolist; case 'M': dirlist = &mandirs; goto dolist; case 'S': dirlist = &sourcedirs; dolist: i = 0; *dirlist = realloc(*dirlist, (i + 1) * sizeof(char *)); (*dirlist)[i] = NULL; while (optind < argc && strcmp(argv[optind], "-f") != 0 && strcmp(argv[optind], "-B") != 0 && strcmp(argv[optind], "-M") != 0 && strcmp(argv[optind], "-S") != 0) { decolonify(argv[optind], dirlist, &i); optind++; } break; case 'a': opt_a = 1; break; case 'b': opt_b = 1; break; case 'f': goto breakout; case 'm': opt_m = 1; break; case 'q': opt_q = 1; break; case 's': opt_s = 1; break; case 'u': opt_u = 1; break; case 'x': opt_x = 1; break; default: usage(); } breakout: if (optind == argc) usage(); query = argv + optind; }
/* * Provide defaults for all options and directory lists. */ void defaults(void) { size_t s; char *b, buf[BUFSIZ], *cp; int nele; FILE *p; DIR *dir; struct stat sb; struct dirent *dirp; /* default to -bms if none has been specified */ if (!opt_b && !opt_m && !opt_s) opt_b = opt_m = opt_s = 1; /* -b defaults to default path + /usr/libexec + * /usr/games + user's path */ if (!bindirs) { if (sysctlbyname("user.cs_path", NULL, &s, NULL, 0) == -1) err(EX_OSERR, "sysctlbyname(\"user.cs_path\")"); if ((b = malloc(s + 1)) == NULL) abort(); if (sysctlbyname("user.cs_path", b, &s, NULL, 0) == -1) err(EX_OSERR, "sysctlbyname(\"user.cs_path\")"); nele = 0; decolonify(b, &bindirs, &nele); bindirs = realloc(bindirs, (nele + 3) * sizeof(char *)); if (bindirs == NULL) abort(); bindirs[nele++] = PATH_LIBEXEC; bindirs[nele++] = PATH_GAMES; bindirs[nele] = NULL; if ((cp = getenv("PATH")) != NULL) { /* don't destroy the original environment... */ if ((b = malloc(strlen(cp) + 1)) == NULL) abort(); strcpy(b, cp); decolonify(b, &bindirs, &nele); } } /* -m defaults to $(manpath) */ if (!mandirs) { if ((p = popen(MANPATHCMD, "r")) == NULL) err(EX_OSERR, "cannot execute manpath command"); if (fgets(buf, BUFSIZ - 1, p) == NULL || pclose(p)) err(EX_OSERR, "error processing manpath results"); if ((b = strchr(buf, '\n')) != NULL) *b = '\0'; if ((b = malloc(strlen(buf) + 1)) == NULL) abort(); strcpy(b, buf); nele = 0; decolonify(b, &mandirs, &nele); } /* -s defaults to precompiled list, plus subdirs of /usr/dports */ if (!sourcedirs) { if ((b = malloc(strlen(sourcepath) + 1)) == NULL) abort(); strcpy(b, sourcepath); nele = 0; decolonify(b, &sourcedirs, &nele); if (stat(PATH_DPORTS, &sb) == -1) { if (errno != ENOENT) err(EX_OSERR, "stat(" PATH_DPORTS ")"); } else { if ((sb.st_mode & S_IFMT) != S_IFDIR) /* /usr/dports is not a directory, ignore */ return; if (access(PATH_DPORTS, R_OK | X_OK) != 0) return; if ((dir = opendir(PATH_DPORTS)) == NULL) err(EX_OSERR, "opendir" PATH_DPORTS ")"); while ((dirp = readdir(dir)) != NULL) { if (dirp->d_name[0] == '.') /* ignore dot entries */ continue; b = malloc(sizeof PATH_DPORTS + 1 + dirp->d_namlen); if (b == NULL) abort(); strcpy(b, PATH_DPORTS); strcat(b, "/"); strcat(b, dirp->d_name); if (stat(b, &sb) == -1 || (sb.st_mode & S_IFMT) != S_IFDIR || access(b, R_OK | X_OK) != 0) { free(b); continue; } sourcedirs = realloc(sourcedirs, (nele + 2) * sizeof(char *)); if (sourcedirs == NULL) abort(); sourcedirs[nele++] = b; sourcedirs[nele] = NULL; } closedir(dir); } } }
/* * Provide defaults for all options and directory lists. */ static void defaults(void) { size_t s; char *b, buf[BUFSIZ], *cp; int nele; FILE *p; DIR *dir; struct stat sb; struct dirent *dirp; /* default to -bms if none has been specified */ if (!opt_b && !opt_m && !opt_s) opt_b = opt_m = opt_s = 1; /* -b defaults to default path + /usr/libexec + * /usr/games + user's path */ if (!bindirs) { if (sysctlbyname("user.cs_path", (void *)NULL, &s, (void *)NULL, 0) == -1) err(EX_OSERR, "sysctlbyname(\"user.cs_path\")"); if ((b = malloc(s + 1)) == NULL) abort(); if (sysctlbyname("user.cs_path", b, &s, (void *)NULL, 0) == -1) err(EX_OSERR, "sysctlbyname(\"user.cs_path\")"); nele = 0; decolonify(b, &bindirs, &nele); bindirs = realloc(bindirs, (nele + 3) * sizeof(char *)); if (bindirs == NULL) abort(); bindirs[nele++] = PATH_LIBEXEC; bindirs[nele++] = PATH_GAMES; bindirs[nele] = NULL; if ((cp = getenv("PATH")) != NULL) { /* don't destroy the original environment... */ if ((b = malloc(strlen(cp) + 1)) == NULL) abort(); strcpy(b, cp); decolonify(b, &bindirs, &nele); } } /* -m defaults to $(manpath) */ if (!mandirs) { if ((p = popen(MANPATHCMD, "r")) == NULL) err(EX_OSERR, "cannot execute manpath command"); if (fgets(buf, BUFSIZ - 1, p) == NULL || pclose(p)) err(EX_OSERR, "error processing manpath results"); if ((b = strchr(buf, '\n')) != NULL) *b = '\0'; if ((b = malloc(strlen(buf) + 1)) == NULL) abort(); strcpy(b, buf); nele = 0; decolonify(b, &mandirs, &nele); } /* -s defaults to precompiled list, plus subdirs of /usr/ports */ if (!sourcedirs) { if ((b = malloc(strlen(sourcepath) + 1)) == NULL) abort(); strcpy(b, sourcepath); nele = 0; decolonify(b, &sourcedirs, &nele); if (stat(PATH_PORTS, &sb) == -1) { if (errno == ENOENT) /* no /usr/ports, we are done */ return; err(EX_OSERR, "stat(" PATH_PORTS ")"); } if ((sb.st_mode & S_IFMT) != S_IFDIR) /* /usr/ports is not a directory, ignore */ return; if (access(PATH_PORTS, R_OK | X_OK) != 0) return; if ((dir = opendir(PATH_PORTS)) == NULL) err(EX_OSERR, "opendir" PATH_PORTS ")"); while ((dirp = readdir(dir)) != NULL) { /* * Not everything below PATH_PORTS is of * interest. First, all dot files and * directories (e. g. .snap) can be ignored. * Also, all subdirectories starting with a * capital letter are not going to be * examined, as they are used for internal * purposes (Mk, Tools, ...). This also * matches a possible CVS subdirectory. * Finally, the distfiles subdirectory is also * special, and should not be considered to * avoid false matches. */ if (dirp->d_name[0] == '.' || /* * isupper() not used on purpose: the * check is supposed to default to the C * locale instead of the current user's * locale. */ (dirp->d_name[0] >= 'A' && dirp->d_name[0] <= 'Z') || strcmp(dirp->d_name, "distfiles") == 0) continue; if ((b = malloc(sizeof PATH_PORTS + 1 + dirp->d_namlen)) == NULL) abort(); strcpy(b, PATH_PORTS); strcat(b, "/"); strcat(b, dirp->d_name); if (stat(b, &sb) == -1 || (sb.st_mode & S_IFMT) != S_IFDIR || access(b, R_OK | X_OK) != 0) { free(b); continue; } sourcedirs = realloc(sourcedirs, (nele + 2) * sizeof(char *)); if (sourcedirs == NULL) abort(); sourcedirs[nele++] = b; sourcedirs[nele] = NULL; } closedir(dir); } }