From 2dcffed7ef84c2009020f2c105db781e9a7dff18 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Sat, 26 Nov 2011 16:41:36 +0000 Subject: Resync to bsd.lv, most code from kristaps@. In particular, support the MANPATH environment variable and don't confuse index record numbers when working with multiple mandoc databases at once. Besides, remove lots of gratuitious code and whitespace differences. --- usr.bin/mandoc/Makefile | 4 +- usr.bin/mandoc/apropos.1 | 51 ++++++++++------ usr.bin/mandoc/apropos.c | 74 +++++++++++----------- usr.bin/mandoc/apropos_db.c | 146 +++++++++++++++++++++++--------------------- usr.bin/mandoc/apropos_db.h | 11 +++- usr.bin/mandoc/man_conf.c | 88 -------------------------- usr.bin/mandoc/man_conf.h | 26 -------- usr.bin/mandoc/mandocdb.c | 56 +++++++++-------- usr.bin/mandoc/mandocdb.h | 6 +- usr.bin/mandoc/manpath.c | 141 ++++++++++++++++++++++++++++++++++++++++++ usr.bin/mandoc/manpath.h | 40 ++++++++++++ 11 files changed, 374 insertions(+), 269 deletions(-) delete mode 100644 usr.bin/mandoc/man_conf.c delete mode 100644 usr.bin/mandoc/man_conf.h create mode 100644 usr.bin/mandoc/manpath.c create mode 100644 usr.bin/mandoc/manpath.h (limited to 'usr.bin') diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile index 9fe438b5d8f..6c2ef54d434 100644 --- a/usr.bin/mandoc/Makefile +++ b/usr.bin/mandoc/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.64 2011/11/17 14:52:32 schwarze Exp $ +# $OpenBSD: Makefile,v 1.65 2011/11/26 16:41:35 schwarze Exp $ .include @@ -18,7 +18,7 @@ SRCS+= main.c mdoc_term.c chars.c term.c tree.c man_term.c eqn_term.c SRCS+= mdoc_man.c SRCS+= html.c mdoc_html.c man_html.c out.c eqn_html.c SRCS+= term_ps.c term_ascii.c tbl_term.c tbl_html.c -SRCS+= man_conf.c mandocdb.c apropos_db.c apropos.c +SRCS+= manpath.c mandocdb.c apropos_db.c apropos.c PROG= mandoc diff --git a/usr.bin/mandoc/apropos.1 b/usr.bin/mandoc/apropos.1 index 30184f4c924..34e2e0fe721 100644 --- a/usr.bin/mandoc/apropos.1 +++ b/usr.bin/mandoc/apropos.1 @@ -1,4 +1,4 @@ -.\" $Id: apropos.1,v 1.5 2011/11/26 13:07:15 schwarze Exp $ +.\" $Id: apropos.1,v 1.6 2011/11/26 16:41:35 schwarze Exp $ .\" .\" Copyright (c) 2011 Kristaps Dzonsons .\" @@ -19,22 +19,36 @@ .Os .Sh NAME .Nm apropos -.Nd search the manual page database +.Nd search manual page databases .Sh SYNOPSIS .Nm +.Op Fl M Ar manpath +.Op Fl m Ar manpath .Op Fl S Ar arch .Op Fl s Ar section .Ar expression... .Sh DESCRIPTION The .Nm -utility queries a manual page database generated by +utility queries manual page databases generated by .Xr mandocdb 8 , evaluating on .Ar expression -for each file in the database. +for each file in each database. Its arguments are as follows: .Bl -tag -width Ds +.It Fl M Ar manpath +Use the colon-separated path instead of the default list of paths +searched for +.Xr mandocdb 8 +databases. +Invalid paths, or paths without manual databases, are ignored. +.It Fl m Ar manpath +Prepend the colon-separated paths to the list of paths searched +for +.Xr mandocdb 8 +databases. +Invalid paths, or paths without manual databases, are ignored. .It Fl S Ar arch Search only for a particular architecture. .It Fl s Ar cat @@ -104,6 +118,10 @@ is evaluated case-insensitively. .Pp By default, .Nm +searches for +.Xr mandocdb 8 +databases in the default paths stipulated by +.Xr man 1 , parses terms as case-sensitive regular expressions .Pq the Li \&~ operator over manual names and descriptions @@ -133,12 +151,15 @@ Resulting manuals may be accessed as If an architecture is specified in the output, use .Pp .Dl $ man \-s sec \-S arch title -.\" .Sh IMPLEMENTATION NOTES -.\" Not used in OpenBSD. -.\" .Sh RETURN VALUES -.\" For sections 2, 3, & 9 only. -.\" .Sh ENVIRONMENT -.\" For sections 1, 6, 7, & 8 only. +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev MANPATH +Colon-separated paths overriding the default list of paths searched for +manual databases. +Invalid paths, or paths without manual databases, are ignored. +Overridden by +.Fl M . +.El .\" .Sh FILES .Sh EXIT STATUS .Ex -std @@ -172,23 +193,13 @@ Search for all manuals referencing in any letter case: .Pp .Dl $ apropos \-\- \-i posix -.\" .Sh DIAGNOSTICS -.\" For sections 1, 4, 6, 7, & 8 only. -.\" .Sh ERRORS -.\" For sections 2, 3, & 9 only. .Sh SEE ALSO .Xr man 1 , .Xr mandoc 1 , .Xr re_format 7 -.\" .Sh STANDARDS -.\" .Sh HISTORY .Sh AUTHORS The .Nm utility was written by .An Kristaps Dzonsons , .Mt kristaps@bsd.lv . -.\" .Sh CAVEATS -.\" .Sh BUGS -.\" .Sh SECURITY CONSIDERATIONS -.\" Not used in OpenBSD. diff --git a/usr.bin/mandoc/apropos.c b/usr.bin/mandoc/apropos.c index a2a15647601..b1d84a42090 100644 --- a/usr.bin/mandoc/apropos.c +++ b/usr.bin/mandoc/apropos.c @@ -1,6 +1,7 @@ -/* $Id: apropos.c,v 1.7 2011/11/18 01:10:03 schwarze Exp $ */ +/* $Id: apropos.c,v 1.8 2011/11/26 16:41:35 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons + * Copyright (c) 2011 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,14 +17,13 @@ */ #include #include -#include #include #include #include #include "apropos_db.h" -#include "man_conf.h" #include "mandoc.h" +#include "manpath.h" static int cmp(const void *, const void *); static void list(struct res *, size_t, void *); @@ -34,31 +34,35 @@ static char *progname; int apropos(int argc, char *argv[]) { - struct man_conf dirs; - int ch, use_man_conf; + int ch, rc; + struct manpaths paths; size_t terms; struct opts opts; struct expr *e; + char *defpaths, *auxpaths; extern int optind; extern char *optarg; - memset(&dirs, 0, sizeof(struct man_conf)); - memset(&opts, 0, sizeof(struct opts)); - use_man_conf = 1; - progname = strrchr(argv[0], '/'); if (progname == NULL) progname = argv[0]; else ++progname; - while (-1 != (ch = getopt(argc, argv, "M:m:S:s:"))) + memset(&paths, 0, sizeof(struct manpaths)); + memset(&opts, 0, sizeof(struct opts)); + + auxpaths = defpaths = NULL; + e = NULL; + rc = 0; + + while (-1 != (ch = getopt(argc, argv, "M:m:S:s:"))) switch (ch) { case ('M'): - use_man_conf = 0; - /* FALLTHROUGH */ + defpaths = optarg; + break; case ('m'): - manpath_parse(&dirs, optarg); + auxpaths = optarg; break; case ('S'): opts.arch = optarg; @@ -68,37 +72,37 @@ apropos(int argc, char *argv[]) break; default: usage(); - return(EXIT_FAILURE); + goto out; } argc -= optind; argv += optind; - if (0 == argc) - return(EXIT_SUCCESS); + if (0 == argc) { + rc = 1; + goto out; + } + + manpath_parse(&paths, defpaths, auxpaths); if (NULL == (e = exprcomp(argc, argv, &terms))) { - fprintf(stderr, "Bad expression\n"); - return(EXIT_FAILURE); + fprintf(stderr, "%s: Bad expression\n", progname); + goto out; } - /* - * Configure databases. - * The keyword database is a btree that allows for duplicate - * entries. - * The index database is a recno. - */ + rc = apropos_search + (paths.sz, paths.paths, + &opts, e, terms, NULL, list); - if (use_man_conf) - man_conf_parse(&dirs); - ch = apropos_search(dirs.argc, dirs.argv, &opts, - e, terms, NULL, list); + if (0 == rc) + fprintf(stderr, "%s: Error reading " + "manual database\n", progname); - man_conf_free(&dirs); +out: + manpath_free(&paths); exprfree(e); - if (0 == ch) - fprintf(stderr, "%s: Database error\n", progname); - return(ch ? EXIT_SUCCESS : EXIT_FAILURE); + + return(rc ? EXIT_SUCCESS : EXIT_FAILURE); } /* ARGSUSED */ @@ -110,8 +114,8 @@ list(struct res *res, size_t sz, void *arg) qsort(res, sz, sizeof(struct res), cmp); for (i = 0; i < (int)sz; i++) - printf("%s(%s%s%s) - %s\n", res[i].title, - res[i].cat, + printf("%s(%s%s%s) - %s\n", res[i].title, + res[i].cat, *res[i].arch ? "/" : "", *res[i].arch ? res[i].arch : "", res[i].desc); @@ -134,6 +138,6 @@ usage(void) "[-m path] " "[-S arch] " "[-s section] " - "expression...\n", + "expression...\n", progname); } diff --git a/usr.bin/mandoc/apropos_db.c b/usr.bin/mandoc/apropos_db.c index 8021ecaa145..8a120a54724 100644 --- a/usr.bin/mandoc/apropos_db.c +++ b/usr.bin/mandoc/apropos_db.c @@ -1,4 +1,4 @@ -/* $Id: apropos_db.c,v 1.7 2011/11/18 01:10:03 schwarze Exp $ */ +/* $Id: apropos_db.c,v 1.8 2011/11/26 16:41:35 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze @@ -34,11 +34,6 @@ #include "apropos_db.h" #include "mandoc.h" -struct rectree { - struct rec *node; - int len; -}; - struct rec { struct res res; /* resulting record info */ /* @@ -70,6 +65,11 @@ struct type { const char *name; }; +struct rectree { + struct rec *node; /* record array for dir tree */ + int len; /* length of record array */ +}; + static const struct type types[] = { { TYPE_An, "An" }, { TYPE_Ar, "Ar" }, @@ -125,7 +125,7 @@ static int exprmark(const struct expr *, static struct expr *exprexpr(int, char *[], int *, int *, size_t *); static struct expr *exprterm(char *, int); static DB *index_open(void); -static int index_read(const DBT *, const DBT *, +static int index_read(const DBT *, const DBT *, int, const struct mchars *, struct rec *); static void norm_string(const char *, const struct mchars *, char **); @@ -133,7 +133,7 @@ static size_t norm_utf8(unsigned int, char[7]); static void recfree(struct rec *); static int single_search(struct rectree *, const struct opts *, const struct expr *, size_t terms, - struct mchars *); + struct mchars *, int); /* * Open the keyword mandoc-db database. @@ -148,7 +148,7 @@ btree_open(void) info.flags = R_DUP; db = dbopen(MANDOC_DB, O_RDONLY, 0, DB_BTREE, &info); - if (NULL != db) + if (NULL != db) return(db); return(NULL); @@ -165,6 +165,7 @@ btree_read(const DBT *v, const struct mchars *mc, char **buf) /* Sanity: are we nil-terminated? */ assert(v->size > 0); + if ('\0' != ((char *)v->data)[(int)v->size - 1]) return(0); @@ -175,7 +176,7 @@ btree_read(const DBT *v, const struct mchars *mc, char **buf) /* * Take a Unicode codepoint and produce its UTF-8 encoding. * This isn't the best way to do this, but it works. - * The magic numbers are from the UTF-8 packaging. + * The magic numbers are from the UTF-8 packaging. * They're not as scary as they seem: read the UTF-8 spec for details. */ static size_t @@ -240,7 +241,7 @@ norm_string(const char *val, const struct mchars *mc, char **buf) const char *seq, *cpp; int len, u, pos; enum mandoc_esc esc; - static const char res[] = { '\\', '\t', + static const char res[] = { '\\', '\t', ASCII_NBRSP, ASCII_HYPH, '\0' }; /* Pre-allocate by the length of the input */ @@ -286,7 +287,7 @@ norm_string(const char *val, const struct mchars *mc, char **buf) if (ESCAPE_ERROR == esc) break; - /* + /* * XXX - this just does UTF-8, but we need to know * beforehand whether we should do text substitution. */ @@ -344,7 +345,7 @@ index_open(void) * Returns 1 if an entry was unpacked, 0 if the database is insane. */ static int -index_read(const DBT *key, const DBT *val, +index_read(const DBT *key, const DBT *val, int index, const struct mchars *mc, struct rec *rec) { size_t left; @@ -363,6 +364,7 @@ index_read(const DBT *key, const DBT *val, cp = (char *)val->data; rec->res.rec = *(recno_t *)key->data; + rec->res.volume = index; INDEX_BREAD(rec->res.file); INDEX_BREAD(rec->res.cat); @@ -373,14 +375,14 @@ index_read(const DBT *key, const DBT *val, } /* - * Search the mandocdb database for the expression "expr". + * Search mandocdb databases in paths for expression "expr". * Filter out by "opts". * Call "res" with the results, which may be zero. * Return 0 if there was a database error, else return 1. */ int -apropos_search(int argc, char *argv[], const struct opts *opts, - const struct expr *expr, size_t terms, void *arg, +apropos_search(int pathsz, char **paths, const struct opts *opts, + const struct expr *expr, size_t terms, void *arg, void (*res)(struct res *, size_t, void *)) { struct rectree tree; @@ -390,47 +392,57 @@ apropos_search(int argc, char *argv[], const struct opts *opts, memset(&tree, 0, sizeof(struct rectree)); + rc = 0; mc = mchars_alloc(); - rc = 1; - for (i = 0; i < argc; i++) { - if (chdir(argv[i])) + /* + * Main loop. Change into the directory containing manpage + * databases. Run our expession over each database in the set. + */ + + for (i = 0; i < pathsz; i++) { + if (chdir(paths[i])) continue; - if (0 == single_search(&tree, opts, expr, terms, mc)) - rc = 0; + if ( ! single_search(&tree, opts, expr, terms, mc, i)) + goto out; } /* - * Count the matching files - * and feed them to the output handler. + * Count matching files, transfer to a "clean" array, then feed + * them to the output handler. */ for (mlen = i = 0; i < tree.len; i++) if (tree.node[i].matched) mlen++; + ress = mandoc_malloc(mlen * sizeof(struct res)); + for (mlen = i = 0; i < tree.len; i++) if (tree.node[i].matched) - memcpy(&ress[mlen++], &tree.node[i].res, + memcpy(&ress[mlen++], &tree.node[i].res, sizeof(struct res)); + (*res)(ress, mlen, arg); free(ress); + rc = 1; +out: for (i = 0; i < tree.len; i++) recfree(&tree.node[i]); - if (mc) - mchars_free(mc); - + free(tree.node); + mchars_free(mc); return(rc); } static int single_search(struct rectree *tree, const struct opts *opts, const struct expr *expr, size_t terms, - struct mchars *mc) + struct mchars *mc, int vol) { - int root, leaf, rc; + int root, leaf, ch; + uint64_t mask; DBT key, val; DB *btree, *idx; char *buf; @@ -445,36 +457,33 @@ single_search(struct rectree *tree, const struct opts *opts, idx = NULL; buf = NULL; rs = tree->node; - rc = 0; memset(&r, 0, sizeof(struct rec)); - /* XXX: return fact that we've errored? */ + if (NULL == (btree = btree_open())) + return(1); - if (NULL == (btree = btree_open())) - goto out; - if (NULL == (idx = index_open())) - goto out; + if (NULL == (idx = index_open())) { + (*btree->close)(btree); + return(1); + } - while (0 == (*btree->seq)(btree, &key, &val, R_NEXT)) { - /* - * Low-water mark for key and value. - * The key must have something in it, and the value must - * have the correct tags/recno mix. - */ - if (key.size < 2 || sizeof(struct db_val) != val.size) - goto out; + while (0 == (ch = (*btree->seq)(btree, &key, &val, R_NEXT))) { + if (key.size < 2 || sizeof(struct db_val) != val.size) + break; if ( ! btree_read(&key, mc, &buf)) - goto out; + break; + + vbuf = val.data; + rec = vbuf->rec; + mask = vbuf->mask; /* * See if this keyword record matches any of the * expressions we have stored. */ - vbuf = val.data; - if ( ! exprmark(expr, buf, vbuf->mask, NULL)) + if ( ! exprmark(expr, buf, mask, NULL)) continue; - rec = vbuf->rec; /* * O(log n) scan for prior records. Since a record @@ -489,7 +498,7 @@ single_search(struct rectree *tree, const struct opts *opts, else if (rec < rs[leaf].res.rec && rs[leaf].lhs >= 0) leaf = rs[leaf].lhs; - else + else break; /* @@ -500,7 +509,7 @@ single_search(struct rectree *tree, const struct opts *opts, if (leaf >= 0 && rs[leaf].res.rec == rec) { if (0 == rs[leaf].matched) - exprexec(expr, buf, vbuf->mask, &rs[leaf]); + exprexec(expr, buf, mask, &rs[leaf]); continue; } @@ -514,13 +523,14 @@ single_search(struct rectree *tree, const struct opts *opts, key.size = sizeof(recno_t); if (0 != (*idx->get)(idx, &key, &val, 0)) - goto out; + break; r.lhs = r.rhs = -1; - if ( ! index_read(&key, &val, mc, &r)) - goto out; + if ( ! index_read(&key, &val, vol, mc, &r)) + break; /* XXX: this should be elsewhere, I guess? */ + if (opts->cat && strcasecmp(opts->cat, r.res.cat)) continue; if (opts->arch && strcasecmp(opts->arch, r.res.arch)) @@ -530,9 +540,10 @@ single_search(struct rectree *tree, const struct opts *opts, (rs, (tree->len + 1) * sizeof(struct rec)); memcpy(&rs[tree->len], &r, sizeof(struct rec)); - rs[tree->len].matches = mandoc_calloc(terms, sizeof(int)); + rs[tree->len].matches = + mandoc_calloc(terms, sizeof(int)); - exprexec(expr, buf, vbuf->mask, &rs[tree->len]); + exprexec(expr, buf, mask, &rs[tree->len]); /* Append to our tree. */ @@ -543,23 +554,16 @@ single_search(struct rectree *tree, const struct opts *opts, rs[leaf].lhs = tree->len; } else root = tree->len; - + memset(&r, 0, sizeof(struct rec)); tree->len++; } - rc = 1; - -out: - recfree(&r); - if (btree) - (*btree->close)(btree); - if (idx) - (*idx->close)(idx); + (*btree->close)(btree); + (*idx->close)(idx); free(buf); - - return(rc); + return(1 == ch); } static void @@ -629,7 +633,7 @@ exprexpr(int argc, char *argv[], int *pos, int *lvl, size_t *tt) log = 0; if (NULL != e && 0 == strcmp("-a", argv[*pos])) - log = 1; + log = 1; else if (NULL != e && 0 == strcmp("-o", argv[*pos])) log = 2; @@ -741,7 +745,7 @@ void exprfree(struct expr *p) { struct expr *pp; - + while (NULL != p) { if (p->subexpr) exprfree(p->subexpr); @@ -755,7 +759,8 @@ exprfree(struct expr *p) } static int -exprmark(const struct expr *p, const char *cp, uint64_t mask, int *ms) +exprmark(const struct expr *p, const char *cp, + uint64_t mask, int *ms) { for ( ; p; p = p->next) { @@ -782,6 +787,8 @@ exprmark(const struct expr *p, const char *cp, uint64_t mask, int *ms) else ms[p->index] = 1; } + + return(0); } static int @@ -824,7 +831,8 @@ expreval(const struct expr *p, int *ms) * If this evaluates to true, mark the expression as satisfied. */ static void -exprexec(const struct expr *e, const char *cp, uint64_t mask, struct rec *r) +exprexec(const struct expr *e, const char *cp, + uint64_t mask, struct rec *r) { assert(0 == r->matched); diff --git a/usr.bin/mandoc/apropos_db.h b/usr.bin/mandoc/apropos_db.h index f7a26bcec45..2c1b286cefc 100644 --- a/usr.bin/mandoc/apropos_db.h +++ b/usr.bin/mandoc/apropos_db.h @@ -1,4 +1,4 @@ -/* $Id: apropos_db.h,v 1.6 2011/11/18 01:10:03 schwarze Exp $ */ +/* $Id: apropos_db.h,v 1.7 2011/11/26 16:41:35 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -24,6 +24,11 @@ struct res { char *arch; /* arch (or empty string) */ char *desc; /* description (from Nd) */ unsigned int rec; /* record in index */ + /* + * The index volume. This indexes into the array of directories + * searched for manual page databases. + */ + unsigned int volume; }; struct opts { @@ -35,8 +40,8 @@ __BEGIN_DECLS struct expr; -int apropos_search(int, char **, const struct opts *, - const struct expr *, size_t, void *, +int apropos_search(int, char **, const struct opts *, + const struct expr *, size_t, void *, void (*)(struct res *, size_t, void *)); struct expr *exprcomp(int, char *[], size_t *); void exprfree(struct expr *); diff --git a/usr.bin/mandoc/man_conf.c b/usr.bin/mandoc/man_conf.c deleted file mode 100644 index 8e46d6ae1ce..00000000000 --- a/usr.bin/mandoc/man_conf.c +++ /dev/null @@ -1,88 +0,0 @@ -/* $Id: man_conf.c,v 1.1 2011/11/17 14:52:32 schwarze Exp $ */ -/* - * Copyright (c) 2011 Ingo Schwarze - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "mandoc.h" -#include "man_conf.h" - -#define MAN_CONF_FILE "/etc/man.conf" - -static void add_dir(struct man_conf *, const char *); - -static void -add_dir(struct man_conf *dirs, const char *dir) { - - if (dirs->maxargs == dirs->argc) { - dirs->maxargs += 8; - assert(0 < dirs->maxargs); - dirs->argv = mandoc_realloc(dirs->argv, - (size_t)dirs->maxargs); - } - dirs->argv[dirs->argc++] = mandoc_strdup(dir); -} - -void -manpath_parse(struct man_conf *dirs, char *path) { - char *dir; - - for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":")) - add_dir(dirs, dir); -} - -void -man_conf_parse(struct man_conf *dirs) { - FILE *stream; - char *p, *q; - size_t len; - - if (NULL == (stream = fopen(MAN_CONF_FILE, "r"))) - return; - - while (NULL != (p = fgetln(stream, &len)) && '\n' == p[--len]) { - p[len] = '\0'; - while (isspace(*p)) - p++; - if (strncmp("_whatdb", p, 7)) - continue; - p += 7; - while (isspace(*p)) - p++; - if ('\0' == *p) - continue; - if (NULL == (q = strrchr(p, '/'))) - continue; - *q = '\0'; - add_dir(dirs, p); - } - - fclose(stream); -} - -void -man_conf_free(struct man_conf *dirs) { - - while (dirs->argc--) - free(dirs->argv[dirs->argc]); - free(dirs->argv); - dirs->maxargs = 0; -} diff --git a/usr.bin/mandoc/man_conf.h b/usr.bin/mandoc/man_conf.h deleted file mode 100644 index b93cf5189a5..00000000000 --- a/usr.bin/mandoc/man_conf.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id: man_conf.h,v 1.1 2011/11/17 14:52:32 schwarze Exp $ */ -/* - * Copyright (c) 2011 Ingo Schwarze - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -struct man_conf { - int maxargs; - int argc; - char **argv; -}; - -void manpath_parse(struct man_conf *, char *); -void man_conf_parse(struct man_conf *); -void man_conf_free(struct man_conf *); diff --git a/usr.bin/mandoc/mandocdb.c b/usr.bin/mandoc/mandocdb.c index 15981d6f268..10413256cff 100644 --- a/usr.bin/mandoc/mandocdb.c +++ b/usr.bin/mandoc/mandocdb.c @@ -1,6 +1,7 @@ -/* $Id: mandocdb.c,v 1.9 2011/11/17 15:38:27 schwarze Exp $ */ +/* $Id: mandocdb.c,v 1.10 2011/11/26 16:41:35 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons + * Copyright (c) 2011 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,14 +25,13 @@ #include #include #include -#include #include #include "man.h" #include "mdoc.h" #include "mandoc.h" #include "mandocdb.h" -#include "man_conf.h" +#include "manpath.h" #define MANDOC_BUFSZ BUFSIZ #define MANDOC_SLOP 1024 @@ -244,8 +244,8 @@ static const char *progname; int mandocdb(int argc, char *argv[]) { - struct man_conf dirs; struct mparse *mp; /* parse sequence */ + struct manpaths dirs; enum op op; /* current operation */ const char *dir; char ibuf[MAXPATHLEN], /* index fname */ @@ -274,6 +274,8 @@ mandocdb(int argc, char *argv[]) else ++progname; + memset(&dirs, 0, sizeof(struct manpaths)); + verb = 0; use_all = 0; of = NULL; @@ -310,7 +312,6 @@ mandocdb(int argc, char *argv[]) argc -= optind; argv += optind; - memset(&dirs, 0, sizeof(struct man_conf)); memset(&info, 0, sizeof(BTREEINFO)); info.flags = R_DUP; @@ -367,35 +368,42 @@ mandocdb(int argc, char *argv[]) index_prune(of, db, fbuf, idx, ibuf, verb, &maxrec, &recs, &recsz); - if (OP_UPDATE == op) { - chdir(dir); - index_merge(of, mp, &dbuf, &buf, hash, + if (OP_UPDATE == op) + index_merge(of, mp, &dbuf, &buf, hash, db, fbuf, idx, ibuf, use_all, verb, maxrec, recs, reccur); - } goto out; } - if (0 == argc) { - man_conf_parse(&dirs); - argc = dirs.argc; - argv = dirs.argv; - } + /* + * Configure the directories we're going to scan. + * If we have command-line arguments, use them. + * If not, we use man(1)'s method (see mandocdb.8). + */ - for (i = 0; i < argc; i++) { + if (argc > 0) { + dirs.paths = mandoc_malloc(argc * sizeof(char *)); + dirs.sz = argc; + for (i = 0; i < argc; i++) + dirs.paths[i] = mandoc_strdup(argv[i]); + } else + manpath_parse(&dirs, NULL, NULL); + + for (i = 0; i < dirs.sz; i++) { ibuf[0] = fbuf[0] = '\0'; - strlcat(fbuf, argv[i], MAXPATHLEN); + strlcat(fbuf, dirs.paths[i], MAXPATHLEN); strlcat(fbuf, "/", MAXPATHLEN); sz1 = strlcat(fbuf, MANDOC_DB, MAXPATHLEN); - strlcat(ibuf, argv[i], MAXPATHLEN); + strlcat(ibuf, dirs.paths[i], MAXPATHLEN); strlcat(ibuf, "/", MAXPATHLEN); sz2 = strlcat(ibuf, MANDOC_IDX, MAXPATHLEN); if (sz1 >= MAXPATHLEN || sz2 >= MAXPATHLEN) { - fprintf(stderr, "%s: Path too long\n", argv[i]); + fprintf(stderr, "%s: Path too long\n", + dirs.paths[i]); exit((int)MANDOCLEVEL_BADARG); } @@ -423,8 +431,8 @@ mandocdb(int argc, char *argv[]) ofile_free(of); of = NULL; - if ( ! ofile_dirbuild(argv[i], NULL, NULL, - use_all, verb, &of)) + if ( ! ofile_dirbuild(dirs.paths[i], NULL, NULL, + use_all, verb, &of)) exit((int)MANDOCLEVEL_SYSERR); if (NULL == of) @@ -432,8 +440,7 @@ mandocdb(int argc, char *argv[]) of = of->first; - chdir(argv[i]); - index_merge(of, mp, &dbuf, &buf, hash, db, fbuf, + index_merge(of, mp, &dbuf, &buf, hash, db, fbuf, idx, ibuf, use_all, verb, maxrec, recs, reccur); } @@ -447,9 +454,8 @@ out: (*hash->close)(hash); if (mp) mparse_free(mp); - if (dirs.argc) - man_conf_free(&dirs); + manpath_free(&dirs); ofile_free(of); free(buf.cp); free(dbuf.cp); @@ -461,7 +467,7 @@ out: void index_merge(const struct of *of, struct mparse *mp, struct buf *dbuf, struct buf *buf, - DB *hash, DB *db, const char *dbf, + DB *hash, DB *db, const char *dbf, DB *idx, const char *idxf, int use_all, int verb, recno_t maxrec, const recno_t *recs, size_t reccur) { diff --git a/usr.bin/mandoc/mandocdb.h b/usr.bin/mandoc/mandocdb.h index 8b5bd54df4c..c69292e4e2b 100644 --- a/usr.bin/mandoc/mandocdb.h +++ b/usr.bin/mandoc/mandocdb.h @@ -1,4 +1,4 @@ -/* $Id: mandocdb.h,v 1.2 2011/11/17 15:38:27 schwarze Exp $ */ +/* $Id: mandocdb.h,v 1.3 2011/11/26 16:41:35 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * @@ -14,6 +14,8 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef MANDOCDB_H +#define MANDOCDB_H struct db_val { uint64_t mask; @@ -61,3 +63,5 @@ struct db_val { #define TYPE_Va 0x0000000800000000ULL #define TYPE_Vt 0x0000001000000000ULL #define TYPE_Xr 0x0000002000000000ULL + +#endif /*!MANDOCDB_H */ diff --git a/usr.bin/mandoc/manpath.c b/usr.bin/mandoc/manpath.c new file mode 100644 index 00000000000..cbe70e5339a --- /dev/null +++ b/usr.bin/mandoc/manpath.c @@ -0,0 +1,141 @@ +/* $Id: manpath.c,v 1.1 2011/11/26 16:41:35 schwarze Exp $ */ +/* + * Copyright (c) 2011 Ingo Schwarze + * Copyright (c) 2011 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "mandoc.h" +#include "manpath.h" + +#define MAN_CONF_FILE "/etc/man.conf" +#define MAN_CONF_KEY "_whatdb" + +static void manpath_add(struct manpaths *, const char *); + +void +manpath_parse(struct manpaths *dirs, char *defp, char *auxp) +{ + + manpath_parseline(dirs, auxp); + + if (NULL == defp) + defp = getenv("MANPATH"); + + if (NULL == defp) + manpath_parseconf(dirs); + else + manpath_parseline(dirs, defp); +} + +/* + * Parse a FULL pathname from a colon-separated list of arrays. + */ +void +manpath_parseline(struct manpaths *dirs, char *path) +{ + char *dir; + + if (NULL == path) + return; + + for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":")) + manpath_add(dirs, dir); +} + +/* + * Add a directory to the array, ignoring bad directories. + * Grow the array one-by-one for simplicity's sake. + */ +static void +manpath_add(struct manpaths *dirs, const char *dir) +{ + char buf[PATH_MAX]; + char *cp; + int i; + + if (NULL == (cp = realpath(dir, buf))) + return; + + for (i = 0; i < dirs->sz; i++) + if (0 == strcmp(dirs->paths[i], dir)) + return; + + dirs->paths = mandoc_realloc + (dirs->paths, + ((size_t)dirs->sz + 1) * sizeof(char *)); + + dirs->paths[dirs->sz++] = mandoc_strdup(cp); +} + +void +manpath_parseconf(struct manpaths *dirs) +{ + + manpath_manconf(MAN_CONF_FILE, dirs); +} + +void +manpath_free(struct manpaths *p) +{ + int i; + + for (i = 0; i < p->sz; i++) + free(p->paths[i]); + + free(p->paths); +} + +void +manpath_manconf(const char *file, struct manpaths *dirs) +{ + FILE *stream; + char *p, *q; + size_t len, keysz; + + keysz = strlen(MAN_CONF_KEY); + assert(keysz > 0); + + if (NULL == (stream = fopen(file, "r"))) + return; + + while (NULL != (p = fgetln(stream, &len))) { + if (0 == len || '\n' != p[--len]) + break; + p[len] = '\0'; + while (isspace((unsigned char)*p)) + p++; + if (strncmp(MAN_CONF_KEY, p, keysz)) + continue; + p += keysz; + while (isspace(*p)) + p++; + if ('\0' == *p) + continue; + if (NULL == (q = strrchr(p, '/'))) + continue; + *q = '\0'; + manpath_add(dirs, p); + } + + fclose(stream); +} diff --git a/usr.bin/mandoc/manpath.h b/usr.bin/mandoc/manpath.h new file mode 100644 index 00000000000..a30b1c26082 --- /dev/null +++ b/usr.bin/mandoc/manpath.h @@ -0,0 +1,40 @@ +/* $Id: manpath.h,v 1.1 2011/11/26 16:41:35 schwarze Exp $ */ +/* + * Copyright (c) 2011 Ingo Schwarze + * Copyright (c) 2011 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef MANPATH_H +#define MANPATH_H + +/* + * Unsorted list of unique, absolute paths to be searched for manual + * databases. + */ +struct manpaths { + int sz; + char **paths; +}; + +__BEGIN_DECLS + +void manpath_manconf(const char *, struct manpaths *); +void manpath_parse(struct manpaths *, char *, char *); +void manpath_parseconf(struct manpaths *); +void manpath_parseline(struct manpaths *, char *); +void manpath_free(struct manpaths *); + +__END_DECLS + +#endif /*!MANPATH_H*/ -- cgit v1.2.3