xref: /csrg-svn/usr.bin/whatis/whatis.c (revision 65273)
1 /*
2  * Copyright (c) 1987, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1987, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)whatis.c	8.3 (Berkeley) 01/02/94";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/queue.h>
20 
21 #include <ctype.h>
22 #include <err.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "../man/config.h"
28 #include "../man/pathnames.h"
29 
30 #define	MAXLINELEN	256			/* max line handled */
31 
32 static int *found, foundman;
33 
34 int
35 main(argc, argv)
36 	int argc;
37 	char *argv[];
38 {
39 	extern char *optarg;
40 	extern int optind;
41 	ENTRY *ep;
42 	int ch;
43 	char *beg, *conffile, **p, *p_augment, *p_path;
44 
45 	conffile = NULL;
46 	p_augment = p_path = NULL;
47 	while ((ch = getopt(argc, argv, "C:M:m:P:")) != EOF)
48 		switch (ch) {
49 		case 'C':
50 			conffile = optarg;
51 			break;
52 		case 'M':
53 		case 'P':		/* backward compatible */
54 			p_path = optarg;
55 			break;
56 		case 'm':
57 			p_augment = optarg;
58 			break;
59 		case '?':
60 		default:
61 			usage();
62 		}
63 	argv += optind;
64 	argc -= optind;
65 
66 	if (argc < 1)
67 		usage();
68 
69 	if ((found = malloc((u_int)argc)) == NULL)
70 		err(1, NULL);
71 	memset(found, 0, argc * sizeof(int));
72 
73 	for (p = argv; *p; ++p)			/* trim full paths */
74 		if (beg = rindex(*p, '/'))
75 			*p = beg + 1;
76 
77 	if (p_augment)
78 		whatis(argv, p_augment, 1);
79 	if (p_path || (p_path = getenv("MANPATH")))
80 		whatis(argv, p_path, 1);
81 	else {
82 		config(conffile);
83 		ep = getlist("_whatdb");
84 		if (ep != NULL)
85 			ep = ep->list.qe_next;
86 		for (; ep != NULL; ep = ep->list.qe_next)
87 			whatis(argv, ep->s, 0);
88 	}
89 
90 	if (!foundman) {
91 		fprintf(stderr, "whatis: no %s file found.\n", _PATH_WHATIS);
92 		exit(1);
93 	}
94 	for (p = argv; *p; ++p)
95 		if (!found[p - argv])
96 			printf("%s: not found\n", *p);
97 }
98 
99 whatis(argv, path, buildpath)
100 	char **argv, *path;
101 	int buildpath;
102 {
103 	register char *end, *name, **p;
104 	char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
105 
106 	for (name = path; name; name = end) {	/* through name list */
107 		if (end = index(name, ':'))
108 			*end++ = '\0';
109 
110 		if (buildpath) {
111 			char hold[MAXPATHLEN + 1];
112 
113 			(void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
114 			name = hold;
115 		}
116 
117 		if (!freopen(name, "r", stdin))
118 			continue;
119 
120 		foundman = 1;
121 
122 		/* for each file found */
123 		while (fgets(buf, sizeof(buf), stdin)) {
124 			dashtrunc(buf, wbuf);
125 			for (p = argv; *p; ++p)
126 				if (match(wbuf, *p)) {
127 					printf("%s", buf);
128 					found[p - argv] = 1;
129 
130 					/* only print line once */
131 					while (*++p)
132 						if (match(wbuf, *p))
133 							found[p - argv] = 1;
134 					break;
135 				}
136 		}
137 	}
138 }
139 
140 /*
141  * match --
142  *	match a full word
143  */
144 match(bp, str)
145 	register char *bp, *str;
146 {
147 	register int len;
148 	register char *start;
149 
150 	if (!*str || !*bp)
151 		return(0);
152 	for (len = strlen(str);;) {
153 		for (; *bp && !isdigit(*bp) && !isalpha(*bp); ++bp);
154 		if (!*bp)
155 			break;
156 		for (start = bp++;
157 		    *bp && (*bp == '_' || isdigit(*bp) || isalpha(*bp)); ++bp);
158 		if (bp - start == len && !strncasecmp(start, str, len))
159 			return(1);
160 	}
161 	return(0);
162 }
163 
164 /*
165  * dashtrunc --
166  *	truncate a string at " - "
167  */
168 dashtrunc(from, to)
169 	register char *from, *to;
170 {
171 	register int ch;
172 
173 	for (; (ch = *from) && ch != '\n' &&
174 	    (ch != ' ' || from[1] != '-' || from[2] != ' '); ++from)
175 		*to++ = ch;
176 	*to = '\0';
177 }
178 
179 /*
180  * usage --
181  *	print usage message and die
182  */
183 usage()
184 {
185 	(void)fprintf(stderr,
186 	    "usage: whatis [-C file] [-M path] [-m path] command ...\n");
187 	exit(1);
188 }
189