Lint (and new copyrights).
[unix-history] / usr / src / usr.bin / apropos / apropos.c
CommitLineData
43f23b36
KB
1/*
2 * Copyright (c) 1987 Regents of the University of California.
ea9afd82
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
b36fc510
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
43f23b36
KB
16 */
17
18#ifndef lint
19char copyright[] =
20"@(#) Copyright (c) 1987 Regents of the University of California.\n\
21 All rights reserved.\n";
ea9afd82 22#endif /* not lint */
43f23b36
KB
23
24#ifndef lint
b36fc510 25static char sccsid[] = "@(#)apropos.c 5.6 (Berkeley) %G%";
ea9afd82 26#endif /* not lint */
43f23b36
KB
27
28#include <sys/param.h>
29#include <stdio.h>
30#include <ctype.h>
76f1f97b 31#include <strings.h>
43f23b36 32
beb0c7d1 33#define DEF_PATH "/usr/man:/usr/new/man:/usr/local/man"
e39a3843 34#define MAXLINELEN 1000 /* max line handled */
43f23b36 35#define WHATIS "whatis" /* database name */
43f23b36 36
76f1f97b
KB
37#define NO 0 /* no/false */
38#define YES 1 /* yes/true */
39
40static char *myname;
43f23b36
KB
41
42main(argc, argv)
76f1f97b
KB
43 int argc;
44 char **argv;
43f23b36 45{
76f1f97b
KB
46 extern char *optarg;
47 extern int optind;
48 register char *beg, *end, **C;
49 int ch, foundman = NO, *found, isapropos;
50 int a_match(), w_match(), (*match)();
51 char *manpath = NULL, buf[MAXLINELEN + 1], fname[MAXPATHLEN + 1];
52 char wbuf[MAXLINELEN + 1], *getenv(), *malloc();
43f23b36
KB
53
54 myname = (beg = rindex(*argv, '/')) ? beg + 1 : *argv;
55 if (!strcmp(myname, "apropos")) {
56 isapropos = YES;
57 match = a_match;
58 }
59 else {
60 isapropos = NO;
61 match = w_match;
62 }
63 while ((ch = getopt(argc, argv, "M:P:")) != EOF)
64 switch((char)ch) {
65 case 'M':
66 case 'P': /* backward contemptible */
67 manpath = optarg;
68 break;
69 case '?':
70 default:
71 usage();
72 }
73 argv += optind;
74 argc -= optind;
75 if (argc < 1)
76 usage();
77
78 if (!(manpath = getenv("MANPATH")))
79 manpath = DEF_PATH;
80
81 /*NOSTRICT*/
82 if (!(found = (int *)malloc((u_int)argc))) {
83 fprintf(stderr, "%s: out of space.\n", myname);
84 exit(1);
85 }
76f1f97b 86 bzero((char *)found, argc * sizeof(int));
43f23b36 87
76f1f97b
KB
88 if (isapropos)
89 for (C = argv; *C; ++C) /* convert to lower-case */
90 lowstr(*C, *C);
91 else for (C = argv; *C; ++C) /* trim full paths */
92 if (beg = rindex(*C, '/'))
93 *C = beg + 1;
43f23b36
KB
94
95 for (beg = manpath; beg; beg = end) { /* through path list */
96 end = index(beg, ':');
97 if (!end)
98 (void)sprintf(fname, "%s/%s", beg, WHATIS);
99 else {
100 (void)sprintf(fname, "%.*s/%s", end - beg, beg, WHATIS);
101 ++end;
102 }
76f1f97b
KB
103 if (!freopen(fname, "r", stdin))
104 continue;
105
43f23b36 106 /* for each file found */
76f1f97b
KB
107 for (foundman = YES; gets(buf);) {
108 if (isapropos)
43f23b36 109 lowstr(buf, wbuf);
76f1f97b
KB
110 else
111 dashtrunc(buf, wbuf);
112 for (C = argv; *C; ++C)
113 if ((*match)(wbuf, *C)) {
114 puts(buf);
115 found[C - argv] = YES;
116
117 /* only print line once */
118 while (*++C)
119 if ((*match)(wbuf, *C))
120 found[C - argv] = YES;
121 break;
122 }
43f23b36
KB
123 }
124 }
125 if (!foundman) {
126 fprintf(stderr, "%s: no %s file found in %s.\n", myname, WHATIS, manpath);
127 exit(1);
128 }
76f1f97b 129 for (C = argv; *C; ++C)
43f23b36
KB
130 if (!found[C - argv])
131 printf("%s: %s\n", *C, isapropos ? "nothing appropriate" : "not found");
132}
133
76f1f97b
KB
134/*
135 * a_match --
136 * match for apropos; anywhere the string appears
137 */
43f23b36
KB
138static
139a_match(bp, str)
76f1f97b 140 register char *bp, *str;
43f23b36 141{
76f1f97b
KB
142 register int len;
143 register char test;
43f23b36
KB
144
145 if (!*bp)
146 return(NO);
76f1f97b 147 /* backward compatible: everything matches empty string */
43f23b36
KB
148 if (!*str)
149 return(YES);
76f1f97b
KB
150 for (test = *str++, len = strlen(str); *bp;)
151 if (test == *bp++ && !strncmp(bp, str, len))
152 return(YES);
43f23b36
KB
153 return(NO);
154}
155
76f1f97b
KB
156/*
157 * w_match --
158 * match for whatis; looks for full word match
159 */
43f23b36
KB
160static
161w_match(bp, str)
76f1f97b 162 register char *bp, *str;
43f23b36 163{
76f1f97b
KB
164 register int len;
165 register char *start;
43f23b36
KB
166
167 if (!*str || !*bp)
168 return(NO);
76f1f97b
KB
169 for (len = strlen(str);;) {
170 for (; *bp && !isdigit(*bp) && !isalpha(*bp); ++bp);
171 if (!*bp)
172 break;
173 for (start = bp++; *bp && (isdigit(*bp) || isalpha(*bp)); ++bp);
174 if (bp - start == len && !strncasecmp(start, str, len))
175 return(YES);
176 }
43f23b36
KB
177 return(NO);
178}
179
76f1f97b
KB
180/*
181 * dashtrunc --
182 * truncate a string at " - "
183 */
184static
185dashtrunc(from, to)
186 register char *from, *to;
187{
188 do {
189 if (from[0] == ' ' && from[1] == '-' && from[2] == ' ')
190 break;
191 } while (*to++ = *from++);
192 *to = '\0';
193}
194
195/*
196 * lowstr --
197 * convert a string to lower case
198 */
43f23b36
KB
199static
200lowstr(from, to)
76f1f97b 201 register char *from, *to;
43f23b36 202{
76f1f97b
KB
203 do {
204 *to++ = isupper(*from) ? tolower(*from) : *from;
205 } while (*from++);
43f23b36
KB
206}
207
76f1f97b
KB
208/*
209 * usage --
210 * print usage message and die
211 */
43f23b36
KB
212static
213usage()
214{
215 fprintf(stderr, "usage: %s [-M path] string ...\n", myname);
216 exit(1);
217}