NetBSD Problem Report #1904
From gnats Sat Jan 6 15:36:20 1996
Received: from snarf.umiacs.umd.edu by pain.lcs.mit.edu (8.6.12/8.6.9) with ESMTP id PAA09414 for <gnats-bugs@gnats.netbsd.org>; Sat, 6 Jan 1996 15:31:36 -0500
Message-Id: <199601062031.PAA19882@snarf.umiacs.umd.edu>
Date: Sat, 6 Jan 1996 15:31:23 -0500
From: kashmir@umiacs.umd.edu
To: gnats-bugs@gnats.netbsd.org
Subject: changes to man programs
X-Send-Pr-Version: 3.95
>Number: 1904
>Category: bin
>Synopsis: changes to man programs
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: closed
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Jan 06 15:50:01 +0000 1996
>Closed-Date: Sun May 29 22:37:10 +0000 2016
>Last-Modified: Sun May 29 22:37:10 +0000 2016
>Originator: Mike Grupenhoff
>Release: 19960106
>Organization:
nyuk nyuk
>Environment:
System: NetBSD snarf.umiacs.umd.edu 1.1A NetBSD 1.1A (SNARF) #7: Fri Dec 29 23:04:19 EST 1995 kashmir@snarf.umiacs.umd.edu:/usr/src/sys/arch/i386/compile/SNARF i386
>Description:
- apropos and whatis can't handle multiple whatis db's when they
are specified in shell glob syntax. For example, a line like:
_whatdb /usr/{share,local,afs,X11}/man/whatis.db
in /etc/man.conf will not be handled properly.
- catman doesn't work with /etc/man.conf and linked manpages
- bsd.man.mk doesn't use the build rules listed in /etc/man.conf
catman should be used in bsd.man.mk instead of nroff
>How-To-Repeat:
look at the source
>Fix:
4 patches are attached.
The first patch adds support to apropos for globbing _whatdb.
-----cut-here-----
Index: apropos.c
===================================================================
RCS file: /snarf/netbsd/master/src/usr.bin/apropos/apropos.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 apropos.c
--- apropos.c 1995/11/16 02:27:00 1.1.1.1
+++ apropos.c 1996/01/02 05:28:43
@@ -52,6 +52,7 @@
#include <ctype.h>
#include <err.h>
+#include <glob.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -77,6 +78,7 @@
TAG *tp;
int ch, rv;
char *conffile, **p, *p_augment, *p_path;
+ glob_t pg;
conffile = NULL;
p_augment = p_path = NULL;
@@ -117,8 +119,15 @@
config(conffile);
ep = (tp = getlist("_whatdb")) == NULL ?
NULL : tp->list.tqh_first;
- for (; ep != NULL; ep = ep->q.tqe_next)
- apropos(argv, ep->s, 0);
+ for (; ep != NULL; ep = ep->q.tqe_next) {
+ if (glob(ep->s, GLOB_BRACE|GLOB_QUOTE, NULL, &pg) != 0)
+ err(1, "glob");
+ if (pg.gl_matchc == 0)
+ continue;
+ for (ch = 0; pg.gl_pathv[ch] != NULL; ch++)
+ apropos(argv, pg.gl_pathv[ch], 0);
+ globfree(&pg);
+ }
}
if (!foundman)
-----cut-here-----
The second patch adds glob support to whatis.
-----cut-here-----
Index: whatis.c
===================================================================
RCS file: /snarf/netbsd/master/src/usr.bin/whatis/whatis.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 whatis.c
--- whatis.c 1995/11/16 02:28:52 1.1.1.1
+++ whatis.c 1996/01/02 05:27:59
@@ -1,3 +1,5 @@
+/* $NetBSD$ */
+
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
@@ -38,7 +40,11 @@
#endif /* not lint */
#ifndef lint
+#if 0
static char sccsid[] = "@(#)whatis.c 8.5 (Berkeley) 11/26/93";
+#else
+static char rcsid[] = "$NetBSD$";
+#endif
#endif /* not lint */
#include <sys/param.h>
@@ -46,6 +52,7 @@
#include <ctype.h>
#include <err.h>
+#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -71,6 +78,7 @@
TAG *tp;
int ch, rv;
char *beg, *conffile, **p, *p_augment, *p_path;
+ glob_t pg;
conffile = NULL;
p_augment = p_path = NULL;
@@ -112,8 +120,15 @@
config(conffile);
ep = (tp = getlist("_whatdb")) == NULL ?
NULL : tp->list.tqh_first;
- for (; ep != NULL; ep = ep->q.tqe_next)
- whatis(argv, ep->s, 0);
+ for (; ep != NULL; ep = ep->q.tqe_next) {
+ if (glob(ep->s, GLOB_BRACE|GLOB_QUOTE, NULL, &pg) != 0)
+ err(1, "glob");
+ if (pg.gl_matchc == 0)
+ continue;
+ for (ch = 0; pg.gl_pathv[ch] != NULL; ch++)
+ whatis(argv, pg.gl_pathv[ch], 0);
+ globfree(&pg);
+ }
}
if (!foundman) {
-----cut-here-----
The third patch is for catman. It does the following:
-adds $NetBSD$ rcsids
-adds support for parsing man.conf
-adds support for handling hard and symlinked manpages (it hard
links the catpage together in both cases)
-adds a second mode of operation:
catman <manpage>
will format the manpage using the build rules in /etc/man.conf,
and dump it to stdout. This can be used in bsd.man.mk to
format manpages instead of assuming everything works with
nroff -man.
After applying this patch, TODO and pathnames.h should be removed from the
catman directory. Note that this patch also modifies pathnames.h in the man
src directory (it adds _PATH_MAKEWHATIS).
-----cut-here-----
Index: Makefile
===================================================================
RCS file: /snarf/netbsd/master/src/usr.sbin/catman/Makefile,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Makefile
--- Makefile 1995/11/16 02:29:24 1.1.1.1
+++ Makefile 1996/01/02 02:45:05
@@ -1,7 +1,8 @@
-# $Id: Makefile,v 1.1.1.1 1995/11/16 02:29:24 kashmir Exp $
+# $NetBSD$
-BINDIR= /usr/sbin
PROG= catman
+SRCS= catman.c config.c
MAN= catman.8
+.PATH: ${.CURDIR}/../../usr.bin/man
.include <bsd.prog.mk>
Index: catman.8
===================================================================
RCS file: /snarf/netbsd/master/src/usr.sbin/catman/catman.8,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 catman.8
--- catman.8 1995/11/16 02:29:24 1.1.1.1
+++ catman.8 1996/01/02 02:29:22
@@ -1,3 +1,4 @@
+.\" $NetBSD$
.\"
.\" Copyright (c) 1993 Winning Strategies, Inc.
.\" All rights reserved.
@@ -27,9 +28,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $Id: catman.8,v 1.1.1.1 1995/11/16 02:29:24 kashmir Exp $
-.\"
-.Dd July 30, 1993
+.Dd January 1, 1995
.Dt CATMAN 8
.Os
.Sh NAME
@@ -38,13 +37,20 @@
.Sh SYNOPSIS
.Nm catman
.Op Fl knpsw
+.Op Fl C Ar file
.Op Fl M Ar directory
.Op Ar sections
+.Nm catman
+.Op Fl C Ar file
+.Ar manpage
.Sh DESCRIPTION
.Nm Catman
creates formatted versions of the on-line manual pages from their
.Xr nroff 1
source.
+.Pp
+The first form of the command operates on the man directories specified in
+/etc/man.conf.
Manual pages whose formatted versions are missing or out of date are
regenerated.
If manual pages are regenerated,
@@ -66,6 +72,9 @@
.Nm catman
will try to operate on all of the known manual sections.
.Pp
+The second form of the command takes a filename on the command line and
+generates formatted output to stdout.
+.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl k
@@ -86,15 +95,32 @@
Only create the
.Nm whatis
database.
+.It Fl C Ar file
+Use the specified
+.Ar file
+instead of the default configuration file.
.It Fl M Ar directory
Update manual pages in
.Ar directory.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width MANPATH
+.It Ev MANPATH
+The standard search path may be overridden by specifying a path in the
+.Ev MANPATH
+environment variable.
+.El
+.Sh FILES
+.Bl -tag
+.It Pa /etc/man.conf
+default man configuration file.
+.El
+.Bl -tag
+.It Pa whatis.db
+name of the whatis database.
+.El
.Sh SEE ALSO
.Xr apropos 1 ,
.Xr man 1 ,
.Xr whatis 1
-.Sh BUGS
-Currently knows nothing about
-.Pa /etc/man.conf
-and machine specific man pages.
+.Xr man.conf 5
Index: catman.c
===================================================================
RCS file: /snarf/netbsd/master/src/usr.sbin/catman/catman.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 catman.c
--- catman.c 1995/11/16 02:29:24 1.1.1.1
+++ catman.c 1996/01/06 19:49:46
@@ -1,4 +1,7 @@
+/* $NetBSD$ */
+
/*
+ * Copyright (c) 1996 Michael E. Grupenhoff. All rights reserved.
* Copyright (c) 1993 Winning Strategies, Inc.
* All rights reserved.
*
@@ -29,23 +32,28 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: catman.c,v 1.1.1.1 1995/11/16 02:29:24 kashmir Exp $";
+static char rcsid[] = "$NetBSD$";
#endif /* not lint */
#include <sys/types.h>
+#include <sys/queue.h>
#include <sys/stat.h>
#include <sys/wait.h>
+
+#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
+#include <fnmatch.h>
+#include <glob.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <paths.h>
-#include "pathnames.h"
+#include "../../usr.bin/man/config.h"
+#include "../../usr.bin/man/pathnames.h"
int f_nowhatis;
int f_noaction;
@@ -53,23 +61,29 @@
int f_ignerr;
int f_noprint;
-int dowhatis;
-
-char *mp = _PATH_MAN;
-char *sp = _MAN_SECTIONS;
-
-void usage __P((void));
-void catman __P((const char *, char *));
-void makewhatis __P((const char *));
+int catman __P((const char *));
+int dirformat __P((char *, char *, char *));
void dosystem __P((const char *));
+void lncatpages __P((char *, char *, char *, char *, char *));
+void makedefault __P((char *));
+void makesubdir __P((const char *));
+void makewhatis __P((const char *));
+void mformat __P((char *, char *));
+void usage __P((void));
int
main(argc, argv)
int argc;
char **argv;
{
- int c;
+ int c, needwhatis;
+ char *conffile, *mp;
+ glob_t pg;
+ ENTRY *ep;
+ TAG *tp;
+ mp = NULL;
+ conffile = _PATH_MANCONF;
while ((c = getopt(argc, argv, "knpswM:")) != EOF) {
switch (c) {
case 'k':
@@ -87,6 +101,9 @@
case 'w':
f_noformat = 1;
break;
+ case 'C':
+ conffile = optarg;
+ break;
case 'M':
mp = optarg;
break;
@@ -105,37 +122,167 @@
if (argc > 1)
usage();
- if (argc == 1)
- sp = *argv;
- if (f_noformat == 0 || f_nowhatis == 0)
- catman(mp, sp);
- if (f_nowhatis == 0 && dowhatis)
- makewhatis(mp);
+ config(conffile);
+
+ /*
+ * Remaining argument could either be an nroff source file, in
+ * which case we format it to stdout, or a list of man sections.
+ */
+ if (argc == 1)
+ if (access(*argv, F_OK) == 0) {
+ mformat(*argv, NULL);
+ exit(0);
+ } else
+ makesubdir(*argv);
+
+ if (mp != NULL || (mp = getenv("MANPATH")) != NULL)
+ makedefault(mp);
+
+ if ((tp = getlist("_default")) == NULL)
+ errx(1, "No manpath in %s.\n", _PATH_MANCONF);
+ for (ep = tp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next) {
+ memset(&pg, 0, sizeof(pg));
+ if (glob(ep->s, GLOB_BRACE | GLOB_QUOTE, NULL, &pg) != 0)
+ err(1, "glob");
+ if (pg.gl_matchc == 0)
+ continue;
+ for (c = 0; pg.gl_pathv[c] != NULL; c++) {
+ if (f_noformat == 0 || f_nowhatis == 0)
+ needwhatis = catman(pg.gl_pathv[c]);
+ if (f_noformat || (needwhatis && f_nowhatis == 0))
+ makewhatis(pg.gl_pathv[c]);
+ }
+ globfree(&pg);
+ }
exit(0);
}
-
-void
-catman(path, section)
+int
+catman(path)
const char *path;
- char *section;
{
+ int rval;
char mandir[PATH_MAX];
char catdir[PATH_MAX];
- char manpage[PATH_MAX];
- char catpage[PATH_MAX];
+ char *catsuffix, *slash;
+ TAG *subdirp, *sufp;
+ ENTRY *ep;
+
+ if (chdir(path) != 0) {
+ warn(path);
+ return (0);
+ }
+
+ if (path[strlen(path) - 1] == '/')
+ slash = "";
+ else
+ slash = "/";
+
+ if ((sufp = getlist("_suffix")) == NULL)
+ catsuffix = ".0";
+ else
+ catsuffix = sufp->list.tqh_first->s;
+
+ if ((subdirp = getlist("_subdir")) == NULL)
+ errx(1, "No man subdirectories to scan!\n");
+
+ rval = 0;
+ for (ep = subdirp->list.tqh_first; ep != NULL; ep = ep->q.tqe_next) {
+ if (strncmp(ep->s, "man", strlen("man")) != 0)
+ continue;
+ sprintf(mandir, "%s%s%s", path, slash, ep->s);
+ sprintf(catdir, "%s%scat%c", path, slash, ep->s[3]);
+ rval |= dirformat(mandir, catdir, catsuffix);
+ }
+
+ return (rval);
+}
+
+void
+makewhatis(path)
+ const char *path;
+{
char sysbuf[1024];
- struct stat manstat;
- struct stat catstat;
- struct dirent *dp;
- DIR *dirp;
- char *s, *tmp;
- int sectlen, error;
- for (s = section; *s; s += sectlen) {
-#ifdef notdef
+ sprintf(sysbuf, "%s %s", _PATH_MAKEWHATIS, path);
+ if (f_noprint == 0)
+ printf("%s\n", sysbuf);
+ if (f_noaction == 0)
+ dosystem(sysbuf);
+}
+
+void
+dosystem(cmd)
+ const char *cmd;
+{
+ int status;
+
+ if ((status = system(cmd)) == 0)
+ return;
+
+ if (status == -1)
+ err(1, "cannot execute action");
+ if (WIFSIGNALED(status))
+ errx(1, "child was signaled to quit. aborting");
+ if (WIFSTOPPED(status))
+ errx(1, "child was stopped. aborting");
+ if (f_ignerr == 0)
+ errx(1, "*** Exited %d", status);
+ warnx("*** Exited %d (continuing)", status);
+}
+
+/*
+ * Replace the current _default entry
+ */
+void
+makedefault(mp)
+ char *mp;
+{
+ ENTRY *ep;
+ TAG *defp;
+ char *p;
+
+ if ((defp = getlist("_default")) == NULL)
+ defp = addlist("_default");
+ while ((ep = defp->list.tqh_first) != NULL) {
+ free(ep->s);
+ TAILQ_REMOVE(&defp->list, ep, q);
+ free(ep);
+ }
+
+ for (p = strsep(&mp, ":"); p != NULL; p = strsep(&mp, ":")) {
+ if (*p == '\0')
+ continue;
+ if ((ep = malloc(sizeof(ENTRY))) == NULL ||
+ (ep->s = strdup(p)) == NULL)
+ errx(1, "Out of memory");
+ TAILQ_INSERT_TAIL(&defp->list, ep, q);
+ }
+}
+
+/*
+ * Replace the current _subdir entry
+ */
+void
+makesubdir(subsec)
+ const char *subsec;
+{
+ ENTRY *ep;
+ TAG *subdirp;
+ const char *s, *tmp;
+ int sectlen;
+
+ if ((subdirp = getlist("_subdir")) == NULL)
+ subdirp = addlist("_subdir");
+ while ((ep = subdirp->list.tqh_first) != NULL) {
+ free(ep->s);
+ TAILQ_REMOVE(&subdirp->list, ep, q);
+ free(ep);
+ }
+
+ for (s = subsec, sectlen = 0; *s; s += sectlen) {
tmp = s;
sectlen = 0;
if (isdigit(*tmp)) {
@@ -146,123 +293,225 @@
tmp++;
}
}
-#else
- sectlen = 1;
-#endif
if (sectlen == 0)
- errx(1, "malformed section string");
+ errx(1, "malformed section string \"%s\"", subsec);
- sprintf(mandir, "%s/%s%.*s", path, _PATH_MANPAGES, sectlen, s);
- sprintf(catdir, "%s/%s%.*s", path, _PATH_CATPAGES, sectlen, s);
+ if ((ep = malloc(sizeof(ENTRY))) == NULL ||
+ (ep->s = malloc(sectlen + strlen("man") + 1)) == NULL)
+ err(1, "Out of memory");
+ sprintf(ep->s, "man%.*s", sectlen, s);
+ TAILQ_INSERT_TAIL(&subdirp->list, ep, q);
+ }
+}
- if ((dirp = opendir(mandir)) == 0) {
- warn("can't open %s", mandir);
+void
+lncatpages(mandir, manpage, catdir, catpage, catsuffix)
+ char *mandir, *manpage, *catdir, *catpage, *catsuffix;
+{
+ DIR *dirp;
+ struct dirent *dp;
+ struct stat st, manstat;
+ char manfile[PATH_MAX];
+ char catfile[PATH_MAX];
+ char *tmp;
+
+ if (stat(manpage, &manstat) < 0) {
+ warn("can't stat %s", manpage);
+ return;
+ }
+ if ((dirp = opendir(mandir)) == NULL) {
+ warn(mandir);
+ return;
+ }
+ while ((dp = readdir(dirp)) != NULL) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0)
+ continue;
+ sprintf(manfile, "%s/%s", mandir, dp->d_name);
+ if (strcmp(manfile, manpage) == 0)
+ continue;
+ if (stat(manfile, &st) < 0) {
+ warn("can't stat %s", manfile);
continue;
}
-
- if (stat(catdir, &catstat) < 0) {
- if (errno != ENOENT) {
- warn("can't stat %s", catdir);
- closedir(dirp);
+ if (st.st_ino == manstat.st_ino) {
+ sprintf(catfile, "%s/%s", catdir, dp->d_name);
+ if ((tmp = strrchr(catfile, '.')) == NULL)
continue;
- }
+ strcpy(tmp, catsuffix);
+ unlink(catfile);
if (f_noprint == 0)
- printf("mkdir %s\n", catdir);
- if (f_noaction == 0 && mkdir(catdir, 0755) < 0) {
- warn("can't create %s", catdir);
- closedir(dirp);
- return;
+ printf("ln %s %s\n", catpage, catfile);
+ if (f_noaction == 0 && link(catpage, catfile) < 0) {
+ warn("can't link %s to %s", catpage, catfile);
+ continue;
}
+ }
+ }
+ closedir(dirp);
+}
+/*
+ * Format all pages in mandir, placing the output in catdir.
+ */
+int
+dirformat(mandir, catdir, catsuffix)
+ char *mandir, *catdir, *catsuffix;
+{
+ int error, rval, symlink;
+ char manpage[PATH_MAX];
+ char catpage[PATH_MAX];
+ char *tmp, *mansuffix;
+ DIR *dirp;
+ struct dirent *dp;
+ struct stat manstat;
+ struct stat catstat;
+
+ if (chdir(mandir) || (dirp = opendir(".")) == NULL) {
+ if (errno != ENOENT)
+ warn(mandir);
+ return (0);
+ }
+ if (stat(catdir, &catstat) < 0) {
+ if (errno != ENOENT) {
+ warn("can't stat %s", catdir);
+ closedir(dirp);
+ return (0);
+ }
+ if (f_noprint == 0)
+ printf("mkdir %s\n", catdir);
+ if (f_noaction == 0 && mkdir(catdir, 0755) < 0) {
+ warn("can't create %s", catdir);
+ closedir(dirp);
+ return (0);
}
- while ((dp = readdir(dirp)) != NULL) {
- if (strcmp(dp->d_name, ".") == 0 ||
- strcmp(dp->d_name, "..") == 0)
- continue;
+ }
- sprintf(manpage, "%s/%s", mandir, dp->d_name);
- sprintf(catpage, "%s/%s", catdir, dp->d_name);
- if ((tmp = strrchr(catpage, '.')) != NULL)
- strcpy(tmp, ".0");
- else
- continue;
+ rval = 0;
+ while ((dp = readdir(dirp)) != NULL) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0)
+ continue;
+ sprintf(manpage, "%s/%s", mandir, dp->d_name);
+ sprintf(catpage, "%s/%s", catdir, dp->d_name);
+
+ if (lstat(manpage, &manstat) < 0) {
+ warn("can't stat %s", manpage);
+ continue;
+ }
+
+ symlink = 0;
+ if (S_ISLNK(manstat.st_mode)) {
+ symlink = 1;
if (stat(manpage, &manstat) < 0) {
warn("can't stat %s", manpage);
continue;
}
+ }
- if (!S_ISREG(manstat.st_mode)) {
+ if (!S_ISREG(manstat.st_mode)) {
+ /*
+ * Subdirectories within man directories contain
+ * architecture specific pages.
+ */
+ if (S_ISDIR(manstat.st_mode))
+ dirformat(manpage, catpage, catsuffix);
+ else
warnx("not a regular file %s", manpage);
- continue;
- }
- if ((error = stat(catpage, &catstat)) &&
- errno != ENOENT) {
- warn("can't stat %s", catpage);
- continue;
- }
-
- if ((error && errno == ENOENT) ||
- manstat.st_mtime >= catstat.st_mtime) {
- if (f_noformat)
- dowhatis = 1;
- else {
- /*
- * manpage is out of date,
- * reformat
- */
- sprintf(sysbuf, "nroff -mandoc %s > %s",
- manpage, catpage);
- if (f_noprint == 0)
- printf("%s\n", sysbuf);
- if (f_noaction == 0)
- dosystem(sysbuf);
- dowhatis = 1;
- }
- }
+ continue;
}
- closedir(dirp);
- }
-}
-void
-makewhatis(path)
- const char *path;
-{
- char sysbuf[1024];
+ if ((mansuffix = strrchr(manpage, '.')) == NULL)
+ continue;
+ if ((tmp = strrchr(catpage, '.')) == NULL)
+ continue;
+ else
+ strcpy(tmp, catsuffix);
- sprintf(sysbuf, "%s %s", _PATH_MAKEWHATIS, path);
- if (f_noprint == 0)
- printf("%s\n", sysbuf);
- if (f_noaction == 0)
- dosystem(sysbuf);
+ if ((error = stat(catpage, &catstat)) &&
+ errno != ENOENT) {
+ warn("can't stat %s", catpage);
+ continue;
+ }
+
+ /*
+ * If manpage is out of date, reformat
+ */
+ if ((error && errno == ENOENT) ||
+ (manstat.st_mtime >= catstat.st_mtime &&
+ f_noformat == 0)) {
+ mformat(manpage, catpage);
+ /*
+ * If manpages hardlinked together, duplicate
+ * with catpages.
+ */
+ if (manstat.st_nlink > 1 || symlink)
+ lncatpages(mandir, manpage, catdir, catpage,
+ catsuffix);
+ rval = 1;
+ }
+ }
+ closedir(dirp);
+ return (rval);
}
void
-dosystem(cmd)
- const char *cmd;
+mformat(manpage, catpage)
+ char *manpage, *catpage;
{
- int status;
-
- if ((status = system(cmd)) == 0)
- return;
+ int fnd;
+ char buf[1024], fmtbuf[1024], *p, *sufent, *mansuffix;
+ TAG *sufp;
+ ENTRY *e_sufp;
+
+ if ((mansuffix = strrchr(manpage, '.')) == NULL)
+ mansuffix = ".1";
+
+ if ((sufp = getlist("_build")) == NULL)
+ errx(1, "No _build keywords found in %s", _PATH_MANCONF);
+
+ for (fnd = 0, e_sufp = sufp->list.tqh_first; e_sufp != NULL;
+ e_sufp = e_sufp->q.tqe_next) {
+ if ((sufent = strdup(e_sufp->s)) == NULL)
+ errx(1, "Out of memory");
+ for (p = sufent; *p != '\0' && !isspace(*p); p++);
+ if (*p == '\0') {
+ free(sufent);
+ continue;
+ }
+ *p = '\0';
+ if (fnmatch(sufent, mansuffix, 0) != 0) {
+ free(sufent);
+ continue;
+ }
+ fnd = 1;
- if (status == -1)
- err(1, "cannot execute action");
- if (WIFSIGNALED(status))
- errx(1, "child was signaled to quit. aborting");
- if (WIFSTOPPED(status))
- errx(1, "child was stopped. aborting");
- if (f_ignerr == 0)
- errx(1,"*** Exited %d");
- warnx("*** Exited %d (continuing)");
+ for (++p; isspace(*p); p++);
+ /*
+ * If catpage is NULL, then we send it to stdout
+ */
+ if (catpage == NULL)
+ strncpy(fmtbuf, p, sizeof(fmtbuf));
+ else
+ snprintf(fmtbuf, sizeof(fmtbuf), "%s > %s", p, catpage);
+ snprintf(buf, sizeof(buf), fmtbuf, manpage);
+ if (f_noprint == 0 && catpage != NULL)
+ printf("%s\n", buf);
+ if (f_noaction == 0)
+ dosystem(buf);
+ free(sufent);
+ }
+ if (fnd == 0)
+ warnx("Don't know how to format %s", manpage);
}
void
usage()
{
(void)fprintf(stderr,
- "usage: catman [-knpsw] [-M manpath] [sections]\n");
+ "usage: catman [-knpsw] [-C file] [-M manpath] [sections]\n"
+ " catman [-C file] manpage\n");
exit(1);
}
Index: ../../usr.bin/man/config.c
===================================================================
RCS file: /snarf/netbsd/master/src/usr.bin/man/config.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 config.c
--- config.c 1995/11/16 02:27:52 1.1.1.1
+++ config.c 1996/01/02 02:43:53
@@ -119,12 +119,12 @@
while (*++t && isspace(*t));
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
(ep->s = strdup(t)) == NULL)
- err(1, NULL);
+ err(1, "Out of memory");
TAILQ_INSERT_TAIL(&tp->list, ep, q);
} else for (++t; (p = strtok(t, " \t\n")) != NULL; t = NULL) {
if ((ep = malloc(sizeof(ENTRY))) == NULL ||
(ep->s = strdup(p)) == NULL)
- err(1, NULL);
+ err(1, "Out of memory");
TAILQ_INSERT_TAIL(&tp->list, ep, q);
}
}
@@ -144,7 +144,7 @@
if ((tp = calloc(1, sizeof(TAG))) == NULL ||
(tp->s = strdup(name)) == NULL)
- err(1, NULL);
+ err(1, "Out of memory");
TAILQ_INIT(&tp->list);
TAILQ_INSERT_TAIL(&head, tp, q);
return (tp);
Index: ../../usr.bin/man/pathnames.h
===================================================================
RCS file: /snarf/netbsd/master/src/usr.bin/man/pathnames.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 pathnames.h
--- pathnames.h 1995/11/16 02:27:53 1.1.1.1
+++ pathnames.h 1996/01/01 20:16:32
@@ -35,6 +35,7 @@
* @(#)pathnames.h 8.3 (Berkeley) 1/2/94
*/
+#define _PATH_MAKEWHATIS "/usr/libexec/makewhatis"
#define _PATH_MANCONF "/etc/man.conf"
#define _PATH_PAGER "/usr/bin/more -s"
#define _PATH_TMP "/tmp/man.XXXXXX"
-----cut-here-----
This final patch changes bsd.man.mk to use catman instead of nroff.
-----cut-here-----
Index: bsd.man.mk
===================================================================
RCS file: /snarf/netbsd/master/src/share/mk/bsd.man.mk,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 bsd.man.mk
--- bsd.man.mk 1995/12/15 12:08:10 1.1.1.2
+++ bsd.man.mk 1996/01/02 01:37:48
@@ -15,8 +15,8 @@
.cat7 .cat8 .cat9
.9.cat9 .8.cat8 .7.cat7 .6.cat6 .5.cat5 .4.cat4 .3.cat3 .2.cat2 .1.cat1:
- @echo "nroff -mandoc ${.IMPSRC} > ${.TARGET}"
- @nroff -mandoc ${.IMPSRC} > ${.TARGET} || ( rm -f ${.TARGET} ; false )
+ @echo "catman ${.IMPSRC} > ${.TARGET}"
+ @catman ${.IMPSRC} > ${.TARGET} || ( rm -f ${.TARGET} ; false )
.if defined(MAN) && !empty(MAN)
MANALL= ${MAN:S/.1$/.cat1/g:S/.2$/.cat2/g:S/.3$/.cat3/g:S/.4$/.cat4/g:S/.5$/.cat5/g:S/.6$/.cat6/g:S/.7$/.cat7/g:S/.8$/.cat8/g:S/.9$/.cat9/g}
-----cut-here-----
>Release-Note:
>Audit-Trail:
From: Mike Grupenhoff <kashmir@umiacs.umd.edu>
To: gnats-bugs@gnats.netbsd.org
Cc: Subject: Re: bin/1904
Date: Mon, 8 Jan 1996 20:25:28 -0500 (EST)
The patch to catman that I sent in bin/1904 was incomplete with respect to
handling manpages with extentions with more then one period (foo.1.gz, etc).
I wasn't sure at the time about the proper way to handle this, since a
manpage might have a period in its name.
The previous patch did a strrchr(manpage, '.') to get the extension,
which obviously breaks with compressed pages. At the bottom of this mail
is a patch which does a better job of guessing what the extension really
is. Of course, if someone could guarantee to me that a manpage name will
never contain a '.', this could all be done a lot cleaner. alas..
I apologize for not getting this right the first time, in the first patch. I
had a moment of clarity today while shoveling snow, and came up with this
workaround. If you have a better way of handling this, let me know.
mike
This patch should be applied after applying the one in bin/1904.
Index: catman.c
===================================================================
RCS file: /snarf/netbsd/master/src/usr.sbin/catman/catman.c,v
retrieving revision 1.2
diff -u -r1.2 catman.c
--- catman.c 1996/01/07 15:50:45 1.2
+++ catman.c 1996/01/08 01:51:53
@@ -62,13 +62,14 @@
int f_noprint;
int catman __P((const char *));
-int dirformat __P((char *, char *, char *));
+int dirformat __P((char *, char *));
void dosystem __P((const char *));
-void lncatpages __P((char *, char *, char *, char *, char *));
+void lncatpages __P((char *, char *, char *, char *));
void makedefault __P((char *));
void makesubdir __P((const char *));
void makewhatis __P((const char *));
-void mformat __P((char *, char *));
+int mformat __P((char *, struct stat *, char *));
+void mkcatsuff __P((char *, char *));
void usage __P((void));
int
@@ -131,7 +132,7 @@
*/
if (argc == 1)
if (access(*argv, F_OK) == 0) {
- mformat(*argv, NULL);
+ mformat(*argv, NULL, NULL);
exit(0);
} else
makesubdir(*argv);
@@ -166,8 +167,8 @@
int rval;
char mandir[PATH_MAX];
char catdir[PATH_MAX];
- char *catsuffix, *slash;
- TAG *subdirp, *sufp;
+ char *slash;
+ TAG *subdirp;
ENTRY *ep;
if (chdir(path) != 0) {
@@ -180,11 +181,6 @@
else
slash = "/";
- if ((sufp = getlist("_suffix")) == NULL)
- catsuffix = ".0";
- else
- catsuffix = sufp->list.tqh_first->s;
-
if ((subdirp = getlist("_subdir")) == NULL)
errx(1, "No man subdirectories to scan!\n");
@@ -194,7 +190,7 @@
continue;
sprintf(mandir, "%s%s%s", path, slash, ep->s);
sprintf(catdir, "%s%scat%c", path, slash, ep->s[3]);
- rval |= dirformat(mandir, catdir, catsuffix);
+ rval |= dirformat(mandir, catdir);
}
return (rval);
@@ -305,15 +301,14 @@
}
void
-lncatpages(mandir, manpage, catdir, catpage, catsuffix)
- char *mandir, *manpage, *catdir, *catpage, *catsuffix;
+lncatpages(mandir, manpage, catdir, catpage)
+ char *mandir, *manpage, *catdir, *catpage;
{
DIR *dirp;
struct dirent *dp;
struct stat st, manstat;
char manfile[PATH_MAX];
char catfile[PATH_MAX];
- char *tmp;
if (stat(manpage, &manstat) < 0) {
warn("can't stat %s", manpage);
@@ -336,9 +331,7 @@
}
if (st.st_ino == manstat.st_ino) {
sprintf(catfile, "%s/%s", catdir, dp->d_name);
- if ((tmp = strrchr(catfile, '.')) == NULL)
- continue;
- strcpy(tmp, catsuffix);
+ mkcatsuff(manfile, catfile);
unlink(catfile);
if (f_noprint == 0)
printf("ln %s %s\n", catpage, catfile);
@@ -355,24 +348,22 @@
* Format all pages in mandir, placing the output in catdir.
*/
int
-dirformat(mandir, catdir, catsuffix)
- char *mandir, *catdir, *catsuffix;
+dirformat(mandir, catdir)
+ char *mandir, *catdir;
{
- int error, rval, symlink;
+ int rval, slink;
char manpage[PATH_MAX];
char catpage[PATH_MAX];
- char *tmp, *mansuffix;
DIR *dirp;
struct dirent *dp;
struct stat manstat;
- struct stat catstat;
if (chdir(mandir) || (dirp = opendir(".")) == NULL) {
if (errno != ENOENT)
warn(mandir);
return (0);
}
- if (stat(catdir, &catstat) < 0) {
+ if (stat(catdir, &manstat) < 0) {
if (errno != ENOENT) {
warn("can't stat %s", catdir);
closedir(dirp);
@@ -402,9 +393,9 @@
continue;
}
- symlink = 0;
+ slink = 0;
if (S_ISLNK(manstat.st_mode)) {
- symlink = 1;
+ slink = 1;
if (stat(manpage, &manstat) < 0) {
warn("can't stat %s", manpage);
continue;
@@ -417,39 +408,19 @@
* architecture specific pages.
*/
if (S_ISDIR(manstat.st_mode))
- dirformat(manpage, catpage, catsuffix);
+ dirformat(manpage, catpage);
else
warnx("not a regular file %s", manpage);
continue;
}
- if ((mansuffix = strrchr(manpage, '.')) == NULL)
- continue;
- if ((tmp = strrchr(catpage, '.')) == NULL)
- continue;
- else
- strcpy(tmp, catsuffix);
-
- if ((error = stat(catpage, &catstat)) &&
- errno != ENOENT) {
- warn("can't stat %s", catpage);
- continue;
- }
-
- /*
- * If manpage is out of date, reformat
- */
- if ((error && errno == ENOENT) ||
- (manstat.st_mtime >= catstat.st_mtime &&
- f_noformat == 0)) {
- mformat(manpage, catpage);
+ if (mformat(manpage, &manstat, catpage)) {
/*
* If manpages hardlinked together, duplicate
* with catpages.
*/
- if (manstat.st_nlink > 1 || symlink)
- lncatpages(mandir, manpage, catdir, catpage,
- catsuffix);
+ if (manstat.st_nlink > 1 || slink)
+ lncatpages(mandir, manpage, catdir, catpage);
rval = 1;
}
}
@@ -457,12 +428,14 @@
return (rval);
}
-void
-mformat(manpage, catpage)
+int
+mformat(manpage, manstat, catpage)
char *manpage, *catpage;
+ struct stat *manstat;
{
- int fnd;
+ int error, fnd, rval;
char buf[1024], fmtbuf[1024], *p, *sufent, *mansuffix;
+ struct stat catstat;
TAG *sufp;
ENTRY *e_sufp;
@@ -472,7 +445,7 @@
if ((sufp = getlist("_build")) == NULL)
errx(1, "No _build keywords found in %s", _PATH_MANCONF);
- for (fnd = 0, e_sufp = sufp->list.tqh_first; e_sufp != NULL;
+ for (rval = fnd = 0, e_sufp = sufp->list.tqh_first; e_sufp != NULL;
e_sufp = e_sufp->q.tqe_next) {
if ((sufent = strdup(e_sufp->s)) == NULL)
errx(1, "Out of memory");
@@ -482,7 +455,9 @@
continue;
}
*p = '\0';
- if (fnmatch(sufent, mansuffix, 0) != 0) {
+
+ snprintf(buf, sizeof(buf), "*%s", sufent);
+ if (fnmatch(buf, manpage, 0) != 0) {
free(sufent);
continue;
}
@@ -494,17 +469,70 @@
*/
if (catpage == NULL)
strncpy(fmtbuf, p, sizeof(fmtbuf));
- else
- snprintf(fmtbuf, sizeof(fmtbuf), "%s > %s", p, catpage);
+ else {
+ mkcatsuff(sufent, catpage);
+ if ((error = stat(catpage, &catstat)) &&
+ errno != ENOENT) {
+ warn("can't stat %s", catpage);
+ continue;
+ }
+
+ /*
+ * See if manpage is out of date.
+ */
+ if ((error && errno == ENOENT) ||
+ (manstat->st_mtime >= catstat.st_mtime &&
+ f_noformat == 0))
+ snprintf(fmtbuf, sizeof(fmtbuf), "%s > %s", p,
+ catpage);
+ else {
+ free(sufent);
+ break;
+ }
+ }
snprintf(buf, sizeof(buf), fmtbuf, manpage);
if (f_noprint == 0 && catpage != NULL)
printf("%s\n", buf);
if (f_noaction == 0)
dosystem(buf);
free(sufent);
+ rval = 1;
}
if (fnd == 0)
warnx("Don't know how to format %s", manpage);
+ return (rval);
+}
+
+/*
+ * Given a path to a manpage and a path to a catpage, change
+ * the catpage suffix to _suffix.
+ */
+void
+mkcatsuff(mansuffix, catpage)
+ char *mansuffix, *catpage;
+{
+ int ndots;
+ char *q;
+ static char *catsuffix = NULL;
+ TAG *sufp;
+
+ if (catsuffix == NULL)
+ if ((sufp = getlist("_suffix")) == NULL)
+ catsuffix = ".0";
+ else
+ catsuffix = sufp->list.tqh_first->s;
+
+ /*
+ * Hack: We count the number of dots in the manpage suffix
+ * and jump back that many dots in the catpage.
+ */
+ for (ndots = 0, q = mansuffix; *q; q++)
+ if (*q == '.')
+ ndots++;
+ for (q = catpage + strlen(catpage); ndots; q--)
+ if (*q == '.')
+ ndots--;
+ strcpy(q + 1, catsuffix);
}
void
Responsible-Changed-From-To: bin-bug-people->mikel
Responsible-Changed-By: mikel
Responsible-Changed-When: Sat Sep 27 23:06:15 1997
Responsible-Changed-Why:
I'm handling this one.
Responsible-Changed-From-To: mikel->bin-bug-people
Responsible-Changed-By: fair
Responsible-Changed-When: Thu Mar 22 12:29:11 PST 2001
Responsible-Changed-Why:
Mike Long's E-mail address now bounces, so he appears to have vanished.
Back to the role account this PR goes, ready for some other intrepid
developer to step up to the plate.
From: Abhinav Upadhyay <er.abhinav.upadhyay@gmail.com>
To: NetBSD GNATS <gnats-bugs@netbsd.org>
Cc:
Subject: Re: bin/1904
Date: Sat, 21 May 2016 15:17:33 +0530
Is this still relevant?
The first two issues regarding apropos and whatis are not valid anymore
as we don't use whatis.db for them.
Not quite sure about the 3rd and 4th points.
-
Abhinav
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: bin/1904
Date: Sat, 28 May 2016 16:36:05 +0000
On Sat, May 21, 2016 at 09:50:00AM +0000, Abhinav Upadhyay wrote:
> Is this still relevant?
> The first two issues regarding apropos and whatis are not valid anymore
> as we don't use whatis.db for them.
>
> Not quite sure about the 3rd and 4th points.
The last point (the one about bsd.man.mk using catman) is wrong; or at
least, not useful. The build rules in the default man.conf are supposed
to be consistent with the build rules in the makefiles; using custom
rules from an installed man.conf is not consistent with the principle
of the build being self-contained, cross builds working reliably, etc.
Also it's only relevant if one is generating cat pages at build time,
which has not been the default for some years now.
The other point "catman doesn't work with /etc/man.conf and linked
manpages" ... not even sure what that means. However, I guess we might
want some of the patches to catman(8) in here...
--
David A. Holland
dholland@netbsd.org
From: Abhinav Upadhyay <er.abhinav.upadhyay@gmail.com>
To: NetBSD GNATS <gnats-bugs@netbsd.org>
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, kashmir@umiacs.umd.edu
Subject: Re: bin/1904
Date: Sat, 28 May 2016 22:54:24 +0530
On Sat, May 28, 2016 at 10:10 PM, David Holland
<dholland-bugs@netbsd.org> wrote:
> The following reply was made to PR bin/1904; it has been noted by GNATS.
>
> From: David Holland <dholland-bugs@netbsd.org>
> To: gnats-bugs@NetBSD.org
> Cc:
> Subject: Re: bin/1904
> Date: Sat, 28 May 2016 16:36:05 +0000
>
> On Sat, May 21, 2016 at 09:50:00AM +0000, Abhinav Upadhyay wrote:
> > Is this still relevant?
> > The first two issues regarding apropos and whatis are not valid anymore
> > as we don't use whatis.db for them.
> >
> > Not quite sure about the 3rd and 4th points.
>
> The last point (the one about bsd.man.mk using catman) is wrong; or at
> least, not useful. The build rules in the default man.conf are supposed
> to be consistent with the build rules in the makefiles; using custom
> rules from an installed man.conf is not consistent with the principle
> of the build being self-contained, cross builds working reliably, etc.
> Also it's only relevant if one is generating cat pages at build time,
> which has not been the default for some years now.
I guess that settles the 4th point as not being useful (in present time).
> The other point "catman doesn't work with /etc/man.conf and linked
> manpages" ... not even sure what that means. However, I guess we might
> want some of the patches to catman(8) in here...
As per the description of the 3rd patch, it means that catman doesn't
parse and use the rules from /etc/man.conf and, it also doesn't handle
the symlinked or hard linked man pages, the patch fixes those issues.
I think those are useful fixes if we are going to maintain catman.
-
Abhinav
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: bin/1904
Date: Sat, 28 May 2016 18:41:59 +0000
On Sat, May 28, 2016 at 05:25:00PM +0000, Abhinav Upadhyay wrote:
> As per the description of the 3rd patch, it means that catman doesn't
> parse and use the rules from /etc/man.conf and, it also doesn't handle
> the symlinked or hard linked man pages, the patch fixes those issues.
>
> I think those are useful fixes if we are going to maintain catman.
Maybe; ISTM that the way to deal with man.conf is that it should use
man(1) to generate the cat pages. Except for that man(1) needs a way
to be told "please print this page" and while I thought it had an
option for that, it doesn't currently seem to.
(Also, I'd thought there was an option to man(1) to run troff to generate
postscript for printing, but this doesn't seem to exist either...)
Am I remembering options from some old vendor Unix?
--
David A. Holland
dholland@netbsd.org
From: Abhinav Upadhyay <er.abhinav.upadhyay@gmail.com>
To: NetBSD GNATS <gnats-bugs@netbsd.org>
Cc: gnats-admin@netbsd.org, netbsd-bugs@netbsd.org, kashmir@umiacs.umd.edu
Subject: Re: bin/1904
Date: Mon, 30 May 2016 01:57:40 +0530
On Sun, May 29, 2016 at 1:35 AM, David Holland <dholland-bugs@netbsd.org> wrote:
> The following reply was made to PR bin/1904; it has been noted by GNATS.
>
> From: David Holland <dholland-bugs@netbsd.org>
> To: gnats-bugs@NetBSD.org
> Cc:
> Subject: Re: bin/1904
> Date: Sat, 28 May 2016 18:41:59 +0000
>
> On Sat, May 28, 2016 at 05:25:00PM +0000, Abhinav Upadhyay wrote:
> > As per the description of the 3rd patch, it means that catman doesn't
> > parse and use the rules from /etc/man.conf and, it also doesn't handle
> > the symlinked or hard linked man pages, the patch fixes those issues.
> >
> > I think those are useful fixes if we are going to maintain catman.
>
> Maybe; ISTM that the way to deal with man.conf is that it should use
> man(1) to generate the cat pages. Except for that man(1) needs a way
> to be told "please print this page" and while I thought it had an
> option for that, it doesn't currently seem to.
We could do that, mandoc has -Tascii option (I assume that's
equivalent to a cat page output, correct me if I'm wrong)
>
> (Also, I'd thought there was an option to man(1) to run troff to generate
> postscript for printing, but this doesn't seem to exist either...)
>
> Am I remembering options from some old vendor Unix?
>
mandoc has an option for this too, and could be added to man(1).
As we are already using mandoc for formatting man pages, we could add
these options to man(1) too?
-
Abhinav
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: bin/1904
Date: Sun, 29 May 2016 22:31:20 +0000
On Sun, May 29, 2016 at 08:30:00PM +0000, Abhinav Upadhyay wrote:
> > Maybe; ISTM that the way to deal with man.conf is that it should use
> > man(1) to generate the cat pages. Except for that man(1) needs a way
> > to be told "please print this page" and while I thought it had an
> > option for that, it doesn't currently seem to.
>
> We could do that, mandoc has -Tascii option (I assume that's
> equivalent to a cat page output, correct me if I'm wrong)
It is. What I meant was something like "man -Q /some/path/foo.1" to
print /some/path/foo.1 directly rather than search for a page by name.
Like I said, I remember man having such an option but that must have
been on some other platform long ago.
Anyway, more careful inspection of catman shows that it's had man.conf
support since 1999. The only thing left in this PR is the support for
hardlinked man pages... the patch here doesn't even begin to apply
because the 1999 changes were a big rewrite, and the logic in this
patch for identifying hardlinks does O(n^2) directory reads, which is
neither necessary nor desirable. So I don't think we should bother
with the amount of work it'll take to merge it.
If anyone wants to implement hardlink handling it seems fairly
straightforward in the current catman code to add a structure to hold
a (fsid, ino) -> name mapping, to add to it when handling a page whose
linkcount > 1, and to check it when encountering a page whose
linkcount > 1. It doesn't seem to me to be worth the trouble given
that we don't even build cat pages by default and with mandoc there's
really no reason to except on the slowest of slow machines.
I've added a note in catman(8) about how to do this in case anyone
sees fit to bother.
In the meantime I see no reason to keep this PR open.
--
David A. Holland
dholland@netbsd.org
State-Changed-From-To: open->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Sun, 29 May 2016 22:37:10 +0000
State-Changed-Why:
Everything in here has been overtaken by events, except for the logic for
handling hardlinks... which in turn would take substantial work to merge
and isn't really done right, and therefore doesn't seem worthwhile.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.