home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume3 / man < prev    next >
Internet Message Format  |  1986-11-30  |  15KB

  1. From: genrad!decvax!ukma!ukecc!edward
  2. Subject: A compiled 'man' program for System V
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 3, Issue 70
  7. Submitted by: cbosgd!ukma!ukecc!edward (Edward C. Bennett)
  8.  
  9.     In System V (at least on our 3B20) the man(1) command is a shell
  10. script and, because it calls nroff *every time*, it is painfully slow to
  11. use. Even the catman(1) command, which uses preformatted and packed versions
  12. of the man pages, takes a noticeably long time to get your data on-screen.
  13. Furthermore, catman(1) has no easy way to keep the /usr/catman files up-
  14. to-date. Such is the inspiration for this new version of man(1).
  15.     This version of man(1) eliminates all these problems.  It is compiled
  16. rather than interpreted to increase speed.
  17. [This program compiles on BSD4.2 after changing <string.h> to <strings.h>
  18.  and converting calls to strchr() to index()                 - moderator ]
  19.                         It uses the /usr/catman files
  20. to avoid repetative nroff'ing. And checks to see if the formatted version
  21. postdates the raw version and if not, a new formatted version is created.
  22. This automates the problem of maintaining a current manual.
  23.     Additionally, the program allows you to select the order that the
  24. sections are searched. This way you can put little-used sections like 5
  25. and 8 at the end of the line. The program also looks at the environment
  26. variable PAGER for a preferred paging program, finding none it uses a
  27. preselected default. An option is provided to look for man pages applicable
  28. to a given keyword.
  29.  
  30. #! /bin/sh
  31. : This is a shell archive, meaning:
  32. : 1. Remove everything above the '#! /bin/sh' line.
  33. : 2. Save the resulting text in a file.
  34. : 3. Execute the file with /bin/sh '(not csh)' to create the files:
  35. :    'README'
  36. :    'Makefile'
  37. :    'man.1'
  38. :    'man.c'
  39. :    'mkxref.c'
  40. :    'updateall.c'
  41. : This archive created: 'Mon Dec 23 16:31:07 1985'
  42. : By:    'Edward C. Bennett'
  43. export PATH; PATH=/bin:$PATH
  44. if test -f 'README'
  45. then
  46.     echo shar: will not over-write existing file "'README'"
  47. else
  48. cat  >'README' <<\SHAR_EOF
  49. To set this system up:
  50.  
  51.     Check the makefile to be sure all paths are OK.
  52.  
  53.     Su to 'root' and do "make convert"
  54.  
  55.     Compile the updateall command. This should be run at an off
  56.     hour as it takes quite awhile.
  57. SHAR_EOF
  58. fi
  59. if test -f 'Makefile'
  60. then
  61.     echo shar: will not over-write existing file "'Makefile'"
  62. else
  63. cat  >'Makefile' <<\SHAR_EOF
  64. # makefile of System V man program
  65. #
  66. # AUTHOR
  67. #    Edward C. Bennett, edward@ukecc.UUCP
  68. #
  69. # Copyright 1985 by Edward C. Bennett
  70. #
  71. # Permission is given to alter this code as needed to adapt it to forign
  72. # systems provided that this header is included and that the original
  73. # author's name is preserved.
  74.  
  75. USRBIN=/usr/bin
  76. MANOWN=bin
  77.  
  78. man: man.c
  79.     cc -O man.c -o man
  80.  
  81. xref: mkxref
  82.     mkxref > /usr/man/xref
  83.  
  84. mkxref: mkxref.c
  85.     cc -O mkxref.c -o mkxref
  86.  
  87. updateall: updateall.c
  88.     cc -O updateall.c -o updateall
  89.  
  90. install: man
  91.     /etc/install -f ${USRBIN} man
  92.     chown ${MANOWN} ${USRBIN}/man
  93.     chmod 4755 ${USRBIN}/man
  94.  
  95. convert: man mkxref
  96.     mv ${USRBIN}/man ${USRBIN}/oman
  97.     mv /usr/man/u_man/man1/man.1 /usr/man/u_man/man1/oman.1
  98.     /etc/install -f ${USRBIN} man
  99.     chown ${MANOWN} ${USRBIN}/man
  100.     chmod 4755 ${USRBIN}/man
  101.     mkxref > /usr/man/xref
  102.     chown ${MANOWN} /usr/bin/xref
  103.  
  104. clean:
  105.     rm -f man mkxref updateall
  106.  
  107. shar:
  108.     shar README Makefile man.1 man.c mkxref.c updateall.c > man.shar
  109. SHAR_EOF
  110. fi
  111. if test -f 'man.1'
  112. then
  113.     echo shar: will not over-write existing file "'man.1'"
  114. else
  115. cat  >'man.1' <<\SHAR_EOF
  116. .TH MAN 1 "23 December 1985"
  117. .SH NAME
  118. man \- print manual pages
  119. .SH SYNOPSIS
  120. .B man
  121. [
  122. .B section
  123. ]
  124. title
  125. .PP
  126. .B man \-k keyword
  127. .SH DESCRIPTION
  128. .I Man
  129. finds and prints pages from the on-line manual.
  130. To speed things up,
  131. .I man
  132. keeps preformatted and packed versions of the manual pages
  133. in the /usr/catman directory.
  134. The date of the formatted version is checked against the date
  135. of the raw version and if the raw version is newer,
  136. a new formatted version is created with
  137. .IR nroff (1)
  138. and
  139. .IR pack (1).
  140. .PP
  141. The environmental variable PAGER is checked for a preferred
  142. paging program.
  143. If none is specified,
  144. .IR pg (1)
  145. is used.
  146. .PP
  147. If
  148. .I man
  149. is used with the \-k option,
  150. a list of all subject lines is searched for the given keyword.
  151. This is useful if you don't know the name of a command,
  152. but you know what it does.
  153. .SH FILES
  154. .TP 38
  155. /usr/man/[apu]_man/man[1-8]/*
  156. unformatted pages
  157. .TP 38
  158. /usr/catman/[apu]_man/man[1-8]/*.z
  159. formatted, packed pages
  160. .TP 38
  161. /usr/man/xref
  162. collection of title lines
  163. .SH AUTHOR
  164. Edward C. Bennett
  165. .SH DIAGNOSTICS
  166. Hopefully self-explanatory.
  167. .SH BUGS
  168. .I Man
  169. only prints the first manual entry with the given title that it finds.
  170. To keep things simple,
  171. .IR nroff (1)
  172. uses no fancy options.
  173. The \-k option should search for multiple keywords.
  174. SHAR_EOF
  175. fi
  176. if test -f 'man.c'
  177. then
  178.     echo shar: will not over-write existing file "'man.c'"
  179. else
  180. cat  >'man.c' <<\SHAR_EOF
  181. /*
  182.  *    man - view the on-line manual
  183.  *
  184.  *    man [ section ] title
  185.  *
  186.  *    man -k keyword
  187.  *
  188.  *    This manual program is designed primarily for a speed increase
  189.  * in viewing the manual. Rather than run nroff every time a man page is
  190.  * requested, pre-formatted packed versions of the pages are kept in the
  191.  * /usr/catman directory and pcat is used to read them. This agrees with
  192.  * System V's catman program. This program stats both the unformatted and
  193.  * formatted versions of the requested page and, if the formatted page is
  194.  * up-to-date, it is printed, otherwise a new packed page is created with
  195.  * nroff and pack. This automates the task of keeping up-to-date man pages
  196.  * on-line. The environmental variable PAGER is checked for a preferred
  197.  * pager, if none is specified /usr/bin/pg is used. To keep things simple,
  198.  * nroff uses no fancy options.
  199.  *    With the -k option, the /usr/man/xref database is searched for the
  200.  * given keyword.
  201.  *
  202.  * AUTHOR
  203.  *    Edward C. Bennett, edward@ukecc.UUCP
  204.  *
  205.  * Copyright 1985 by Edward C. Bennett
  206.  *
  207.  * Permission is given to alter this code as needed to adapt it to forign
  208.  * systems provided that this header is included and that the original
  209.  * author's name is preserved.
  210.  */
  211. #include <stdio.h>
  212. #include <fcntl.h>
  213. #include <sys/types.h>
  214. #include <sys/stat.h>
  215. #include <sys/dir.h>
  216. #include <string.h>
  217.  
  218. #define    DEFPAGER    "/usr/bin/pg"
  219. #define    GREP        "/bin/grep"
  220. #define    XREF        "/usr/man/xref"
  221.  
  222. /*
  223.  * These are the directories under /usr/man that are to be searched for the
  224.  * requested man page. The order in the array is the order of the search
  225.  * so to minimize searching effort the more frequently used sections should
  226.  * go at the top.
  227.  */
  228. char    *mandirs[] = {
  229.     "u_man/man1",
  230.     "p_man/man2",
  231.     "p_man/man3",
  232.     "u_man/man6",
  233.     "p_man/man4",
  234.     "p_man/man5",
  235.     "a_man/man1",
  236.     "a_man/man7",
  237.     "a_man/man8",
  238. };
  239. #define    NUMDIRS        sizeof(mandirs)/sizeof(char *)
  240.  
  241. main(argc, argv)
  242. int argc;
  243. char **argv;
  244. {
  245.     char    *manpage, *pager, *section, *title, *Findpage(), *getenv();
  246.     char    cmd[BUFSIZ], catbuf[BUFSIZ], catbufz[BUFSIZ];
  247.     int    status;
  248.     void    exit();
  249.     struct    stat    manstat, catstat;
  250.  
  251.     if (!strcmp(argv[1], "-k")) {
  252.         execl(GREP, GREP, argv[2], XREF, 0);
  253.     }
  254.  
  255.     switch (argc) {
  256.     case 2:
  257.         title = argv[1];
  258.         section = NULL;
  259.         break;
  260.  
  261.     case 3:
  262.         title = argv[2];
  263.         section = argv[1];
  264.         break;
  265.  
  266.     default:
  267.         fprintf(stderr, "Usage: %s [ section ] title\n", argv[0]);
  268.         exit(1);
  269.     }
  270.  
  271.     if ((pager = getenv("PAGER")) == NULL)
  272.         pager = DEFPAGER;
  273.  
  274.     chdir("/usr/man");
  275.  
  276.     if ((manpage = Findpage(title, section)) == NULL) {
  277.         if (section)
  278.             printf("No entry for %s in section %s of the manual\n", title, section);
  279.         else
  280.             printf("No manual entry for %s\n", title);
  281.         exit(1);
  282.     }
  283.  
  284.     strcpy(catbuf, "/usr/catman/");
  285.     strcat(catbuf, manpage);
  286.     strcpy(catbufz, catbuf);
  287.     strcat(catbufz, ".z");
  288.  
  289.     stat(manpage, &manstat);
  290.     if (stat(catbufz, &catstat) == -1)
  291.         catstat.st_mtime = -1;
  292.  
  293.     if (catstat.st_mtime < manstat.st_mtime) {
  294.         unlink(catbufz);
  295.         printf("Reformatting page, wait...");
  296.         fflush(stdout);
  297.         if (fork() == 0) {
  298.             sprintf(cmd, "nroff -man %s > %s", manpage, catbuf);
  299.             execl("/bin/sh", "sh", "-c", cmd, 0);
  300.         }
  301.         wait(&status);
  302.         printf("\nCompressing output, wait...");
  303.         fflush(stdout);
  304.         if (fork() == 0) {
  305.             sprintf(cmd, "pack -f %s", catbuf);
  306.             execl("/bin/sh", "sh", "-c", cmd, 0);
  307.         }
  308.         wait(&status);
  309.     }
  310.  
  311.     /*
  312.      * Do this in case the user does something like 'man curses > file'
  313.      */
  314.     if (isatty(1))
  315.         sprintf(cmd, "pcat %s | %s", catbuf, pager);
  316.     else
  317.         sprintf(cmd, "pcat %s", catbuf);
  318.  
  319.     execl("/bin/sh", "sh", "-c", cmd, 0);
  320. }
  321.  
  322. /*
  323.  * Findpage - determine the pathname of the requested page
  324.  *
  325.  * path = Findpage(title, sect);
  326.  *    path    is a pointer to the requested path
  327.  *    title    is a pointer to the title of the requested page
  328.  *    sect    is a pointer to the section to search, NULL if all sections
  329.  *
  330.  *    Findpage() returns a pointer to a buffer containing the path name
  331.  * of the unformatted version of the request man page in the form
  332.  * [apu]_man/man[1-8]/title.[1-8]. The user can specify a section to search.
  333.  * This is needed for cases like write(1) and write(2). If 'section' is given
  334.  * as NULL, all sections are searched. If no match for title.sect can be found,
  335.  * NULL is returned.
  336.  */
  337. char *
  338. Findpage(title, sect)
  339. char *title, *sect;
  340. {
  341.     int    fd, i, len, tlen;
  342.     long    lseek();
  343.     static    char    manbuf[BUFSIZ];
  344.     struct    direct    manent;
  345.  
  346.     tlen = strlen(title);
  347.     for (i = 0; i < NUMDIRS; i++) {
  348.         if (sect && *sect != *(mandirs[i] + 9))
  349.             continue;
  350.  
  351.         if ((fd = open(mandirs[i], O_RDONLY)) == -1)
  352.             continue;
  353.  
  354.         /*
  355.          * Skip "." and ".."
  356.          */
  357.         lseek(fd, 2*sizeof(manent), 0);
  358.         while (read(fd, &manent, sizeof(manent)) == sizeof(manent)) {
  359.             if (manent.d_ino == 0)
  360.                 continue;
  361.  
  362.             len = (int)(strchr(manent.d_name, '.') - manent.d_name);
  363.             if (!strncmp(manent.d_name, title, (len > tlen ? len : tlen))) {
  364.                 if (sect && strcmp(sect, manent.d_name+len+1))
  365.                     continue;
  366.  
  367.                 sprintf(manbuf, "%s/%s", mandirs[i], manent.d_name);
  368.                 return(manbuf);
  369.             }
  370.         }
  371.     }
  372.     return(NULL);
  373. }
  374. SHAR_EOF
  375. fi
  376. if test -f 'mkxref.c'
  377. then
  378.     echo shar: will not over-write existing file "'mkxref.c'"
  379. else
  380. cat  >'mkxref.c' <<\SHAR_EOF
  381.  
  382. /*
  383.  * mkxref - a program to list the titles from man pages
  384.  *
  385.  * All files in /usr/man/?_man/man? are searched for their title lines.
  386.  * A title line is the first line following the ".SH NAME" line. Nroff
  387.  * escapes are removed and the lines are written to the standard output.
  388.  * If no title line is found in a file, the file's name is printed on
  389.  * the standard error output.
  390.  *
  391.  * AUTHOR
  392.  *    Edward C. Bennett, edward@ukecc.UUCP
  393.  *
  394.  * Copyright 1985 by Edward C. Bennett
  395.  *
  396.  * Permission is given to alter this code as needed to adapt it to forign
  397.  * systems provided that this header is included and that the original
  398.  * author's name is preserved.
  399.  */
  400. #include <stdio.h>
  401. #include <ctype.h>
  402. #include <sys/types.h>
  403. #include <sys/dir.h>
  404. #include <fcntl.h>
  405. #include <string.h>
  406.  
  407. char    *mandirs[] = {
  408.     "u_man/man1",
  409.     "p_man/man2",
  410.     "p_man/man3",
  411.     "u_man/man6",
  412.     "p_man/man4",
  413.     "p_man/man5",
  414.     "a_man/man1",
  415.     "a_man/man7",
  416.     "a_man/man8",
  417. };
  418. #define    NUMDIRS        sizeof(mandirs)/sizeof(char *)
  419.  
  420. main(argc, argv)
  421. int argc;
  422. char **argv;
  423. {
  424.     char    manbuf[BUFSIZ];
  425.     int    fd, i, len;
  426.     long    lseek();
  427.     struct    direct    manent;
  428.  
  429.     chdir("/usr/man");
  430.  
  431.     for (i = 0; i < NUMDIRS; i++) {
  432.         if ((fd = open(mandirs[i], O_RDONLY)) == -1)
  433.             continue;
  434.  
  435.         /*
  436.          * Skip "." and ".."
  437.          */
  438.         lseek(fd, 2*sizeof(manent), 0);
  439.         while (read(fd, &manent, sizeof(manent)) == sizeof(manent)) {
  440.             if (manent.d_ino == 0)
  441.                 continue;
  442.  
  443.             sprintf(manbuf, "%s/%s", mandirs[i], manent.d_name);
  444.             Findname(manbuf);
  445.         }
  446.     }
  447. }
  448.  
  449. Findname(manfile)
  450. char *manfile;
  451. {
  452.     char    *p, line[BUFSIZ], section[4];
  453.     int    i, flag = 0;
  454.     FILE    *fp;
  455.  
  456.     strcpy(section, strchr(manfile, '.')+1);
  457.     if ((fp = fopen(manfile, "r")) == NULL)
  458.         return;
  459.  
  460.     while (fgets(line, BUFSIZ, fp) != NULL) {
  461.         if (!strncmp(line, ".SH NAME", 8)) {
  462.             flag++;
  463.             if ((p = fgets(line, BUFSIZ, fp)) != NULL) {
  464.                 i = 0;
  465.                 while (*p) {
  466.                     /*
  467.                      * Remove escapes
  468.                      */
  469.                     if (*p == '\\') {
  470.                         if (*++p == 's') {
  471.                             if (*++p == '-' || *p == '+') {
  472.                                 p++;
  473.                                 i--;
  474.                             }
  475.                             p++;
  476.                             i -= 2;
  477.                         }
  478.                         else if (*p == '*') {
  479.                             p += 2;
  480.                             i -= 3;
  481.                         }
  482.                         else if (*p == '&') {
  483.                             p++;
  484.                             i -= 2;
  485.                         }
  486.                         else if (*p == '-') {
  487.                             printf("(%s) ", section, ")");
  488.                             for (i += (int)(p - line) + strlen(section); i < 25; i++)
  489.                                 putchar(' ');
  490.                             putchar(*p++);
  491.                         }
  492.                         else
  493.                             putchar(*p++);
  494.                     }
  495.                     else
  496.                         putchar(*p++);
  497.                 }
  498.             }
  499.             break;
  500.         }
  501.     }
  502.     if (!flag)
  503.         fprintf(stderr, "%s\n", manfile);
  504.     fclose(fp);
  505.  
  506.     return;
  507. }
  508. SHAR_EOF
  509. fi
  510. if test -f 'updateall.c'
  511. then
  512.     echo shar: will not over-write existing file "'updateall.c'"
  513. else
  514. cat  >'updateall.c' <<\SHAR_EOF
  515. /*
  516.  * updateall - update the /usr/catman files
  517.  *
  518.  * All of the unformatted manual pages are checked against the copies
  519.  * in the /usr/catman directory. If the unformatted copy is newer, a
  520.  * new formatted and packed copy is placed in /usr/catman.
  521.  *
  522.  * AUTHOR
  523.  *    Edward C. Bennett, edward@ukecc.UUCP
  524.  *
  525.  * Copyright 1985 by Edward C. Bennett
  526.  *
  527.  * Permission is given to alter this code as needed to adapt it to forign
  528.  * systems provided that this header is included and that the original
  529.  * author's name is preserved.
  530.  */
  531. #include <stdio.h>
  532. #include <fcntl.h>
  533. #include <sys/types.h>
  534. #include <sys/stat.h>
  535. #include <sys/dir.h>
  536. #include <string.h>
  537.  
  538. char    *mandirs[] = {
  539.     "u_man/man1",
  540.     "p_man/man2",
  541.     "p_man/man3",
  542.     "u_man/man6",
  543.     "p_man/man4",
  544.     "p_man/man5",
  545.     "a_man/man1",
  546.     "a_man/man7",
  547.     "a_man/man8",
  548. };
  549. #define    NUMDIRS        sizeof(mandirs)/sizeof(char *)
  550.  
  551. main()
  552. {
  553.     char    manbuf[BUFSIZ], cmd[BUFSIZ], catbuf[BUFSIZ], catbufz[BUFSIZ];
  554.     int    status;
  555.     void    exit();
  556.     struct    stat    manstat, catstat;
  557.     int    fd, i;
  558.     long    lseek();
  559.     struct    direct    manent;
  560.  
  561.     chdir("/usr/man");
  562.  
  563.     for (i = 0; i < NUMDIRS; i++) {
  564.  
  565.         if ((fd = open(mandirs[i], O_RDONLY)) == -1)
  566.             continue;
  567.  
  568.         lseek(fd, 2*sizeof(manent), 0);
  569.         while (read(fd, &manent, sizeof(manent)) == sizeof(manent)) {
  570.             if (manent.d_ino == 0)
  571.                 continue;
  572.  
  573.             sprintf(manbuf, "%s/%s", mandirs[i], manent.d_name);
  574.  
  575.             strcpy(catbuf, "/usr/catman/");
  576.             strcat(catbuf, manbuf);
  577.             strcpy(catbufz, catbuf);
  578.             strcat(catbufz, ".z");
  579.  
  580.             stat(manbuf, &manstat);
  581.             if (stat(catbufz, &catstat) == -1)
  582.                 catstat.st_mtime = -1;
  583.  
  584.             if (catstat.st_mtime < manstat.st_mtime) {
  585.                 unlink(catbufz);
  586.                 if (fork() == 0) {
  587.                     sprintf(cmd, "nroff -man %s > %s", manbuf, catbuf);
  588.                     execl("/bin/sh", "sh", "-c", cmd, 0);
  589.                 }
  590.                 wait(&status);
  591.                 if (fork() == 0) {
  592.                     sprintf(cmd, "pack -f %s", catbuf);
  593.                     execl("/bin/sh", "sh", "-c", cmd, 0);
  594.                 }
  595.                 wait(&status);
  596.             }
  597.         }
  598.     }
  599. }
  600. SHAR_EOF
  601. fi
  602. :    End of shell archive
  603. exit 0
  604.  
  605. Edward C. Bennett
  606.  
  607. UUCP: ihnp4!cbosgd!ukma!ukecc!edward
  608.  
  609. /* A charter member of the Scooter bunch */
  610.  
  611. "Goodnight M.A."
  612.  
  613.  
  614.