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