aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2015-01-13 23:17:52 +0000
committerIngo Schwarze <schwarze@openbsd.org>2015-01-13 23:17:52 +0000
commitede54d9a7f9a40179b8d87dde1625a95b5b83692 (patch)
tree34361639fc959def38285c59801a05f4023142e2
parent9872a27825e0c9c8793fb6141af047bdc5412181 (diff)
downloadmandoc-ede54d9a7f9a40179b8d87dde1625a95b5b83692.tar.gz
mandoc-ede54d9a7f9a40179b8d87dde1625a95b5b83692.tar.zst
mandoc-ede54d9a7f9a40179b8d87dde1625a95b5b83692.zip
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.
-rw-r--r--main.c111
1 files changed, 106 insertions, 5 deletions
diff --git a/main.c b/main.c
index 24e3537c..010dfaa4 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.212 2015/01/13 13:22:22 schwarze Exp $ */
+/* $Id: main.c,v 1.213 2015/01/13 23:17:52 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -82,6 +82,15 @@ struct curparse {
char outopts[BUFSIZ]; /* buf of output opts */
};
+#if HAVE_SQLITE3
+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 *);
+#endif
static int koptions(int *, char *);
#if HAVE_SQLITE3
int mandocdb(int, char**);
@@ -340,12 +349,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;
}
@@ -364,6 +372,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);
@@ -525,6 +534,98 @@ usage(enum argmode argmode)
exit((int)MANDOCLEVEL_BADARG);
}
+#if HAVE_SQLITE3
+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--;
+ }
+}
+#endif
+
static void
parse(struct curparse *curp, int fd, const char *file,
enum mandoclevel *level)