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