date and time created 87/06/29 20:53:49 by bostic
[unix-history] / usr / src / usr.bin / apropos / apropos.c
CommitLineData
43f23b36
KB
1/*
2 * Copyright (c) 1987 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1987 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
13#ifndef lint
14static char sccsid[] = "@(#)apropos.c 5.1 (Berkeley) %G%";
15#endif not lint
16
17#include <sys/param.h>
18#include <stdio.h>
19#include <ctype.h>
20
21#define DEF_PATH "/usr/man" /* default man path */
22#define MAXLINELEN 500 /* max line handled */
23#define NO 0 /* no/false */
24#define WHATIS "whatis" /* database name */
25#define YES 1 /* yes/true */
26
27static char *myname;
28
29main(argc, argv)
30 int argc;
31 char **argv;
32{
33 extern char *optarg;
34 extern int optind;
35 register char *beg, *end, **C;
36 int ch, foundman = NO, *found, isapropos,
37 a_match(), w_match(), (*match)();
38 char *manpath = NULL,
39 buf[MAXLINELEN + 1], fname[MAXPATHLEN + 1],
40 wbuf[MAXLINELEN + 1],
41 *getenv(), *index(), *malloc(), *rindex();
42
43 myname = (beg = rindex(*argv, '/')) ? beg + 1 : *argv;
44 if (!strcmp(myname, "apropos")) {
45 isapropos = YES;
46 match = a_match;
47 }
48 else {
49 isapropos = NO;
50 match = w_match;
51 }
52 while ((ch = getopt(argc, argv, "M:P:")) != EOF)
53 switch((char)ch) {
54 case 'M':
55 case 'P': /* backward contemptible */
56 manpath = optarg;
57 break;
58 case '?':
59 default:
60 usage();
61 }
62 argv += optind;
63 argc -= optind;
64 if (argc < 1)
65 usage();
66
67 if (!(manpath = getenv("MANPATH")))
68 manpath = DEF_PATH;
69
70 /*NOSTRICT*/
71 if (!(found = (int *)malloc((u_int)argc))) {
72 fprintf(stderr, "%s: out of space.\n", myname);
73 exit(1);
74 }
75 bzero(found, argc * sizeof(int)); /* calloc is silly */
76
77 if (!isapropos)
78 for (C = argv; *C; ++C) { /* trim full paths */
79 if (beg = rindex(*C, '/'))
80 *C = beg + 1;
81 }
82 for (C = argv; *C; ++C) /* convert to lower-case */
83 lowstr(*C, *C);
84
85 for (beg = manpath; beg; beg = end) { /* through path list */
86 end = index(beg, ':');
87 if (!end)
88 (void)sprintf(fname, "%s/%s", beg, WHATIS);
89 else {
90 (void)sprintf(fname, "%.*s/%s", end - beg, beg, WHATIS);
91 ++end;
92 }
93 /* for each file found */
94 if (freopen(fname, "r", stdin)) {
95 foundman = YES;
96 while (gets(buf)) { /* read & convert to lcase */
97 lowstr(buf, wbuf);
98 for (C = argv; *C; ++C)
99 if ((*match)(wbuf, *C)) {
100 puts(buf);
101 found[C - argv] = YES;
102
103 /* only print line once */
104 while (*++C)
105 if ((*match)(wbuf, *C))
106 found[C - argv] = YES;
107 break;
108 }
109 }
110 }
111 }
112 if (!foundman) {
113 fprintf(stderr, "%s: no %s file found in %s.\n", myname, WHATIS, manpath);
114 exit(1);
115 }
116 for (C = argv; *C; C++)
117 if (!found[C - argv])
118 printf("%s: %s\n", *C, isapropos ? "nothing appropriate" : "not found");
119}
120
121static
122a_match(bp, str)
123 register char *bp, *str;
124{
125 register char test, *Cs, *Cb;
126
127 if (!*bp)
128 return(NO);
129 /* backward contemptible: everything matches empty string */
130 if (!*str)
131 return(YES);
132 for (test = *str++; *bp;)
133 if (test == *bp++) {
134 Cs = str;
135 Cb = bp;
136 do {
137 if (!*Cs)
138 return(YES);
139 } while (*Cb++ == *Cs++);
140 }
141 return(NO);
142}
143
144static
145w_match(bp, str)
146 register char *bp, *str;
147{
148 register char test, *Cs, *Cb;
149
150 if (!*str || !*bp)
151 return(NO);
152 for (test = *str++; *bp;)
153 if (test == *bp++) {
154 for (Cs = str, Cb = bp; *Cs == *Cb; ++Cs, ++Cb);
155 if (!*Cs && (isspace(*Cb) || *Cb == '(' || *Cb == ','))
156 return(YES);
157 }
158 return(NO);
159}
160
161static
162lowstr(from, to)
163 register char *from, *to;
164{
165 for (; *from; ++from, ++to)
166 *to = isupper(*from) ? tolower(*from) : *from;
167 *to = '\0';
168}
169
170static
171usage()
172{
173 fprintf(stderr, "usage: %s [-M path] string ...\n", myname);
174 exit(1);
175}
176