summaryrefslogtreecommitdiffstats
path: root/usr.bin/mandoc
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/mandoc')
-rw-r--r--usr.bin/mandoc/Makefile4
-rw-r--r--usr.bin/mandoc/apropos.151
-rw-r--r--usr.bin/mandoc/apropos.c74
-rw-r--r--usr.bin/mandoc/apropos_db.c146
-rw-r--r--usr.bin/mandoc/apropos_db.h11
-rw-r--r--usr.bin/mandoc/man_conf.c88
-rw-r--r--usr.bin/mandoc/mandocdb.c56
-rw-r--r--usr.bin/mandoc/mandocdb.h6
-rw-r--r--usr.bin/mandoc/manpath.c141
-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*/