summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/mandoc/Makefile4
-rw-r--r--usr.bin/mandoc/apropos.1116
-rw-r--r--usr.bin/mandoc/apropos.c120
-rw-r--r--usr.bin/mandoc/cgi.c8
-rw-r--r--usr.bin/mandoc/main.c404
-rw-r--r--usr.bin/mandoc/man.1369
-rw-r--r--usr.bin/mandoc/mandoc.136
-rw-r--r--usr.bin/mandoc/mansearch.c62
-rw-r--r--usr.bin/mandoc/mansearch.h21
9 files changed, 920 insertions, 220 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index ae61827f22a..fad30f9d2a0 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.81 2014/08/14 02:49:23 schwarze Exp $
+# $OpenBSD: Makefile,v 1.82 2014/08/27 00:06:08 schwarze Exp $
.include <bsd.own.mk>
@@ -17,7 +17,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+= manpath.c mandocdb.c mansearch_const.c mansearch.c apropos.c
+SRCS+= manpath.c mandocdb.c mansearch_const.c mansearch.c
PROG= mandoc
diff --git a/usr.bin/mandoc/apropos.1 b/usr.bin/mandoc/apropos.1
index a448e3f0b31..d57702c3988 100644
--- a/usr.bin/mandoc/apropos.1
+++ b/usr.bin/mandoc/apropos.1
@@ -1,6 +1,6 @@
-.\" $Id: apropos.1,v 1.24 2014/04/24 00:28:02 schwarze Exp $
+.\" $Id: apropos.1,v 1.25 2014/08/27 00:06:08 schwarze Exp $
.\"
-.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
@@ -15,14 +15,16 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: April 24 2014 $
+.Dd $Mdocdate: August 27 2014 $
.Dt APROPOS 1
.Os
.Sh NAME
-.Nm apropos
+.Nm apropos ,
+.Nm whatis
.Nd search manual page databases
.Sh SYNOPSIS
.Nm
+.Op Fl acfkw
.Op Fl C Ar file
.Op Fl M Ar path
.Op Fl m Ar path
@@ -32,13 +34,15 @@
.Ar expression ...
.Sh DESCRIPTION
The
-.Nm
-utility queries manual page databases generated by
+.Nm apropos
+and
+.Nm whatis
+utilities query manual page databases generated by
.Xr makewhatis 8 ,
evaluating
.Ar expression
for each file in each database.
-By default, it displays the names, section numbers, and description lines
+By default, they display the names, section numbers, and description lines
of all matching manuals.
.Pp
By default,
@@ -54,14 +58,62 @@ over manual names and descriptions
Multiple terms imply pairwise
.Fl o .
.Pp
-Its arguments are as follows:
+.Nm whatis
+is a synonym for
+.Nm
+.Fl f .
+.Pp
+The options are as follows:
.Bl -tag -width Ds
+.It Fl a
+Instead of showing only the title lines, show the complete manual pages,
+just like
+.Xr man 1
+.Fl a
+would.
+If the standard output is a terminal device and
+.Fl c
+is not specified, use
+.Xr more 1
+to paginate them.
+In
+.Fl a
+mode, the options
+.Fl IOTW
+described in the
+.Xr mandoc 1
+manual are also available.
.It Fl C Ar file
Specify an alternative configuration
.Ar file
in
.Xr man.conf 5
format.
+.It Fl c
+In
+.Fl a
+mode, copy the formatted manual pages to the standard output without using
+.Xr more 1
+to paginate them.
+.It Fl f
+Search for all words in
+.Ar expression
+in manual page names only.
+The search is case insensitive and matches whole words only.
+In this mode, macro keys, comparison operators, and logical operators
+are not available.
+This overrides any earlier
+.Fl k
+option.
+.It Fl k
+Support the full
+.Ar expression
+syntax.
+This overrides any earlier
+.Fl f
+option.
+It is the default for
+.Nm .
.It Fl M Ar path
Use the colon-separated path instead of the default list of paths
searched for
@@ -91,6 +143,12 @@ By default, pages from all sections are shown.
See
.Xr man 1
for a listing of sections.
+.It Fl w
+Instead of showing title lines, show the pathnames of the matching
+manual pages, just like
+.Xr man 1
+.Fl w
+would.
.El
.Pp
An
@@ -260,7 +318,12 @@ Text production:
.It Li \&Dx Ta Dx No version reference
.El
.Sh ENVIRONMENT
-.Bl -tag -width MANPATH
+.Bl -tag -width MANPAGER
+.It Ev MANPAGER
+Any non-empty value of the environment variable
+.Ev MANPAGER
+will be used instead of the standard pagination program,
+.Xr more 1 .
.It Ev MANPATH
The standard search path used by
.Xr man 1
@@ -278,6 +341,13 @@ or if it contains two adjacent colons,
the standard search path is inserted between the colons.
If none of these conditions are met, it overrides the
standard search path.
+.It Ev PAGER
+Specifies the pagination program to use when
+.Ev MANPAGER
+is not defined.
+If neither PAGER nor MANPAGER is defined,
+.Pa /usr/bin/more Fl s
+will be used.
.El
.Sh FILES
.Bl -tag -width "/etc/man.conf" -compact
@@ -339,11 +409,19 @@ The following two invocations are equivalent:
.Xr re_format 7 ,
.Xr makewhatis 8
.Sh HISTORY
-An
+Part of the functionality of
+.Nm whatis
+was already provided by the former
+.Nm manwhere
+utility in
+.Bx 1 .
+The
.Nm
-utility first appeared in
+and
+.Nm whatis
+utilities first appeared in
.Bx 2 .
-It was rewritten from scratch for
+They were rewritten from scratch for
.Ox 5.6 .
.Pp
The
@@ -363,13 +441,23 @@ and
and
.Fl s
in
-.Ox 4.5 .
+.Ox 4.5
+for
+.Nm
+and in
+.Ox 5.6
+for
+.Nm whatis .
.Sh AUTHORS
.An -nosplit
.An Bill Joy
-wrote the original
+wrote
+.Nm manwhere
+in 1977 and the original
.Bx
.Nm
+and
+.Nm whatis
in February 1979.
The current version was written by
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
diff --git a/usr.bin/mandoc/apropos.c b/usr.bin/mandoc/apropos.c
deleted file mode 100644
index 618d3115a5b..00000000000
--- a/usr.bin/mandoc/apropos.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* $Id: apropos.c,v 1.22 2014/04/20 16:44:44 schwarze Exp $ */
-/*
- * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013 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/param.h>
-
-#include <assert.h>
-#include <getopt.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "manpath.h"
-#include "mansearch.h"
-
-
-int
-apropos(int argc, char *argv[])
-{
- int ch, whatis;
- struct mansearch search;
- size_t i, sz;
- struct manpage *res;
- struct manpaths paths;
- char *defpaths, *auxpaths;
- char *conf_file;
- char *progname;
- const char *outkey;
- extern char *optarg;
- extern int optind;
-
- progname = strrchr(argv[0], '/');
- if (progname == NULL)
- progname = argv[0];
- else
- ++progname;
-
- whatis = (0 == strncmp(progname, "whatis", 6));
-
- memset(&paths, 0, sizeof(struct manpaths));
- memset(&search, 0, sizeof(struct mansearch));
-
- auxpaths = defpaths = NULL;
- conf_file = NULL;
- outkey = "Nd";
-
- while (-1 != (ch = getopt(argc, argv, "C:M:m:O:S:s:")))
- switch (ch) {
- case 'C':
- conf_file = optarg;
- break;
- case 'M':
- defpaths = optarg;
- break;
- case 'm':
- auxpaths = optarg;
- break;
- case 'O':
- outkey = optarg;
- break;
- case 'S':
- search.arch = optarg;
- break;
- case 's':
- search.sec = optarg;
- break;
- default:
- goto usage;
- }
-
- argc -= optind;
- argv += optind;
-
- if (0 == argc)
- goto usage;
-
- search.deftype = whatis ? TYPE_Nm : TYPE_Nm | TYPE_Nd;
- search.flags = whatis ? MANSEARCH_WHATIS : 0;
-
- manpath_parse(&paths, conf_file, defpaths, auxpaths);
- mansearch_setup(1);
- ch = mansearch(&search, &paths, argc, argv, outkey, &res, &sz);
- manpath_free(&paths);
-
- if (0 == ch)
- goto usage;
-
- for (i = 0; i < sz; i++) {
- printf("%s - %s\n", res[i].names,
- NULL == res[i].output ? "" : res[i].output);
- free(res[i].file);
- free(res[i].names);
- free(res[i].output);
- }
-
- free(res);
- mansearch_setup(0);
- return(sz ? EXIT_SUCCESS : EXIT_FAILURE);
-usage:
- fprintf(stderr, "usage: %s [-C file] [-M path] [-m path] "
- "[-O outkey] "
- "[-S arch] [-s section]%s ...\n", progname,
- whatis ? " name" : "\n expression");
- return(EXIT_FAILURE);
-}
diff --git a/usr.bin/mandoc/cgi.c b/usr.bin/mandoc/cgi.c
index 3d1d1e0f184..bc910f06ed4 100644
--- a/usr.bin/mandoc/cgi.c
+++ b/usr.bin/mandoc/cgi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cgi.c,v 1.34 2014/08/26 11:13:58 schwarze Exp $ */
+/* $OpenBSD: cgi.c,v 1.35 2014/08/27 00:06:08 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014 Ingo Schwarze <schwarze@usta.de>
@@ -973,8 +973,8 @@ pg_search(const struct req *req)
search.arch = req->q.arch;
search.sec = req->q.sec;
- search.deftype = req->q.equal ? TYPE_Nm : (TYPE_Nm | TYPE_Nd);
- search.flags = req->q.equal ? MANSEARCH_MAN : 0;
+ search.outkey = "Nd";
+ search.argmode = req->q.equal ? ARG_NAME : ARG_EXPR;
paths.sz = 1;
paths.paths = mandoc_malloc(sizeof(char *));
@@ -1003,7 +1003,7 @@ pg_search(const struct req *req)
ep++;
}
- if (0 == mansearch(&search, &paths, sz, cp, "Nd", &res, &ressz))
+ if (0 == mansearch(&search, &paths, sz, cp, &res, &ressz))
pg_noresult(req, "You entered an invalid query.");
else if (0 == ressz)
pg_noresult(req, "No results found.");
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index 6e03ce84016..157e63ecf3d 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,6 +1,6 @@
-/* $Id: main.c,v 1.94 2014/06/21 22:23:44 schwarze Exp $ */
+/* $OpenBSD: main.c,v 1.95 2014/08/27 00:06:08 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011, 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
*
@@ -17,7 +17,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/types.h>
+
#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -29,6 +34,17 @@
#include "main.h"
#include "mdoc.h"
#include "man.h"
+#include "manpath.h"
+#include "mansearch.h"
+
+enum outmode {
+ OUTMODE_DEF = 0,
+ OUTMODE_FLN,
+ OUTMODE_LST,
+ OUTMODE_ALL,
+ OUTMODE_INT,
+ OUTMODE_ONE
+};
typedef void (*out_mdoc)(void *, const struct mdoc *);
typedef void (*out_man)(void *, const struct man *);
@@ -59,30 +75,41 @@ struct curparse {
char outopts[BUFSIZ]; /* buf of output opts */
};
-int apropos(int, char**);
int mandocdb(int, char**);
-
static int moptions(int *, char *);
static void mmsg(enum mandocerr, enum mandoclevel,
const char *, int, int, const char *);
static void parse(struct curparse *, int,
const char *, enum mandoclevel *);
+static enum mandoclevel passthrough(const char *);
+static void spawn_pager(void);
static int toptions(struct curparse *, char *);
-static void usage(void) __attribute__((noreturn));
+static void usage(enum argmode) __attribute__((noreturn));
static void version(void) __attribute__((noreturn));
static int woptions(struct curparse *, char *);
+static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
static const char *progname;
int
main(int argc, char *argv[])
{
- int c;
struct curparse curp;
- int options;
- enum mandoclevel rc;
+ struct mansearch search;
+ struct manpaths paths;
+ char *conf_file, *defpaths, *auxpaths;
char *defos;
+ struct manpage *res, *resp;
+ size_t isec, i, sz;
+ int prio, best_prio;
+ char sec;
+ enum mandoclevel rc;
+ enum outmode outmode;
+ int show_usage;
+ int use_pager;
+ int options;
+ int c;
progname = strrchr(argv[0], '/');
if (progname == NULL)
@@ -90,22 +117,53 @@ main(int argc, char *argv[])
else
++progname;
- if (0 == strncmp(progname, "apropos", 7) ||
- 0 == strncmp(progname, "whatis", 6))
- return(apropos(argc, argv));
if (0 == strncmp(progname, "mandocdb", 8) ||
0 == strncmp(progname, "makewhatis", 10))
return(mandocdb(argc, argv));
- memset(&curp, 0, sizeof(struct curparse));
+ /* Search options. */
- options = MPARSE_SO;
+ memset(&paths, 0, sizeof(struct manpaths));
+ conf_file = defpaths = auxpaths = NULL;
+
+ memset(&search, 0, sizeof(struct mansearch));
+ search.outkey = "Nd";
+
+ if (strcmp(progname, "man") == 0)
+ search.argmode = ARG_NAME;
+ else if (strncmp(progname, "apropos", 7) == 0)
+ search.argmode = ARG_EXPR;
+ else if (strncmp(progname, "whatis", 6) == 0)
+ search.argmode = ARG_WORD;
+ else
+ search.argmode = ARG_FILE;
+
+ /* Parser and formatter options. */
+
+ memset(&curp, 0, sizeof(struct curparse));
curp.outtype = OUTT_ASCII;
curp.wlevel = MANDOCLEVEL_FATAL;
+ options = MPARSE_SO;
defos = NULL;
- while (-1 != (c = getopt(argc, argv, "I:m:O:T:VW:")))
+ use_pager = 1;
+ show_usage = 0;
+ outmode = OUTMODE_DEF;
+
+ while (-1 != (c = getopt(argc, argv, "aC:cfI:ikM:m:O:S:s:T:VW:w"))) {
switch (c) {
+ case 'a':
+ outmode = OUTMODE_ALL;
+ break;
+ case 'C':
+ conf_file = optarg;
+ break;
+ case 'c':
+ use_pager = 0;
+ break;
+ case 'f':
+ search.argmode = ARG_WORD;
+ break;
case 'I':
if (strncmp(optarg, "os=", 3)) {
fprintf(stderr,
@@ -121,14 +179,29 @@ main(int argc, char *argv[])
}
defos = mandoc_strdup(optarg + 3);
break;
+ case 'i':
+ outmode = OUTMODE_INT;
+ break;
+ case 'k':
+ search.argmode = ARG_EXPR;
+ break;
+ case 'M':
+ defpaths = optarg;
+ break;
case 'm':
- if ( ! moptions(&options, optarg))
- return((int)MANDOCLEVEL_BADARG);
+ auxpaths = optarg;
break;
case 'O':
+ search.outkey = optarg;
(void)strlcat(curp.outopts, optarg, BUFSIZ);
(void)strlcat(curp.outopts, ",", BUFSIZ);
break;
+ case 'S':
+ search.arch = optarg;
+ break;
+ case 's':
+ search.sec = optarg;
+ break;
case 'T':
if ( ! toptions(&curp, optarg))
return((int)MANDOCLEVEL_BADARG);
@@ -137,14 +210,133 @@ main(int argc, char *argv[])
if ( ! woptions(&curp, optarg))
return((int)MANDOCLEVEL_BADARG);
break;
+ case 'w':
+ outmode = OUTMODE_FLN;
+ break;
case 'V':
version();
/* NOTREACHED */
default:
- usage();
- /* NOTREACHED */
+ show_usage = 1;
+ break;
+ }
+ }
+
+ if (show_usage)
+ usage(search.argmode);
+
+ /* Postprocess options. */
+
+ if (outmode == OUTMODE_DEF) {
+ switch (search.argmode) {
+ case ARG_FILE:
+ outmode = OUTMODE_ALL;
+ use_pager = 0;
+ break;
+ case ARG_NAME:
+ outmode = OUTMODE_ONE;
+ break;
+ default:
+ outmode = OUTMODE_LST;
+ break;
+ }
+ }
+
+ /* Parse arguments. */
+
+ argc -= optind;
+ argv += optind;
+ resp = NULL;
+
+ /* Quirk for a man(1) section argument without -s. */
+
+ if (search.argmode == ARG_NAME &&
+ argv[0] != NULL &&
+ isdigit((unsigned char)argv[0][0]) &&
+ (argv[0][1] == '\0' || !strcmp(argv[0], "3p"))) {
+ search.sec = argv[0];
+ argv++;
+ argc--;
+ }
+
+ rc = MANDOCLEVEL_OK;
+
+ /* man(1), whatis(1), apropos(1) */
+
+ if (search.argmode != ARG_FILE) {
+ if (argc == 0)
+ usage(search.argmode);
+
+ /* Access the mandoc database. */
+
+ manpath_parse(&paths, conf_file, defpaths, auxpaths);
+ mansearch_setup(1);
+ if( ! mansearch(&search, &paths, argc, argv, &res, &sz))
+ usage(search.argmode);
+ manpath_free(&paths);
+ resp = res;
+
+ 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;
+ }
+
+ /*
+ * For standard man(1) and -a output mode,
+ * prepare for copying filename pointers
+ * into the program parameter array.
+ */
+
+ if (outmode == OUTMODE_ONE) {
+ argc = 1;
+ best_prio = 10;
+ } else if (outmode == OUTMODE_ALL)
+ argc = (int)sz;
+
+ /* Iterate all matching manuals. */
+
+ for (i = 0; i < sz; i++) {
+ if (outmode == OUTMODE_FLN)
+ puts(res[i].file);
+ else if (outmode == OUTMODE_LST)
+ printf("%s - %s\n", res[i].names,
+ res[i].output == NULL ? "" :
+ res[i].output);
+ else if (outmode == OUTMODE_ONE) {
+ /* Search for the best section. */
+ isec = strcspn(res[i].file, "123456789");
+ sec = res[i].file[isec];
+ if ('\0' == sec)
+ continue;
+ prio = sec_prios[sec - '1'];
+ if (prio >= best_prio)
+ continue;
+ best_prio = prio;
+ resp = res + i;
+ }
}
+ /*
+ * For man(1), -a and -i output mode, fall through
+ * to the main mandoc(1) code iterating files
+ * and running the parsers on each of them.
+ */
+
+ if (outmode == OUTMODE_FLN || outmode == OUTMODE_LST)
+ goto out;
+ }
+
+ /* mandoc(1) */
+
+ if ( ! moptions(&options, auxpaths))
+ return((int)MANDOCLEVEL_BADARG);
+
+ if (use_pager && isatty(STDOUT_FILENO))
+ spawn_pager();
+
curp.mp = mparse_alloc(options, curp.wlevel, mmsg, defos);
/*
@@ -153,25 +345,34 @@ main(int argc, char *argv[])
if (OUTT_MAN == curp.outtype)
mparse_keep(curp.mp);
- argc -= optind;
- argv += optind;
-
- rc = MANDOCLEVEL_OK;
-
- if (NULL == *argv)
+ if (argc == 0)
parse(&curp, STDIN_FILENO, "<stdin>", &rc);
- while (*argv) {
- parse(&curp, -1, *argv, &rc);
+ while (argc) {
+ if (resp != NULL) {
+ if (resp->form)
+ parse(&curp, -1, resp->file, &rc);
+ else
+ rc = passthrough(resp->file);
+ resp++;
+ } else
+ parse(&curp, -1, *argv++, &rc);
if (MANDOCLEVEL_OK != rc && curp.wstop)
break;
- ++argv;
+ argc--;
}
if (curp.outfree)
(*curp.outfree)(curp.outdata);
if (curp.mp)
mparse_free(curp.mp);
+
+out:
+ if (search.argmode != ARG_FILE) {
+ mansearch_free(res, sz);
+ mansearch_setup(0);
+ }
+
free(defos);
return((int)rc);
@@ -181,24 +382,35 @@ static void
version(void)
{
- printf("%s %s\n", progname, VERSION);
+ printf("mandoc %s\n", VERSION);
exit((int)MANDOCLEVEL_OK);
}
static void
-usage(void)
+usage(enum argmode argmode)
{
- fprintf(stderr, "usage: %s "
- "[-V] "
- "[-Ios=name] "
- "[-mformat] "
- "[-Ooption] "
- "[-Toutput] "
- "[-Wlevel]\n"
- "\t [file ...]\n",
- progname);
-
+ switch (argmode) {
+ case ARG_FILE:
+ fputs("usage: mandoc [-V] [-Ios=name] [-mformat]"
+ " [-Ooption] [-Toutput] [-Wlevel]\n"
+ "\t [file ...]\n", stderr);
+ break;
+ case ARG_NAME:
+ fputs("usage: man [-acfhkVw] [-C file] "
+ "[-M path] [-m path] [-S arch] [-s section]\n"
+ "\t [section] name ...\n", stderr);
+ break;
+ case ARG_WORD:
+ fputs("usage: whatis [-V] [-C file] [-M path] [-m path] "
+ "[-S arch] [-s section] name ...\n", stderr);
+ break;
+ case ARG_EXPR:
+ fputs("usage: apropos [-V] [-C file] [-M path] [-m path] "
+ "[-O outkey] [-S arch]\n"
+ "\t [-s section] expression ...\n", stderr);
+ break;
+ }
exit((int)MANDOCLEVEL_BADARG);
}
@@ -315,11 +527,47 @@ parse(struct curparse *curp, int fd, const char *file,
*level = rc;
}
+static enum mandoclevel
+passthrough(const char *file)
+{
+ char buf[BUFSIZ];
+ const char *syscall;
+ ssize_t nr, nw, off;
+ int fd;
+
+ fd = open(file, O_RDONLY);
+ if (fd == -1) {
+ syscall = "open";
+ goto fail;
+ }
+
+ while ((nr = read(fd, buf, BUFSIZ)) != -1 && nr != 0)
+ for (off = 0; off < nr; off += nw)
+ if ((nw = write(STDOUT_FILENO, buf + off,
+ (size_t)(nr - off))) == -1 || nw == 0) {
+ syscall = "write";
+ goto fail;
+ }
+
+ if (nr == 0) {
+ close(fd);
+ return(MANDOCLEVEL_OK);
+ }
+
+ syscall = "read";
+fail:
+ fprintf(stderr, "%s: %s: SYSERR: %s: %s",
+ progname, file, syscall, strerror(errno));
+ return(MANDOCLEVEL_SYSERR);
+}
+
static int
moptions(int *options, char *arg)
{
- if (0 == strcmp(arg, "doc"))
+ if (arg == NULL)
+ /* nothing to do */;
+ else if (0 == strcmp(arg, "doc"))
*options |= MPARSE_MDOC;
else if (0 == strcmp(arg, "andoc"))
/* nothing to do */;
@@ -429,3 +677,79 @@ mmsg(enum mandocerr t, enum mandoclevel lvl,
fputc('\n', stderr);
}
+
+static void
+spawn_pager(void)
+{
+#define MAX_PAGER_ARGS 16
+ char *argv[MAX_PAGER_ARGS];
+ const char *pager;
+ char *cp;
+ int fildes[2];
+ int argc;
+
+ if (pipe(fildes) == -1) {
+ fprintf(stderr, "%s: pipe: %s\n",
+ progname, strerror(errno));
+ return;
+ }
+
+ switch (fork()) {
+ case -1:
+ fprintf(stderr, "%s: fork: %s\n",
+ progname, strerror(errno));
+ exit((int)MANDOCLEVEL_SYSERR);
+ case 0:
+ close(fildes[0]);
+ if (dup2(fildes[1], STDOUT_FILENO) == -1) {
+ fprintf(stderr, "%s: dup output: %s\n",
+ progname, strerror(errno));
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ return;
+ default:
+ break;
+ }
+
+ /* The original process becomes the pager. */
+
+ close(fildes[1]);
+ if (dup2(fildes[0], STDIN_FILENO) == -1) {
+ fprintf(stderr, "%s: dup input: %s\n",
+ progname, strerror(errno));
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+
+ pager = getenv("MANPAGER");
+ if (pager == NULL || *pager == '\0')
+ pager = getenv("PAGER");
+ if (pager == NULL || *pager == '\0')
+ pager = "/usr/bin/more -s";
+ cp = mandoc_strdup(pager);
+
+ /*
+ * Parse the pager command into words.
+ * Intentionally do not do anything fancy here.
+ */
+
+ argc = 0;
+ while (argc + 1 < MAX_PAGER_ARGS) {
+ argv[argc++] = cp;
+ cp = strchr(cp, ' ');
+ if (cp == NULL)
+ break;
+ *cp++ = '\0';
+ while (*cp == ' ')
+ cp++;
+ if (*cp == '\0')
+ break;
+ }
+ argv[argc] = NULL;
+
+ /* Hand over to the pager. */
+
+ execvp(argv[0], argv);
+ fprintf(stderr, "%s: exec: %s\n",
+ progname, strerror(errno));
+ exit((int)MANDOCLEVEL_SYSERR);
+}
diff --git a/usr.bin/mandoc/man.1 b/usr.bin/mandoc/man.1
new file mode 100644
index 00000000000..cf06eb65f24
--- /dev/null
+++ b/usr.bin/mandoc/man.1
@@ -0,0 +1,369 @@
+.\" $Id: man.1,v 1.1 2014/08/27 00:06:08 schwarze Exp $
+.\" $OpenBSD: man.1,v 1.1 2014/08/27 00:06:08 schwarze Exp $
+.\"
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\" Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
+.\" Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)man.1 8.2 (Berkeley) 1/2/94
+.\"
+.Dd $Mdocdate: August 27 2014 $
+.Dt MAN 1
+.Os
+.Sh NAME
+.Nm man
+.Nd display manual pages
+.Sh SYNOPSIS
+.Nm man
+.Op Fl acfhkw
+.Op Fl C Ar file
+.Op Fl M Ar path
+.Op Fl m Ar path
+.Op Fl S Ar subsection
+.Op Fl s Ar section
+.Op Ar section
+.Ar name ...
+.Sh DESCRIPTION
+The
+.Nm
+utility
+displays the
+manual pages entitled
+.Ar name .
+Pages may be selected according to
+a specific category
+.Pq Ar section
+or
+machine architecture
+.Pq Ar subsection .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Display all of the manual pages for a specified
+.Ar section
+and
+.Ar name
+combination.
+Normally, only the first manual page found is displayed.
+.It Fl C Ar file
+Use the specified
+.Ar file
+instead of the default configuration file.
+This permits users to configure their own manual environment.
+See
+.Xr man.conf 5
+for a description of the contents of this file.
+.It Fl c
+Copy the manual page to the standard output instead of using
+.Xr more 1
+to paginate it.
+This is done by default if the standard output is not a terminal device.
+.It Fl f
+A synonym for
+.Xr whatis 1 .
+It searches for
+.Ar name
+in manual page names and displays the header lines from all matching pages.
+The search is case insensitive and matches whole words only.
+.It Fl h
+Display only the
+.Dq SYNOPSIS
+lines of the requested manual pages.
+.It Fl k
+A synonym for
+.Xr apropos 1 .
+Instead of
+.Ar name ,
+an expression can be provided using the syntax described in the
+.Xr apropos 1
+manual.
+By default, it displays the header lines of all matching pages.
+.It Fl M Ar path
+Override the list of standard directories which
+.Nm
+searches for manual pages.
+The supplied
+.Ar path
+must be a colon
+.Pq Ql \&:
+separated list of directories.
+This search path may also be set using the environment variable
+.Ev MANPATH .
+The subdirectories to be searched, and their search order,
+are specified by the
+.Dq _subdir
+line in the
+.Nm
+configuration file.
+.It Fl m Ar path
+Augment the list of standard directories which
+.Nm
+searches for manual pages.
+The supplied
+.Ar path
+must be a colon
+.Pq Ql \&:
+separated list of directories.
+These directories will be searched before the standard directories or
+the directories specified using the
+.Fl M
+option or the
+.Ev MANPATH
+environment variable.
+The subdirectories to be searched, and their search order,
+are specified by the
+.Dq _subdir
+line in the
+.Nm
+configuration file.
+.It Fl S Ar subsection
+Restricts the directories that
+.Nm
+will search to those of a specific
+.Xr machine 1
+architecture.
+.Ar subsection
+is case insensitive.
+.Pp
+By default manual pages for all architectures are installed.
+Therefore this option can be used to view pages for one
+architecture whilst using another.
+.Pp
+This option overrides the
+.Ev MACHINE
+environment variable.
+.It Xo
+.Op Fl s
+.Ar section
+.Xc
+Restricts the directories that
+.Nm
+will search to a specific section.
+The currently available sections are:
+.Pp
+.Bl -tag -width "localXXX" -offset indent -compact
+.It 1
+General commands
+.Pq tools and utilities .
+.It 2
+System calls and error numbers.
+.It 3
+Libraries.
+.It 3f
+Fortran programmer's reference guide.
+.It 3p
+.Xr perl 1
+programmer's reference guide.
+.It 4
+Device drivers.
+.It 5
+File formats.
+.It 6
+Games.
+.It 7
+Miscellaneous.
+.It 8
+System maintenance and operation commands.
+.It 9
+Kernel internals.
+.It X11
+An alias for X11R6.
+.It X11R6
+X Window System.
+.It local
+Pages located in
+.Pa /usr/local .
+.It n
+Tcl/Tk commands.
+.El
+.Pp
+The
+.Nm
+configuration file,
+.Xr man.conf 5 ,
+specifies the possible
+.Ar section
+values, and their search order.
+Additional sections may be specified.
+.It Fl w
+List the pathnames of the manual pages which
+.Nm
+would display for the specified
+.Ar section
+and
+.Ar name
+combination.
+.El
+.Pp
+The
+.Nm
+utility also supports the options
+.Fl IOTW
+described in the
+.Xr mandoc 1
+manual.
+.Pp
+Guidelines for writing
+man pages can be found in
+.Xr mdoc 7 .
+.Pp
+If both a formatted and an unformatted version of the same manual page,
+for example
+.Pa cat1/foo.0
+and
+.Pa man1/foo.1 ,
+exist in the same directory, and at least one of them is selected,
+only the newer one is used.
+However, if both the
+.Fl a
+and the
+.Fl w
+options are specified, both file names are printed.
+.Sh ENVIRONMENT
+.Bl -tag -width MANPATHX
+.It Ev MACHINE
+As some manual pages are intended only for specific architectures,
+.Nm
+searches any subdirectories,
+with the same name as the current architecture,
+in every directory which it searches.
+Machine specific areas are checked before general areas.
+The current machine type may be overridden by setting the environment
+variable
+.Ev MACHINE
+to the name of a specific architecture,
+or with the
+.Fl S
+option.
+.Ev MACHINE
+is case insensitive.
+.It Ev MANPAGER
+Any non-empty value of the environment variable
+.Ev MANPAGER
+will be used instead of the standard pagination program,
+.Xr more 1 .
+.It Ev MANPATH
+The standard search path used by
+.Nm
+may be overridden by specifying a path in the
+.Ev MANPATH
+environment
+variable.
+The format of the path is a colon
+.Pq Ql \&:
+separated list of directories.
+The subdirectories to be searched, as well as their search order,
+are specified by the
+.Dq _subdir
+line in the
+.Nm
+configuration file.
+.It Ev PAGER
+Specifies the pagination program to use when
+.Ev MANPAGER
+is not defined.
+If neither PAGER nor MANPAGER is defined,
+.Pa /usr/bin/more Fl s
+will be used.
+.El
+.Sh FILES
+.Bl -tag -width /etc/man.conf -compact
+.It Pa /etc/man.conf
+default man configuration file
+.El
+.Sh EXIT STATUS
+.Ex -std man
+.Sh SEE ALSO
+.Xr apropos 1 ,
+.Xr intro 1 ,
+.Xr whatis 1 ,
+.Xr whereis 1 ,
+.Xr intro 2 ,
+.Xr intro 3 ,
+.Xr intro 4 ,
+.Xr intro 5 ,
+.Xr man.conf 5 ,
+.Xr intro 6 ,
+.Xr intro 7 ,
+.Xr mdoc 7 ,
+.Xr intro 8 ,
+.Xr intro 9
+.Sh STANDARDS
+The
+.Nm
+utility is compliant with the
+.St -p1003.1-2008
+specification.
+.Pp
+The flags
+.Op Fl aCcfhMmSsw ,
+as well as the environment variables
+.Ev MACHINE ,
+.Ev MANPAGER ,
+and
+.Ev MANPATH ,
+are extensions to that specification.
+.Sh HISTORY
+A
+.Nm
+command first appeared in
+.At v3 .
+.Pp
+The
+.Fl w
+option first appeared in
+.At v7 ;
+.Fl f
+and
+.Fl k
+in
+.Bx 4 ;
+.Fl M
+in
+.Bx 4.3 ;
+.Fl a
+in
+.Bx 4.3 Tahoe ;
+.Fl c
+and
+.Fl m
+in
+.Bx 4.3 Reno ;
+.Fl h
+in
+.Bx 4.3 Net/2 ;
+.Fl C
+in
+.Nx 1.0 ;
+and
+.Fl s
+and
+.Fl S
+in
+.Ox 2.3 .
diff --git a/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1
index b6a316bb420..e6a3cc75024 100644
--- a/usr.bin/mandoc/mandoc.1
+++ b/usr.bin/mandoc/mandoc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: mandoc.1,v 1.59 2014/08/08 16:25:15 schwarze Exp $
+.\" $OpenBSD: mandoc.1,v 1.60 2014/08/27 00:06:08 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2012, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: August 8 2014 $
+.Dd $Mdocdate: August 27 2014 $
.Dt MANDOC 1
.Os
.Sh NAME
@@ -23,7 +23,7 @@
.Nd format and display UNIX manuals
.Sh SYNOPSIS
.Nm mandoc
-.Op Fl V
+.Op Fl acV
.Sm off
.Op Fl I Cm os Li = Ar name
.Sm on
@@ -53,6 +53,21 @@ output.
.Pp
The arguments are as follows:
.Bl -tag -width Ds
+.It Fl a
+If the standard output is a terminal device and
+.Fl c
+is not specified, use
+.Xr more 1
+to paginate the output, just like
+.Xr man 1
+would.
+.It Fl c
+Copy the formatted manual pages to the standard output without using
+.Xr more 1
+to paginate them.
+This is the default.
+It can be specified to override
+.Fl a .
.Sm off
.It Fl I Cm os Li = Ar name
.Sm on
@@ -425,6 +440,21 @@ See
.Sx HTML Output
for details; beyond generating XHTML tags instead of HTML tags, these
output modes are identical.
+.Sh ENVIRONMENT
+.Bl -tag -width MANPAGER
+.It Ev MANPAGER
+Any non-empty value of the environment variable
+.Ev MANPAGER
+will be used instead of the standard pagination program,
+.Xr more 1 .
+.It Ev PAGER
+Specifies the pagination program to use when
+.Ev MANPAGER
+is not defined.
+If neither PAGER nor MANPAGER is defined,
+.Pa /usr/bin/more Fl s
+will be used.
+.El
.Sh EXIT STATUS
The
.Nm
diff --git a/usr.bin/mandoc/mansearch.c b/usr.bin/mandoc/mansearch.c
index 8cc8e6ee9ad..f31a9fee232 100644
--- a/usr.bin/mandoc/mansearch.c
+++ b/usr.bin/mandoc/mansearch.c
@@ -1,4 +1,4 @@
-/* $Id: mansearch.c,v 1.32 2014/08/21 20:27:03 schwarze Exp $ */
+/* $OpenBSD: mansearch.c,v 1.33 2014/08/27 00:06:08 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,10 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+
#include <sys/mman.h>
+#include <sys/types.h>
+
#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
@@ -148,7 +151,6 @@ int
mansearch(const struct mansearch *search,
const struct manpaths *paths,
int argc, char *argv[],
- const char *outkey,
struct manpage **res, size_t *sz)
{
int fd, rc, c, indexbit;
@@ -184,11 +186,11 @@ mansearch(const struct mansearch *search,
goto out;
outbit = 0;
- if (NULL != outkey) {
+ if (NULL != search->outkey) {
for (indexbit = 0, iterbit = 1;
indexbit < mansearch_keymax;
indexbit++, iterbit <<= 1) {
- if (0 == strcasecmp(outkey,
+ if (0 == strcasecmp(search->outkey,
mansearch_keynames[indexbit])) {
outbit = iterbit;
break;
@@ -356,6 +358,19 @@ out:
return(rc);
}
+void
+mansearch_free(struct manpage *res, size_t sz)
+{
+ size_t i;
+
+ for (i = 0; i < sz; i++) {
+ free(res[i].file);
+ free(res[i].names);
+ free(res[i].output);
+ }
+ free(res);
+}
+
static int
manpage_compare(const void *vp1, const void *vp2)
{
@@ -728,35 +743,30 @@ exprterm(const struct mansearch *search, char *buf, int cs)
e = mandoc_calloc(1, sizeof(struct expr));
- if (MANSEARCH_MAN & search->flags) {
- e->bits = search->deftype;
+ if (search->argmode == ARG_NAME) {
+ e->bits = TYPE_Nm;
e->substr = buf;
e->equal = 1;
return(e);
}
/*
- * Look for an '=' or '~' operator,
- * unless forced to some fixed macro keys.
+ * Separate macro keys from search string.
+ * If needed, request regular expression handling
+ * by setting e->substr to NULL.
*/
- if (MANSEARCH_WHATIS & search->flags)
- val = NULL;
- else
- val = strpbrk(buf, "=~");
-
- if (NULL == val) {
- e->bits = search->deftype;
+ if (search->argmode == ARG_WORD) {
+ e->bits = TYPE_Nm;
+ e->substr = NULL;
+ mandoc_asprintf(&val, "[[:<:]]%s[[:>:]]", buf);
+ cs = 0;
+ } else if ((val = strpbrk(buf, "=~")) == NULL) {
+ e->bits = TYPE_Nm | TYPE_Nd;
e->substr = buf;
-
- /*
- * Found an operator.
- * Regexp search is requested by !e->substr.
- */
-
} else {
if (val == buf)
- e->bits = search->deftype;
+ e->bits = TYPE_Nm | TYPE_Nd;
if ('=' == *val)
e->substr = val + 1;
*val++ = '\0';
@@ -766,16 +776,10 @@ exprterm(const struct mansearch *search, char *buf, int cs)
/* Compile regular expressions. */
- if (MANSEARCH_WHATIS & search->flags) {
- e->substr = NULL;
- mandoc_asprintf(&val, "[[:<:]]%s[[:>:]]", buf);
- cs = 0;
- }
-
if (NULL == e->substr) {
irc = regcomp(&e->regexp, val,
REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE));
- if (MANSEARCH_WHATIS & search->flags)
+ if (search->argmode == ARG_WORD)
free(val);
if (irc) {
regerror(irc, &e->regexp, errbuf, sizeof(errbuf));
diff --git a/usr.bin/mandoc/mansearch.h b/usr.bin/mandoc/mansearch.h
index 18d76362db0..1dd4c15fbb4 100644
--- a/usr.bin/mandoc/mansearch.h
+++ b/usr.bin/mandoc/mansearch.h
@@ -1,4 +1,4 @@
-/* $Id: mansearch.h,v 1.11 2014/07/24 20:30:38 schwarze Exp $ */
+/* $OpenBSD: mansearch.h,v 1.12 2014/08/27 00:06:08 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -68,7 +68,12 @@
#define NAME_HEAD 0x0000004000000010ULL
#define NAME_MASK 0x000000000000001fULL
-__BEGIN_DECLS
+enum argmode {
+ ARG_FILE = 0,
+ ARG_NAME,
+ ARG_WORD,
+ ARG_EXPR
+};
struct manpage {
char *file; /* to be prefixed by manpath */
@@ -81,21 +86,21 @@ struct manpage {
struct mansearch {
const char *arch; /* architecture/NULL */
const char *sec; /* mansection/NULL */
- uint64_t deftype; /* type if no key */
- int flags;
-#define MANSEARCH_WHATIS 0x01 /* whatis(1) mode: whole words, no keys */
-#define MANSEARCH_MAN 0x02 /* man(1) mode: string equality, no keys */
+ const char *outkey; /* show content of this macro */
+ enum argmode argmode; /* interpretation of arguments */
};
+__BEGIN_DECLS
+
int mansearch_setup(int);
int mansearch(const struct mansearch *cfg, /* options */
const struct manpaths *paths, /* manpaths */
int argc, /* size of argv */
char *argv[], /* search terms */
- const char *outkey, /* name of additional output key */
struct manpage **res, /* results */
size_t *ressz); /* results returned */
+void mansearch_free(struct manpage *, size_t);
__END_DECLS
-#endif /*!MANSEARCH_H*/
+#endif /* MANSEARCH_H */