BSD 4 development
[unix-history] / usr / src / cmd / man / man.c
CommitLineData
15a247ae
BJ
1#include <stdio.h>
2#include <ctype.h>
3#include <sgtty.h>
4#include <sys/types.h>
5#include <stat.h>
6#include <signal.h>
7/*
8 * man
9 */
10int nomore;
11int cflag;
12char *strcpy();
13char *strcat();
14char *trim();
15int remove();
16int section;
17int subsec;
18int troffit;
19int killtmp;
20
21#define eq(a,b) (strcmp(a,b) == 0)
22
23main(argc, argv)
24 int argc;
25 char *argv[];
26{
27
28 if (signal(SIGINT, SIG_IGN) == SIG_DFL) {
29 signal(SIGINT, remove);
30 signal(SIGQUIT, remove);
31 signal(SIGTERM, remove);
32 }
33 umask(0);
34 if (argc <= 1) {
35 fprintf(stderr, "Usage: man [ section ] name ...\n");
36 fprintf(stderr, "or: man -k keyword ...\n");
37 fprintf(stderr, "or: man -f file ...\n");
38 exit(1);
39 }
40 if (chdir("/usr/man") < 0) {
41 fprintf(stderr, "Can't chdir to /usr/man.\n");
42 exit(1);
43 }
44 argc--, argv++;
45 while (argc > 0 && argv[0][0] == '-') {
46 switch(argv[0][1]) {
47
48 case 0:
49 nomore++;
50 break;
51
52 case 't':
53 troffit++;
54 break;
55
56 case 'k':
57 apropos(argc-1, argv+1);
58 exit(0);
59
60 case 'f':
61 whatis(argc-1, argv+1);
62 exit(0);
63 }
64 argc--, argv++;
65 }
66 if (troffit == 0 && nomore == 0 && !isatty(1))
67 nomore++;
68 section = 0;
69 do {
70 if (eq(argv[0], "local")) {
71 section = 'l';
72 goto sectin;
73 } else if (eq(argv[0], "new")) {
74 section = 'n';
75 goto sectin;
76 } else if (eq(argv[0], "public")) {
77 section = 'p';
78 goto sectin;
79 } else if (argv[0][0] >= '0' && argv[0][0] <= '9' && (argv[0][1] == 0 || argv[0][2] == 0)) {
80 section = argv[0][0];
81 subsec = argv[0][1];
82sectin:
83 argc--, argv++;
84 if (argc == 0) {
85 fprintf(stderr, "But what do you want from section %s?\n", argv[-1]);
86 exit(1);
87 }
88 continue;
89 }
90 manual(section, argv[0]);
91 argc--, argv++;
92 } while (argc > 0);
93 exit(0);
94}
95
96manual(sec, name)
97 char sec;
98 char *name;
99{
100 char section = sec;
101 char work[100], work2[100], cmdbuf[100];
102 int ss;
103 struct stat stbuf, stbuf2;
104 int last;
105 char *sp = "1nl6823457p";
106
107 strcpy(work, "manx/");
108 strcat(work, name);
109 strcat(work, ".x");
110 last = strlen(work) - 1;
111 if (section == '1') {
112 sp = "1nl";
113 section = 0;
114 }
115 if (section == 0) {
116 ss = 0;
117 for (section = *sp++; section; section = *sp++) {
118 work[3] = section;
119 work[last] = section;
120 work[last+1] = 0;
121 if (stat(work, &stbuf) >= 0)
122 break;
123 if (work[last] >= '1' && work[last] <= '3') {
124 char *cp;
125search:
126 switch (work[last]) {
127 case '1': cp = "mcg"; break;
128 case '2': cp = "jv"; break;
129 case '3': cp = "jxmsf"; break;
130 }
131 while (*cp) {
132 work[last+1] = *cp++;
133 if (stat(work, &stbuf) >= 0) {
134 ss = work[last+1];
135 goto found;
136 }
137 }
138 if (ss = 0)
139 work[last+1] = 0;
140 }
141 }
142 if (section == 0) {
143 if (sec == 0)
144 printf("No manual entry for %s.\n", name);
145 else
146 printf("No entry for %s in section %c of the manual.\n", name, sec);
147 return;
148 }
149 } else {
150 work[3] = section;
151 work[last] = section;
152 work[last+1] = subsec;
153 if (stat(work, &stbuf) < 0) {
154 if ((section >= '1' && section <= '3') && subsec == 0) {
155 sp = "\0";
156 goto search;
157 }
158 printf("No entry for %s in section %c", name, section);
159 if (subsec)
160 putchar(subsec);
161 printf(" of the manual.\n");
162 return;
163 }
164 }
165found:
166 if (troffit)
167 troff(work);
168 else {
169 FILE *it;
170 char abuf[BUFSIZ];
171
172 if (!nomore) {
173 it = fopen(work, "r");
174 if (fgets(abuf, BUFSIZ-1, it) &&
175 abuf[0] == '.' && abuf[1] == 's' &&
176 abuf[2] == 'o' && abuf[3] == ' ') {
177 register char *cp = abuf+strlen(".so ");
178 char *dp;
179
180 while (*cp && *cp != '\n')
181 cp++;
182 *cp = 0;
183 while (cp > abuf && *--cp != '/')
184 ;
185 dp = ".so /usr/man/man";
186 if (cp != abuf+strlen(dp)+1) {
187tohard:
188 nomore = 1;
189 strcpy(work, abuf+4);
190 goto hardway;
191 }
192 for (cp = abuf; *cp == *dp && *cp; cp++, dp++)
193 ;
194 if (*dp)
195 goto tohard;
196 strcpy(work, cp-3);
197 }
198 fclose(it);
199 strcpy(work2, "cat");
200 strcpy(work2+3, work+3);
201 work2[4] = 0;
202 if (stat(work2, &stbuf2) < 0)
203 goto hardway;
204 strcpy(work2+3, work+3);
205 if (stat(work2, &stbuf2) < 0 || stbuf2.st_mtime < stbuf.st_mtime) {
206 printf("Reformatting page. Wait...");
207 fflush(stdout);
208 unlink(work2);
209 sprintf(cmdbuf,
210"nroff -h -man %s > /tmp/man%d; trap '' 1 15; mv /tmp/man%d %s", work, getpid(), getpid(), work2);
211 if (system(cmdbuf)) {
212 printf(" aborted (sorry)\n");
213 remove();
214 /*NOTREACHED*/
215 }
216 printf(" done\n");
217 }
218 strcpy(work, work2);
219 }
220hardway:
221 nroff(work);
222 }
223}
224
225nroff(cp)
226 char *cp;
227{
228 char cmd[BUFSIZ];
229
230 sprintf(cmd, nomore ?
231 "%s %s" : "%s %s|/usr/ucb/ul|/usr/ucb/more -f",
232 cp[0] == 'c' ? "cat -s" : "nroff -man", cp);
233 system(cmd);
234}
235
236troff(cp)
237 char *cp;
238{
239 char cmdbuf[BUFSIZ];
240
241 sprintf(cmdbuf,
242"troff -t -man /usr/lib/tmac/tmac.vcat %s|/usr/lib/rvsort|/usr/ucb/vpr -t",
243 cp);
244 system(cmdbuf);
245}
246
247any(c, sp)
248 register int c;
249 register char *sp;
250{
251 register int d;
252
253 while (d = *sp++)
254 if (c == d)
255 return (1);
256 return (0);
257}
258
259remove()
260{
261 char name[15];
262
263 sprintf(name, "/tmp/man%d", getpid());
264 unlink(name);
265 exit(1);
266}
267
268apropos(argc, argv)
269 int argc;
270 char **argv;
271{
272 char buf[BUFSIZ];
273 char *gotit;
274 register char **vp;
275
276 if (argc == 0) {
277 fprintf(stderr, "man: -a what?\n");
278 exit(1);
279 }
280 if (freopen("/usr/lib/whatis", "r", stdin) == NULL) {
281 perror("/usr/lib/whatis");
282 exit (1);
283 }
284 gotit = (char *) calloc(1, blklen(argv));
285 while (fgets(buf, sizeof buf, stdin) != NULL)
286 for (vp = argv; *vp; vp++)
287 if (match(buf, *vp)) {
288 printf("%s", buf);
289 gotit[vp - argv] = 1;
290 for (vp++; *vp; vp++)
291 if (match(buf, *vp))
292 gotit[vp - argv] = 1;
293 break;
294 }
295 for (vp = argv; *vp; vp++)
296 if (gotit[vp - argv] == 0)
297 printf("%s: nothing apropriate\n", *vp);
298}
299
300match(buf, str)
301 char *buf, *str;
302{
303 register char *bp, *cp;
304
305 bp = buf;
306 for (;;) {
307 if (*bp == 0)
308 return (0);
309 if (amatch(bp, str))
310 return (1);
311 bp++;
312 }
313}
314
315amatch(cp, dp)
316 register char *cp, *dp;
317{
318
319 while (*cp && *dp && lmatch(*cp, *dp))
320 cp++, dp++;
321 if (*dp == 0)
322 return (1);
323 return (0);
324}
325
326lmatch(c, d)
327 char c, d;
328{
329
330 if (c == d)
331 return (1);
332 if (!isalpha(c) || !isalpha(d))
333 return (0);
334 if (islower(c))
335 c = toupper(c);
336 if (islower(d))
337 d = toupper(d);
338 return (c == d);
339}
340
341blklen(ip)
342 register int *ip;
343{
344 register int i = 0;
345
346 while (*ip++)
347 i++;
348 return (i);
349}
350
351whatis(argc, argv)
352 int argc;
353 char **argv;
354{
355 register char **avp;
356
357 if (argc == 0) {
358 fprintf(stderr, "man: -f what?\n");
359 exit(1);
360 }
361 if (freopen("/usr/lib/whatis", "r", stdin) == NULL) {
362 perror("/usr/lib/whatis");
363 exit (1);
364 }
365 for (avp = argv; *avp; avp++)
366 *avp = trim(*avp);
367 whatisit(argv);
368 exit(0);
369}
370
371whatisit(argv)
372 char **argv;
373{
374 char buf[BUFSIZ];
375 register char *gotit;
376 register char **vp;
377
378 gotit = (char *)calloc(1, blklen(argv));
379 while (fgets(buf, sizeof buf, stdin) != NULL)
380 for (vp = argv; *vp; vp++)
381 if (wmatch(buf, *vp)) {
382 printf("%s", buf);
383 gotit[vp - argv] = 1;
384 for (vp++; *vp; vp++)
385 if (wmatch(buf, *vp))
386 gotit[vp - argv] = 1;
387 break;
388 }
389 for (vp = argv; *vp; vp++)
390 if (gotit[vp - argv] == 0)
391 printf("%s: not found\n", *vp);
392}
393
394wmatch(buf, str)
395 char *buf, *str;
396{
397 register char *bp, *cp;
398
399 bp = buf;
400again:
401 cp = str;
402 while (*bp && *cp && lmatch(*bp, *cp))
403 bp++, cp++;
404 if (*cp == 0 && (*bp == '(' || *bp == ',' || *bp == '\t' || *bp == ' '))
405 return (1);
406 while (isalpha(*bp) || isdigit(*bp))
407 bp++;
408 if (*bp != ',')
409 return (0);
410 bp++;
411 while (isspace(*bp))
412 bp++;
413 goto again;
414}
415
416char *
417trim(cp)
418 register char *cp;
419{
420 register char *dp;
421
422 for (dp = cp; *dp; dp++)
423 if (*dp == '/')
424 cp = dp + 1;
425 if (cp[0] != '.') {
426 if (cp + 3 <= dp && dp[-2] == '.' && any(dp[-1], "cosa12345678npP"))
427 dp[-2] = 0;
428 if (cp + 4 <= dp && dp[-3] == '.' && any(dp[-2], "13") && isalpha(dp[-1]))
429 dp[-3] = 0;
430 }
431 return (cp);
432}
433
434system(s)
435char *s;
436{
437 int status, pid, w;
438
439 if ((pid = vfork()) == 0) {
440 execl("/bin/sh", "sh", "-c", s, 0);
441 _exit(127);
442 }
443 while ((w = wait(&status)) != pid && w != -1)
444 ;
445 if (w == -1)
446 status = -1;
447 return (status);
448}