From c5921aad51ca8f387c3147a2dc20e12427d87050 Mon Sep 17 00:00:00 2001 From: schwarze Date: Tue, 13 Jan 2015 23:16:12 +0000 Subject: [PATCH] Be developer-friendly, 'cause OpenBSD devs like to: cd /usr/src/share/man/man4; vi newdev.4 Makefile; make install; man newdev When a manual is missing from an outdated database, let man(1) show it anyway, using a KISS file system lookup as a fallback. Requested by deraadt@. 87 new lines of code doesn't seem too much bloat to me. Of course, keeping your mandoc.db(5) files up to date with makewhatis(8) or weekly(8) is still required for apropos(1) to find your new pages. --- usr.bin/mandoc/main.c | 107 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 5 deletions(-) diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c index 5558923ef7e..b607d94a1c8 100644 --- a/usr.bin/mandoc/main.c +++ b/usr.bin/mandoc/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.118 2015/01/13 13:22:13 schwarze Exp $ */ +/* $OpenBSD: main.c,v 1.119 2015/01/13 23:16:12 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze @@ -75,6 +75,13 @@ struct curparse { char outopts[BUFSIZ]; /* buf of output opts */ }; +static int fs_lookup(const struct manpaths *, + size_t ipath, const char *, + const char *, const char *, + struct manpage **, size_t *); +static void fs_search(const struct mansearch *, + const struct manpaths *, int, char**, + struct manpage **, size_t *); static int koptions(int *, char *); int mandocdb(int, char**); static int moptions(int *, char *); @@ -313,12 +320,11 @@ main(int argc, char *argv[]) mansearch_setup(1); if( ! mansearch(&search, &paths, argc, argv, &res, &sz)) usage(search.argmode); - resp = res; + + if (sz == 0 && search.argmode == ARG_NAME) + fs_search(&search, &paths, argc, argv, &res, &sz); if (sz == 0) { - if (search.argmode == ARG_NAME) - fprintf(stderr, "%s: No entry for %s " - "in the manual.\n", progname, argv[0]); rc = MANDOCLEVEL_BADARG; goto out; } @@ -337,6 +343,7 @@ main(int argc, char *argv[]) /* Iterate all matching manuals. */ + resp = res; for (i = 0; i < sz; i++) { if (outmode == OUTMODE_FLN) puts(res[i].file); @@ -482,6 +489,96 @@ usage(enum argmode argmode) exit((int)MANDOCLEVEL_BADARG); } +static int +fs_lookup(const struct manpaths *paths, size_t ipath, + const char *sec, const char *arch, const char *name, + struct manpage **res, size_t *ressz) +{ + struct manpage *page; + char *file; + int form; + + mandoc_asprintf(&file, "%s/man%s/%s.%s", + paths->paths[ipath], sec, name, sec); + if (access(file, R_OK) != -1) { + form = FORM_SRC; + goto found; + } + free(file); + + mandoc_asprintf(&file, "%s/cat%s/%s.0", + paths->paths[ipath], sec, name); + if (access(file, R_OK) != -1) { + form = FORM_CAT; + goto found; + } + free(file); + + if (arch != NULL) { + mandoc_asprintf(&file, "%s/man%s/%s/%s.%s", + paths->paths[ipath], sec, arch, name, sec); + if (access(file, R_OK) != -1) { + form = FORM_SRC; + goto found; + } + free(file); + } + return(0); + +found: + fprintf(stderr, "%s: outdated mandoc.db lacks %s(%s) entry,\n" + " consider running # makewhatis %s\n", + progname, name, sec, paths->paths[ipath]); + + *res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage)); + page = *res + (*ressz - 1); + page->file = file; + page->names = NULL; + page->output = NULL; + page->ipath = ipath; + page->bits = NAME_FILE & NAME_MASK; + page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; + page->form = form; + return(1); +} + +static void +fs_search(const struct mansearch *cfg, const struct manpaths *paths, + int argc, char **argv, struct manpage **res, size_t *ressz) +{ + const char *const sections[] = + {"1", "8", "6", "2", "3", "3p", "5", "7", "4", "9"}; + const size_t nsec = sizeof(sections)/sizeof(sections[0]); + + size_t ipath, isec, lastsz; + + assert(cfg->argmode == ARG_NAME); + + *res = NULL; + *ressz = lastsz = 0; + while (argc) { + for (ipath = 0; ipath < paths->sz; ipath++) { + if (cfg->sec != NULL) { + if (fs_lookup(paths, ipath, cfg->sec, + cfg->arch, *argv, res, ressz) && + cfg->firstmatch) + return; + } else for (isec = 0; isec < nsec; isec++) + if (fs_lookup(paths, ipath, sections[isec], + cfg->arch, *argv, res, ressz) && + cfg->firstmatch) + return; + } + if (*ressz == lastsz) + fprintf(stderr, + "%s: No entry for %s in the manual.\n", + progname, *argv); + lastsz = *ressz; + argv++; + argc--; + } +} + static void parse(struct curparse *curp, int fd, const char *file, enum mandoclevel *level) -- 2.20.1