Path: seismo!harvard!talcott!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: Client/server context diffs to 4.2BSD man.c Message-ID: <1624@panda.UUCP> Date: 8 Apr 86 14:05:58 GMT Sender: jpn@panda.UUCP Lines: 673 Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 55 Submitted by: talcott!ut-sally!im4u!jsq (John Quarterman) : This is a shar archive. Extract with sh, not csh. echo x - README.man sed -e 's/^X//' > README.man << '!RoNnIe!RaYgUn!' XThis article includes a context diff of the source to the 4.2BSD man command Xto make it work with the generic client and server programs previously posted. X XOnce again: I make no claims whatever as to the security, safety, or utility Xof this software. USE AT YOUR OWN RISK! X X John Quarterman, ut-sally!jsq, jsq@sally.utexas.edu X X XThe diffs to the man command found in man.c.diffs include not only Xthe changes to make it call client if necessary, but also at least Xtwo other modifications which you may or may not want: X Files in /usr/man/manl may be named, e.g., server.8 instead of server.l. X Manual pages are kept compressed (compress 4.0 is recommended for this). XThe idea for the latter change came from Sequent Computer Systems, Inc., Xbut this implementation was done without seeing their code. X XObviously man could be made to work with the client and server programs Xwithout changing man.c itself by using the same sort of shell script Xhack as in the phone program example. However, the difference in speed Xis worth the hacking in this case (I tried it both ways). !RoNnIe!RaYgUn! echo x - man.c.diff sed -e 's/^X//' > man.c.diff << '!RoNnIe!RaYgUn!' X*** man.c.orig Thu Apr 3 12:15:08 1986 X--- man.c Fri Dec 20 11:54:43 1985 X*************** X*** 5,13 **** X #include X #include X #include X! #include X #include X- #include X /* X * man X * link also to apropos and whatis X--- 5,12 ---- X #include X #include X #include X! #include X #include X /* X * man X * link also to apropos and whatis X*************** X*** 14,26 **** X * This version uses more for underlining and paging. X */ X #define MANDIR "/usr/man" /* this is deeply embedded */ X #define NROFFCAT "nroff -h -man" /* for nroffing to cat file */ X #define NROFF "nroff -man" /* for nroffing to tty */ X! #define MORE "more -s" /* paging filter */ X! #define CAT "cat -s" /* for '-' opt (no more) */ X X #define TROFFCMD \ X! "itroff -man %s" X #ifdef notdef X "troff -t -man /usr/lib/tmac/tmac.vcat %s | /usr/lib/rvsort |/usr/ucb/vpr -t" X #endif X--- 13,27 ---- X * This version uses more for underlining and paging. X */ X #define MANDIR "/usr/man" /* this is deeply embedded */ X+ #define WHATIS "/usr/lib/whatis" /* whatis database */ X #define NROFFCAT "nroff -h -man" /* for nroffing to cat file */ X #define NROFF "nroff -man" /* for nroffing to tty */ X! #define MORE "more" /* paging filter */ X! #define CAT "cat" /* for '-' opt (no more) */ X X #define TROFFCMD \ X! "ditroff -man %s" X! X #ifdef notdef X "troff -t -man /usr/lib/tmac/tmac.vcat %s | /usr/lib/rvsort |/usr/ucb/vpr -t" X #endif X*************** X*** 29,45 **** X #define TROFFCMD "troff -man %s" X */ X X! #define ALLSECT "1nl6823457po" /* order to look through sections */ X! #define SECT1 "1nlo" /* sections to look at if 1 is specified */ X! #define SUBSEC1 "mcgprv" /* subsections to try in section 1 */ X! #define SUBSEC2 "v" X! #define SUBSEC3 "jxmsnvcf" X! #define SUBSEC4 "pfvsn" X! #define SUBSEC8 "vc" X X int nomore; X int cflag; X! char *manpath = "/usr/man"; X char *strcpy(); X char *strcat(); X char *trim(); X--- 30,63 ---- X #define TROFFCMD "troff -man %s" X */ X X! #define ALLSECT "16823457" /* order to look through sections */ X! #define SECTS "nlxpo" /* additional sections to look at if 1-8 is specified */ X! #define SUBSEC1 "mcgprvx" /* subsections to try in section 1 */ X! #define SUBSEC2 "pvx" X! #define SUBSEC3 "jxmsnpvcfx" X! #define SUBSEC4 "pfvsnx" X! #define SUBSEC8 "vcpx" X X int nomore; X+ int isremote; X int cflag; X! char manpath[MAXPATHLEN] = MANDIR; X! char whatispath[MAXPATHLEN] = WHATIS; X! char *machine = NULL; X! #if vax X! #define OURMACHINE "vax" X! #else X! #if sun X! #define OURMACHINE "sun" X! #else X! #if ns32000 X! #define OURMACHINE "b8k" X! #else X! #define OURMACHINE "vax" X! #endif X! #endif X! #endif X! #define DOMAIN ".CS.UTEXAS.EDU" X char *strcpy(); X char *strcat(); X char *trim(); X*************** X*** 55,61 **** X--- 73,121 ---- X int argc; X char *argv[]; X { X+ char *command, *dot, *rindex(), *index(); X X+ /* check how we are called and append suffix to X+ manual path. This enables an alternate manual X+ set to be used. We also have to change the X+ location of the whatis database by also appending X+ the suffix. I.e for a sun manual set the path is X+ set to MANDIR.sun and whatis is WHATIS.sun. X+ But don't append .local if called as man.local. X+ */ X+ X+ if ((command = rindex(*argv, '/')) != NULL) X+ command++; X+ else X+ command = *argv; X+ if ((dot = index(command, '.')) != NULL) { X+ *dot++ = '\0'; X+ if (strcmp(dot, "local") != 0) X+ dot = NULL; X+ else X+ machine = dot; X+ } X+ if (argv[1] != NULL && strcmp(argv[1], "-m") == 0 X+ && argv[2] != NULL) { X+ argc--, argv++; X+ argc--, argv++; X+ machine = *argv; X+ } X+ if (machine != NULL && strcmp(machine, OURMACHINE) != 0) { X+ dot = manpath + strlen(manpath); X+ strcat (dot, "."); X+ strcat (dot, machine); X+ strcat (whatispath, dot); X+ } X+ { X+ struct stat stbuf; X+ if (fstat(0, &stbuf) != -1 X+ && ((stbuf.st_mode&S_IFMT) == S_IFSOCK X+ || (stbuf.st_mode&S_IFMT) == 0)) X+ isremote++; X+ } X+ if (chdir(manpath) < 0 || (chdir("man1") < 0 && chdir("cat1") < 0)) X+ remoteman(command, ++argv); X if (signal(SIGINT, SIG_IGN) == SIG_DFL) { X signal(SIGINT, remove); X signal(SIGQUIT, remove); X*************** X*** 62,77 **** X signal(SIGTERM, remove); X } X umask(0); X! if (strcmp(argv[0], "apropos") == 0) { X apropos(argc-1, argv+1); X exit(0); X } X! if (strcmp(argv[0], "whatis") == 0) { X whatis(argc-1, argv+1); X exit(0); X } X if (argc <= 1) { X! fprintf(stderr, "Usage: man [ section ] name ...\n"); X exit(1); X } X argc--, argv++; X--- 122,137 ---- X signal(SIGTERM, remove); X } X umask(0); X! if (strcmp(command, "apropos") == 0) { X apropos(argc-1, argv+1); X exit(0); X } X! if (strcmp(command, "whatis") == 0) { X whatis(argc-1, argv+1); X exit(0); X } X if (argc <= 1) { X! fprintf(stderr, "Usage: man [ -m machine ] [ section ] name ...\n"); X exit(1); X } X argc--, argv++; X*************** X*** 96,102 **** X X case 'P': X argc--, argv++; X! manpath = *argv; X break; X } X argc--, argv++; X--- 156,162 ---- X X case 'P': X argc--, argv++; X! strcpy(manpath, *argv); X break; X } X argc--, argv++; X*************** X*** 105,111 **** X fprintf(stderr, "Can't chdir to %s.\n", manpath); X exit(1); X } X! if (troffit == 0 && nomore == 0 && !isatty(1)) X nomore++; X section = 0; X do { X--- 165,171 ---- X fprintf(stderr, "Can't chdir to %s.\n", manpath); X exit(1); X } X! if (isremote == 0 && troffit == 0 && nomore == 0 && !isatty(1)) X nomore++; X section = 0; X do { X*************** X*** 132,174 **** X } X continue; X } X! manual(section, argv[0]); X argc--, argv++; X } while (argc > 0); X exit(0); X } X X! manual(sec, name) X! char sec; X! char *name; X { X! char section = sec; X! char work[100], work2[100], cmdbuf[150]; X int ss; X! struct stat stbuf, stbuf2; X int last; X! char *sp = ALLSECT; X X strcpy(work, "manx/"); X strcat(work, name); X strcat(work, ".x"); X last = strlen(work) - 1; X! if (section == '1') { X! sp = SECT1; X! section = 0; X } X! if (section == 0) { X! ss = 0; X! for (section = *sp++; section; section = *sp++) { X! work[3] = section; X work[last] = section; X! work[last+1] = 0; X work[last+2] = 0; X if (stat(work, &stbuf) >= 0) X! break; X! if (work[last] >= '1' && work[last] <= '8') { X char *cp; X- search: X switch (work[last]) { X case '1': cp = SUBSEC1; break; X case '2': cp = SUBSEC2; break; X--- 192,263 ---- X } X continue; X } X! manual(section, subsec, argv[0]); X argc--, argv++; X } while (argc > 0); X exit(0); X } X X! manual(sec, subsec, name) X! char sec; X! char subsec; X! char *name; X { X! char work[100], work2[100], workZ[100], cmdbuf[150]; X! char sects[100], lsects[100]; X! char section; X int ss; X! struct stat stbuf, stbuf2, stbufZ; X int last; X! char *sp, *lsp, *secp; X! extern char *index(); X X strcpy(work, "manx/"); X strcat(work, name); X strcat(work, ".x"); X last = strlen(work) - 1; X! X! /* set up sections to search */ X! if (sec == '\0') { X! strcpy(sects, ALLSECT); X! sp = sects; X! strcpy(lsects, SECTS); /* special sections */ X } X! else { X! sects[0] = sec; X! sects[1] = '\0'; X! sp = sects; X! if (sec >= '1' && sec <= '8') X! strcpy(lsects, SECTS); /* special sections */ X! else X! strcpy(lsects, "x"); /* only search in specified sectin */ X! } X! X! /* do the search */ X! secp = index(lsects, 'x'); X! ss = 0; X! for (section = *sp++; section; section = *sp++) { X! #ifdef DEBUG X! fprintf (stderr, "section = %c\n", section); X! #endif X! *secp = section; X! /* special section searching X! this will search through the specified section plus all X! the sections in lsect X! Note that the 'x' entry in lsect is replaced with X! the specific main section to search */ X! for (lsp = lsects; *lsp != NULL; lsp++) { X! work[3] = *lsp; X work[last] = section; X! work[last+1] = subsec; X work[last+2] = 0; X+ #ifdef DEBUG X+ fprintf(stderr, "work - %s\n", work); X+ #endif X if (stat(work, &stbuf) >= 0) X! goto found; X! if (subsec == '\0') { X char *cp; X switch (work[last]) { X case '1': cp = SUBSEC1; break; X case '2': cp = SUBSEC2; break; X*************** X*** 176,182 **** X case '4': cp = SUBSEC4; break; X case '8': cp = SUBSEC8; break; X } X! while (*cp) { X work[last+1] = *cp++; X if (stat(work, &stbuf) >= 0) { X ss = work[last+1]; X--- 265,271 ---- X case '4': cp = SUBSEC4; break; X case '8': cp = SUBSEC8; break; X } X! while (cp && *cp) { X work[last+1] = *cp++; X if (stat(work, &stbuf) >= 0) { X ss = work[last+1]; X*************** X*** 187,216 **** X work[last+1] = 0; X } X } X- if (section == 0) { X- if (sec == 0) X- printf("No manual entry for %s.\n", name); X- else X- printf("No entry for %s in section %c of the manual.\n", name, sec); X- return; X- } X- } else { X- work[3] = section; X- work[last] = section; X- work[last+1] = subsec; X- work[last+2] = 0; X- if (stat(work, &stbuf) < 0) { X- if ((section >= '1' && section <= '8') && subsec == 0) { X- sp = "\0"; X- goto search; X- } X- printf("No entry for %s in section %c", name, section); X- if (subsec) X- putchar(subsec); X- printf(" of the manual.\n"); X- return; X- } X } X found: X if (troffit) X troff(work); X--- 276,291 ---- X work[last+1] = 0; X } X } X } X+ if (sec == 0) X+ printf("No manual entry for %s.\n", name); X+ else { X+ printf("No entry for %s in section %c", name, sec); X+ if (subsec != '\0') X+ putchar(subsec); X+ printf(" of the manual.\n"); X+ } X+ return; X found: X if (troffit) X troff(work); X*************** X*** 229,235 **** X register char *cp = abuf+strlen(".so "); X char *dp; X X! while (*cp && *cp != '\n') X cp++; X *cp = 0; X while (cp > abuf && *--cp != '/') X--- 304,310 ---- X register char *cp = abuf+strlen(".so "); X char *dp; X X! while (cp && *cp && *cp != '\n') X cp++; X *cp = 0; X while (cp > abuf && *--cp != '/') X*************** X*** 254,260 **** X if (stat(work2, &stbuf2) < 0) X goto hardway; X strcpy(work2+3, work+3); X! if (stat(work2, &stbuf2) < 0 || stbuf2.st_mtime < stbuf.st_mtime) { X printf("Reformatting page. Wait..."); X fflush(stdout); X unlink(work2); X--- 329,346 ---- X if (stat(work2, &stbuf2) < 0) X goto hardway; X strcpy(work2+3, work+3); X! strcpy(workZ, work2); X! strcat(workZ, ".Z"); X! #ifdef DEBUG X! fprintf (stderr, "%s %s %s\n", work, work2, workZ); X! exit(0); X! #endif X! if (stat(work2, &stbuf2) >= 0) { X! if (stbuf2.st_mtime > stbuf.st_mtime) X! compress(work2, workZ); X! unlink(work2); X! } X! if (stat(workZ, &stbufZ) < 0 || stbufZ.st_mtime < stbuf.st_mtime) { X printf("Reformatting page. Wait..."); X fflush(stdout); X unlink(work2); X*************** X*** 266,274 **** X remove(); X /*NOTREACHED*/ X } X printf(" done\n"); X } X! strcpy(work, work2); X } X hardway: X nroff(work); X--- 352,361 ---- X remove(); X /*NOTREACHED*/ X } X+ compress(work2, workZ); X printf(" done\n"); X } X! strcpy(work, workZ); X } X hardway: X nroff(work); X*************** X*** 275,289 **** X } X } X X nroff(cp) X char *cp; X { X char cmd[BUFSIZ]; X X! if (cp[0] == 'c') X! sprintf(cmd, "%s %s", nomore? CAT : MORE, cp); X! else X! sprintf(cmd, nomore? "%s %s" : "%s %s|%s", NROFF, cp, MORE); X system(cmd); X } X X--- 362,466 ---- X } X } X X+ compress(cp, z) X+ char *cp, *z; X+ { X+ char cmdbuf[100]; X+ X+ printf("Compressing..."); X+ fflush(stdout); X+ unlink(z); X+ sprintf(cmdbuf, "compress -f %s\n", cp); X+ if (system(cmdbuf)) { X+ printf(" aborted (sorry)\n"); X+ remove(); X+ /*NOTREACHED*/ X+ } X+ printf("."); X+ X+ } X+ X+ static X+ char * X+ more() X+ { X+ extern char *getenv(); X+ char *more; X+ X+ if ((more = getenv("PAGER")) == NULL) X+ more = MORE; X+ return(more); X+ } X+ X+ remoteman(command, argv) X+ char *command; X+ char **argv; X+ { X+ char host[128]; X+ char *args[32]; X+ char **ap = args, **tp = &args[sizeof(args)/sizeof(args[0]) - 1]; X+ X+ if (machine == NULL) X+ machine = OURMACHINE; X+ (void)strcpy(host, "man."); X+ (void)strcat(host, machine); X+ (void)strcat(host, DOMAIN); X+ *ap++ = "client"; X+ *ap++ = host; X+ *ap++ = command; X+ *ap++ = "-m"; X+ *ap++ = machine; X+ while (*argv && ap < tp) X+ *ap++ = *argv++; X+ *ap = NULL; X+ if (!isremote) { X+ int pipefds[2], pid; X+ char *filter; X+ X+ if (pipe(pipefds) == -1) { X+ perror("pipe"); X+ exit(1); X+ } X+ switch (pid = vfork()) { X+ case -1: X+ perror("vfork"); X+ exit(1); X+ break; X+ case 0: X+ dup2(pipefds[1], 1); X+ close(pipefds[0]); X+ close(pipefds[1]); X+ break; X+ default: X+ dup2(pipefds[0], 0); X+ close(pipefds[0]); X+ close(pipefds[1]); X+ filter = nomore ? CAT : more(); X+ execlp (filter, filter, "-s", NULL); X+ perror(filter); X+ exit(1); X+ break; X+ } X+ } X+ execvp(*args, args); X+ perror(*args); X+ exit(1); X+ } X+ X nroff(cp) X char *cp; X { X char cmd[BUFSIZ]; X X! if (cp[0] == 'c') { X! if (isremote) { X! execlp ("zcat", "zcat", cp, NULL); X! perror("zcat"); X! exit(1); X! } else X! sprintf(cmd, "zcat %s | %s -s", cp, nomore? CAT:more()); X! } else X! sprintf(cmd, nomore? "%s %s" : "%s %s|%s -s", NROFF, cp,more()); X system(cmd); X } X X*************** X*** 329,336 **** X fprintf(stderr, "apropos what?\n"); X exit(1); X } X! if (freopen("/usr/lib/whatis", "r", stdin) == NULL) { X! perror("/usr/lib/whatis"); X exit (1); X } X gotit = (char *) calloc(1, blklen(argv)); X--- 506,513 ---- X fprintf(stderr, "apropos what?\n"); X exit(1); X } X! if (freopen(whatispath, "r", stdin) == NULL) { X! perror(whatispath); X exit (1); X } X gotit = (char *) calloc(1, blklen(argv)); X*************** X*** 410,417 **** X fprintf(stderr, "whatis what?\n"); X exit(1); X } X! if (freopen("/usr/lib/whatis", "r", stdin) == NULL) { X! perror("/usr/lib/whatis"); X exit (1); X } X for (avp = argv; *avp; avp++) X--- 587,594 ---- X fprintf(stderr, "whatis what?\n"); X exit(1); X } X! if (freopen(whatispath, "r", stdin) == NULL) { X! perror(whatispath); X exit (1); X } X for (avp = argv; *avp; avp++) !RoNnIe!RaYgUn! exit