Fri May 8 12:48:43 2009 UTC ()
Add support for -S and -s option, which limit the results to a specific
architecture or section, respectively.
Based on a patch for OpenBSD from Ingo Schwarze, modified for NetBSD by me.

Add some constification.

Ok lukem@ (to the non-constified version of the patch).


(wiz)
diff -r1.10 -r1.11 src/usr.bin/apropos/apropos.1
diff -r1.29 -r1.30 src/usr.bin/apropos/apropos.c

cvs diff -r1.10 -r1.11 src/usr.bin/apropos/apropos.1 (expand / switch to unified diff)

--- src/usr.bin/apropos/apropos.1 2003/08/07 11:13:07 1.10
+++ src/usr.bin/apropos/apropos.1 2009/05/08 12:48:43 1.11
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1.\" $NetBSD: apropos.1,v 1.10 2003/08/07 11:13:07 agc Exp $ 1.\" $NetBSD: apropos.1,v 1.11 2009/05/08 12:48:43 wiz Exp $
2.\" 2.\"
3.\" Copyright (c) 1989, 1990, 1993 3.\" Copyright (c) 1989, 1990, 1993
4.\" The Regents of the University of California. All rights reserved. 4.\" The Regents of the University of California. All rights reserved.
5.\" 5.\"
6.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
8.\" are met: 8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright 9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer. 10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors 14.\" 3. Neither the name of the University nor the names of its contributors
@@ -19,37 +19,39 @@ @@ -19,37 +19,39 @@
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
29.\" 29.\"
30.\" @(#)apropos.1 8.1 (Berkeley) 6/29/93 30.\" @(#)apropos.1 8.1 (Berkeley) 6/29/93
31.\" 31.\"
32.Dd June 29, 1993 32.Dd May 7, 2009
33.Dt APROPOS 1 33.Dt APROPOS 1
34.Os 34.Os
35.Sh NAME 35.Sh NAME
36.Nm apropos 36.Nm apropos
37.Nd locate commands by keyword lookup 37.Nd locate commands by keyword lookup
38.Sh SYNOPSIS 38.Sh SYNOPSIS
39.Nm apropos 39.Nm apropos
40.Op Fl C Ar path 40.Op Fl C Ar path
41.Op Fl M Ar path 41.Op Fl M Ar path
42.Op Fl m Ar path 42.Op Fl m Ar path
 43.Op Fl S Ar subsection
 44.Op Fl s Ar section
43.Ar keyword ... 45.Ar keyword ...
44.Sh DESCRIPTION 46.Sh DESCRIPTION
45.Nm 47.Nm
46shows which manual pages contain instances of any of the given 48shows which manual pages contain instances of any of the given
47.Ar keyword(s) 49.Ar keyword(s)
48in their title line. 50in their title line.
49Each word is considered separately and case of letters is ignored. 51Each word is considered separately and case of letters is ignored.
50Words which are part of other words are considered; when looking for 52Words which are part of other words are considered; when looking for
51.Dq compile , 53.Dq compile ,
52.Nm 54.Nm
53will also list all instances of 55will also list all instances of
54.Dq compiler . 56.Dq compiler .
55.Pp 57.Pp
@@ -86,26 +88,32 @@ Augment the list of standard directories @@ -86,26 +88,32 @@ Augment the list of standard directories
86.Nm 88.Nm
87searches for its database. 89searches for its database.
88The supplied 90The supplied
89.Ar path 91.Ar path
90must be a colon 92must be a colon
91.Dq \&: 93.Dq \&:
92separated list of directories. 94separated list of directories.
93These directories will be searched before the standard directories, 95These directories will be searched before the standard directories,
94or the directories supplied with the 96or the directories supplied with the
95.Fl M 97.Fl M
96option or the 98option or the
97.Ev MANPATH 99.Ev MANPATH
98environment variable. 100environment variable.
 101.It Fl S Ar subsection
 102Restrict the search to pages for the specified machine architecture.
 103By default, pages for all architectures are shown.
 104.It Fl s Ar section
 105Restrict the search to the specified section of the manual.
 106By default, pages from all sections are shown.
99.El 107.El
100.Sh ENVIRONMENT 108.Sh ENVIRONMENT
101.Bl -tag -width MANPATH 109.Bl -tag -width MANPATH
102.It Ev MANPATH 110.It Ev MANPATH
103The standard search path used by 111The standard search path used by
104.Xr man 1 112.Xr man 1
105may be overridden by specifying a path in the 113may be overridden by specifying a path in the
106.Ev MANPATH 114.Ev MANPATH
107environment variable. 115environment variable.
108The format of the path is a colon 116The format of the path is a colon
109.Dq \&: 117.Dq \&:
110separated list of directories. 118separated list of directories.
111.El 119.El

cvs diff -r1.29 -r1.30 src/usr.bin/apropos/apropos.c (expand / switch to unified diff)

--- src/usr.bin/apropos/apropos.c 2008/07/21 14:19:20 1.29
+++ src/usr.bin/apropos/apropos.c 2009/05/08 12:48:43 1.30
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: apropos.c,v 1.29 2008/07/21 14:19:20 lukem Exp $ */ 1/* $NetBSD: apropos.c,v 1.30 2009/05/08 12:48:43 wiz Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1987, 1993, 1994 4 * Copyright (c) 1987, 1993, 1994
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -30,215 +30,248 @@ @@ -30,215 +30,248 @@
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33 33
34#ifndef lint 34#ifndef lint
35__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\ 35__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\
36 The Regents of the University of California. All rights reserved."); 36 The Regents of the University of California. All rights reserved.");
37#endif /* not lint */ 37#endif /* not lint */
38 38
39#ifndef lint 39#ifndef lint
40#if 0 40#if 0
41static char sccsid[] = "@(#)apropos.c 8.8 (Berkeley) 5/4/95"; 41static char sccsid[] = "@(#)apropos.c 8.8 (Berkeley) 5/4/95";
42#else 42#else
43__RCSID("$NetBSD: apropos.c,v 1.29 2008/07/21 14:19:20 lukem Exp $"); 43__RCSID("$NetBSD: apropos.c,v 1.30 2009/05/08 12:48:43 wiz Exp $");
44#endif 44#endif
45#endif /* not lint */ 45#endif /* not lint */
46 46
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/queue.h> 48#include <sys/queue.h>
49 49
50#include <ctype.h> 50#include <ctype.h>
51#include <err.h> 51#include <err.h>
52#include <glob.h> 52#include <glob.h>
53#include <limits.h> 53#include <limits.h>
54#include <stdbool.h> 54#include <stdbool.h>
55#include <stdio.h> 55#include <stdio.h>
56#include <stdlib.h> 56#include <stdlib.h>
57#include <string.h> 57#include <string.h>
58#include <unistd.h> 58#include <unistd.h>
59 59
60#include "manconf.h" /* from ../man/ */ 60#include "manconf.h" /* from ../man/ */
61#include "pathnames.h" /* from ../man/ */ 61#include "pathnames.h" /* from ../man/ */
62 62
63static bool *found; 63static bool *found;
64static bool foundman = false; 64static bool foundman = false;
65 65
66#define MAXLINELEN 8192 /* max line handled */ 66#define MAXLINELEN 8192 /* max line handled */
67 67
68static void apropos(char **, char *, bool); 68static void apropos(char **, const char *, bool, const char *, const char *);
69static void lowstr(char *, char *); 69static void lowstr(const char *, char *);
70static bool match(char *, char *); 70static bool match(const char *, const char *);
71static void usage(void) __dead; 71static void usage(void) __dead;
72 72
73int 73int
74main(int argc, char *argv[]) 74main(int argc, char *argv[])
75{ 75{
76 ENTRY *ep; 76 ENTRY *ep;
77 TAG *tp; 77 TAG *tp;
78 int ch, rv; 78 int ch, rv;
79 char *conffile, **p, *p_augment, *p_path; 79 char *conffile, *machine, **p, *p_augment, *p_path, *sflag;
80 glob_t pg; 80 glob_t pg;
81 81
82 conffile = NULL; 82 conffile = NULL;
83 p_augment = p_path = NULL; 83 p_augment = p_path = NULL;
84 while ((ch = getopt(argc, argv, "C:M:m:P:")) != -1) { 84 machine = sflag = NULL;
 85 while ((ch = getopt(argc, argv, "C:M:m:P:S:s:")) != -1) {
85 switch (ch) { 86 switch (ch) {
86 case 'C': 87 case 'C':
87 conffile = optarg; 88 conffile = optarg;
88 break; 89 break;
89 case 'M': 90 case 'M':
90 case 'P': /* backward compatible */ 91 case 'P': /* backward compatible */
91 p_path = optarg; 92 p_path = optarg;
92 break; 93 break;
93 case 'm': 94 case 'm':
94 p_augment = optarg; 95 p_augment = optarg;
95 break; 96 break;
 97 case 'S':
 98 machine = optarg;
 99 lowstr(machine, machine);
 100 break;
 101 case 's':
 102 sflag = optarg;
 103 lowstr(sflag, sflag);
 104 break;
96 case '?': 105 case '?':
97 default: 106 default:
98 usage(); 107 usage();
99 } 108 }
100 } 109 }
101 argv += optind; 110 argv += optind;
102 argc -= optind; 111 argc -= optind;
103 112
104 if (argc < 1) 113 if (argc < 1)
105 usage(); 114 usage();
106 115
107 if ((found = malloc(argc * sizeof(*found))) == NULL) 116 if ((found = malloc(argc * sizeof(*found))) == NULL)
108 err(EXIT_FAILURE, "malloc"); 117 err(EXIT_FAILURE, "malloc");
109 (void)memset(found, 0, argc * sizeof(*found)); 118 (void)memset(found, 0, argc * sizeof(*found));
110 119
111 for (p = argv; *p; ++p) /* convert to lower-case */ 120 for (p = argv; *p; ++p) /* convert to lower-case */
112 lowstr(*p, *p); 121 lowstr(*p, *p);
113 122
114 if (p_augment) 123 if (p_augment)
115 apropos(argv, p_augment, true); 124 apropos(argv, p_augment, true, sflag, machine);
116 if (p_path || (p_path = getenv("MANPATH"))) 125 if (p_path || (p_path = getenv("MANPATH")))
117 apropos(argv, p_path, true); 126 apropos(argv, p_path, true, sflag, machine);
118 else { 127 else {
119 config(conffile); 128 config(conffile);
120 tp = gettag("_whatdb", 1); 129 tp = gettag("_whatdb", 1);
121 if (!tp) 130 if (!tp)
122 errx(EXIT_FAILURE, "malloc"); 131 errx(EXIT_FAILURE, "malloc");
123 TAILQ_FOREACH(ep, &tp->entrylist, q) { 132 TAILQ_FOREACH(ep, &tp->entrylist, q) {
124 if ((rv = glob(ep->s, GLOB_BRACE | GLOB_NOSORT, NULL, 133 if ((rv = glob(ep->s, GLOB_BRACE | GLOB_NOSORT, NULL,
125 &pg)) != 0) { 134 &pg)) != 0) {
126 if (rv == GLOB_NOMATCH) 135 if (rv == GLOB_NOMATCH)
127 continue; 136 continue;
128 else 137 else
129 err(EXIT_FAILURE, "glob"); 138 err(EXIT_FAILURE, "glob");
130 } 139 }
131 if (pg.gl_pathc) 140 if (pg.gl_pathc)
132 for (p = pg.gl_pathv; *p; p++) 141 for (p = pg.gl_pathv; *p; p++)
133 apropos(argv, *p, false); 142 apropos(argv, *p, false, sflag,
 143 machine);
134 globfree(&pg); 144 globfree(&pg);
135 } 145 }
136 } 146 }
137 147
138 if (!foundman) 148 if (!foundman)
139 errx(EXIT_FAILURE, "no %s file found", _PATH_WHATIS); 149 errx(EXIT_FAILURE, "no %s file found", _PATH_WHATIS);
140 150
141 rv = 1; 151 rv = 1;
142 for (p = argv; *p; ++p) 152 for (p = argv; *p; ++p)
143 if (found[p - argv]) 153 if (found[p - argv])
144 rv = 0; 154 rv = 0;
145 else 155 else
146 (void)printf("%s: nothing appropriate\n", *p); 156 (void)printf("%s: nothing appropriate\n", *p);
147 return rv; 157 return rv;
148} 158}
149 159
150static void 160static void
151apropos(char **argv, char *path, bool buildpath) 161apropos(char **argv, const char *path, bool buildpath,
 162 const char *sflag, const char *machine)
152{ 163{
153 char *end, *name, **p; 164 char *end, **p;
 165 const char *name;
154 char buf[MAXLINELEN + 1]; 166 char buf[MAXLINELEN + 1];
155 char hold[MAXPATHLEN + 1]; 167 char hold[MAXPATHLEN + 1];
156 char wbuf[MAXLINELEN + 1]; 168 char wbuf[MAXLINELEN + 1];
 169 size_t slen = 0, mlen = 0;
 170
 171 if (sflag)
 172 slen = strlen(sflag);
 173 if (machine)
 174 mlen = strlen(machine);
157 175
158 for (name = path; name; name = end) { /* through name list */ 176 for (name = path; name; name = end) { /* through name list */
159 if ((end = strchr(name, ':')) != NULL) 177 if ((end = strchr(name, ':')) != NULL)
160 *end++ = '\0'; 178 *end++ = '\0';
161 179
162 if (buildpath) { 180 if (buildpath) {
163 (void)snprintf(hold, sizeof(hold), "%s/%s", name, 181 (void)snprintf(hold, sizeof(hold), "%s/%s", name,
164 _PATH_WHATIS); 182 _PATH_WHATIS);
165 name = hold; 183 name = hold;
166 } 184 }
167 185
168 if (!freopen(name, "r", stdin)) 186 if (!freopen(name, "r", stdin))
169 continue; 187 continue;
170 188
171 foundman = true; 189 foundman = true;
172 190
173 /* for each file found */ 191 /* for each file found */
174 while (fgets(buf, (int)sizeof(buf), stdin)) { 192 while (fgets(buf, (int)sizeof(buf), stdin)) {
175 if (!strchr(buf, '\n')) { 193 if (!strchr(buf, '\n')) {
176 warnx("%s: line too long", name); 194 warnx("%s: line too long", name);
177 continue; 195 continue;
178 } 196 }
179 lowstr(buf, wbuf); 197 lowstr(buf, wbuf);
 198 if (machine) {
 199 if ((strncmp(wbuf, machine, mlen) != 0) ||
 200 strlen(wbuf) <= mlen || wbuf[mlen] != '/')
 201 continue;
 202 }
 203 if (sflag) {
 204 char *s = strchr(wbuf, '(');
 205
 206 if (!s)
 207 continue;
 208 if (strncmp(s+1, sflag, slen) != 0)
 209 continue;
 210 }
180 for (p = argv; *p; ++p) { 211 for (p = argv; *p; ++p) {
181 if (match(wbuf, *p)) { 212 if (match(wbuf, *p)) {
182 (void)printf("%s", buf); 213 (void)printf("%s", buf);
183 found[p - argv] = true; 214 found[p - argv] = true;
184 215
185 /* only print line once */ 216 /* only print line once */
186 while (*++p) 217 while (*++p)
187 if (match(wbuf, *p)) 218 if (match(wbuf, *p))
188 found[p - argv] = true; 219 found[p - argv] = true;
189 break; 220 break;
190 } 221 }
191 } 222 }
192 } 223 }
193 } 224 }
194} 225}
195 226
196/* 227/*
197 * match -- 228 * match --
198 * match anywhere the string appears 229 * match anywhere the string appears
199 */ 230 */
200static bool 231static bool
201match(char *bp, char *str) 232match(const char *bp, const char *str)
202{ 233{
203 size_t len; 234 size_t len;
204 char test; 235 char test;
205 236
206 if (!*bp) 237 if (!*bp)
207 return false; 238 return false;
208 /* backward compatible: everything matches empty string */ 239 /* backward compatible: everything matches empty string */
209 if (!*str) 240 if (!*str)
210 return true; 241 return true;
211 for (test = *str++, len = strlen(str); *bp;) 242 for (test = *str++, len = strlen(str); *bp;)
212 if (test == *bp++ && !strncmp(bp, str, len)) 243 if (test == *bp++ && !strncmp(bp, str, len))
213 return true; 244 return true;
214 return false; 245 return false;
215} 246}
216 247
217/* 248/*
218 * lowstr -- 249 * lowstr --
219 * convert a string to lower case 250 * convert a string to lower case
220 */ 251 */
221static void 252static void
222lowstr(char *from, char *to) 253lowstr(const char *from, char *to)
223{ 254{
224 char ch; 255 char ch;
225 256
226 while ((ch = *from++) && ch != '\n') 257 while ((ch = *from++) && ch != '\n')
227 *to++ = tolower((unsigned char)ch); 258 *to++ = tolower((unsigned char)ch);
228 *to = '\0'; 259 *to = '\0';
229} 260}
230 261
231/* 262/*
232 * usage -- 263 * usage --
233 * print usage message and die 264 * print usage message and die
234 */ 265 */
235__dead 266__dead
236static void 267static void
237usage(void) 268usage(void)
238{ 269{
239 270
240 (void)fprintf(stderr, 271 (void)fprintf(stderr,
241 "usage: %s [-C file] [-M path] [-m path] keyword ...\n", 272 "usage: %s [-C file] [-M path] [-m path] "
 273 "[-S subsection] [-s section]\n"
 274 " keyword ...\n",
242 getprogname()); 275 getprogname());
243 exit(1); 276 exit(1);
244} 277}