xref: /netbsd-src/usr.bin/whereis/whereis.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
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/gnu/usr.bin",
103 	"/usr/src/usr.sbin",
104 	"/usr/src/usr.ucb",
105 	"/usr/src/usr.new",
106 	"/usr/src/lib",
107 	"/usr/src/gnu/lib",
108 	"/usr/src/libexec",
109 	"/usr/src/gnu/libexec",
110 	"/usr/src/libdata",
111 	"/usr/src/share",
112 	"/usr/src/contrib",
113 	"/usr/src/athena",
114 	"/usr/src/devel",
115 	"/usr/src/games",
116 	"/usr/src/gnu/games",
117 	"/usr/src/local",
118 	"/usr/src/man",
119 	"/usr/src/root",
120 	"/usr/src/old",
121 	"/usr/src/include",
122 	/* still need libs */
123 #ifdef notdef /* before reorg */
124 	"/usr/src/bin",
125 	"/usr/src/usr.bin",
126 	"/usr/src/etc",
127 	"/usr/src/ucb",
128 	"/usr/src/games",
129 	"/usr/src/usr.lib",
130 	"/usr/src/lib",
131 	"/usr/src/local",
132 	"/usr/src/new",
133 	"/usr/src/old",
134 	"/usr/src/include",
135 	"/usr/src/lib/libc/gen",
136 	"/usr/src/lib/libc/stdio",
137 	"/usr/src/lib/libc/sys",
138 	"/usr/src/lib/libc/net/common",
139 	"/usr/src/lib/libc/net/inet",
140 	"/usr/src/lib/libc/net/misc",
141 	"/usr/src/ucb/pascal",
142 	"/usr/src/ucb/pascal/utilities",
143 	"/usr/src/undoc",
144 #endif
145 	0
146 };
147 
148 char	sflag = 1;
149 char	bflag = 1;
150 char	mflag = 1;
151 char	**Sflag;
152 int	Scnt;
153 char	**Bflag;
154 int	Bcnt;
155 char	**Mflag;
156 int	Mcnt;
157 char	uflag;
158 /*
159  * whereis name
160  * look for source, documentation and binaries
161  */
162 main(argc, argv)
163 	int argc;
164 	char *argv[];
165 {
166 
167 	argc--, argv++;
168 	if (argc == 0) {
169 usage:
170 		fprintf(stderr, "whereis [ -sbmu ] [ -SBM dir ... -f ] name...\n");
171 		exit(1);
172 	}
173 	do
174 		if (argv[0][0] == '-') {
175 			register char *cp = argv[0] + 1;
176 			while (*cp) switch (*cp++) {
177 
178 			case 'f':
179 				break;
180 
181 			case 'S':
182 				getlist(&argc, &argv, &Sflag, &Scnt);
183 				break;
184 
185 			case 'B':
186 				getlist(&argc, &argv, &Bflag, &Bcnt);
187 				break;
188 
189 			case 'M':
190 				getlist(&argc, &argv, &Mflag, &Mcnt);
191 				break;
192 
193 			case 's':
194 				zerof();
195 				sflag++;
196 				continue;
197 
198 			case 'u':
199 				uflag++;
200 				continue;
201 
202 			case 'b':
203 				zerof();
204 				bflag++;
205 				continue;
206 
207 			case 'm':
208 				zerof();
209 				mflag++;
210 				continue;
211 
212 			default:
213 				goto usage;
214 			}
215 			argv++;
216 		} else
217 			lookup(*argv++);
218 	while (--argc > 0);
219 	exit(0);
220 }
221 
222 getlist(argcp, argvp, flagp, cntp)
223 	char ***argvp;
224 	int *argcp;
225 	char ***flagp;
226 	int *cntp;
227 {
228 
229 	(*argvp)++;
230 	*flagp = *argvp;
231 	*cntp = 0;
232 	for ((*argcp)--; *argcp > 0 && (*argvp)[0][0] != '-'; (*argcp)--)
233 		(*cntp)++, (*argvp)++;
234 	(*argcp)++;
235 	(*argvp)--;
236 }
237 
238 
239 zerof()
240 {
241 
242 	if (sflag && bflag && mflag)
243 		sflag = bflag = mflag = 0;
244 }
245 int	count;
246 int	print;
247 
248 
249 lookup(cp)
250 	register char *cp;
251 {
252 	register char *dp;
253 
254 	for (dp = cp; *dp; dp++)
255 		continue;
256 	for (; dp > cp; dp--) {
257 		if (*dp == '.') {
258 			*dp = 0;
259 			break;
260 		}
261 	}
262 	for (dp = cp; *dp; dp++)
263 		if (*dp == '/')
264 			cp = dp + 1;
265 	if (uflag) {
266 		print = 0;
267 		count = 0;
268 	} else
269 		print = 1;
270 again:
271 	if (print)
272 		printf("%s:", cp);
273 	if (sflag) {
274 		looksrc(cp);
275 		if (uflag && print == 0 && count != 1) {
276 			print = 1;
277 			goto again;
278 		}
279 	}
280 	count = 0;
281 	if (bflag) {
282 		lookbin(cp);
283 		if (uflag && print == 0 && count != 1) {
284 			print = 1;
285 			goto again;
286 		}
287 	}
288 	count = 0;
289 	if (mflag) {
290 		lookman(cp);
291 		if (uflag && print == 0 && count != 1) {
292 			print = 1;
293 			goto again;
294 		}
295 	}
296 	if (print)
297 		printf("\n");
298 }
299 
300 looksrc(cp)
301 	char *cp;
302 {
303 	if (Sflag == 0) {
304 		find(srcdirs, cp);
305 	} else
306 		findv(Sflag, Scnt, cp);
307 }
308 
309 lookbin(cp)
310 	char *cp;
311 {
312 	if (Bflag == 0)
313 		find(bindirs, cp);
314 	else
315 		findv(Bflag, Bcnt, cp);
316 }
317 
318 lookman(cp)
319 	char *cp;
320 {
321 	if (Mflag == 0) {
322 		find(mandirs, cp);
323 	} else
324 		findv(Mflag, Mcnt, cp);
325 }
326 
327 findv(dirv, dirc, cp)
328 	char **dirv;
329 	int dirc;
330 	char *cp;
331 {
332 
333 	while (dirc > 0)
334 		findin(*dirv++, cp), dirc--;
335 }
336 
337 find(dirs, cp)
338 	char **dirs;
339 	char *cp;
340 {
341 
342 	while (*dirs)
343 		findin(*dirs++, cp);
344 }
345 
346 findin(dir, cp)
347 	char *dir, *cp;
348 {
349 	DIR *dirp;
350 	struct direct *dp;
351 
352 	dirp = opendir(dir);
353 	if (dirp == NULL)
354 		return;
355 	while ((dp = readdir(dirp)) != NULL) {
356 		if (itsit(cp, dp->d_name)) {
357 			count++;
358 			if (print)
359 				printf(" %s/%s", dir, dp->d_name);
360 		}
361 	}
362 	closedir(dirp);
363 }
364 
365 itsit(cp, dp)
366 	register char *cp, *dp;
367 {
368 	register int i = strlen(dp);
369 
370 	if (dp[0] == 's' && dp[1] == '.' && itsit(cp, dp+2))
371 		return (1);
372 	while (*cp && *dp && *cp == *dp)
373 		cp++, dp++, i--;
374 	if (*cp == 0 && *dp == 0)
375 		return (1);
376 	while (isdigit(*dp))
377 		dp++;
378 	if (*cp == 0 && *dp++ == '.') {
379 		--i;
380 		while (i > 0 && *dp)
381 			if (--i, *dp++ == '.')
382 				return (*dp++ == 'C' && *dp++ == 0);
383 		return (1);
384 	}
385 	return (0);
386 }
387