]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/whereis.c
Imported from util-linux-2.9v tarball.
[thirdparty/util-linux.git] / misc-utils / whereis.c
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 /* *:aeb */
35
36 /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
37 * - added Native Language Support
38 */
39
40 #include <sys/param.h>
41 #include <sys/dir.h>
42 #include <sys/stat.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include "nls.h"
47
48 void zerof(void);
49 void getlist(int *, char ***, char ***, int *);
50 void lookup(char *);
51 void looksrc(char *);
52 void lookbin(char *);
53 void lookman(char *);
54 void findv(char **, int, char *);
55 void find(char **, char *);
56 void findin(char *, char *);
57 int itsit(char *, char *);
58
59 static char *bindirs[] = {
60 "/bin",
61 "/usr/bin",
62 "/sbin",
63 "/usr/sbin",
64 "/etc",
65 "/usr/etc",
66 "/lib",
67 "/usr/lib",
68 "/usr/games",
69 "/usr/games/bin",
70 "/usr/games/lib",
71 "/usr/emacs/etc",
72 "/usr/lib/emacs/*/etc",
73 "/usr/TeX/bin",
74 "/usr/tex/bin",
75 "/usr/interviews/bin/LINUX",
76
77 "/usr/X11R6/bin",
78 "/usr/X386/bin",
79 "/usr/bin/X11",
80 "/usr/X11/bin",
81 "/usr/X11R5/bin",
82
83 "/usr/local/bin",
84 "/usr/local/sbin",
85 "/usr/local/etc",
86 "/usr/local/lib",
87 "/usr/local/games",
88 "/usr/local/games/bin",
89 "/usr/local/emacs/etc",
90 "/usr/local/TeX/bin",
91 "/usr/local/tex/bin",
92 "/usr/local/bin/X11",
93
94 "/usr/contrib",
95 "/usr/hosts",
96 "/usr/include",
97
98 "/usr/g++-include",
99
100 "/usr/ucb",
101 "/usr/old",
102 "/usr/new",
103 "/usr/local",
104 "/usr/libexec",
105 "/usr/share",
106
107 "/opt/*/bin",
108
109 0
110 };
111
112 static char *mandirs[] = {
113 "/usr/man/*",
114 "/usr/X386/man/*",
115 "/usr/X11/man/*",
116 "/usr/TeX/man/*",
117 "/usr/interviews/man/mann",
118 0
119 };
120
121 static char *srcdirs[] = {
122 "/usr/src/*",
123 "/usr/src/lib/libc/*",
124 "/usr/src/lib/libc/net/*",
125 "/usr/src/ucb/pascal",
126 "/usr/src/ucb/pascal/utilities",
127 "/usr/src/undoc",
128 0
129 };
130
131 char sflag = 1;
132 char bflag = 1;
133 char mflag = 1;
134 char **Sflag;
135 int Scnt;
136 char **Bflag;
137 int Bcnt;
138 char **Mflag;
139 int Mcnt;
140 char uflag;
141 /*
142 * whereis name
143 * look for source, documentation and binaries
144 */
145 int
146 main(argc, argv)
147 int argc;
148 char *argv[];
149 {
150 setlocale(LC_ALL, "");
151 bindtextdomain(PACKAGE, LOCALEDIR);
152 textdomain(PACKAGE);
153
154
155 argc--, argv++;
156 if (argc == 0) {
157 usage:
158 fprintf(stderr, _("whereis [ -sbmu ] [ -SBM dir ... -f ] name...\n"));
159 exit(1);
160 }
161 do
162 if (argv[0][0] == '-') {
163 register char *cp = argv[0] + 1;
164 while (*cp) switch (*cp++) {
165
166 case 'f':
167 break;
168
169 case 'S':
170 getlist(&argc, &argv, &Sflag, &Scnt);
171 break;
172
173 case 'B':
174 getlist(&argc, &argv, &Bflag, &Bcnt);
175 break;
176
177 case 'M':
178 getlist(&argc, &argv, &Mflag, &Mcnt);
179 break;
180
181 case 's':
182 zerof();
183 sflag++;
184 continue;
185
186 case 'u':
187 uflag++;
188 continue;
189
190 case 'b':
191 zerof();
192 bflag++;
193 continue;
194
195 case 'm':
196 zerof();
197 mflag++;
198 continue;
199
200 default:
201 goto usage;
202 }
203 argv++;
204 } else
205 lookup(*argv++);
206 while (--argc > 0);
207 return 0;
208 }
209
210 void
211 getlist(int *argcp, char ***argvp, char ***flagp, int *cntp) {
212 (*argvp)++;
213 *flagp = *argvp;
214 *cntp = 0;
215 for ((*argcp)--; *argcp > 0 && (*argvp)[0][0] != '-'; (*argcp)--)
216 (*cntp)++, (*argvp)++;
217 (*argcp)++;
218 (*argvp)--;
219 }
220
221
222 void
223 zerof()
224 {
225 if (sflag && bflag && mflag)
226 sflag = bflag = mflag = 0;
227 }
228
229 int count;
230 int print;
231
232 void
233 lookup(char *cp) {
234 register char *dp;
235
236 for (dp = cp; *dp; dp++)
237 continue;
238 for (; dp > cp; dp--) {
239 if (*dp == '.') {
240 *dp = 0;
241 break;
242 }
243 }
244 for (dp = cp; *dp; dp++)
245 if (*dp == '/')
246 cp = dp + 1;
247 if (uflag) {
248 print = 0;
249 count = 0;
250 } else
251 print = 1;
252 again:
253 if (print)
254 printf("%s:", cp);
255 if (sflag) {
256 looksrc(cp);
257 if (uflag && print == 0 && count != 1) {
258 print = 1;
259 goto again;
260 }
261 }
262 count = 0;
263 if (bflag) {
264 lookbin(cp);
265 if (uflag && print == 0 && count != 1) {
266 print = 1;
267 goto again;
268 }
269 }
270 count = 0;
271 if (mflag) {
272 lookman(cp);
273 if (uflag && print == 0 && count != 1) {
274 print = 1;
275 goto again;
276 }
277 }
278 if (print)
279 printf("\n");
280 }
281
282 void
283 looksrc(char *cp) {
284 if (Sflag == 0) {
285 find(srcdirs, cp);
286 } else
287 findv(Sflag, Scnt, cp);
288 }
289
290 void
291 lookbin(char *cp) {
292 if (Bflag == 0)
293 find(bindirs, cp);
294 else
295 findv(Bflag, Bcnt, cp);
296 }
297
298 void
299 lookman(char *cp) {
300 if (Mflag == 0) {
301 find(mandirs, cp);
302 } else
303 findv(Mflag, Mcnt, cp);
304 }
305
306 void
307 findv(char **dirv, int dirc, char *cp) {
308 while (dirc > 0)
309 findin(*dirv++, cp), dirc--;
310 }
311
312 void
313 find(char **dirs, char *cp) {
314 while (*dirs)
315 findin(*dirs++, cp);
316 }
317
318 void
319 findin(char *dir, char *cp) {
320 DIR *dirp;
321 struct direct *dp;
322 char *d, *dd;
323 int l;
324 char dirbuf[1024];
325 struct stat statbuf;
326
327 dd = index(dir, '*');
328 if (!dd)
329 goto noglob;
330
331 l = strlen(dir);
332 if (l < sizeof(dirbuf)) { /* refuse excessively long names */
333 strcpy (dirbuf, dir);
334 d = index(dirbuf, '*');
335 *d = 0;
336 dirp = opendir(dirbuf);
337 if (dirp == NULL)
338 return;
339 while ((dp = readdir(dirp)) != NULL) {
340 if (!strcmp(dp->d_name, ".") ||
341 !strcmp(dp->d_name, ".."))
342 continue;
343 if (strlen(dp->d_name) + l > sizeof(dirbuf))
344 continue;
345 sprintf(d, "%s", dp->d_name);
346 if (stat(dirbuf, &statbuf))
347 continue;
348 if (!S_ISDIR(statbuf.st_mode))
349 continue;
350 strcat(d, dd+1);
351 findin(dirbuf, cp);
352 }
353 closedir(dirp);
354 }
355 return;
356
357 noglob:
358 dirp = opendir(dir);
359 if (dirp == NULL)
360 return;
361 while ((dp = readdir(dirp)) != NULL) {
362 if (itsit(cp, dp->d_name)) {
363 count++;
364 if (print)
365 printf(" %s/%s", dir, dp->d_name);
366 }
367 }
368 closedir(dirp);
369 }
370
371 int
372 itsit(char *cp, char *dp) {
373 int i = strlen(dp);
374
375 if (dp[0] == 's' && dp[1] == '.' && itsit(cp, dp+2))
376 return (1);
377 if (!strcmp(dp+i-2, ".Z"))
378 i -= 2;
379 else if (!strcmp(dp+i-3, ".gz"))
380 i -= 3;
381 else if (!strcmp(dp+i-4, ".bz2"))
382 i -= 4;
383 while (*cp && *dp && *cp == *dp)
384 cp++, dp++, i--;
385 if (*cp == 0 && *dp == 0)
386 return (1);
387 while (isdigit(*dp))
388 dp++;
389 if (*cp == 0 && *dp++ == '.') {
390 --i;
391 while (i > 0 && *dp)
392 if (--i, *dp++ == '.')
393 return (*dp++ == 'C' && *dp++ == 0);
394 return (1);
395 }
396 return (0);
397 }