whatis.c revision 1.20 1 /* $NetBSD: whatis.c,v 1.20 2005/08/25 16:29:15 rpaulo Exp $ */
2
3 /*
4 * Copyright (c) 1987, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33
34 #ifndef lint
35 __COPYRIGHT("@(#) Copyright (c) 1987, 1993\n\
36 The Regents of the University of California. All rights reserved.\n");
37 #endif /* not lint */
38
39 #ifndef lint
40 #if 0
41 static char sccsid[] = "@(#)whatis.c 8.5 (Berkeley) 1/2/94";
42 #else
43 __RCSID("$NetBSD: whatis.c,v 1.20 2005/08/25 16:29:15 rpaulo Exp $");
44 #endif
45 #endif /* not lint */
46
47 #include <sys/param.h>
48 #include <sys/queue.h>
49
50 #include <ctype.h>
51 #include <err.h>
52 #include <glob.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57
58 #include "manconf.h" /* from ../man/ */
59 #include "pathnames.h" /* from ../man/ */
60
61 #define MAXLINELEN 8192 /* max line handled */
62
63 static int *found, foundman;
64
65 int main __P((int, char **));
66 void dashtrunc __P((char *, char *));
67 int match __P((char *, char *));
68 void usage __P((void));
69 void whatis __P((char **, char *, int));
70
71 int
72 main(argc, argv)
73 int argc;
74 char *argv[];
75 {
76 ENTRY *ep;
77 TAG *tp;
78 int ch, rv;
79 char *beg, *conffile, **p, *p_augment, *p_path;
80 glob_t pg;
81
82 conffile = NULL;
83 p_augment = p_path = NULL;
84 while ((ch = getopt(argc, argv, "C:M:m:P:")) != -1)
85 switch (ch) {
86 case 'C':
87 conffile = optarg;
88 break;
89 case 'M':
90 case 'P': /* backward compatible */
91 p_path = optarg;
92 break;
93 case 'm':
94 p_augment = optarg;
95 break;
96 case '?':
97 default:
98 usage();
99 }
100 argv += optind;
101 argc -= optind;
102
103 if (argc < 1)
104 usage();
105
106 if ((found = malloc((u_int)argc * sizeof(int))) == NULL)
107 err(1, "malloc");
108 memset(found, 0, argc * sizeof(int));
109
110 for (p = argv; *p; ++p) /* trim full paths */
111 if ((beg = strrchr(*p, '/')))
112 *p = beg + 1;
113
114 if (p_augment)
115 whatis(argv, p_augment, 1);
116 if (p_path || (p_path = getenv("MANPATH")))
117 whatis(argv, p_path, 1);
118 else {
119 config(conffile);
120 tp = getlist("_whatdb", 0);
121 TAILQ_FOREACH(ep, &tp->list, q) {
122 if ((rv = glob(ep->s, GLOB_BRACE | GLOB_NOSORT, NULL,
123 &pg)) != 0) {
124 if (rv == GLOB_NOMATCH)
125 continue;
126 else
127 err(EXIT_FAILURE, "glob");
128 }
129 if (pg.gl_pathc)
130 for (p = pg.gl_pathv; *p; p++)
131 whatis(argv, *p, 0);
132 globfree(&pg);
133 }
134 }
135
136 if (!foundman) {
137 fprintf(stderr, "whatis: no %s file found.\n", _PATH_WHATIS);
138 exit(1);
139 }
140 rv = 1;
141 for (p = argv; *p; ++p)
142 if (found[p - argv])
143 rv = 0;
144 else
145 printf("%s: not found\n", *p);
146 exit(rv);
147 }
148
149 void
150 whatis(argv, path, buildpath)
151 char **argv, *path;
152 int buildpath;
153 {
154 char *end, *name, **p;
155 char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
156 char hold[MAXPATHLEN + 1];
157
158 for (name = path; name; name = end) { /* through name list */
159 if ((end = strchr(name, ':')))
160 *end++ = '\0';
161
162 if (buildpath) {
163 (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
164 name = hold;
165 }
166
167 if (!freopen(name, "r", stdin))
168 continue;
169
170 foundman = 1;
171
172 /* for each file found */
173 while (fgets(buf, sizeof(buf), stdin)) {
174 dashtrunc(buf, wbuf);
175 for (p = argv; *p; ++p)
176 if (match(wbuf, *p)) {
177 printf("%s", buf);
178 found[p - argv] = 1;
179
180 /* only print line once */
181 while (*++p)
182 if (match(wbuf, *p))
183 found[p - argv] = 1;
184 break;
185 }
186 }
187 }
188 }
189
190 /*
191 * match --
192 * match a full word
193 */
194 int
195 match(bp, str)
196 char *bp, *str;
197 {
198 int len;
199 char *start;
200
201 if (!*str || !*bp)
202 return(0);
203 for (len = strlen(str);;) {
204 /*
205 * /bin/[ is a special case.
206 */
207 for (; *bp && *bp != '[' && !isalnum((unsigned char)*bp); ++bp);
208 if (!*bp)
209 break;
210 for (start = bp++;
211 *bp && (*bp == '_' || isalnum((unsigned char)*bp)); ++bp);
212 if (bp - start == len && !strncasecmp(start, str, len))
213 return(1);
214 }
215 return(0);
216 }
217
218 /*
219 * dashtrunc --
220 * truncate a string at " - "
221 */
222 void
223 dashtrunc(from, to)
224 char *from, *to;
225 {
226 int ch;
227
228 for (; (ch = *from) && ch != '\n' &&
229 (ch != ' ' || from[1] != '-' || from[2] != ' '); ++from)
230 *to++ = ch;
231 *to = '\0';
232 }
233
234 /*
235 * usage --
236 * print usage message and die
237 */
238 void
239 usage()
240 {
241 (void)fprintf(stderr,
242 "usage: whatis [-C file] [-M path] [-m path] command ...\n");
243 exit(1);
244 }
245