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