adding GNU dc ("desk calculator")
[unix-history] / usr.bin / man / apropos / apropos.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1987 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35char copyright[] =
36"@(#) Copyright (c) 1987 Regents of the University of California.\n\
37 All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)apropos.c 5.12 (Berkeley) 6/1/90";
42#endif /* not lint */
43
44#include <sys/param.h>
45#include <stdio.h>
46#include <ctype.h>
47#include <string.h>
48#include <stdlib.h>
49#include "../man/pathnames.h"
50
51#define MAXLINELEN 256 /* max line handled */
52
53char *progname;
54
55static int *found, foundman;
56
57main(argc, argv)
58 int argc;
59 char **argv;
60{
61 extern char *optarg;
62 extern int optind;
63 register char **p;
64 int ch;
65 char *p_augment, *p_path, **getdb();
66
67 progname = "apropos";
68 p_augment = p_path = NULL;
69 while ((ch = getopt(argc, argv, "M:m:P:")) != EOF)
70 switch((char)ch) {
71 case 'M':
72 case 'P': /* backward compatible */
73 p_path = optarg;
74 break;
75 case 'm':
76 p_augment = optarg;
77 break;
78 case '?':
79 default:
80 usage();
81 }
82 argv += optind;
83 argc -= optind;
84
85 if (argc < 1)
86 usage();
87
88 /*NOSTRICT*/
89 if (!(found = (int *)malloc((u_int)argc)))
90 enomem();
91 bzero((void *)found, argc * sizeof(int));
92
93 for (p = argv; *p; ++p) /* convert to lower-case */
94 lowstr(*p, *p);
95
96 if (p_augment)
97 apropos(argv, p_augment, 1);
98 if (p_path || (p_path = getenv("MANPATH")))
99 apropos(argv, p_path, 1);
100 else
101 for (p = getdb(); *p; ++p)
102 apropos(argv, *p, 0);
103
104 if (!foundman) {
105 (void)fprintf(stderr,
106 "apropos: : no %s file found.\n", _PATH_WHATIS);
107 exit(1);
108 }
109 for (p = argv; *p; ++p)
110 if (!found[p - argv])
111 (void)printf("%s: nothing appropriate\n", *p);
112}
113
114apropos(argv, path, buildpath)
115 char **argv, *path;
116 int buildpath;
117{
118 register char *end, *name, **p;
119 char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
120
121 for (name = path; name; name = end) { /* through name list */
122 if (end = index(name, ':'))
123 *end++ = '\0';
124
125 if (buildpath) {
126 char hold[MAXPATHLEN + 1];
127
128 (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
129 name = hold;
130 }
131
132 if (!freopen(name, "r", stdin))
133 continue;
134
135 foundman = 1;
136
137 /* for each file found */
138 while (fgets(buf, sizeof(buf), stdin)) {
139 if (!index(buf, '\n')) {
140 (void)fprintf(stderr,
141 "apropos: %s line too long.\n", name);
142 exit(1);
143 }
144 lowstr(buf, wbuf);
145 for (p = argv; *p; ++p)
146 if (match(wbuf, *p)) {
147 (void)printf("%s", buf);
148 found[p - argv] = 1;
149
150 /* only print line once */
151 while (*++p)
152 if (match(wbuf, *p))
153 found[p - argv] = 1;
154 break;
155 }
156 }
157 }
158}
159
160/*
161 * match --
162 * match anywhere the string appears
163 */
164match(bp, str)
165 register char *bp, *str;
166{
167 register int len;
168 register char test;
169
170 if (!*bp)
171 return(0);
172 /* backward compatible: everything matches empty string */
173 if (!*str)
174 return(1);
175 for (test = *str++, len = strlen(str); *bp;)
176 if (test == *bp++ && !strncmp(bp, str, len))
177 return(1);
178 return(0);
179}
180
181/*
182 * lowstr --
183 * convert a string to lower case
184 */
185lowstr(from, to)
186 register char *from, *to;
187{
188 register char ch;
189
190 while ((ch = *from++) && ch != '\n')
191 *to++ = isupper(ch) ? tolower(ch) : ch;
192 *to = '\0';
193}
194
195/*
196 * usage --
197 * print usage message and die
198 */
199usage()
200{
201 (void)fprintf(stderr,
202 "usage: apropos [-M path] [-m path] keyword ...\n");
203 exit(1);
204}