xref: /netbsd-src/usr.bin/whereis/whereis.c (revision ce63d6c20fc4ec8ddc95c84bb229e3c4ecf82b69)
1 /*-
2  * Copyright (c) 1980 The 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
35 char copyright[] =
36 "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
37  All rights reserved.\n";
38 #endif /* not lint */
39 
40 #ifndef lint
41 static char sccsid[] = "@(#)whereis.c	5.5 (Berkeley) 4/18/91";
42 #endif /* not lint */
43 
44 #include <sys/param.h>
45 #include <sys/dir.h>
46 #include <stdio.h>
47 #include <ctype.h>
48 
49 static char *bindirs[] = {
50 	"/bin",
51 	"/sbin",
52 	"/usr/ucb",
53 	"/usr/bin",
54 	"/usr/sbin",
55 	"/usr/old",
56 	"/usr/contrib",
57 	"/usr/games",
58 	"/usr/local",
59 	"/usr/libexec",
60 	"/usr/include",
61 	"/usr/hosts",
62 	"/usr/share", /*?*/
63 	"/etc",
64 #ifdef notdef
65 	/* before reorg */
66 	"/etc",
67 	"/bin",
68 	"/usr/bin",
69 	"/usr/games",
70 	"/lib",
71 	"/usr/ucb",
72 	"/usr/lib",
73 	"/usr/local",
74 	"/usr/new",
75 	"/usr/old",
76 	"/usr/hosts",
77 	"/usr/include",
78 #endif
79 	0
80 };
81 /* This needs to be redone - man pages live with sources */
82 static char *mandirs[] = {
83 	"/usr/man/man1",
84 	"/usr/man/man2",
85 	"/usr/man/man3",
86 	"/usr/man/man4",
87 	"/usr/man/man5",
88 	"/usr/man/man6",
89 	"/usr/man/man7",
90 	"/usr/man/man8",
91 	"/usr/man/manl",
92 	"/usr/man/mann",
93 	"/usr/man/mano",
94 	0
95 };
96 static char *srcdirs[]  = {
97 	"/usr/src/bin",
98 	"/usr/src/sbin",
99 	"/usr/src/etc",
100 	"/usr/src/pgrm",
101 	"/usr/src/usr.bin",
102 	"/usr/src/usr.sbin",
103 	"/usr/src/usr.ucb",
104 	"/usr/src/usr.new",
105 	"/usr/src/usr.lib",
106 	"/usr/src/libexec",
107 	"/usr/src/libdata",
108 	"/usr/src/share",
109 	"/usr/src/contrib",
110 	"/usr/src/athena",
111 	"/usr/src/devel",
112 	"/usr/src/games",
113 	"/usr/src/local",
114 	"/usr/src/man",
115 	"/usr/src/root",
116 	"/usr/src/old",
117 	"/usr/src/include",
118 	/* still need libs */
119 #ifdef notdef /* before reorg */
120 	"/usr/src/bin",
121 	"/usr/src/usr.bin",
122 	"/usr/src/etc",
123 	"/usr/src/ucb",
124 	"/usr/src/games",
125 	"/usr/src/usr.lib",
126 	"/usr/src/lib",
127 	"/usr/src/local",
128 	"/usr/src/new",
129 	"/usr/src/old",
130 	"/usr/src/include",
131 	"/usr/src/lib/libc/gen",
132 	"/usr/src/lib/libc/stdio",
133 	"/usr/src/lib/libc/sys",
134 	"/usr/src/lib/libc/net/common",
135 	"/usr/src/lib/libc/net/inet",
136 	"/usr/src/lib/libc/net/misc",
137 	"/usr/src/ucb/pascal",
138 	"/usr/src/ucb/pascal/utilities",
139 	"/usr/src/undoc",
140 #endif
141 	0
142 };
143 
144 char	sflag = 1;
145 char	bflag = 1;
146 char	mflag = 1;
147 char	**Sflag;
148 int	Scnt;
149 char	**Bflag;
150 int	Bcnt;
151 char	**Mflag;
152 int	Mcnt;
153 char	uflag;
154 /*
155  * whereis name
156  * look for source, documentation and binaries
157  */
158 main(argc, argv)
159 	int argc;
160 	char *argv[];
161 {
162 
163 	argc--, argv++;
164 	if (argc == 0) {
165 usage:
166 		fprintf(stderr, "whereis [ -sbmu ] [ -SBM dir ... -f ] name...\n");
167 		exit(1);
168 	}
169 	do
170 		if (argv[0][0] == '-') {
171 			register char *cp = argv[0] + 1;
172 			while (*cp) switch (*cp++) {
173 
174 			case 'f':
175 				break;
176 
177 			case 'S':
178 				getlist(&argc, &argv, &Sflag, &Scnt);
179 				break;
180 
181 			case 'B':
182 				getlist(&argc, &argv, &Bflag, &Bcnt);
183 				break;
184 
185 			case 'M':
186 				getlist(&argc, &argv, &Mflag, &Mcnt);
187 				break;
188 
189 			case 's':
190 				zerof();
191 				sflag++;
192 				continue;
193 
194 			case 'u':
195 				uflag++;
196 				continue;
197 
198 			case 'b':
199 				zerof();
200 				bflag++;
201 				continue;
202 
203 			case 'm':
204 				zerof();
205 				mflag++;
206 				continue;
207 
208 			default:
209 				goto usage;
210 			}
211 			argv++;
212 		} else
213 			lookup(*argv++);
214 	while (--argc > 0);
215 	exit(0);
216 }
217 
218 getlist(argcp, argvp, flagp, cntp)
219 	char ***argvp;
220 	int *argcp;
221 	char ***flagp;
222 	int *cntp;
223 {
224 
225 	(*argvp)++;
226 	*flagp = *argvp;
227 	*cntp = 0;
228 	for ((*argcp)--; *argcp > 0 && (*argvp)[0][0] != '-'; (*argcp)--)
229 		(*cntp)++, (*argvp)++;
230 	(*argcp)++;
231 	(*argvp)--;
232 }
233 
234 
235 zerof()
236 {
237 
238 	if (sflag && bflag && mflag)
239 		sflag = bflag = mflag = 0;
240 }
241 int	count;
242 int	print;
243 
244 
245 lookup(cp)
246 	register char *cp;
247 {
248 	register char *dp;
249 
250 	for (dp = cp; *dp; dp++)
251 		continue;
252 	for (; dp > cp; dp--) {
253 		if (*dp == '.') {
254 			*dp = 0;
255 			break;
256 		}
257 	}
258 	for (dp = cp; *dp; dp++)
259 		if (*dp == '/')
260 			cp = dp + 1;
261 	if (uflag) {
262 		print = 0;
263 		count = 0;
264 	} else
265 		print = 1;
266 again:
267 	if (print)
268 		printf("%s:", cp);
269 	if (sflag) {
270 		looksrc(cp);
271 		if (uflag && print == 0 && count != 1) {
272 			print = 1;
273 			goto again;
274 		}
275 	}
276 	count = 0;
277 	if (bflag) {
278 		lookbin(cp);
279 		if (uflag && print == 0 && count != 1) {
280 			print = 1;
281 			goto again;
282 		}
283 	}
284 	count = 0;
285 	if (mflag) {
286 		lookman(cp);
287 		if (uflag && print == 0 && count != 1) {
288 			print = 1;
289 			goto again;
290 		}
291 	}
292 	if (print)
293 		printf("\n");
294 }
295 
296 looksrc(cp)
297 	char *cp;
298 {
299 	if (Sflag == 0) {
300 		find(srcdirs, cp);
301 	} else
302 		findv(Sflag, Scnt, cp);
303 }
304 
305 lookbin(cp)
306 	char *cp;
307 {
308 	if (Bflag == 0)
309 		find(bindirs, cp);
310 	else
311 		findv(Bflag, Bcnt, cp);
312 }
313 
314 lookman(cp)
315 	char *cp;
316 {
317 	if (Mflag == 0) {
318 		find(mandirs, cp);
319 	} else
320 		findv(Mflag, Mcnt, cp);
321 }
322 
323 findv(dirv, dirc, cp)
324 	char **dirv;
325 	int dirc;
326 	char *cp;
327 {
328 
329 	while (dirc > 0)
330 		findin(*dirv++, cp), dirc--;
331 }
332 
333 find(dirs, cp)
334 	char **dirs;
335 	char *cp;
336 {
337 
338 	while (*dirs)
339 		findin(*dirs++, cp);
340 }
341 
342 findin(dir, cp)
343 	char *dir, *cp;
344 {
345 	DIR *dirp;
346 	struct direct *dp;
347 
348 	dirp = opendir(dir);
349 	if (dirp == NULL)
350 		return;
351 	while ((dp = readdir(dirp)) != NULL) {
352 		if (itsit(cp, dp->d_name)) {
353 			count++;
354 			if (print)
355 				printf(" %s/%s", dir, dp->d_name);
356 		}
357 	}
358 	closedir(dirp);
359 }
360 
361 itsit(cp, dp)
362 	register char *cp, *dp;
363 {
364 	register int i = strlen(dp);
365 
366 	if (dp[0] == 's' && dp[1] == '.' && itsit(cp, dp+2))
367 		return (1);
368 	while (*cp && *dp && *cp == *dp)
369 		cp++, dp++, i--;
370 	if (*cp == 0 && *dp == 0)
371 		return (1);
372 	while (isdigit(*dp))
373 		dp++;
374 	if (*cp == 0 && *dp++ == '.') {
375 		--i;
376 		while (i > 0 && *dp)
377 			if (--i, *dp++ == '.')
378 				return (*dp++ == 'C' && *dp++ == 0);
379 		return (1);
380 	}
381 	return (0);
382 }
383