int main(int argc, char *argv[]) { int ch, term; size_t i, sz, len; struct mansearch search; struct manpage *res; char *conf_file, *defpaths, *auxpaths, *cp; char buf[PATH_MAX]; const char *cmd; struct manpaths paths; char *progname; extern char *optarg; extern int optind; term = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO); progname = strrchr(argv[0], '/'); if (progname == NULL) progname = argv[0]; else ++progname; auxpaths = defpaths = conf_file = NULL; memset(&paths, 0, sizeof(struct manpaths)); memset(&search, 0, sizeof(struct mansearch)); while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:"))) switch (ch) { case ('C'): conf_file = optarg; break; case ('M'): defpaths = optarg; break; case ('m'): auxpaths = optarg; break; case ('S'): search.arch = optarg; break; case ('s'): search.sec = optarg; break; default: goto usage; } argc -= optind; argv += optind; if (0 == argc) goto usage; search.deftype = TYPE_Nm | TYPE_Nd; manpath_parse(&paths, conf_file, defpaths, auxpaths); ch = mansearch(&search, &paths, argc, argv, "Nd", &res, &sz); manpath_free(&paths); if (0 == ch) goto usage; if (0 == sz) { free(res); return(EXIT_FAILURE); } else if (1 == sz && term) { i = 1; goto show; } else if (NULL == res) return(EXIT_FAILURE); for (i = 0; i < sz; i++) { printf("%6zu %s: %s\n", i + 1, res[i].names, res[i].output); free(res[i].names); free(res[i].output); } if (0 == term) { for (i = 0; i < sz; i++) free(res[i].file); free(res); return(EXIT_SUCCESS); } i = 1; printf("Enter a choice [1]: "); fflush(stdout); if (NULL != (cp = fgetln(stdin, &len))) if ('\n' == cp[--len] && len > 0) { cp[len] = '\0'; if ((i = atoi(cp)) < 1 || i > sz) i = 0; } if (0 == i) { for (i = 0; i < sz; i++) free(res[i].file); free(res); return(EXIT_SUCCESS); } show: cmd = res[i - 1].form ? "mandoc" : "cat"; strlcpy(buf, res[i - 1].file, PATH_MAX); for (i = 0; i < sz; i++) free(res[i].file); free(res); show(cmd, buf); /* NOTREACHED */ usage: fprintf(stderr, "usage: %s [-C conf] " "[-M paths] " "[-m paths] " "[-S arch] " "[-s section] " "expr ...\n", progname); return(EXIT_FAILURE); }
static void pg_search(const struct req *req) { struct mansearch search; struct manpaths paths; struct manpage *res; char **argv; char *query, *rp, *wp; size_t ressz; int argc; /* * Begin by chdir()ing into the root of the manpath. * This way we can pick up the database files, which are * relative to the manpath root. */ if (-1 == (chdir(req->q.manpath))) { fprintf(stderr, "chdir %s: %s\n", req->q.manpath, strerror(errno)); pg_error_internal(); return; } search.arch = req->q.arch; search.sec = req->q.sec; search.outkey = "Nd"; search.argmode = req->q.equal ? ARG_NAME : ARG_EXPR; search.firstmatch = 1; paths.sz = 1; paths.paths = mandoc_malloc(sizeof(char *)); paths.paths[0] = mandoc_strdup("."); /* * Break apart at spaces with backslash-escaping. */ argc = 0; argv = NULL; rp = query = mandoc_strdup(req->q.query); for (;;) { while (isspace((unsigned char)*rp)) rp++; if (*rp == '\0') break; argv = mandoc_reallocarray(argv, argc + 1, sizeof(char *)); argv[argc++] = wp = rp; for (;;) { if (isspace((unsigned char)*rp)) { *wp = '\0'; rp++; break; } if (rp[0] == '\\' && rp[1] != '\0') rp++; if (wp != rp) *wp = *rp; if (*rp == '\0') break; wp++; rp++; } } if (0 == mansearch(&search, &paths, argc, argv, &res, &ressz)) pg_noresult(req, "You entered an invalid query."); else if (0 == ressz) pg_noresult(req, "No results found."); else pg_searchres(req, res, ressz); free(query); mansearch_free(res, ressz); free(paths.paths[0]); free(paths.paths); }