tools/llvm: Do not build with symbols
[minix3.git] / usr.bin / whatis / whatis.c
blobf30623e79d19a6097a4157afa758dc0535a61307
1 /* $NetBSD: whatis.c,v 1.24 2011/09/06 18:46:03 joerg Exp $ */
3 /*
4 * Copyright (c) 1987, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
32 #include <sys/cdefs.h>
34 #ifndef lint
35 __COPYRIGHT("@(#) Copyright (c) 1987, 1993\
36 The Regents of the University of California. All rights reserved.");
37 #endif /* not lint */
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.24 2011/09/06 18:46:03 joerg Exp $");
44 #endif
45 #endif /* not lint */
47 #include <sys/param.h>
48 #include <sys/queue.h>
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>
58 #include "manconf.h" /* from ../man/ */
59 #include "pathnames.h" /* from ../man/ */
61 #define MAXLINELEN 8192 /* max line handled */
63 static int *found, foundman;
65 static void dashtrunc(char *, char *);
66 static int match(char *, char *);
67 __dead static void usage(void);
68 static void whatis(char **, char *, int);
70 int
71 main(int argc, char **argv)
73 ENTRY *ep;
74 TAG *tp;
75 int ch, rv;
76 char *beg, *conffile, **p, *p_augment, *p_path;
77 glob_t pg;
79 conffile = NULL;
80 p_augment = p_path = NULL;
81 while ((ch = getopt(argc, argv, "C:M:m:P:")) != -1)
82 switch (ch) {
83 case 'C':
84 conffile = optarg;
85 break;
86 case 'M':
87 case 'P': /* backward compatible */
88 p_path = optarg;
89 break;
90 case 'm':
91 p_augment = optarg;
92 break;
93 case '?':
94 default:
95 usage();
97 argv += optind;
98 argc -= optind;
100 if (argc < 1)
101 usage();
103 if ((found = malloc((u_int)argc * sizeof(int))) == NULL)
104 err(1, "malloc");
105 memset(found, 0, argc * sizeof(int));
107 for (p = argv; *p; ++p) /* trim full paths */
108 if ((beg = strrchr(*p, '/')))
109 *p = beg + 1;
111 if (p_augment)
112 whatis(argv, p_augment, 1);
113 if (p_path || (p_path = getenv("MANPATH")))
114 whatis(argv, p_path, 1);
115 else {
116 config(conffile);
117 tp = gettag("_whatdb", 0);
118 if (!tp)
119 errx(EXIT_FAILURE,
120 "no database dirs (_whatdb) in config file");
121 TAILQ_FOREACH(ep, &tp->entrylist, 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");
129 if (pg.gl_pathc)
130 for (p = pg.gl_pathv; *p; p++)
131 whatis(argv, *p, 0);
132 globfree(&pg);
136 if (!foundman) {
137 fprintf(stderr, "whatis: no %s file found.\n", _PATH_WHATIS);
138 exit(1);
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);
149 static void
150 whatis(char **argv, char *path, int buildpath)
152 char *end, *name, **p;
153 char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
154 char hold[MAXPATHLEN + 1];
156 for (name = path; name; name = end) { /* through name list */
157 if ((end = strchr(name, ':')))
158 *end++ = '\0';
160 if (buildpath) {
161 (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
162 name = hold;
165 if (!freopen(name, "r", stdin))
166 continue;
168 foundman = 1;
170 /* for each file found */
171 while (fgets(buf, sizeof(buf), stdin)) {
172 dashtrunc(buf, wbuf);
173 for (p = argv; *p; ++p)
174 if (match(wbuf, *p)) {
175 printf("%s", buf);
176 found[p - argv] = 1;
178 /* only print line once */
179 while (*++p)
180 if (match(wbuf, *p))
181 found[p - argv] = 1;
182 break;
189 * match --
190 * match a full word
192 static int
193 match(char *bp, char *str)
195 int len;
196 char *start;
198 if (!*str || !*bp)
199 return(0);
200 for (len = strlen(str);;) {
202 * /bin/[ is a special case.
204 for (; *bp && *bp != '[' && !isalnum((unsigned char)*bp); ++bp);
205 if (!*bp)
206 break;
208 /* check for word match first */
209 for (start = bp++; *bp && (*bp == '_' ||
210 isalnum((unsigned char) *bp)); ++bp);
211 if (bp - start == len && strncasecmp(start, str, len) == 0) {
212 return(1);
213 } else if (*bp && *bp != ',') {
214 /* check for full string match */
215 for (bp = start; *bp && *bp != ',' && *bp != '(' &&
216 !isspace((unsigned char) *bp); ++bp);
217 if (bp - start == len &&
218 strncasecmp(start, str, len) == 0)
219 return(1);
222 return(0);
226 * dashtrunc --
227 * truncate a string at " - "
229 static void
230 dashtrunc(char *from, char *to)
232 int ch;
234 for (; (ch = *from) && ch != '\n' &&
235 (ch != ' ' || from[1] != '-' || from[2] != ' '); ++from)
236 *to++ = ch;
237 *to = '\0';
241 * usage --
242 * print usage message and die
244 static void
245 usage(void)
247 (void)fprintf(stderr,
248 "usage: whatis [-C file] [-M path] [-m path] command ...\n");
249 exit(1);