summaryrefslogtreecommitdiff
path: root/usr.bin/man
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2011-07-07 04:24:36 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2011-07-07 04:24:36 +0000
commit19703c0e30e9beaa96da075c43ff0412ea45c88d (patch)
tree7ffc0626cfcdd20f881b57920bd016673c4775e9 /usr.bin/man
parentef73fe0c4db1445d289c4ac3b6b50b178295bae0 (diff)
For man -a and -w, drop companion pages that are also in the path,
such that we don't display them twice. To be able to do that path check, we have to brace-expand the search path up front - of course, for -a and -w only, so it doesn't slow us down in the standard case. As a free bonus, let -wa print all the filenames without looking at the timestamps. In the past, -w implied -a, so that's not introducing any incompatibility. Issue originally reported and fix OK'd by guenther@, and deraadt@ agrees with the semantics.
Diffstat (limited to 'usr.bin/man')
-rw-r--r--usr.bin/man/man.117
-rw-r--r--usr.bin/man/man.c82
2 files changed, 82 insertions, 17 deletions
diff --git a/usr.bin/man/man.1 b/usr.bin/man/man.1
index 7d585a2389e..54d196225a5 100644
--- a/usr.bin/man/man.1
+++ b/usr.bin/man/man.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: man.1,v 1.46 2010/09/19 07:40:01 jmc Exp $
+.\" $OpenBSD: man.1,v 1.47 2011/07/07 04:24:35 schwarze Exp $
.\"
.\" Copyright (c) 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" @(#)man.1 8.2 (Berkeley) 1/2/94
.\"
-.Dd $Mdocdate: September 19 2010 $
+.Dd $Mdocdate: July 7 2011 $
.Dt MAN 1
.Os
.Sh NAME
@@ -260,6 +260,19 @@ man pages can be found in
.Xr mdoc 7 .
A full tutorial for writing man pages is provided in
.Xr mdoc.samples 7 .
+.Pp
+If both a formatted and an unformatted version of the same manual page,
+for example
+.Pa cat1/foo.0
+and
+.Pa man1/foo.1 ,
+exist in the same directory, and at least one of them is selected,
+only the newer one is used.
+However, if both the
+.Fl a
+and the
+.Fl w
+options are specified, both file names are printed.
.Sh ENVIRONMENT
.Bl -tag -width MANPATHX
.It Ev MACHINE
diff --git a/usr.bin/man/man.c b/usr.bin/man/man.c
index f7d7c384be9..f833d35c6c8 100644
--- a/usr.bin/man/man.c
+++ b/usr.bin/man/man.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: man.c,v 1.42 2011/07/05 05:47:20 schwarze Exp $ */
+/* $OpenBSD: man.c,v 1.43 2011/07/07 04:24:35 schwarze Exp $ */
/* $NetBSD: man.c,v 1.7 1995/09/28 06:05:34 tls Exp $ */
/*
@@ -83,7 +83,7 @@ static int cleanup(int);
static void how(char *);
static void jump(char **, char *, char *);
static int manual(char *, TAG *, glob_t *);
-static void check_companion(char **);
+static void check_companion(char **, TAG *);
static void onsig(int);
static void usage(void);
@@ -153,7 +153,7 @@ main(int argc, char *argv[])
jump(argv, "-k", "apropos");
/* NOTREACHED */
case 'w':
- f_all = f_where = 1;
+ f_where = 1;
break;
case '?':
default:
@@ -434,20 +434,54 @@ manual(char *page, TAG *tag, glob_t *pg)
{
ENTRY *ep, *e_sufp, *e_tag;
TAG *missp, *sufp;
- int anyfound, cnt, found;
+ int anyfound, cnt, found, globres;
char *p, buf[MAXPATHLEN];
anyfound = 0;
buf[0] = '*';
+ /* Expand the search path. */
+ if (f_all != f_where) {
+ e_tag = tag == NULL ? NULL : TAILQ_FIRST(&tag->list);
+ for (; e_tag != NULL; e_tag = TAILQ_NEXT(e_tag, q)) {
+ if (glob(e_tag->s, GLOB_BRACE | GLOB_NOSORT,
+ NULL, pg)) {
+ /* No GLOB_NOMATCH here due to {arch,}. */
+ warn("globbing directories");
+ (void)cleanup(0);
+ exit(1);
+ }
+ ep = e_tag;
+ for (cnt = 0; cnt < pg->gl_pathc; cnt++) {
+ if ((e_tag = malloc(sizeof(ENTRY))) == NULL ||
+ (e_tag->s = strdup(pg->gl_pathv[cnt])) ==
+ NULL) {
+ warn(NULL);
+ (void)cleanup(0);
+ exit(1);
+ }
+ TAILQ_INSERT_BEFORE(ep, e_tag, q);
+ }
+ free(ep->s);
+ TAILQ_REMOVE(&tag->list, ep, q);
+ free(ep);
+ globfree(pg);
+ pg->gl_pathc = 0;
+ }
+ }
+
/* For each element in the list... */
e_tag = tag == NULL ? NULL : TAILQ_FIRST(&tag->list);
for (; e_tag != NULL; e_tag = TAILQ_NEXT(e_tag, q)) {
(void)snprintf(buf, sizeof(buf), "%s/%s.*", e_tag->s, page);
- if (glob(buf,
- GLOB_APPEND | GLOB_BRACE | GLOB_NOSORT | GLOB_QUOTE,
+ switch (glob(buf, GLOB_APPEND | GLOB_BRACE | GLOB_NOSORT,
NULL, pg)) {
- warn("globbing");
+ case (0):
+ break;
+ case (GLOB_NOMATCH):
+ continue;
+ default:
+ warn("globbing files");
(void)cleanup(0);
exit(1);
}
@@ -458,8 +492,11 @@ manual(char *page, TAG *tag, glob_t *pg)
for (cnt = pg->gl_pathc - pg->gl_matchc;
cnt < pg->gl_pathc; ++cnt) {
- if (!f_all)
- check_companion(pg->gl_pathv + cnt);
+ if (!f_all || !f_where) {
+ check_companion(pg->gl_pathv + cnt, tag);
+ if (*pg->gl_pathv[cnt] == '\0')
+ continue;
+ }
/*
* Try the _suffix key words first.
@@ -512,7 +549,7 @@ manual(char *page, TAG *tag, glob_t *pg)
}
if (found) {
next: anyfound = 1;
- if (!f_all) {
+ if (!f_all && !f_where) {
/* Delete any other matches. */
while (++cnt< pg->gl_pathc)
pg->gl_pathv[cnt] = "";
@@ -525,7 +562,7 @@ next: anyfound = 1;
pg->gl_pathv[cnt] = "";
}
- if (anyfound && !f_all)
+ if (anyfound && !f_all && !f_where)
break;
}
@@ -551,13 +588,15 @@ next: anyfound = 1;
/*
* check_companion --
- * Check for a companion [un]formatted page
- * and use the newer one of the two.
+ * Check for a companion [un]formatted page.
+ * If one is found, skip this page.
+ * Use the companion instead, unless it will be found anyway.
*/
static void
-check_companion(char **orig) {
+check_companion(char **orig, TAG *tag) {
struct stat sb_orig, sb_comp;
char *p, *pext, comp[MAXPATHLEN];
+ ENTRY *entry;
size_t len;
int found;
@@ -574,14 +613,18 @@ check_companion(char **orig) {
/* Search for slashes. */
for (found = 0; 1; p--) {
+ if (*p != '/')
+ continue;
/* Did not find /{cat,man}. */
if (p == comp)
return;
/* Pass over one slash, the one before "page". */
- if (*p != '/' || !found++)
+ if (!found++) {
+ len = p - comp;
continue;
+ }
/* Rewrite manN/page.N <-> catN/page.0. */
if (!strncmp(p+1, "man", 3)) {
@@ -611,6 +654,15 @@ check_companion(char **orig) {
sb_orig.st_mtim.tv_nsec > sb_comp.st_mtim.tv_nsec))
return;
+ /* Drop the companion if it is in the path, too. */
+ if (f_all || f_where)
+ for(entry = TAILQ_FIRST(&tag->list); entry != NULL;
+ entry = TAILQ_NEXT(entry, q))
+ if (!strncmp(entry->s, comp, len)) {
+ **orig = '\0';
+ return;
+ }
+
/* The companion file is newer, use it. */
free(*orig);
if ((p = strdup(comp)) == NULL) {