|
|
1.1 root 1: /*
2: * Copyright (c) 1987 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)apropos.c 5.6 (Berkeley) 6/29/88";
26: #endif /* not lint */
27:
28: #include <sys/param.h>
29: #include <stdio.h>
30: #include <ctype.h>
31: #include <strings.h>
32:
33: #define DEF_PATH "/usr/man:/usr/new/man:/usr/local/man"
34: #define MAXLINELEN 1000 /* max line handled */
35: #define WHATIS "whatis" /* database name */
36:
37: #define NO 0 /* no/false */
38: #define YES 1 /* yes/true */
39:
40: static char *myname;
41:
42: main(argc, argv)
43: int argc;
44: char **argv;
45: {
46: extern char *optarg;
47: extern int optind;
48: register char *beg, *end, **C;
49: int ch, foundman = NO, *found, isapropos;
50: int a_match(), w_match(), (*match)();
51: char *manpath = NULL, buf[MAXLINELEN + 1], fname[MAXPATHLEN + 1];
52: char wbuf[MAXLINELEN + 1], *getenv(), *malloc();
53:
54: myname = (beg = rindex(*argv, '/')) ? beg + 1 : *argv;
55: if (!strcmp(myname, "apropos")) {
56: isapropos = YES;
57: match = a_match;
58: }
59: else {
60: isapropos = NO;
61: match = w_match;
62: }
63: while ((ch = getopt(argc, argv, "M:P:")) != EOF)
64: switch((char)ch) {
65: case 'M':
66: case 'P': /* backward contemptible */
67: manpath = optarg;
68: break;
69: case '?':
70: default:
71: usage();
72: }
73: argv += optind;
74: argc -= optind;
75: if (argc < 1)
76: usage();
77:
78: if (!(manpath = getenv("MANPATH")))
79: manpath = DEF_PATH;
80:
81: /*NOSTRICT*/
82: if (!(found = (int *)malloc((u_int)argc))) {
83: fprintf(stderr, "%s: out of space.\n", myname);
84: exit(1);
85: }
86: bzero((char *)found, argc * sizeof(int));
87:
88: if (isapropos)
89: for (C = argv; *C; ++C) /* convert to lower-case */
90: lowstr(*C, *C);
91: else for (C = argv; *C; ++C) /* trim full paths */
92: if (beg = rindex(*C, '/'))
93: *C = beg + 1;
94:
95: for (beg = manpath; beg; beg = end) { /* through path list */
96: end = index(beg, ':');
97: if (!end)
98: (void)sprintf(fname, "%s/%s", beg, WHATIS);
99: else {
100: (void)sprintf(fname, "%.*s/%s", end - beg, beg, WHATIS);
101: ++end;
102: }
103: if (!freopen(fname, "r", stdin))
104: continue;
105:
106: /* for each file found */
107: for (foundman = YES; gets(buf);) {
108: if (isapropos)
109: lowstr(buf, wbuf);
110: else
111: dashtrunc(buf, wbuf);
112: for (C = argv; *C; ++C)
113: if ((*match)(wbuf, *C)) {
114: puts(buf);
115: found[C - argv] = YES;
116:
117: /* only print line once */
118: while (*++C)
119: if ((*match)(wbuf, *C))
120: found[C - argv] = YES;
121: break;
122: }
123: }
124: }
125: if (!foundman) {
126: fprintf(stderr, "%s: no %s file found in %s.\n", myname, WHATIS, manpath);
127: exit(1);
128: }
129: for (C = argv; *C; ++C)
130: if (!found[C - argv])
131: printf("%s: %s\n", *C, isapropos ? "nothing appropriate" : "not found");
132: }
133:
134: /*
135: * a_match --
136: * match for apropos; anywhere the string appears
137: */
138: static
139: a_match(bp, str)
140: register char *bp, *str;
141: {
142: register int len;
143: register char test;
144:
145: if (!*bp)
146: return(NO);
147: /* backward compatible: everything matches empty string */
148: if (!*str)
149: return(YES);
150: for (test = *str++, len = strlen(str); *bp;)
151: if (test == *bp++ && !strncmp(bp, str, len))
152: return(YES);
153: return(NO);
154: }
155:
156: /*
157: * w_match --
158: * match for whatis; looks for full word match
159: */
160: static
161: w_match(bp, str)
162: register char *bp, *str;
163: {
164: register int len;
165: register char *start;
166:
167: if (!*str || !*bp)
168: return(NO);
169: for (len = strlen(str);;) {
170: for (; *bp && !isdigit(*bp) && !isalpha(*bp); ++bp);
171: if (!*bp)
172: break;
173: for (start = bp++; *bp && (isdigit(*bp) || isalpha(*bp)); ++bp);
174: if (bp - start == len && !strncasecmp(start, str, len))
175: return(YES);
176: }
177: return(NO);
178: }
179:
180: /*
181: * dashtrunc --
182: * truncate a string at " - "
183: */
184: static
185: dashtrunc(from, to)
186: register char *from, *to;
187: {
188: do {
189: if (from[0] == ' ' && from[1] == '-' && from[2] == ' ')
190: break;
191: } while (*to++ = *from++);
192: *to = '\0';
193: }
194:
195: /*
196: * lowstr --
197: * convert a string to lower case
198: */
199: static
200: lowstr(from, to)
201: register char *from, *to;
202: {
203: do {
204: *to++ = isupper(*from) ? tolower(*from) : *from;
205: } while (*from++);
206: }
207:
208: /*
209: * usage --
210: * print usage message and die
211: */
212: static
213: usage()
214: {
215: fprintf(stderr, "usage: %s [-M path] string ...\n", myname);
216: exit(1);
217: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.