diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2011-11-26 16:41:36 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2011-11-26 16:41:36 +0000 |
commit | 2dcffed7ef84c2009020f2c105db781e9a7dff18 (patch) | |
tree | 7c1ddfc75f4a9ff8c777c0ce18bf230235d06a71 /usr.bin | |
parent | cac096a251aba33da0ad525aabf2877d4fed991f (diff) |
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.
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/mandoc/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/mandoc/apropos.1 | 51 | ||||
-rw-r--r-- | usr.bin/mandoc/apropos.c | 74 | ||||
-rw-r--r-- | usr.bin/mandoc/apropos_db.c | 146 | ||||
-rw-r--r-- | usr.bin/mandoc/apropos_db.h | 11 | ||||
-rw-r--r-- | usr.bin/mandoc/man_conf.c | 88 | ||||
-rw-r--r-- | usr.bin/mandoc/mandocdb.c | 56 | ||||
-rw-r--r-- | usr.bin/mandoc/mandocdb.h | 6 | ||||
-rw-r--r-- | usr.bin/mandoc/manpath.c | 141 | ||||
-rw-r--r-- | usr.bin/mandoc/manpath.h (renamed from usr.bin/mandoc/man_conf.h) | 30 |
10 files changed, 356 insertions, 251 deletions
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 <bsd.own.mk> @@ -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 <kristaps@bsd.lv> .\" @@ -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 <kristaps@bsd.lv> + * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org> * * 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 <assert.h> #include <getopt.h> -#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #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 <kristaps@bsd.lv> * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org> @@ -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 <kristaps@bsd.lv> * @@ -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 <schwarze@openbsd.org> - * - * 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 <sys/types.h> -#include <assert.h> -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#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/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 <kristaps@bsd.lv> + * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org> * * 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 <stdint.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <db.h> #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 <kristaps@bsd.lv> * @@ -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 <schwarze@openbsd.org> + * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * + * 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 <sys/types.h> +#include <assert.h> +#include <ctype.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#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/man_conf.h b/usr.bin/mandoc/manpath.h index b93cf5189a5..a30b1c26082 100644 --- a/usr.bin/mandoc/man_conf.h +++ b/usr.bin/mandoc/manpath.h @@ -1,6 +1,7 @@ -/* $Id: man_conf.h,v 1.1 2011/11/17 14:52:32 schwarze Exp $ */ +/* $Id: manpath.h,v 1.1 2011/11/26 16:41:35 schwarze Exp $ */ /* * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,13 +15,26 @@ * 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 -struct man_conf { - int maxargs; - int argc; - char **argv; +/* + * Unsorted list of unique, absolute paths to be searched for manual + * databases. + */ +struct manpaths { + int sz; + char **paths; }; -void manpath_parse(struct man_conf *, char *); -void man_conf_parse(struct man_conf *); -void man_conf_free(struct man_conf *); +__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*/ |