Update to mdocml 1.13.4

This commit is contained in:
Baptiste Daroussin 2016-07-23 11:45:42 +00:00
parent 9927192e4f
commit 05798824d2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/mdocml/dist/; revision=303221
svn path=/vendor/mdocml/1.13.4/; revision=303222; tag=vendor/mandoc/1.13.4
32 changed files with 1183 additions and 644 deletions

View File

@ -1,4 +1,4 @@
$Id: INSTALL,v 1.13 2015/11/07 14:01:16 schwarze Exp $
$Id: INSTALL,v 1.15 2016/07/14 11:09:06 schwarze Exp $
About mdocml, the portable mandoc distribution
----------------------------------------------
@ -16,7 +16,7 @@ tech@ mailing list, too.
Enjoy using the mandoc toolset!
Ingo Schwarze, Karlsruhe, March 2015
Ingo Schwarze, Karlsruhe, July 2016
Installation
@ -52,7 +52,7 @@ and go back to step 2.
4. Run "make -n install" and check whether everything will be
installed to the intended places. Otherwise, put some *DIR or *NM*
variables into "configure.local" and go back to step 2.
variables into "configure.local" and go back to step 2.
5. Run "sudo make install". If you intend to build a binary
package using some kind of fake root mechanism, you may need a
@ -63,7 +63,7 @@ in the "Makefile" to understand how DESTDIR is used.
manpath(1), make sure it is configured correctly, in particular,
it returns all directory trees where manual pages are installed.
Otherwise, if your system uses man.conf(5), make sure it contains
a "_whatdb" line for each directory tree, and the order of these
a "manpath" line for each directory tree, and the order of these
lines meets your wishes.
7. If you compiled with database support, run the command "sudo

View File

@ -1,11 +1,11 @@
$Id: LICENSE,v 1.11 2015/11/07 17:58:55 schwarze Exp $
$Id: LICENSE,v 1.12 2016/07/07 23:46:36 schwarze Exp $
With the exceptions noted below, all code and documentation
contained in the mdocml toolkit is protected by the Copyright
of the following developers:
Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org>
Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>

View File

@ -1,7 +1,7 @@
# $Id: Makefile,v 1.480 2015/11/07 21:53:14 schwarze Exp $
# $Id: Makefile,v 1.488 2016/07/12 05:18:38 kristaps Exp $
#
# Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
# Copyright (c) 2011, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
# Copyright (c) 2011, 2013-2016 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
@ -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.
VERSION = 1.13.3
VERSION = 1.13.4
# === LIST OF FILES ====================================================
@ -31,6 +31,9 @@ TESTSRCS = test-dirent-namlen.c \
test-pledge.c \
test-progname.c \
test-reallocarray.c \
test-rewb-bsd.c \
test-rewb-sysv.c \
test-sandbox_init.c \
test-sqlite3.c \
test-sqlite3_errstr.c \
test-strcasestr.c \
@ -138,6 +141,7 @@ DISTFILES = INSTALL \
makewhatis.8 \
man.1 \
man.7 \
man.cgi.3 \
man.cgi.8 \
man.conf.5 \
man.h \
@ -164,6 +168,7 @@ DISTFILES = INSTALL \
predefs.in \
roff.7 \
roff.h \
roff_int.h \
soelim.1 \
st.in \
tag.h \
@ -293,6 +298,7 @@ WWW_MANS = apropos.1.html \
roff.7.html \
tbl.7.html \
makewhatis.8.html \
man.cgi.3.html \
man.cgi.8.html \
man.h.html \
manconf.h.html \
@ -392,34 +398,30 @@ db-install: base-build
cgi-install: cgi-build
mkdir -p $(DESTDIR)$(CGIBINDIR)
mkdir -p $(DESTDIR)$(HTDOCDIR)
mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1
mkdir -p $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8
$(INSTALL_PROGRAM) man.cgi $(DESTDIR)$(CGIBINDIR)
$(INSTALL_DATA) mandoc.css $(DESTDIR)$(HTDOCDIR)
$(INSTALL_MAN) apropos.1 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man1/
$(INSTALL_MAN) man.cgi.8 $(DESTDIR)$(WWWPREFIX)/man/mandoc/man8/
Makefile.local config.h: configure ${TESTSRCS}
@echo "$@ is out of date; please run ./configure"
@exit 1
libmandoc.a: $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
$(AR) rs $@ $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
ar rs $@ $(COMPAT_OBJS) $(LIBMANDOC_OBJS)
mandoc: $(MAIN_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(MAIN_OBJS) libmandoc.a $(DBLIB)
$(CC) -o $@ $(LDFLAGS) $(MAIN_OBJS) libmandoc.a $(LDADD)
manpage: $(MANPAGE_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(MANPAGE_OBJS) libmandoc.a $(DBLIB)
$(CC) -o $@ $(LDFLAGS) $(MANPAGE_OBJS) libmandoc.a $(LDADD)
man.cgi: $(CGI_OBJS) libmandoc.a
$(CC) $(LDFLAGS) $(STATIC) -o $@ $(CGI_OBJS) libmandoc.a $(DBLIB)
$(CC) $(STATIC) -o $@ $(LDFLAGS) $(CGI_OBJS) libmandoc.a $(LDADD)
demandoc: $(DEMANDOC_OBJS) libmandoc.a
$(CC) $(LDFLAGS) -o $@ $(DEMANDOC_OBJS) libmandoc.a $(DBLIB)
$(CC) -o $@ $(LDFLAGS) $(DEMANDOC_OBJS) libmandoc.a $(LDADD)
soelim: $(SOELIM_OBJS)
$(CC) $(LDFLAGS) -o $@ $(SOELIM_OBJS)
$(CC) -o $@ $(LDFLAGS) $(SOELIM_OBJS)
# --- maintainer targets ---
@ -439,6 +441,8 @@ depend: config.h
Makefile.depend > Makefile.tmp
mv Makefile.tmp Makefile.depend
dist: mdocml.sha256
mdocml.sha256: mdocml.tar.gz
sha256 mdocml.tar.gz > $@

135
NEWS
View File

@ -1,7 +1,140 @@
$Id: NEWS,v 1.10 2015/11/05 16:58:20 schwarze Exp $
$Id: NEWS,v 1.12 2016/07/14 11:09:06 schwarze Exp $
This file lists the most important changes in the mdocml.bsd.lv distribution.
Changes in version 1.13.4, released on July 14, 2016
--- MAJOR NEW FEATURES ---
* man.conf(5): Design and implement a simpler configuration file format.
* man(1): Leverage less(1) -T and :t in a way resembling ctags(1)
to jump to the definitions of various terms inside manual pages.
* soelim(1): New implementation by Baptiste Daroussin.
* privilege limitation: Use OpenBSD pledge(2) or OS X sandbox_init(3)
when available.
* man.cgi(8): Support short URIs like http://man.openbsd.org/mdoc .
* mandoc.css: Use one unified stylesheet rather than three different ones.
--- MAJOR FUNCTIONALLY RELEVANT BUGFIXES ---
* mdoc(7): Fix multiple aspects of SYNOPSIS .Nm formatting.
* man(1): Fix process group handling, avoiding unclean shutdowns.
--- PORTABILITY IMPROVEMENTS ---
* Correctly use the ohash(3) compatibility implementation
even when building without SQLite support.
* Add compat glue for building on Solaris 9 and 10.
* Let ./configure select a supported RE syntax for word boundaries.
* Support LDFLAGS, to be used for example for hardening options.
* Avoid mixing putchar(3) and putwchar(3) on the same file descriptor,
it resulted in output corruption on some platforms.
* Avoid reusing va_lists, use va_copy(3) for better portability.
* Do not hardcode the path to the more(1) program.
--- MINOR NEW FEATURES ---
* roff(7): Implement \n(.$ (number of macro arguments).
* roff(7): Fully implement \z (do not advance cursor).
* roff(7): Implement the `r' conditional (register exists).
* roff(7): Implement \\$* (interpolate all arguments).
* roff(7): Parse and ignore \, and \/ (italic corrections).
* When there is no -m, no -M, no MANPATH and no /etc/man.conf,
fall back to /usr/share/man:/usr/X11R6/man:/usr/local/man.
* man(1): Give manuals in purely numerical sections priority over
manuals of the same name in sections with an alphabetical suffix.
* man.cgi(8): Support "header.html" and "footer.html".
* man.cgi(8): Set the "autofocus" attribute on the query text box.
* man.cgi(8): Simplify the search form, drop two useless buttons.
* man.cgi(8): Delete the pseudo-manpath "mandoc", assume that
apropos(1) and man.cgi(8) are installed in the default manpath.
--- RELIABILITY BUGFIXES ---
* mdoc(7): Avoid a use after free and an assertion failure when nodes
are deleted during validation.
* mdoc(7): Avoid a NULL pointer access when .Bd has no arguments.
* mdoc(7): Avoid a NULL pointer access triggered by mismatching end macros.
* mdoc(7): Avoid an assertion when .Fo has no argument.
* mdoc(7): Avoid an assertion when .Ta<tab> occurs in .Bl -column.
* mdoc(7): Avoid an assertion when a body gets broken and has a tail.
* roff(7): Avoid an assertion caused by blanks inside \o.
* roff(7): Make .so links to gziped manuals work without mandoc.db(5).
* tbl(7): Avoid a use after free when the last line of a layout is empty.
* eqn(7): Avoid an infinite loop caused by recursive "define".
* makewhatis(8): Avoid a segfault caused by unusual directory structures.
* Fix handling of leading, trailing, and double colons in MANPATH and -m.
--- MINOR BUGFIXES ---
* mdoc(7): Put arguments to end macros of broken partial explicit blocks
inside the breaking block.
* mdoc(7): Let .Dv force normal font.
* mdoc(7): Make trailing whitespace significant in .Bl -tag widths.
* mdoc(7): Fix macro interpretation around tabs in .Bl -column.
* man(7): Use the default width for .RS without arguments.
* man(7): On a new RS nesting level, the saved width starts from
the default width, not from the saved width of the previous level.
* man(7): Allow .PD in next-line scope.
* man(7): Improve handling of empty .HP.
* man(7): Improve formatting of .br and .sp inside .HP.
* man(7): Do not mistreat empty arguments to font alternating
macros as vertical spacing requests.
* man(7): Allow fill mode changes in tagged paragraph next-line scope.
* man(7): Fix minor bugs in block rewinding and simplify the related code.
* man(7): Add missing line breaks before subsection headers.
* man(7): Give section and subsection headers hanging indentation.
* man(7): Make trailing whitespace significant in .TP widths.
* roff(7): Don't allow breaking the output line after hyphens
that immediately follow escape sequences.
* roff(7): Ignore blank characters at the beginning of conditional blocks.
* roff(7): Escape breakable hyphens only after handling input line traps.
* roff(7): Reject \[uD800] to \[uDFFF] (surrogates) in the parser.
* tbl(7): Allow more than one data field after T} on the same input line.
* terminal output: Apply bold and italic to non-ASCII Unicode codepoints.
* terminal output: Improve rounding rules for horizontal scaling widths.
* HTML output: Render ASCII_NBRSP as "&nbsp;", not "-".
* man(1): Do not match the first part of a name if it continues with a dot.
* man(1): Keep working even if the current directory is unusable.
* man(1): Better error message when $PAGER is invalid.
* makewhatis(8): Improve handling of .Va and .Vt macros.
* apropos(1): Print "nothing appropriate" to stderr when appropriate.
* apropos(1): Abort with a useful error message when elementary
database operations like preparing queries or binding variables fail.
--- STRUCTURAL CHANGES, no functional change ---
* mdoc(7) and man(7): Unified data structures struct roff_node etc.
* mdoc(7) and man(7): Unified node handling library in roff.c.
* mdoc(7) and man(7): Seperate validation phase from parsing.
* roff(7): Major character table cleanup.
* Link with libz rather than forking gunzip(1).
--- THANKS TO ---
* Baptiste Daroussin (FreeBSD) for the new soelim(1)
and for release testing.
* Anthony Bentley (OpenBSD) for unifying mandoc.css, two nice
patches for man.cgi(8), some documentation patches, some bug
reports, and various useful discussions.
* Todd Miller (OpenBSD) for lots of help with process group and
signal handling, a few patches, some bug reports and some useful
discussions.
* Jonathan Gray (OpenBSD) for yet more testing with afl(1)
again resulting in more than half a dozen important bug reports.
* Svyatoslav Mishyn (Crux Linux) for some patches, several bug
reports, and extensive release testing.
* Christian Neukirchen (void Linux) for a number of compatibility
patches and suggestions and several bug reports.
* Christos Zoulas (NetBSD) for a bug fix patch and some useful
suggestions for cleanup.
* Florian Obser (OpenBSD) for a bugfix patch and some bug reports.
* Sevan Janiyan for help with Solaris compatibility and release
testing on many platforms.
* Jan Holzhueter and OpenCSW in general for help with Solaris
compatibility, and for providing me with a Solaris 9/10/11 testing
environment.
* Michael McConville (OpenBSD) for some simple cleanup patches.
* Thomas Klausner (NetBSD) for some bug reports and release testing.
* Christian Weisgerber, Dmitrij Czarkoff, Igor Sobrado,
Ken Westerback, Marc Espie, Mike Belopuhov, Rafael Neves,
Ted Unangst, Tim van der Molen, Theo Buehler, Theo de Raadt
(OpenBSD), Kurt Jaeger, Dag Erling Smoergrav (FreeBSD),
Joerg Sonnenberger (NetBSD), Carsten Kunze (Heirloom troff),
Daniel Levai, Fabian Raetz, Jan Stary, Jean-Yves Migeon,
Lorenzo Beretta, Markus Waldeck, Maxim Belooussov, Michael Reed,
Peter Bray, and Serguey Parkhomovsky for bug reports and feature
suggestions.
* Alexander Hall, Andrew Fresh, Antoine Jacoutot, Doug Hogan,
Jason McIntyre, Jasper Lievisse Adriaanse, Kent Spillner,
Nicholas Marriott, Peter Hessler, Sebastien Marie, Stefan Sperling,
and Theo de Raadt (OpenBSD) for helpful discussions and feedback.
Changes in version 1.13.3, released on March 13, 2015
--- MAJOR NEW FEATURES ---

12
TODO
View File

@ -1,6 +1,6 @@
************************************************************************
* Official mandoc TODO.
* $Id: TODO,v 1.216 2016/01/08 01:37:32 schwarze Exp $
* $Id: TODO,v 1.218 2016/06/05 21:06:04 schwarze Exp $
************************************************************************
Many issues are annotated for difficulty as follows:
@ -416,6 +416,11 @@ are mere guesses, and some may be wrong.
see also matthew@ Fri, 18 Jul 2014 19:25:12 -0700
loc * exist * algo ** size * imp ***
- In -man -Thtml, .nf does not preserve indentation.
It should either convert blanks to &nbsp;
or use <pre> rather than <div> (like .Bd -literal does).
Reported by afresh1@ 12 Apr 2016 14:35:45 -0700
- .Bf at the beginning of a paragraph inserts a bogus 1ex horizontal
space, see for example random(3). Introduced in
http://mdocml.bsd.lv/cgi-bin/cvsweb/mdoc_html.c.diff?r1=1.91&r2=1.92
@ -583,8 +588,6 @@ are mere guesses, and some may be wrong.
to tech@mdocml, naddy@ Wed, 28 Sep 2011 11:21:46 +0200
wait! kristaps@ Sun, 02 Oct 2011 17:12:52 +0200
- for system errors, use errno/strerror/warn/err
************************************************************************
* documentation issues
************************************************************************
@ -628,9 +631,6 @@ Several areas can be cleaned up to make mandoc even faster. These are
* structural issues
************************************************************************
- Use libz directly instead of forking gunzip(1).
Suggested by bapt at FreeBSD among others.
- We use the input line number at several places to distinguish
same-line from different-line input. That plainly doesn't work
with user-defined macros, leading to random breakage.

487
cgi.c
View File

@ -1,7 +1,7 @@
/* $Id: cgi.c,v 1.116 2016/01/04 12:36:26 schwarze Exp $ */
/* $Id: cgi.c,v 1.135 2016/07/11 22:48:37 schwarze Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@usta.de>
* Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@usta.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -21,6 +21,7 @@
#include <sys/time.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@ -55,15 +56,20 @@ struct req {
struct query q;
char **p; /* array of available manpaths */
size_t psz; /* number of available manpaths */
int isquery; /* QUERY_STRING used, not PATH_INFO */
};
enum focus {
FOCUS_NONE = 0,
FOCUS_QUERY
};
static void catman(const struct req *, const char *);
static void format(const struct req *, const char *);
static void html_print(const char *);
static void html_putchar(char);
static int http_decode(char *);
static void http_parse(struct req *, const char *);
static void pathgen(struct req *);
static void parse_manpath_conf(struct req *);
static void parse_path_info(struct req *req, const char *path);
static void parse_query_string(struct req *, const char *);
static void pg_error_badrequest(const char *);
static void pg_error_internal(void);
static void pg_index(const struct req *);
@ -74,16 +80,18 @@ static void pg_searchres(const struct req *,
static void pg_show(struct req *, const char *);
static void resp_begin_html(int, const char *);
static void resp_begin_http(int, const char *);
static void resp_catman(const struct req *, const char *);
static void resp_copy(const char *);
static void resp_end_html(void);
static void resp_searchform(const struct req *);
static void resp_format(const struct req *, const char *);
static void resp_searchform(const struct req *, enum focus);
static void resp_show(const struct req *, const char *);
static void set_query_attr(char **, char **);
static int validate_filename(const char *);
static int validate_manpath(const struct req *, const char *);
static int validate_urifrag(const char *);
static const char *scriptname; /* CGI script name */
static const char *scriptname = SCRIPT_NAME;
static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9};
static const char *const sec_numbers[] = {
@ -106,16 +114,16 @@ static const int sec_MAX = sizeof(sec_names) / sizeof(char *);
static const char *const arch_names[] = {
"amd64", "alpha", "armish", "armv7",
"aviion", "hppa", "hppa64", "i386",
"ia64", "landisk", "loongson", "luna88k",
"macppc", "mips64", "octeon", "sgi",
"socppc", "solbourne", "sparc", "sparc64",
"vax", "zaurus",
"hppa", "hppa64", "i386", "landisk",
"loongson", "luna88k", "macppc", "mips64",
"octeon", "sgi", "socppc", "sparc",
"sparc64", "zaurus",
"amiga", "arc", "arm32", "atari",
"beagle", "cats", "hp300", "mac68k",
"mvme68k", "mvme88k", "mvmeppc", "palm",
"pc532", "pegasos", "pmax", "powerpc",
"sun3", "wgrisc", "x68k"
"aviion", "beagle", "cats", "hp300",
"ia64", "mac68k", "mvme68k", "mvme88k",
"mvmeppc", "palm", "pc532", "pegasos",
"pmax", "powerpc", "solbourne", "sun3",
"vax", "wgrisc", "x68k"
};
static const int arch_MAX = sizeof(arch_names) / sizeof(char *);
@ -182,11 +190,12 @@ set_query_attr(char **attr, char **val)
* and store the values into the query structure.
*/
static void
http_parse(struct req *req, const char *qs)
parse_query_string(struct req *req, const char *qs)
{
char *key, *val;
size_t keysz, valsz;
req->isquery = 1;
req->q.manpath = NULL;
req->q.arch = NULL;
req->q.sec = NULL;
@ -338,14 +347,14 @@ resp_begin_html(int code, const char *msg)
resp_begin_http(code, msg);
printf("<!DOCTYPE html>\n"
"<HTML>\n"
"<HEAD>\n"
"<META CHARSET=\"UTF-8\" />\n"
"<LINK REL=\"stylesheet\" HREF=\"%s/mandoc.css\""
" TYPE=\"text/css\" media=\"all\">\n"
"<TITLE>%s</TITLE>\n"
"</HEAD>\n"
"<BODY>\n"
"<html>\n"
"<head>\n"
"<meta charset=\"UTF-8\"/>\n"
"<link rel=\"stylesheet\" href=\"%s/mandoc.css\""
" type=\"text/css\" media=\"all\">\n"
"<title>%s</title>\n"
"</head>\n"
"<body>\n"
"<!-- Begin page content. //-->\n",
CSS_DIR, CUSTOMIZE_TITLE);
@ -358,103 +367,87 @@ resp_end_html(void)
resp_copy(MAN_DIR "/footer.html");
puts("</BODY>\n"
"</HTML>");
puts("</body>\n"
"</html>");
}
static void
resp_searchform(const struct req *req)
resp_searchform(const struct req *req, enum focus focus)
{
int i;
puts("<!-- Begin search form. //-->");
printf("<DIV ID=\"mancgi\">\n"
"<FORM ACTION=\"%s\" METHOD=\"get\">\n"
"<FIELDSET>\n"
"<LEGEND>Manual Page Search Parameters</LEGEND>\n",
printf("<div id=\"mancgi\">\n"
"<form action=\"/%s\" method=\"get\">\n"
"<fieldset>\n"
"<legend>Manual Page Search Parameters</legend>\n",
scriptname);
/* Write query input box. */
printf( "<TABLE><TR><TD>\n"
"<INPUT TYPE=\"text\" NAME=\"query\" VALUE=\"");
if (NULL != req->q.query)
printf("<input type=\"text\" name=\"query\" value=\"");
if (req->q.query != NULL)
html_print(req->q.query);
puts("\" SIZE=\"40\">");
printf( "\" size=\"40\"");
if (focus == FOCUS_QUERY)
printf(" autofocus");
puts(">");
/* Write submission and reset buttons. */
/* Write submission buttons. */
printf( "<INPUT TYPE=\"submit\" VALUE=\"Submit\">\n"
"<INPUT TYPE=\"reset\" VALUE=\"Reset\">\n");
/* Write show radio button */
printf( "</TD><TD>\n"
"<INPUT TYPE=\"radio\" ");
if (req->q.equal)
printf("CHECKED=\"checked\" ");
printf( "NAME=\"apropos\" ID=\"show\" VALUE=\"0\">\n"
"<LABEL FOR=\"show\">Show named manual page</LABEL>\n");
printf( "<button type=\"submit\" name=\"apropos\" value=\"0\">"
"man</button>\n"
"<button type=\"submit\" name=\"apropos\" value=\"1\">"
"apropos</button>\n<br/>\n");
/* Write section selector. */
puts( "</TD></TR><TR><TD>\n"
"<SELECT NAME=\"sec\">");
puts("<select name=\"sec\">");
for (i = 0; i < sec_MAX; i++) {
printf("<OPTION VALUE=\"%s\"", sec_numbers[i]);
printf("<option value=\"%s\"", sec_numbers[i]);
if (NULL != req->q.sec &&
0 == strcmp(sec_numbers[i], req->q.sec))
printf(" SELECTED=\"selected\"");
printf(">%s</OPTION>\n", sec_names[i]);
printf(" selected=\"selected\"");
printf(">%s</option>\n", sec_names[i]);
}
puts("</SELECT>");
puts("</select>");
/* Write architecture selector. */
printf( "<SELECT NAME=\"arch\">\n"
"<OPTION VALUE=\"default\"");
printf( "<select name=\"arch\">\n"
"<option value=\"default\"");
if (NULL == req->q.arch)
printf(" SELECTED=\"selected\"");
puts(">All Architectures</OPTION>");
printf(" selected=\"selected\"");
puts(">All Architectures</option>");
for (i = 0; i < arch_MAX; i++) {
printf("<OPTION VALUE=\"%s\"", arch_names[i]);
printf("<option value=\"%s\"", arch_names[i]);
if (NULL != req->q.arch &&
0 == strcmp(arch_names[i], req->q.arch))
printf(" SELECTED=\"selected\"");
printf(">%s</OPTION>\n", arch_names[i]);
printf(" selected=\"selected\"");
printf(">%s</option>\n", arch_names[i]);
}
puts("</SELECT>");
puts("</select>");
/* Write manpath selector. */
if (req->psz > 1) {
puts("<SELECT NAME=\"manpath\">");
puts("<select name=\"manpath\">");
for (i = 0; i < (int)req->psz; i++) {
printf("<OPTION ");
printf("<option ");
if (strcmp(req->q.manpath, req->p[i]) == 0)
printf("SELECTED=\"selected\" ");
printf("VALUE=\"");
printf("selected=\"selected\" ");
printf("value=\"");
html_print(req->p[i]);
printf("\">");
html_print(req->p[i]);
puts("</OPTION>");
puts("</option>");
}
puts("</SELECT>");
puts("</select>");
}
/* Write search radio button */
printf( "</TD><TD>\n"
"<INPUT TYPE=\"radio\" ");
if (0 == req->q.equal)
printf("CHECKED=\"checked\" ");
printf( "NAME=\"apropos\" ID=\"search\" VALUE=\"1\">\n"
"<LABEL FOR=\"search\">Search with apropos query</LABEL>\n");
puts("</TD></TR></TABLE>\n"
"</FIELDSET>\n"
"</FORM>\n"
"</DIV>");
puts("</fieldset>\n"
"</form>\n"
"</div>");
puts("<!-- End search form. //-->");
}
@ -477,9 +470,6 @@ validate_manpath(const struct req *req, const char* manpath)
{
size_t i;
if ( ! strcmp(manpath, "mandoc"))
return 1;
for (i = 0; i < req->psz; i++)
if ( ! strcmp(manpath, req->p[i]))
return 1;
@ -503,15 +493,16 @@ pg_index(const struct req *req)
{
resp_begin_html(200, NULL);
resp_searchform(req);
printf("<P>\n"
resp_searchform(req, FOCUS_QUERY);
printf("<p>\n"
"This web interface is documented in the\n"
"<A HREF=\"%s/mandoc/man8/man.cgi.8\">man.cgi</A>\n"
"<a href=\"/%s%sman.cgi.8\">man.cgi(8)</a>\n"
"manual, and the\n"
"<A HREF=\"%s/mandoc/man1/apropos.1\">apropos</A>\n"
"<a href=\"/%s%sapropos.1\">apropos(1)</a>\n"
"manual explains the query syntax.\n"
"</P>\n",
scriptname, scriptname);
"</p>\n",
scriptname, *scriptname == '\0' ? "" : "/",
scriptname, *scriptname == '\0' ? "" : "/");
resp_end_html();
}
@ -519,10 +510,10 @@ static void
pg_noresult(const struct req *req, const char *msg)
{
resp_begin_html(200, NULL);
resp_searchform(req);
puts("<P>");
resp_searchform(req, FOCUS_QUERY);
puts("<p>");
puts(msg);
puts("</P>");
puts("</p>");
resp_end_html();
}
@ -531,12 +522,12 @@ pg_error_badrequest(const char *msg)
{
resp_begin_html(400, "Bad Request");
puts("<H1>Bad Request</H1>\n"
"<P>\n");
puts("<h1>Bad Request</h1>\n"
"<p>\n");
puts(msg);
printf("Try again from the\n"
"<A HREF=\"%s\">main page</A>.\n"
"</P>", scriptname);
"<a href=\"/%s\">main page</a>.\n"
"</p>", scriptname);
resp_end_html();
}
@ -544,7 +535,7 @@ static void
pg_error_internal(void)
{
resp_begin_html(500, "Internal Server Error");
puts("<P>Internal Server Error</P>");
puts("<p>Internal Server Error</p>");
resp_end_html();
}
@ -552,28 +543,30 @@ static void
pg_searchres(const struct req *req, struct manpage *r, size_t sz)
{
char *arch, *archend;
size_t i, iuse, isec;
const char *sec;
size_t i, iuse;
int archprio, archpriouse;
int prio, priouse;
char sec;
for (i = 0; i < sz; i++) {
if (validate_filename(r[i].file))
continue;
fprintf(stderr, "invalid filename %s in %s database\n",
warnx("invalid filename %s in %s database",
r[i].file, req->q.manpath);
pg_error_internal();
return;
}
if (1 == sz) {
if (req->isquery && sz == 1) {
/*
* If we have just one result, then jump there now
* without any delay.
*/
printf("Status: 303 See Other\r\n");
printf("Location: http://%s%s/%s/%s",
HTTP_HOST, scriptname, req->q.manpath, r[0].file);
printf("Location: http://%s/%s%s%s/%s",
HTTP_HOST, scriptname,
*scriptname == '\0' ? "" : "/",
req->q.manpath, r[0].file);
printf("\r\n"
"Content-Type: text/html; charset=utf-8\r\n"
"\r\n");
@ -581,50 +574,57 @@ pg_searchres(const struct req *req, struct manpage *r, size_t sz)
}
resp_begin_html(200, NULL);
resp_searchform(req);
puts("<DIV CLASS=\"results\">");
puts("<TABLE>");
resp_searchform(req,
req->q.equal || sz == 1 ? FOCUS_NONE : FOCUS_QUERY);
for (i = 0; i < sz; i++) {
printf("<TR>\n"
"<TD CLASS=\"title\">\n"
"<A HREF=\"%s/%s/%s",
scriptname, req->q.manpath, r[i].file);
printf("\">");
html_print(r[i].names);
printf("</A>\n"
"</TD>\n"
"<TD CLASS=\"desc\">");
html_print(r[i].output);
puts("</TD>\n"
"</TR>");
if (sz > 1) {
puts("<div class=\"results\">");
puts("<table>");
for (i = 0; i < sz; i++) {
printf("<tr>\n"
"<td class=\"title\">\n"
"<a href=\"/%s%s%s/%s",
scriptname, *scriptname == '\0' ? "" : "/",
req->q.manpath, r[i].file);
printf("\">");
html_print(r[i].names);
printf("</a>\n"
"</td>\n"
"<td class=\"desc\">");
html_print(r[i].output);
puts("</td>\n"
"</tr>");
}
puts("</table>\n"
"</div>");
}
puts("</TABLE>\n"
"</DIV>");
/*
* In man(1) mode, show one of the pages
* even if more than one is found.
*/
if (req->q.equal) {
puts("<HR>");
if (req->q.equal || sz == 1) {
puts("<hr>");
iuse = 0;
priouse = 10;
priouse = 20;
archpriouse = 3;
for (i = 0; i < sz; i++) {
isec = strcspn(r[i].file, "123456789");
sec = r[i].file[isec];
if ('\0' == sec)
sec = r[i].file;
sec += strcspn(sec, "123456789");
if (sec[0] == '\0')
continue;
prio = sec_prios[sec - '1'];
if (NULL == req->q.arch) {
prio = sec_prios[sec[0] - '1'];
if (sec[1] != '/')
prio += 10;
if (req->q.arch == NULL) {
archprio =
(NULL == (arch = strchr(
r[i].file + isec, '/'))) ? 3 :
(NULL == (archend = strchr(
arch + 1, '/'))) ? 0 :
((arch = strchr(sec + 1, '/'))
== NULL) ? 3 :
((archend = strchr(arch + 1, '/'))
== NULL) ? 0 :
strncmp(arch, "amd64/",
archend - arch) ? 2 : 1;
if (archprio < archpriouse) {
@ -648,7 +648,7 @@ pg_searchres(const struct req *req, struct manpage *r, size_t sz)
}
static void
catman(const struct req *req, const char *file)
resp_catman(const struct req *req, const char *file)
{
FILE *f;
char *p;
@ -658,12 +658,12 @@ catman(const struct req *req, const char *file)
int italic, bold;
if ((f = fopen(file, "r")) == NULL) {
puts("<P>You specified an invalid manual file.</P>");
puts("<p>You specified an invalid manual file.</p>");
return;
}
puts("<DIV CLASS=\"catman\">\n"
"<PRE>");
puts("<div class=\"catman\">\n"
"<pre>");
p = NULL;
sz = 0;
@ -689,9 +689,9 @@ catman(const struct req *req, const char *file)
if ('\b' != p[i + 1]) {
if (italic)
printf("</I>");
printf("</i>");
if (bold)
printf("</B>");
printf("</b>");
italic = bold = 0;
html_putchar(p[i]);
continue;
@ -702,9 +702,9 @@ catman(const struct req *req, const char *file)
if ('_' == p[i]) {
if (bold)
printf("</B>");
printf("</b>");
if ( ! italic)
printf("<I>");
printf("<i>");
bold = 0;
italic = 1;
i += 2;
@ -726,9 +726,9 @@ catman(const struct req *req, const char *file)
('*' == p[i] && '|' == p[i + 2]) ||
('|' == p[i] && '*' == p[i + 2])) {
if (italic)
printf("</I>");
printf("</i>");
if (bold)
printf("</B>");
printf("</b>");
italic = bold = 0;
putchar('*');
i += 2;
@ -740,9 +740,9 @@ catman(const struct req *req, const char *file)
('+' == p[i] && '|' == p[i + 1]) ||
('|' == p[i] && '+' == p[i + 1])) {
if (italic)
printf("</I>");
printf("</i>");
if (bold)
printf("</B>");
printf("</b>");
italic = bold = 0;
putchar('+');
i += 2;
@ -752,9 +752,9 @@ catman(const struct req *req, const char *file)
/* Bold mode. */
if (italic)
printf("</I>");
printf("</i>");
if ( ! bold)
printf("<B>");
printf("<b>");
bold = 1;
italic = 0;
i += 2;
@ -767,9 +767,9 @@ catman(const struct req *req, const char *file)
*/
if (italic)
printf("</I>");
printf("</i>");
if (bold)
printf("</B>");
printf("</b>");
if (i == len - 1 && p[i] != '\n')
html_putchar(p[i]);
@ -778,14 +778,14 @@ catman(const struct req *req, const char *file)
}
free(p);
puts("</PRE>\n"
"</DIV>");
puts("</pre>\n"
"</div>");
fclose(f);
}
static void
format(const struct req *req, const char *file)
resp_format(const struct req *req, const char *file)
{
struct manoutput conf;
struct mparse *mp;
@ -795,7 +795,7 @@ format(const struct req *req, const char *file)
int usepath;
if (-1 == (fd = open(file, O_RDONLY, 0))) {
puts("<P>You specified an invalid manual file.</P>");
puts("<p>You specified an invalid manual file.</p>");
return;
}
@ -807,17 +807,12 @@ format(const struct req *req, const char *file)
memset(&conf, 0, sizeof(conf));
conf.fragment = 1;
usepath = strcmp(req->q.manpath, req->p[0]);
mandoc_asprintf(&conf.man, "%s?query=%%N&sec=%%S%s%s%s%s",
scriptname,
req->q.arch ? "&arch=" : "",
req->q.arch ? req->q.arch : "",
usepath ? "&manpath=" : "",
usepath ? req->q.manpath : "");
mandoc_asprintf(&conf.man, "/%s%s%%N.%%S",
usepath ? req->q.manpath : "", usepath ? "/" : "");
mparse_result(mp, &man, NULL);
if (man == NULL) {
fprintf(stderr, "fatal mandoc error: %s/%s\n",
req->q.manpath, file);
warnx("fatal mandoc error: %s/%s", req->q.manpath, file);
pg_error_internal();
mparse_free(mp);
mchars_free();
@ -848,9 +843,9 @@ resp_show(const struct req *req, const char *file)
file += 2;
if ('c' == *file)
catman(req, file);
resp_catman(req, file);
else
format(req, file);
resp_format(req, file);
}
static void
@ -881,18 +876,12 @@ pg_show(struct req *req, const char *fullpath)
*/
if (chdir(manpath) == -1) {
fprintf(stderr, "chdir %s: %s\n",
manpath, strerror(errno));
warn("chdir %s", manpath);
pg_error_internal();
free(manpath);
return;
}
if (strcmp(manpath, "mandoc")) {
free(req->q.manpath);
req->q.manpath = manpath;
} else
free(manpath);
free(manpath);
if ( ! validate_filename(file)) {
pg_error_badrequest(
@ -901,7 +890,7 @@ pg_show(struct req *req, const char *fullpath)
}
resp_begin_html(200, NULL);
resp_searchform(req);
resp_searchform(req, FOCUS_NONE);
resp_show(req, file);
resp_end_html();
}
@ -923,9 +912,8 @@ pg_search(const struct req *req)
* relative to the manpath root.
*/
if (-1 == (chdir(req->q.manpath))) {
fprintf(stderr, "chdir %s: %s\n",
req->q.manpath, strerror(errno));
if (chdir(req->q.manpath) == -1) {
warn("chdir %s", req->q.manpath);
pg_error_internal();
return;
}
@ -1000,19 +988,7 @@ main(void)
itimer.it_interval.tv_sec = 2;
itimer.it_interval.tv_usec = 0;
if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) {
fprintf(stderr, "setitimer: %s\n", strerror(errno));
pg_error_internal();
return EXIT_FAILURE;
}
/* Scan our run-time environment. */
if (NULL == (scriptname = getenv("SCRIPT_NAME")))
scriptname = "";
if ( ! validate_urifrag(scriptname)) {
fprintf(stderr, "unsafe SCRIPT_NAME \"%s\"\n",
scriptname);
warn("setitimer");
pg_error_internal();
return EXIT_FAILURE;
}
@ -1023,20 +999,31 @@ main(void)
* relative to the same position.
*/
if (-1 == chdir(MAN_DIR)) {
fprintf(stderr, "MAN_DIR: %s: %s\n",
MAN_DIR, strerror(errno));
if (chdir(MAN_DIR) == -1) {
warn("MAN_DIR: %s", MAN_DIR);
pg_error_internal();
return EXIT_FAILURE;
}
memset(&req, 0, sizeof(struct req));
pathgen(&req);
req.q.equal = 1;
parse_manpath_conf(&req);
/* Next parse out the query string. */
/* Parse the path info and the query string. */
if (NULL != (querystring = getenv("QUERY_STRING")))
http_parse(&req, querystring);
if ((path = getenv("PATH_INFO")) == NULL)
path = "";
else if (*path == '/')
path++;
if (*path != '\0') {
parse_path_info(&req, path);
if (req.q.manpath == NULL || access(path, F_OK) == -1)
path = "";
} else if ((querystring = getenv("QUERY_STRING")) != NULL)
parse_query_string(&req, querystring);
/* Validate parsed data and add defaults. */
if (req.q.manpath == NULL)
req.q.manpath = mandoc_strdup(req.p[0]);
@ -1054,12 +1041,6 @@ main(void)
/* Dispatch to the three different pages. */
path = getenv("PATH_INFO");
if (NULL == path)
path = "";
else if ('/' == *path)
path++;
if ('\0' != *path)
pg_show(&req, path);
else if (NULL != req.q.query)
@ -1077,20 +1058,96 @@ main(void)
return EXIT_SUCCESS;
}
/*
* If PATH_INFO is not a file name, translate it to a query.
*/
static void
parse_path_info(struct req *req, const char *path)
{
char *dir[4];
int i;
req->isquery = 0;
req->q.equal = 1;
req->q.manpath = mandoc_strdup(path);
req->q.arch = NULL;
/* Mandatory manual page name. */
if ((req->q.query = strrchr(req->q.manpath, '/')) == NULL) {
req->q.query = req->q.manpath;
req->q.manpath = NULL;
} else
*req->q.query++ = '\0';
/* Optional trailing section. */
if ((req->q.sec = strrchr(req->q.query, '.')) != NULL) {
if(isdigit((unsigned char)req->q.sec[1])) {
*req->q.sec++ = '\0';
req->q.sec = mandoc_strdup(req->q.sec);
} else
req->q.sec = NULL;
}
/* Handle the case of name[.section] only. */
if (req->q.manpath == NULL)
return;
req->q.query = mandoc_strdup(req->q.query);
/* Split directory components. */
dir[i = 0] = req->q.manpath;
while ((dir[i + 1] = strchr(dir[i], '/')) != NULL) {
if (++i == 3) {
pg_error_badrequest(
"You specified too many directory components.");
exit(EXIT_FAILURE);
}
*dir[i]++ = '\0';
}
/* Optional manpath. */
if ((i = validate_manpath(req, req->q.manpath)) == 0)
req->q.manpath = NULL;
else if (dir[1] == NULL)
return;
/* Optional section. */
if (strncmp(dir[i], "man", 3) == 0) {
free(req->q.sec);
req->q.sec = mandoc_strdup(dir[i++] + 3);
}
if (dir[i] == NULL) {
if (req->q.manpath == NULL)
free(dir[0]);
return;
}
if (dir[i + 1] != NULL) {
pg_error_badrequest(
"You specified an invalid directory component.");
exit(EXIT_FAILURE);
}
/* Optional architecture. */
if (i) {
req->q.arch = mandoc_strdup(dir[i]);
if (req->q.manpath == NULL)
free(dir[0]);
} else
req->q.arch = dir[0];
}
/*
* Scan for indexable paths.
*/
static void
pathgen(struct req *req)
parse_manpath_conf(struct req *req)
{
FILE *fp;
char *dp;
size_t dpsz;
ssize_t len;
if (NULL == (fp = fopen("manpath.conf", "r"))) {
fprintf(stderr, "%s/manpath.conf: %s\n",
MAN_DIR, strerror(errno));
if ((fp = fopen("manpath.conf", "r")) == NULL) {
warn("%s/manpath.conf", MAN_DIR);
pg_error_internal();
exit(EXIT_FAILURE);
}
@ -1104,14 +1161,14 @@ pathgen(struct req *req)
req->p = mandoc_realloc(req->p,
(req->psz + 1) * sizeof(char *));
if ( ! validate_urifrag(dp)) {
fprintf(stderr, "%s/manpath.conf contains "
"unsafe path \"%s\"\n", MAN_DIR, dp);
warnx("%s/manpath.conf contains "
"unsafe path \"%s\"", MAN_DIR, dp);
pg_error_internal();
exit(EXIT_FAILURE);
}
if (NULL != strchr(dp, '/')) {
fprintf(stderr, "%s/manpath.conf contains "
"path with slash \"%s\"\n", MAN_DIR, dp);
if (strchr(dp, '/') != NULL) {
warnx("%s/manpath.conf contains "
"path with slash \"%s\"", MAN_DIR, dp);
pg_error_internal();
exit(EXIT_FAILURE);
}
@ -1121,8 +1178,8 @@ pathgen(struct req *req)
}
free(dp);
if ( req->p == NULL ) {
fprintf(stderr, "%s/manpath.conf is empty\n", MAN_DIR);
if (req->p == NULL) {
warnx("%s/manpath.conf is empty", MAN_DIR);
pg_error_internal();
exit(EXIT_FAILURE);
}

View File

@ -1,7 +1,8 @@
/* Example compile-time configuration file for man.cgi(8). */
#define HTTP_HOST "mdocml.bsd.lv"
#define MAN_DIR "/var/www/man"
#define SCRIPT_NAME "cgi-bin/man.cgi"
#define MAN_DIR "/man"
#define CSS_DIR ""
#define CUSTOMIZE_TITLE "Manual pages with mandoc"
#define COMPAT_OLDURI Yes

70
configure vendored
View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
# Copyright (c) 2014, 2015, 2016 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
@ -36,7 +36,10 @@ OSNAME=
CC=`printf "all:\\n\\t@echo \\\$(CC)\\n" | make -f -`
CFLAGS="-g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings"
DBLIB=
LDADD=
LDFLAGS=
LD_OHASH=
LD_SQLITE3=
STATIC="-static"
BUILD_DB=1
@ -55,6 +58,7 @@ HAVE_PROGNAME=
HAVE_REALLOCARRAY=
HAVE_REWB_BSD=
HAVE_REWB_SYSV=
HAVE_SANDBOX_INIT=
HAVE_STRCASESTR=
HAVE_STRINGLIST=
HAVE_STRLCAT=
@ -183,6 +187,7 @@ runtest isblank ISBLANK || true
runtest mkdtemp MKDTEMP || true
runtest mmap MMAP || true
runtest pledge PLEDGE || true
runtest sandbox_init SANDBOX_INIT || true
runtest progname PROGNAME || true
runtest reallocarray REALLOCARRAY || true
runtest rewb-bsd REWB_BSD || true
@ -198,28 +203,32 @@ runtest vasprintf VASPRINTF || true
runtest wchar WCHAR || true
# --- sqlite3 ---
DETECTLIB=
if [ ${BUILD_DB} -eq 0 ]; then
echo "BUILD_DB=0 (manual)" 1>&2
echo "BUILD_DB=0 (manual)" 1>&3
echo 1>&3
HAVE_SQLITE3=0
elif ismanual sqlite3 "${HAVE_SQLITE3}"; then
DETECTLIB="-lsqlite3"
elif [ -n "${DBLIB}" ]; then
runtest sqlite3 SQLITE3 "${DBLIB}" || true
if [ -z "${LD_SQLITE3}" ]; then
LD_SQLITE3="-lsqlite3"
fi
elif [ -n "${LD_SQLITE3}" ]; then
runtest sqlite3 SQLITE3 "${LD_SQLITE3}" || true
elif singletest sqlite3 SQLITE3 "-lsqlite3"; then
DETECTLIB="-lsqlite3"
LD_SQLITE3="-lsqlite3"
elif runtest sqlite3 SQLITE3 \
"-I/usr/local/include -L/usr/local/lib -lsqlite3"; then
DETECTLIB="-L/usr/local/lib -lsqlite3"
LD_SQLITE3="-L/usr/local/lib -lsqlite3"
CFLAGS="${CFLAGS} -I/usr/local/include"
fi
if [ ${BUILD_DB} -gt 0 -a ${HAVE_SQLITE3} -eq 0 ]; then
echo "BUILD_DB=0 (no sqlite3)" 1>&2
echo "BUILD_DB=0 (no sqlite3)" 1>&3
echo 1>&3
BUILD_DB=0
if [ ${HAVE_SQLITE3} -eq 0 ]; then
LD_SQLITE3=
if [ ${BUILD_DB} -gt 0 ]; then
echo "BUILD_DB=0 (no sqlite3)" 1>&2
echo "BUILD_DB=0 (no sqlite3)" 1>&3
echo 1>&3
BUILD_DB=0
fi
fi
# --- sqlite3_errstr ---
@ -227,34 +236,29 @@ if [ ${BUILD_DB} -eq 0 ]; then
HAVE_SQLITE3_ERRSTR=1
elif ismanual sqlite3_errstr "${HAVE_SQLITE3_ERRSTR}"; then
:
elif [ -n "${DBLIB}" ]; then
runtest sqlite3_errstr SQLITE3_ERRSTR "${DBLIB}" || true
else
runtest sqlite3_errstr SQLITE3_ERRSTR "${DETECTLIB}" || true
runtest sqlite3_errstr SQLITE3_ERRSTR "${LD_SQLITE3}" || true
fi
# --- ohash ---
if [ ${BUILD_DB} -eq 0 ]; then
HAVE_OHASH=1
elif ismanual ohash "${HAVE_OHASH}"; then
if ismanual ohash "${HAVE_OHASH}"; then
:
elif [ -n "${DBLIB}" ]; then
runtest ohash OHASH "${DBLIB}" || true
elif [ -n "${LD_OHASH}" ]; then
runtest ohash OHASH "${LD_OHASH}" || true
elif singletest ohash OHASH; then
:
elif runtest ohash OHASH "-lutil"; then
DETECTLIB="${DETECTLIB} -lutil"
LD_OHASH="-lutil"
fi
if [ "${HAVE_OHASH}" -eq 0 ]; then
LD_OHASH=
fi
# --- DBLIB ---
if [ ${BUILD_DB} -eq 0 ]; then
DBLIB="-lz"
elif [ -z "${DBLIB}" ]; then
DBLIB="${DETECTLIB} -lz"
echo "DBLIB=\"${DBLIB}\"" 1>&2
echo "DBLIB=\"${DBLIB}\"" 1>&3
echo 1>&3
fi
# --- LDADD ---
LDADD="${LDADD} ${LD_SQLITE3} ${LD_OHASH} -lz"
echo "LDADD=\"${LDADD}\"" 1>&2
echo "LDADD=\"${LDADD}\"" 1>&3
echo 1>&3
# --- manpath ---
if ismanual manpath "${HAVE_MANPATH}"; then
@ -315,6 +319,7 @@ cat << __HEREDOC__
#define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY}
#define HAVE_REWB_BSD ${HAVE_REWB_BSD}
#define HAVE_REWB_SYSV ${HAVE_REWB_SYSV}
#define HAVE_SANDBOX_INIT ${HAVE_SANDBOX_INIT}
#define HAVE_STRCASESTR ${HAVE_STRCASESTR}
#define HAVE_STRINGLIST ${HAVE_STRINGLIST}
#define HAVE_STRLCAT ${HAVE_STRLCAT}
@ -426,7 +431,8 @@ BUILD_TARGETS = ${BUILD_TARGETS}
INSTALL_TARGETS = ${INSTALL_TARGETS}
CC = ${CC}
CFLAGS = ${CFLAGS}
DBLIB = ${DBLIB}
LDADD = ${LDADD}
LDFLAGS = ${LDFLAGS}
STATIC = ${STATIC}
PREFIX = ${PREFIX}
BINDIR = ${BINDIR}

View File

@ -1,6 +1,6 @@
# $Id: configure.local.example,v 1.10 2015/11/07 13:14:21 schwarze Exp $
# $Id: configure.local.example,v 1.13 2016/07/14 11:09:06 schwarze Exp $
#
# Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
# Copyright (c) 2014, 2015, 2016 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
@ -65,7 +65,7 @@ MANPATH_DEFAULT="/usr/share/man:/usr/X11R6/man:/usr/local/man"
# If you do not want uname(3) to be called but instead want a fixed
# string to be used, use the following line:
OSNAME="OpenBSD 5.6"
OSNAME="OpenBSD 5.9"
# The following installation directories are used.
# It is possible to set only one or a few of these variables,
@ -123,6 +123,26 @@ MANM_TBL="mandoc_tbl" # default is "tbl"
BINM_MAN=mman # default is "man"
BINM_SOELIM=msoelim # default is "soelim"
# Before falling back to the bundled version of the ohash(3) hashing
# library, autoconfiguration tries the following linker flag to
# link against your system version. If you do have ohash(3) on
# your system but it needs different linker flags, set the following
# variable to specify the required linker flags.
LD_OHASH="-lutil"
# Some platforms may need additional linker flags to link against libmandoc
# that are not autodetected.
# For example, Solaris 9 and 10 need -lrt for nanosleep(2).
LDADD="-lrt"
# Some systems may want to set additional linker flags for all the
# binaries, not only for those using libmandoc, for example for
# hardening options.
LDFLAGS="-Wl,-z,relro"
# It is possible to change the utility program used for installation
# and the modes files are installed with. The defaults are:
@ -141,18 +161,16 @@ INSTALL_DATA="${INSTALL} -m 0444"
BUILD_DB=0
# Two libraries are needed: SQLite3 and ohash(3).
# Autoconfiguration tries the following linker flags to find them.
# If none of these work, add a working DBLIB line to configure.local,
# disabling autodetection for library directories.
# Autoconfiguration tries the following linker flags to find the
# SQLite3 library installed on your system. If none of these work,
# set the following variable to specify the required linker flags.
DBLIB="-lsqlite3"
DBLIB="-lsqlite3 -lutil"
DBLIB="-L/usr/local/lib -lsqlite3"
LD_SQLITE3="-lsqlite3"
LD_SQLITE3="-L/usr/local/lib -lsqlite3"
# When library autodetection decides to use -L/usr/local/lib,
# -I/usr/local/include is automatically added to CFLAGS.
# If you manually set DBLIB to something including -L/usr/local/lib,
# If you manually set LD_SQLITE3 to something including -L/usr/local/lib,
# chances are you will also need the following line:
CFLAGS="${CFLAGS} -I/usr/local/include"
@ -218,27 +236,45 @@ CGIBINDIR="${WWWPREFIX}/cgi-bin"
CC=cc
# IBM AIX may need:
CC=xlc
# The default compiler flags are:
CFLAGS="-g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings"
# IBM AIX xlc does not support -W; in that case, please use:
CFLAGS="-g"
# In rare cases, it may be required to skip individual automatic tests.
# Each of the following variables can be set to 0 (test will not be run
# and will be regarded as failed) or 1 (test will not be run and will
# be regarded as successful).
HAVE_DIRENT_NAMLEN=0
HAVE_FGETLN=0
HAVE_ERR=0
HAVE_FTS=0
HAVE_GETLINE=0
HAVE_GETSUBOPT=0
HAVE_ISBLANK=0
HAVE_MKDTEMP=0
HAVE_MMAP=0
HAVE_PLEDGE=0
HAVE_PROGNAME=0
HAVE_REALLOCARRAY=0
HAVE_REWB_BSD=0
HAVE_REWB_SYSV=0
HAVE_STRCASESTR=0
HAVE_STRINGLIST=0
HAVE_STRLCAT=0
HAVE_STRLCPY=0
HAVE_STRPTIME=0
HAVE_STRSEP=0
HAVE_STRTONUM=0
HAVE_VASPRINTF=0
HAVE_WCHAR=0
HAVE_SQLITE3=0
HAVE_SQLITE3_ERRSTR=0

View File

@ -1,4 +1,4 @@
/* $Id: demandoc.c,v 1.26 2016/01/08 02:53:13 schwarze Exp $ */
/* $Id: demandoc.c,v 1.27 2016/07/09 15:24:19 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@ -20,7 +20,6 @@
#include <assert.h>
#include <ctype.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View File

@ -1,4 +1,4 @@
/* $Id: libmandoc.h,v 1.62 2015/11/07 14:01:16 schwarze Exp $ */
/* $Id: libmandoc.h,v 1.63 2016/07/07 19:19:01 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -38,7 +38,6 @@ struct tbl_span;
struct eqn;
struct roff;
struct roff_man;
struct roff_node;
void mandoc_msg(enum mandocerr, struct mparse *,
int, int, const char *);

48
main.c
View File

@ -1,4 +1,4 @@
/* $Id: main.c,v 1.262 2016/01/08 02:53:13 schwarze Exp $ */
/* $Id: main.c,v 1.269 2016/07/12 05:18:38 kristaps Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2012, 2014-2016 Ingo Schwarze <schwarze@openbsd.org>
@ -30,11 +30,15 @@
#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#if HAVE_SANDBOX_INIT
#include <sandbox.h>
#endif
#include <signal.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "mandoc_aux.h"
@ -123,9 +127,9 @@ main(int argc, char *argv[])
unsigned char *uc;
struct manpage *res, *resp;
char *conf_file, *defpaths;
size_t isec, i, sz;
const char *sec;
size_t i, sz;
int prio, best_prio;
char sec;
enum outmode outmode;
int fd;
int show_usage;
@ -158,6 +162,11 @@ main(int argc, char *argv[])
err((int)MANDOCLEVEL_SYSERR, "pledge");
#endif
#if HAVE_SANDBOX_INIT
if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1)
errx((int)MANDOCLEVEL_SYSERR, "sandbox_init");
#endif
/* Search options. */
memset(&conf, 0, sizeof(conf));
@ -389,7 +398,7 @@ main(int argc, char *argv[])
if (outmode == OUTMODE_ONE) {
argc = 1;
best_prio = 10;
best_prio = 20;
} else if (outmode == OUTMODE_ALL)
argc = (int)sz;
@ -405,11 +414,13 @@ main(int argc, char *argv[])
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)
sec = res[i].file;
sec += strcspn(sec, "123456789");
if (sec[0] == '\0')
continue;
prio = sec_prios[sec - '1'];
prio = sec_prios[sec[0] - '1'];
if (sec[1] != '/')
prio += 10;
if (prio >= best_prio)
continue;
best_prio = prio;
@ -476,7 +487,7 @@ main(int argc, char *argv[])
conf.output.synopsisonly);
if (argc > 1 && curp.outtype <= OUTT_UTF8)
ascii_sepline(curp.outdata);
terminal_sepline(curp.outdata);
} else if (rc < MANDOCLEVEL_ERROR)
rc = MANDOCLEVEL_ERROR;
@ -661,8 +672,8 @@ fs_lookup(const struct manpaths *paths, size_t ipath,
found:
#if HAVE_SQLITE3
warnx("outdated mandoc.db lacks %s(%s) entry, run makewhatis %s",
name, sec, paths->paths[ipath]);
warnx("outdated mandoc.db lacks %s(%s) entry, run %s %s",
name, sec, BINM_MAKEWHATIS, paths->paths[ipath]);
#endif
*res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage));
page = *res + (*ressz - 1);
@ -681,7 +692,7 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths,
int argc, char **argv, struct manpage **res, size_t *ressz)
{
const char *const sections[] =
{"1", "8", "6", "2", "3", "3p", "5", "7", "4", "9"};
{"1", "8", "6", "2", "3", "5", "7", "4", "9", "3p"};
const size_t nsec = sizeof(sections)/sizeof(sections[0]);
size_t ipath, isec, lastsz;
@ -1018,6 +1029,7 @@ mmsg(enum mandocerr t, enum mandoclevel lvl,
static pid_t
spawn_pager(struct tag_files *tag_files)
{
const struct timespec timeout = { 0, 100000000 }; /* 0.1s */
#define MAX_PAGER_ARGS 16
char *argv[MAX_PAGER_ARGS];
const char *pager;
@ -1051,11 +1063,11 @@ spawn_pager(struct tag_files *tag_files)
break;
}
/* For more(1) and less(1), use the tag file. */
/* For less(1), use the tag file. */
if ((cmdlen = strlen(argv[0])) >= 4) {
cp = argv[0] + cmdlen - 4;
if (strcmp(cp, "less") == 0 || strcmp(cp, "more") == 0) {
if (strcmp(cp, "less") == 0) {
argv[argc++] = mandoc_strdup("-T");
argv[argc++] = tag_files->tfn;
}
@ -1067,8 +1079,6 @@ spawn_pager(struct tag_files *tag_files)
case -1:
err((int)MANDOCLEVEL_SYSERR, "fork");
case 0:
/* Set pgrp in both parent and child to avoid racing exec. */
(void)setpgid(0, 0);
break;
default:
(void)setpgid(pager_pid, 0);
@ -1087,6 +1097,12 @@ spawn_pager(struct tag_files *tag_files)
err((int)MANDOCLEVEL_SYSERR, "pager stdout");
close(tag_files->ofd);
close(tag_files->tfd);
/* Do not start the pager before controlling the terminal. */
while (tcgetpgrp(STDIN_FILENO) != getpid())
nanosleep(&timeout, NULL);
execvp(argv[0], argv);
err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]);
}

4
main.h
View File

@ -1,4 +1,4 @@
/* $Id: main.h,v 1.24 2015/11/07 14:01:16 schwarze Exp $ */
/* $Id: main.h,v 1.25 2016/07/08 22:29:05 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -43,7 +43,6 @@ void *locale_alloc(const struct manoutput *);
void *utf8_alloc(const struct manoutput *);
void *ascii_alloc(const struct manoutput *);
void ascii_free(void *);
void ascii_sepline(void *);
void *pdf_alloc(const struct manoutput *);
void *ps_alloc(const struct manoutput *);
@ -51,3 +50,4 @@ void pspdf_free(void *);
void terminal_mdoc(void *, const struct roff_man *);
void terminal_man(void *, const struct roff_man *);
void terminal_sepline(void *);

38
man.1
View File

@ -1,4 +1,4 @@
.\" $Id: man.1,v 1.16 2015/09/21 09:59:02 schwarze Exp $
.\" $Id: man.1,v 1.17 2016/07/01 20:24:04 schwarze Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -31,7 +31,7 @@
.\"
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
.\"
.Dd $Mdocdate: September 21 2015 $
.Dd $Mdocdate: July 1 2016 $
.Dt MAN 1
.Os
.Sh NAME
@ -209,13 +209,9 @@ architecture whilst using another.
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.
.It Oo Fl s Oc Ar section
Only select manuals from the specified
.Ar section .
The currently available sections are:
.Pp
.Bl -tag -width "localXXX" -offset indent -compact
@ -225,9 +221,7 @@ General commands
.It 2
System calls and error numbers.
.It 3
Libraries.
.It 3f
Fortran programmer's reference guide.
Library functions.
.It 3p
.Xr perl 1
programmer's reference guide.
@ -238,30 +232,12 @@ File formats.
.It 6
Games.
.It 7
Miscellaneous.
Miscellaneous information.
.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 T Ar output
Select the output format.
The default is

287
man.cgi.3 Normal file
View File

@ -0,0 +1,287 @@
.\" $Id: man.cgi.3,v 1.2 2016/07/07 19:19:01 schwarze Exp $
.\"
.\" Copyright (c) 2016 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.
.\"
.Dd $Mdocdate: July 7 2016 $
.Dt MAN.CGI 3
.Os
.Sh NAME
.Nm man.cgi
.Nd internals of the CGI program to search and display manual pages
.Sh DESCRIPTION
The source code of
.Xr man.cgi 8
is organized in four levels:
.Pp
.Bl -enum -compact
.It
.Sx Top level
.It
.Sx Page generators
.It
.Sx Result generators
.It
.Sx Utility routines
.El
.Ss Top level
The top level of
.Xr man.cgi 8
consists of the
.Fn main
program and a few parser routines.
.Bl -tag -width 1n
.It Ft int Fn main void
The main program
.Bl -dash -compact
.It
limits execution time;
.It
changes to
.Dv MAN_DIR ,
the data directory containing all the manual trees;
.It
calls
.Fn parse_manpath_conf ;
.It
if
.Ev PATH_INFO
is empty, calls
.Fn parse_query_string ;
otherwise,
calls
.Fn parse_path_info ;
.It
validates the manpath and the architecture;
.It
calls the appropriate one among the
.Sx Page generators .
.El
.It Ft void Fn parse_manpath_conf "struct req *req"
Parses and validates
.Pa manpath.conf
and fills
.Va req->p
and
.Va req->psz .
.It Ft void Fn parse_path_info "struct req *req" "const char *path"
Parses and validates
.Ev PATH_INFO ,
clears
.Va req->isquery ,
and fills
.Va req->q .
.It Ft void Fn parse_query_string "struct req *req" "const char *qs"
Parses and validates
.Ev QUERY_STRING ,
sets
.Va req->isquery ,
and fills
.Va req->q .
This function is the only user of the utility functions
.Fn http_decode
and
.Fn set_query_attr .
.El
.Ss Page generators
The purpose of each page generator is to print a complete HTML page,
starting with the HTTP headers and continuing to the page footer.
Before starting HTML output with
.Fn resp_begin_html ,
some page generators do some preparatory work, for example to decide
which page to show.
Each page generator ends with a call to
.Fn resp_end_html .
.Bl -tag -width 1n
.It Ft void Fn pg_show "struct req *req" "const char *fullpath"
This page generator is used when
.Ev PATH_INFO
contains the complete path to a manual page including manpath,
section directory, optional architecture subdirectory, manual name
and section number suffix.
It validates the manpath, changes into it, validate the filename,
and then calls
.Fn resp_begin_html ,
.Fn resp_searchform ,
.Fn resp_show ,
and
.Fn resp_end_html
in that order.
.It Ft void Fn pg_search "const struct req *req"
This page generator is used when
.Ev PATH_INFO
contains a search query in short format or when
.Ev PATH_INFO
is empty and a
.Ev QUERY_STRING
is provided.
It changes into the manpath and calls
.Xr mansearch 3 .
Depending on the result, it calls either
.Fn pg_noresult
or
.Fn pg_searchres .
.It Ft void Fn pg_noresult "const struct req *req" "const char *msg"
This function calls
.Fn resp_begin_html ,
.Fn resp_searchform ,
prints the
.Fa msg
passed to it, and calls
.Fn resp_end_html .
.It Ft void Fn pg_searchres "const struct req *req" "struct manpage *r"\
"size_t sz"
This function first validates the filenames found.
If
.Ev QUERY_STRING
was used and there is exactly one result,
it writes an HTTP redirect to that result.
Otherwise, it writes an HTML result page beginning with
.Fn resp_begin_html
and
.Fn resp_searchform .
If there is more than one result, it writes a list of links
to all the results.
If it was a
.Xr man 1
rather than an
.Xr apropos 1
query or if there is only one single result, it calls
.Fn resp_show .
Finally, it calls
.Fn resp_end_html .
.It Ft void Fn pg_index "const struct req *req"
This page generator is used when
.Ev PATH_INFO
and
.Ev QUERY_STRING
are both empty.
It calls
.Fn resp_begin_html
and
.Fn resp_searchform ,
writes links to help pages, and calls
.Fn resp_end_html .
.It Ft void Fn pg_error_badrequest "const char *msg"
This page generator is used when
.Fn main
or
.Fn pg_show
detect an invalid URI.
It calls
.Fn resp_begin_html ,
prints the
.Fa msg
provided, and calls
.Fn resp_end_html .
.It Ft void Fn pg_error_internal void
This page generator is used by various functions when errors are
detected in the
.Pa manpath.conf
configuration file, in
.Xr mandoc.db 5
databases, in the
.Xr mandoc 3
parser, in file system permissions, or when setting up timeouts.
It calls
.Fn resp_begin_html ,
prints
.Qq "Internal Server Error" ,
and calls
.Fn resp_end_html .
Before calling
.Fn pg_error_internal ,
call
.Xr warn 3
or
.Xr warnx 3
to log the reason of the error to the
.Xr httpd 8
server log file.
.El
.Ss Result generators
The purpose of result generators is to print a chunk of HTML code.
When they print untrusted strings or characters,
.Fn html_print
and
.Fn html_putchar
are used.
The highest level result generators are:
.Bl -tag -width 1n
.It Ft void Fn resp_begin_html "int code" "const char *msg"
This generator calls
.Fn resp_begin_http
to print the HTTP headers, then prints the HTML header up to the
opening tag of the <body> element, then copies the file
.Pa header.html
to the output, if it exists and is readable.
.It Ft void Fn resp_searchform "const struct req *req" "enum focus focus"
This generator prints a search form, filling it with data
from the provided request object.
If the
.Fa focus
argument is
.Dv FOCUS_QUERY ,
it sets the document's autofocus to the query input box.
.It Ft void Fn resp_show "const struct req *req" "const char *file"
This wrapper dispatches to either
.Fn resp_catman
or
.Fn resp_format ,
depending on whether
.Ar file
starts with
.Pa cat
or
.Pa man ,
respectively.
.It Ft void Fn resp_catman "const struct req *req" "const char *file"
This generator translates a preformatted, backspace-encoded manual
page to HTML and prints it to the output.
.It Ft void Fn resp_format "const struct req *req" "const char *file"
This generator formats a manual page on the standard output,
using the functions documented in
.Xr mchars_alloc 3
and
.Xr mandoc 3 .
.It Ft void Fn resp_end_html void
This generator copies the file
.Pa footer.html
to the output, if it exists and is readable,
and closes the <body> and <html> elements.
.El
.Ss Utility routines
These functions take a string and return 1 if it is valid, or 0 otherwise.
.Bl -tag -width 1n
.It Ft int Fn validate_urifrag "const char *frag"
Checks that the string only contains alphanumeric ASCII characters,
dashes, dots, slashes, and underscores.
.It Ft int Fn validate_manpath "const struct req *req" "const char* manpath"
Checks that the string is either
.Qq mandoc
or one of the manpaths configured in
.Pa manpath.conf .
.It Ft int Fn validate_filename "const char *file"
Checks that the string starts with
.Qq man
or
.Qq cat
and does not ascend to parent directories.
.El
.Sh SEE ALSO
.Xr mandoc 3 ,
.Xr mansearch 3 ,
.Xr mchars_alloc 3 ,
.Xr mandoc.db 5 ,
.Xr man.cgi 8

146
man.cgi.8
View File

@ -1,6 +1,6 @@
.\" $Id: man.cgi.8,v 1.13 2015/11/05 20:55:41 schwarze Exp $
.\" $Id: man.cgi.8,v 1.20 2016/07/11 22:48:37 schwarze Exp $
.\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\" Copyright (c) 2014, 2015, 2016 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
@ -14,7 +14,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: November 5 2015 $
.Dd $Mdocdate: July 11 2016 $
.Dt MAN.CGI 8
.Os
.Sh NAME
@ -26,9 +26,9 @@ The
CGI program searches for manual pages on a WWW server
and displays them to HTTP clients,
providing functionality equivalent to the
.Xr apropos 1
and
.Xr man 1
and
.Xr apropos 1
utilities.
It can use multiple manual trees in parallel.
.Ss HTML search interface
@ -51,20 +51,15 @@ The effect of prepending a backslash to another character is undefined;
in the current implementation, it has no effect.
.It
A
.Dq Submit
button to send a search request from the client to the server.
.It
A
.Dq Reset
button to undo any changes to the input boxes and the dropdown menus
and reset them to the values contained in the
.Ev QUERY_STRING .
.It
Radio buttons to select pages either by name like in
.Xr man 1
or using
submit button.
The string in the input box is interpreted as the name of a manual page.
.It
An
.Xr apropos 1
queries.
submit button.
The string in the input box is interpreted as a search
.Ar expression .
.It
A dropdown menu to optionally select a manual section.
If one is provided, it has the same effect as the
@ -162,9 +157,7 @@ Configure your web server to execute CGI programs located in
.Pa /cgi-bin .
When using
.Ox
.Xr httpd 8
or
.Xr nginx 8 ,
.Xr httpd 8 ,
the
.Xr slowcgi 8
proxy daemon is needed to translate FastCGI requests to plain old CGI.
@ -183,31 +176,42 @@ Only useful for running on www.openbsd.org to deal with old URIs containing
.Qq "manpath=OpenBSD "
where the blank character has to be translated to a hyphen.
When compiling for other sites, this definition can be deleted.
.It Ev CSS_DIR
An optional path to the directory containing the CSS files,
.It Dv CSS_DIR
An optional file system path to the directory containing the file
.Pa mandoc.css ,
to be specified relative to the server's document root,
and to be specified without a trailing slash.
When not specified, the CSS files
are assumed to be in the document root.
When empty, the CSS file is assumed to be in the document root.
Otherwise, a leading slash is needed.
This is used in generated HTML code.
.It Ev CUSTOMIZE_TITLE
.It Dv CUSTOMIZE_TITLE
An ASCII string to be used for the HTML <TITLE> element.
.It Ev HTTP_HOST
.It Dv HTTP_HOST
The FQDN of the (possibly virtual) host the HTTP server is running on.
This is used for
.Ic Location:
headers in HTTP 303 responses.
.It Ev MAN_DIR
A path to the
.It Dv MAN_DIR
A file system path to the
.Nm
data directory to be used instead of
.Pa /var/www/man ,
relative to the web server
data directory relative to the web server
.Xr chroot 2
directory, to be specified without a trailing slash.
This is prepended to the manpath when opening
directory, to be specified with a leading slash and without a trailing slash.
It needs to have at least one component; the root directory cannot be used
for this purpose.
The files
.Pa manpath.conf ,
.Pa header.html ,
and
.Pa footer.html
are looked up in this directory.
It is also prepended to the manpath when opening
.Xr mandoc.db 5
and manual page files.
.It Dv SCRIPT_NAME
The initial component of URIs, to be specified without leading
and trailing slashes.
It can be empty.
.El
.Pp
After editing
@ -216,13 +220,16 @@ run
.Pp
.Dl make man.cgi
.Pp
and copy the files to the proper locations.
Reading the
.Cm installcgi
target in the
.Pa Makefile
can help with that, but do not run it without carefully checking it
because the directory layouts of web servers vary greatly.
and copy the resulting binary to the proper location,
for example using the command:
.Pp
.Dl make installcgi
.Pp
In addition to that, make sure the default manpath contains the files
.Pa man1/apropos.1
and
.Pa man8/man.cgi.8 ,
or the documentation links at the bottom of the index page will not work.
.Ss URI interface
.Nm
uniform resource identifiers are not needed for interactive use,
@ -234,14 +241,22 @@ The
.Cm http://
protocol specifier.
.It
The host name and a following slash.
The host name.
.It
The path to the program, normally
.Pa cgi-bin/man.cgi/ .
The
.Dv SCRIPT_NAME ,
preceded by a slash unless empty.
.It
To show a single page, a slash, the manpath, another slash,
and the name of the requested file, for example
.Pa /OpenBSD-current/man1/mandoc.1 .
This can be abbreviated according to the following syntax:
.Sm off
.Op / Ar manpath
.Op / Cm man Ar sec
.Op / Ar arch
.Pf / Ar name Op \&. Ar sec
.Sm on
.It
For searches, a query string starting with a question mark
and consisting of
@ -295,13 +310,20 @@ the underscore
.Pq Sq _
.El
.Pp
In particular, this applies to the
.Ev SCRIPT_NAME ,
to all manpaths, and to all architecture names.
In particular, this applies to all manpaths and architecture names.
.Sh ENVIRONMENT
The web server may pass the following CGI variables to
.Nm :
.Bl -tag -width Ds
.It Ev SCRIPT_NAME
The initial part of the URI passed from the client to the server,
starting after the server's host name and ending before
.Ev PATH_INFO .
This is ignored by
.Nm .
When constructing URIs for links and redirections, the
.Dv SCRIPT_NAME
preprocessor constant is used instead.
.It Ev PATH_INFO
The final part of the URI path passed from the client to the server,
starting after the
@ -317,17 +339,6 @@ It is the final part of the URI, after the question mark.
It is used by the
.Cm search
page to acquire the named parameters it needs.
.It Ev SCRIPT_NAME
The path to the
.Nm
binary relative to the server root, usually
.Pa /cgi-bin/man.cgi .
This is used for generating URIs to be embedded
in generated HTML code and HTTP headers.
If this contains any character not contained in the
.Sx Restricted character set ,
.Nm
reports an internal server error and exits without doing anything.
.El
.Sh FILES
.Bl -tag -width Ds
@ -337,13 +348,18 @@ Default web server
directory.
All the following paths are specified relative to this directory.
.It Pa /cgi-bin/man.cgi
The path to the
The usual file system path to the
.Nm
program relative to the server root.
Can be overridden by
.Ev SCRIPT_NAME .
program inside the web server
.Xr chroot 2
directory.
A different name can be chosen, but in any case, it needs to be configured in
.Xr httpd.conf 5 .
.It Pa /htdocs
The path to the server document root relative to the server root.
The file system path to the server document root directory
relative to the server
.Xr chroot 2
directory.
This is part of the web server configuration and not specific to
.Nm .
.It Pa /htdocs/mandoc.css
@ -355,11 +371,7 @@ Default
.Nm
data directory containing all the manual trees.
Can be overridden by
.Ev MAN_DIR .
.It Pa /man/mandoc/man1/apropos.1 , /man/mandoc/man8/man.cgi.8
Manual pages documenting
.Nm
itself, linked from the index page.
.Dv MAN_DIR .
.It Pa /man/manpath.conf
The list of available manpaths, one per line.
If any of the lines in this file contains a slash

185
mandoc.3
View File

@ -1,4 +1,4 @@
.\" $Id: mandoc.3,v 1.36 2016/01/08 17:48:09 schwarze Exp $
.\" $Id: mandoc.3,v 1.37 2016/07/07 19:19:01 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\" Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
@ -15,18 +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: January 8 2016 $
.Dd $Mdocdate: July 7 2016 $
.Dt MANDOC 3
.Os
.Sh NAME
.Nm mandoc ,
.Nm man_deroff ,
.Nm man_meta ,
.Nm deroff ,
.Nm mandocmsg ,
.Nm man_mparse ,
.Nm man_node ,
.Nm mdoc_deroff ,
.Nm mdoc_meta ,
.Nm mdoc_node ,
.Nm man_validate ,
.Nm mdoc_validate ,
.Nm mparse_alloc ,
.Nm mparse_free ,
.Nm mparse_getkeep ,
@ -91,8 +89,7 @@
.Ft void
.Fo mparse_result
.Fa "struct mparse *parse"
.Fa "struct mdoc **mdoc"
.Fa "struct man **man"
.Fa "struct roff_man **man"
.Fa "char **sodest"
.Fc
.Ft "const char *"
@ -103,45 +100,33 @@
.Fo mparse_strlevel
.Fa "enum mandoclevel"
.Fc
.In roff.h
.Ft void
.Fo deroff
.Fa "char **dest"
.Fa "const struct roff_node *node"
.Fc
.In sys/types.h
.In mandoc.h
.In mdoc.h
.Ft void
.Fo mdoc_deroff
.Fa "char **dest"
.Fa "const struct mdoc_node *node"
.Fc
.Ft "const struct mdoc_meta *"
.Fo mdoc_meta
.Fa "const struct mdoc *mdoc"
.Fc
.Ft "const struct mdoc_node *"
.Fo mdoc_node
.Fa "const struct mdoc *mdoc"
.Fc
.Vt extern const char * const * mdoc_argnames;
.Vt extern const char * const * mdoc_macronames;
.Ft void
.Fo mdoc_validate
.Fa "struct roff_man *mdoc"
.Fc
.In sys/types.h
.In mandoc.h
.In man.h
.Ft void
.Fo man_deroff
.Fa "char **dest"
.Fa "const struct man_node *node"
.Fc
.Ft "const struct man_meta *"
.Fo man_meta
.Fa "const struct man *man"
.Fc
.Vt extern const char * const * man_macronames;
.Ft "const struct mparse *"
.Fo man_mparse
.Fa "const struct man *man"
.Fa "const struct roff_man *man"
.Fc
.Ft "const struct man_node *"
.Fo man_node
.Fa "const struct man *man"
.Ft void
.Fo man_validate
.Fa "struct roff_man *man"
.Fc
.Vt extern const char * const * man_macronames;
.Sh DESCRIPTION
The
.Nm mandoc
@ -182,10 +167,24 @@ close it with
retrieve the syntax tree with
.Fn mparse_result ;
.It
iterate over parse nodes with
.Fn mdoc_node
depending on whether the
.Fa macroset
member of the returned
.Vt struct roff_man
is
.Dv MACROSET_MDOC
or
.Fn man_node ;
.Dv MACROSET_MAN ,
validate it with
.Fn mdoc_validate
or
.Fn man_validate ,
respectively;
.It
iterate over parse nodes with starting from the
.Fa first
member of the returned
.Vt struct roff_man ;
.It
free all allocated memory with
.Fn mparse_free
@ -193,7 +192,7 @@ and
.Xr mchars_free 3 ,
or invoke
.Fn mparse_reset
and parse new files.
and go back to step 2 to parse new files.
.El
.Sh REFERENCE
This section documents the functions, types, and variables available
@ -211,6 +210,9 @@ An error or warning message during parsing.
A classification of an
.Vt "enum mandocerr"
as regards system operation.
See the DIAGNOSTICS section in
.Xr mandoc 1
regarding the meanings of the levels.
.It Vt "struct mparse"
An opaque pointer to a running parse sequence.
Created with
@ -226,67 +228,37 @@ messages emitted by the parser.
.El
.Ss Functions
.Bl -ohang
.It Fn man_deroff
.It Fn deroff
Obtain a text-only representation of a
.Vt struct man_node ,
.Vt struct roff_node ,
including text contained in its child nodes.
To be used on children of the pointer returned from
.Fn man_node .
To be used on children of the
.Fa first
member of
.Vt struct roff_man .
When it is no longer needed, the pointer returned from
.Fn man_deroff
.Fn deroff
can be passed to
.Xr free 3 .
.It Fn man_meta
Obtain the meta-data of a successful
.Xr man 7
parse.
This may only be used on a pointer returned by
.Fn mparse_result .
Declared in
.In man.h ,
implemented in
.Pa man.c .
.It Fn man_mparse
Get the parser used for the current output.
Declared in
.In man.h ,
implemented in
.Pa man.c .
.It Fn man_node
Obtain the root node of a successful
.Xr man 7
parse.
This may only be used on a pointer returned by
.It Fn man_validate
Validate the
.Dv MACROSET_MAN
parse tree obtained with
.Fn mparse_result .
Declared in
.In man.h ,
implemented in
.Pa man.c .
.It Fn mdoc_deroff
Obtain a text-only representation of a
.Vt struct mdoc_node ,
including text contained in its child nodes.
To be used on children of the pointer returned from
.Fn mdoc_node .
When it is no longer needed, the pointer returned from
.Fn mdoc_deroff
can be passed to
.Xr free 3 .
.It Fn mdoc_meta
Obtain the meta-data of a successful
.Xr mdoc
parse.
This may only be used on a pointer returned by
.Fn mparse_result .
Declared in
.In mdoc.h ,
implemented in
.Pa mdoc.c .
.It Fn mdoc_node
Obtain the root node of a successful
.Xr mdoc
parse.
This may only be used on a pointer returned by
.It Fn mdoc_validate
Validate the
.Dv MACROSET_MDOC
parse tree obtained with
.Fn mparse_result .
Declared in
.In mdoc.h ,
@ -335,6 +307,9 @@ A callback function to handle errors and warnings.
See
.Pa main.c
for an example.
If printing of error messages is not desired,
.Dv NULL
may be passed.
.It Ar defos
A default string for the
.Xr mdoc 7
@ -343,6 +318,9 @@ macro, overriding the
.Dv OSNAME
preprocessor definition and the results of
.Xr uname 3 .
Passing
.Dv NULL
sets no default.
.El
.Pp
The same parser may be used for multiple files so long as
@ -421,7 +399,7 @@ implemented in
.Pa read.c .
.It Fn mparse_result
Obtain the result of a parse.
One of the three pointers will be filled in.
One of the two pointers will be filled in.
Declared in
.In mandoc.h ,
implemented in
@ -442,13 +420,19 @@ implemented in
.Ss Variables
.Bl -ohang
.It Va man_macronames
The string representation of a man macro as indexed by
The string representation of a
.Xr man 7
macro as indexed by
.Vt "enum mant" .
.It Va mdoc_argnames
The string representation of a mdoc macro argument as indexed by
The string representation of an
.Xr mdoc 7
macro argument as indexed by
.Vt "enum mdocargt" .
.It Va mdoc_macronames
The string representation of a mdoc macro as indexed by
The string representation of an
.Xr mdoc 7
macro as indexed by
.Vt "enum mdoct" .
.El
.Sh IMPLEMENTATION NOTES
@ -492,15 +476,15 @@ This AST is governed by the ontological rules dictated in
and derives its terminology accordingly.
.Pp
The AST is composed of
.Vt struct man_node
.Vt struct roff_node
nodes with element, root and text types as declared by the
.Va type
field.
Each node also provides its parse point (the
.Va line ,
.Va sec ,
.Va pos ,
and
.Va pos
.Va sec
fields), its position in the tree (the
.Va parent ,
.Va child ,
@ -544,16 +528,16 @@ are described simply as
.Qq elements .
.Pp
The AST is composed of
.Vt struct mdoc_node
.Vt struct roff_node
nodes with block, head, body, element, root and text types as declared
by the
.Va type
field.
Each node also provides its parse point (the
.Va line ,
.Va sec ,
.Va pos ,
and
.Va pos
.Va sec
fields), its position in the tree (the
.Va parent ,
.Va child ,
@ -670,9 +654,13 @@ consistent across troff implementations, especially when using multiple
levels of badly-nested blocks.
.Sh SEE ALSO
.Xr mandoc 1 ,
.Xr man.cgi 3 ,
.Xr mandoc_escape 3 ,
.Xr mandoc_headers 3 ,
.Xr mandoc_malloc 3 ,
.Xr mansearch 3 ,
.Xr mchars_alloc 3 ,
.Xr tbl 3 ,
.Xr eqn 7 ,
.Xr man 7 ,
.Xr mandoc_char 7 ,
@ -680,7 +668,10 @@ levels of badly-nested blocks.
.Xr roff 7 ,
.Xr tbl 7
.Sh AUTHORS
.An -nosplit
The
.Nm
library was written by
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
.An Kristaps Dzonsons Aq Mt kristaps@bsd.lv
and is maintained by
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .

View File

@ -1,4 +1,4 @@
/* $Id: mandoc.css,v 1.1 2015/11/05 17:47:51 schwarze Exp $ */
/* $Id: mandoc.css,v 1.2 2016/04/13 10:19:23 schwarze Exp $ */
/*
* This is an example style-sheet provided for mandoc(1) and the -Thtml
@ -24,7 +24,8 @@ body > div.results { font-size: smaller; }
#mancgi input[name=expr] { width: 25%; }
.results td.title { vertical-align: top;
padding-right: 1em; }
h1 { margin-bottom: 1ex; font-size: 110%; margin-left: -4ex; } /* Section header (Sh, SH). */
h1 { margin-bottom: 1ex; font-size: 110% }
div.section > h1 { margin-left: -4ex; } /* Section header (Sh, SH). */
h2 { margin-bottom: 1ex; font-size: 105%; margin-left: -2ex; } /* Sub-section header (Ss, SS). */
table { width: 100%; margin-top: 0ex; margin-bottom: 0ex; } /* All tables. */
td { vertical-align: top; } /* All table cells. */

View File

@ -1,4 +1,4 @@
.\" $Id: mandoc.db.5,v 1.3 2014/12/30 21:34:57 schwarze Exp $
.\" $Id: mandoc.db.5,v 1.4 2016/07/07 14:35:48 schwarze Exp $
.\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\"
@ -14,7 +14,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: December 30 2014 $
.Dd $Mdocdate: July 7 2016 $
.Dt MANDOC.DB 5
.Os
.Sh NAME
@ -133,7 +133,6 @@ The same for
.Xr man 1 ,
.Xr sqlite3 1 ,
.Xr whatis 1 ,
.Xr mansearch 3 ,
.Xr makewhatis 8
.Sh HISTORY
A manual page database

View File

@ -62,6 +62,11 @@ for
.Vt size_t .
Provides the utility functions documented in
.Xr mandoc_malloc 3 .
.It Qq Pa mandoc_ohash.h
Includes
.In ohash.h
and provides
.Fn mandoc_ohash_init .
.It Qq Pa mandoc.h
Requires
.In sys/types.h
@ -80,7 +85,6 @@ Provides
.Vt enum eqn_pilet ,
.Vt enum eqn_post ,
.Vt struct tbl_opts ,
.Vt struct tbl_head ,
.Vt struct tbl_cell ,
.Vt struct tbl_row ,
.Vt struct tbl_dat ,
@ -103,30 +107,30 @@ Uses the opaque type
from
.Pa read.c
for function prototypes.
Uses the types
.Vt struct mdoc
Uses the type
.Vt struct roff_man
from
.Pa libmdoc.h
and
.Vt struct man
from
.Pa libman.h
as opaque types for function prototypes.
.Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa roff.h
Provides
.Vt enum mdoc_endbody ,
.Vt enum roff_macroset ,
.Vt enum roff_next ,
.Vt enum roff_sec ,
.Vt enum roff_type ,
.Vt struct roff_man ,
.Vt struct roff_meta ,
and
.Vt struct roff_node .
.Vt struct roff_node ,
and the function
.Fn deroff .
.Pp
Uses pointers to the types
.Vt struct mdoc_arg
and
.Vt union mdoc_data
from
.Qq Pa mdoc.h
.Pa mdoc.h
as opaque struct members.
.El
.Pp
@ -139,51 +143,38 @@ Afterwards, any other mandoc headers can be included as needed.
Requires
.In sys/types.h
for
.Vt size_t
and
.Qq Pa roff.h
for
.Vt enum roff_type .
.Vt size_t .
.Pp
Provides
.Vt enum mdocargt ,
.Vt enum mdoc_disp ,
.Vt enum mdoc_list ,
.Vt enum mdoc_auth ,
.Vt enum mdoc_disp ,
.Vt enum mdoc_font ,
.Vt enum mdoc_list ,
.Vt struct mdoc_argv ,
.Vt struct mdoc_arg ,
.Vt struct mdoc_bd ,
.Vt struct mdoc_bl ,
.Vt struct mdoc_an ,
.Vt struct mdoc_bd ,
.Vt struct mdoc_bf ,
.Vt struct mdoc_bl ,
.Vt struct mdoc_rs ,
.Vt union mdoc_data ,
and the functions
.Fn mdoc_*
described in
.Xr mandoc 3 .
.Pp
Uses the type
.Vt struct mdoc
.Vt struct roff_man
from
.Pa libmdoc.h
.Pa roff.h
as an opaque type for function prototypes.
Uses pointers to the types
.Vt struct tbl_span
and
.Vt struct eqn
as opaque struct members.
.Pp
When this header is included, the same file should not include
.Pa libman.h
or
.Pa libroff.h .
.It Qq Pa man.h
Requires
.Qq Pa roff.h
for
.Vt enum roff_type .
.Pp
Provides the functions
.Fn man_*
described in
@ -195,15 +186,10 @@ from
.Pa read.c
for function prototypes.
Uses the type
.Vt struct man
.Vt struct roff_man
from
.Pa libman.h
.Pa roff.h
as an opaque type for function prototypes.
Uses pointers to the types
.Vt struct tbl_span
and
.Vt struct eqn
as opaque struct members.
.Pp
When this header is included, the same file should not include
.Pa libmdoc.h
@ -220,16 +206,11 @@ are included, the same file should not include any formatter headers.
Requires
.In sys/types.h
for
.Vt size_t ,
.Vt size_t
and
.Qq Pa mandoc.h
for
.Vt enum mandocerr ,
and
.Qq Pa roff.h
for
.Vt struct roff_meta
and
.Vt struct roff_node .
.Vt enum mandocerr .
.Pp
Provides
.Vt enum rofferr ,
@ -251,14 +232,42 @@ Uses the types
and
.Vt struct eqn
from
.Pa mandoc.h ,
.Vt struct mdoc
from
.Pa libmdoc.h ,
.Pa mandoc.h
and
.Vt struct man
.Vt struct roff_man
from
.Pa libman.h
.Pa roff.h
as opaque types for function prototypes.
.It Qq Pa roff_int.h
Requires
.Qq Pa roff.h
for
.Vt enum roff_type .
.Pp
Provides functions named
.Fn roff_*
to handle roff nodes and the two special functions
.Fn man_breakscope
and
.Fn mdoc_argv_free
because the latter two are needed by
.Qq Pa roff.c .
.Pp
Uses the types
.Vt struct eqn
and
.Vt struct tbl_span
from
.Pa mandoc.h ,
.Vt struct roff_man
and
.Vt struct roff_node
from
.Pa roff.h ,
and
.Vt struct mdoc_arg
from
.Pa mdoc.h
as opaque types for function prototypes.
.It Qq Pa libmdoc.h
Requires
@ -269,23 +278,24 @@ and
.Vt struct mdoc_* .
.Pp
Provides
.Vt enum mdoc_next ,
.Vt enum margserr ,
.Vt enum mdelim ,
.Vt struct mdoc ,
.Vt struct mdoc_macro ,
and many functions internal to the
.Xr mdoc 7
parser.
.Pp
Uses the opaque types
Uses the opaque type
.Vt struct mparse
from
.Pa read.c
.Pa read.c .
Uses the types
.Vt struct roff_man
and
.Vt struct roff
.Vt struct roff_node
from
.Pa roff.c .
.Pa roff.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
.Pa man.h ,
@ -293,29 +303,19 @@ When this header is included, the same file should not include
or
.Pa libroff.h .
.It Qq Pa libman.h
Requires
.Qq Pa roff.h
for
.Vt struct roff_meta
and
.Vt struct roff_node .
.Pp
Provides
.Vt enum man_next ,
.Vt struct man ,
.Vt struct man_macro ,
and many functions internal to the
.Vt struct man_macro
and some functions internal to the
.Xr man 7
parser.
.Pp
Uses the opaque types
.Vt struct mparse
from
.Pa read.c
Uses the types
.Vt struct roff_man
and
.Vt struct roff
.Vt struct roff_node
from
.Pa roff.c .
.Pa roff.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
.Pa mdoc.h ,
@ -420,7 +420,7 @@ from
and
.Vt struct roff_meta
from
.Qq Pa roff.h
.Pa roff.h
as opaque types for function prototypes.
.Pp
When this header is included, the same file should not include
@ -456,18 +456,26 @@ When this header is included, the same file should not include
.Pa term.h
or
.Pa mansearch.h .
.It Qq Pa tag.h
Requires
.In sys/types.h
for
.Vt size_t .
.Pp
Provides an interface to generate
.Xr ctags 1
files for the
.Ic :t
functionality mentioned in
.Xr man 1 .
.It Qq Pa main.h
Provides the top level steering functions for all formatters.
.Pp
Uses the types
.Vt struct mdoc
Uses the type
.Vt struct roff_man
from
.Pa libmdoc.h
and
.Vt struct man
from
.Pa libman.h
as opaque types for function prototypes.
.Pa roff.h
as an opaque type for function prototypes.
.It Qq Pa manconf.h
Requires
.In sys/types.h

View File

@ -1,4 +1,4 @@
.\" $Id: mandoc_malloc.3,v 1.1 2014/08/05 05:48:56 schwarze Exp $
.\" $Id: mandoc_malloc.3,v 1.2 2016/07/07 19:19:01 schwarze Exp $
.\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\"
@ -14,7 +14,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 5 2014 $
.Dd $Mdocdate: July 7 2016 $
.Dt MANDOC_MALLOC 3
.Os
.Sh NAME
@ -26,8 +26,6 @@
.Nm mandoc_strndup ,
.Nm mandoc_asprintf
.Nd memory allocation function wrappers used in the mandoc library
.Sh LIBRARY
.Lb libmandoc
.Sh SYNOPSIS
.In sys/types.h
.In mandoc_aux.h
@ -67,21 +65,18 @@
.Fa "..."
.Fc
.Sh DESCRIPTION
These functions call the
.Lb libc
functions of the same names, passing through their return values when
successful.
These functions call the libc functions of the same names, passing
through their return values when successful.
In case of failure, they do not return, but instead call
.Xr perror 3
and
.Xr exit 3 .
They can be used both internally by any code in the
.Lb libmandoc
.Xr err 3 .
They can be used both internally by any code in the mandoc libraries
and externally by programs using that library, for example
.Xr mandoc 1 ,
.Xr man 1 ,
.Xr apropos 1 ,
.Xr makewhatis 8 ,
and
.Xr makewhatis 8 .
.Xr man.cgi 8 .
.Pp
The function
.Fn mandoc_malloc
@ -149,9 +144,8 @@ These functions are implemented in
.Pa mandoc_aux.c .
.Sh SEE ALSO
.Xr asprintf 3 ,
.Xr exit 3 ,
.Xr err 3 ,
.Xr malloc 3 ,
.Xr perror 3 ,
.Xr strdup 3
.Sh STANDARDS
The functions

View File

@ -1,4 +1,4 @@
/* $Id: mandocdb.c,v 1.215 2016/01/08 17:48:09 schwarze Exp $ */
/* $Id: mandocdb.c,v 1.218 2016/07/12 05:18:38 kristaps Exp $ */
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org>
@ -33,8 +33,10 @@
#else
#include "compat_fts.h"
#endif
#include <getopt.h>
#include <limits.h>
#if HAVE_SANDBOX_INIT
#include <sandbox.h>
#endif
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
@ -346,6 +348,13 @@ mandocdb(int argc, char *argv[])
}
#endif
#if HAVE_SANDBOX_INIT
if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1) {
warnx("sandbox_init");
return (int)MANDOCLEVEL_SYSERR;
}
#endif
memset(&conf, 0, sizeof(conf));
memset(stmts, 0, STMT__MAX * sizeof(sqlite3_stmt *));
@ -574,7 +583,7 @@ mandocdb(int argc, char *argv[])
* or
* [./]cat<section>[/<arch>]/<name>.0
*
* TODO: accomodate for multi-language directories.
* TODO: accommodate for multi-language directories.
*/
static int
treescan(void)

View File

@ -1,4 +1,4 @@
/* $Id: manpage.c,v 1.13 2015/11/07 17:58:55 schwarze Exp $ */
/* $Id: manpage.c,v 1.14 2016/07/09 15:24:19 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
@ -20,7 +20,6 @@
#include <sys/types.h>
#include <assert.h>
#include <getopt.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>

View File

@ -1,4 +1,4 @@
/* $Id: manpath.c,v 1.29 2015/11/07 17:58:55 schwarze Exp $ */
/* $Id: manpath.c,v 1.30 2016/05/28 13:44:13 schwarze Exp $ */
/*
* Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@ -224,13 +224,12 @@ manconf_file(struct manconf *conf, const char *file)
while ((linelen = getline(&line, &linesz, stream)) != -1) {
cp = line;
ep = cp + linelen;
if (ep[-1] != '\n')
break;
*--ep = '\0';
ep = cp + linelen - 1;
while (ep > cp && isspace((unsigned char)*ep))
*ep-- = '\0';
while (isspace((unsigned char)*cp))
cp++;
if (*cp == '#')
if (cp == ep || *cp == '#')
continue;
for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) {

View File

@ -1,4 +1,4 @@
/* $Id: mansearch.c,v 1.64 2016/01/08 15:02:54 schwarze Exp $ */
/* $Id: mansearch.c,v 1.65 2016/07/09 15:24:19 schwarze Exp $ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -26,7 +26,6 @@
#endif
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <glob.h>
#include <limits.h>
#include <regex.h>

View File

@ -1,4 +1,4 @@
.\" $Id: mchars_alloc.3,v 1.3 2015/10/13 22:59:54 schwarze Exp $
.\" $Id: mchars_alloc.3,v 1.4 2016/07/07 19:19:01 schwarze Exp $
.\"
.\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
.\"
@ -14,7 +14,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: October 13 2015 $
.Dd $Mdocdate: July 7 2016 $
.Dt MCHARS_ALLOC 3
.Os
.Sh NAME
@ -23,7 +23,8 @@
.Nm mchars_num2char ,
.Nm mchars_num2uc ,
.Nm mchars_spec2cp ,
.Nm mchars_spec2str
.Nm mchars_spec2str ,
.Nm mchars_uc2str
.Nd character table for mandoc
.Sh SYNOPSIS
.In sys/types.h

4
read.c
View File

@ -1,4 +1,4 @@
/* $Id: read.c,v 1.148 2016/01/08 02:53:13 schwarze Exp $ */
/* $Id: read.c,v 1.149 2016/07/10 13:34:30 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org>
@ -798,7 +798,7 @@ mparse_open(struct mparse *curp, const char *file)
if ( ! curp->gzip) {
mandoc_asprintf(&cp, "%s.gz", file);
fd = open(file, O_RDONLY);
fd = open(cp, O_RDONLY);
free(cp);
if (fd != -1) {
curp->gzip = 1;

26
tag.c
View File

@ -1,4 +1,4 @@
/* $Id: tag.c,v 1.11 2015/11/20 21:59:54 schwarze Exp $ */
/* $Id: tag.c,v 1.12 2016/07/08 20:42:15 schwarze Exp $ */
/*
* Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
*
@ -57,6 +57,24 @@ tag_init(void)
tag_files.tfd = -1;
tag_files.tcpgid = -1;
/* Clean up when dying from a signal. */
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sa.sa_handler = tag_signal;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
/*
* POSIX requires that a process calling tcsetpgrp(3)
* from the background gets a SIGTTOU signal.
* In that case, do not stop.
*/
sa.sa_handler = SIG_IGN;
sigaction(SIGTTOU, &sa, NULL);
/* Save the original standard output for use by the pager. */
if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1)
@ -68,12 +86,6 @@ tag_init(void)
sizeof(tag_files.ofn));
(void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX",
sizeof(tag_files.tfn));
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sa.sa_handler = tag_signal;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
if ((ofd = mkstemp(tag_files.ofn)) == -1)
goto fail;
if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1)

4
term.c
View File

@ -1,4 +1,4 @@
/* $Id: term.c,v 1.256 2016/01/07 21:03:54 schwarze Exp $ */
/* $Id: term.c,v 1.257 2016/04/12 15:30:00 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
@ -160,7 +160,7 @@ term_flushln(struct termp *p)
if (' ' == p->buf[j] || '\t' == p->buf[j])
break;
/* Back over the the last printed character. */
/* Back over the last printed character. */
if (8 == p->buf[j]) {
assert(j);
vend -= (*p->width)(p, p->buf[j - 1]);

View File

@ -1,4 +1,4 @@
/* $Id: term_ascii.c,v 1.52 2015/11/12 21:50:03 schwarze Exp $ */
/* $Id: term_ascii.c,v 1.53 2016/07/08 22:29:05 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@ -163,18 +163,17 @@ ascii_setwidth(struct termp *p, int iop, int width)
}
void
ascii_sepline(void *arg)
terminal_sepline(void *arg)
{
struct termp *p;
size_t i;
p = (struct termp *)arg;
p->line += 3;
putchar('\n');
(*p->endline)(p);
for (i = 0; i < p->defrmargin; i++)
putchar('-');
putchar('\n');
putchar('\n');
(*p->letter)(p, '-');
(*p->endline)(p);
(*p->endline)(p);
}
static size_t

View File

@ -1,4 +1,5 @@
#include <sys/types.h>
#include <stddef.h>
#include <regex.h>
int

View File

@ -1,4 +1,5 @@
#include <sys/types.h>
#include <stddef.h>
#include <regex.h>
int