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