home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume7 / man.7300 / man.c next >
C/C++ Source or Header  |  1989-07-21  |  8KB  |  276 lines

  1. /***************************************************************************\
  2.  * File name:        man.c                              *
  3.  *                                       *
  4.  * Purpose:        Provide a better user interface to read the manual *
  5.  *            pages.                           *
  6.  *                                       *
  7.  * Programmer:        Gil Kloepfer, Jr.  ICUS Software Systems       *
  8.  *                                       *
  9.  * Revision history:     8-Jun-89  0.1     Program created [Beta release]       *
  10.  *             12-Jul-89  1.0     Program released
  11.  *                                       *
  12.  * Restrictions:    Requires Doug Gwyn's "dirent" subroutine package.  *
  13.  *            Optionally requires "compress" package, as well    *
  14.  *            as links to it called "zcat," and a text pager     *
  15.  *            such as    "more."  Having "nroff" is also a plus.       *
  16.  *                                       *
  17.  *            Program has been tested on the UNIX-pc 3B1.  It    *
  18.  *            should work on other systems, but this hasn't been *
  19.  *            tested.                           *
  20.  *                                       *
  21.  * Usage:        Invoked from the shell or a script by:           *
  22.  *                $ man [section] command               *
  23.  *                                       *
  24.  *            This manual page interface provides the following  *
  25.  *            features:                       *
  26.  *                 o  You can "man" compressed manual pages   *
  27.  *                o  You don't have to know if the manual    *
  28.  *                   pages are unformatted (/usr/man/man?)   *
  29.  *                   or formatted (/usr/man/cat?).       *
  30.  *                o  You don't have to know what section     *
  31.  *                   the manual page is in (and it tells you *
  32.  *                   which one)                   *
  33.  *                o  You get automatic paging when you       *
  34.  *                   invoke man from a tty           *
  35.  *                                       *
  36.  * Compiled by:        $ cc -v -O -o man man.c -ldirent -s           *
  37.  *                                       *
  38.  * Copyright/        (C) 1989 Gil Kloepfer, Jr., ICUS Software Systems  *
  39.  * Disclaimer:        All Rights Reserved                   *
  40.  *                                       *
  41.  *            Permission is granted to use, copy, or redistribute*
  42.  *            this software provided that this header in its     *
  43.  *            entirety is kept in the source code, that all      *
  44.  *            copyright notices are left intact, and that it is  *
  45.  *            not distributed or used for monetary gain of any   *
  46.  *            kind without the express, written permission of    *
  47.  *            the copyright holder(s).  Furthermore, if this     *
  48.  *            software is modified, all changes should be mailed *
  49.  *            to icus!gil.                       *
  50.  *                                       *
  51.  *            The user of this program agrees and understands    *
  52.  *            that this software is distributed on an "as-is"    *
  53.  *            basis, and shall not use this program as the basis *
  54.  *            for any claims, now or in the future, against      *
  55.  *            any individual, organization, or entity.       *
  56. \***************************************************************************/
  57.  
  58. #include <stdio.h>
  59. #include <sys/types.h>
  60. #include <dirent.h>
  61. #include <sys/stat.h>
  62.  
  63. #define    PROCD        "/usr/man/cat"    /* dir prefix for preformatted pages */
  64. #define    NPROCD        "/usr/man/man"    /* dir prefix for nroff format pages */
  65. #define    MAXPATH        128        /* maximum size of path to man page */
  66.  
  67. /* undefine any of the following if your system doesn't have them */
  68.  
  69. #define    TYPECOMP    "/usr/bin/zcat"    /* command to display a compressed file */
  70. #define    FORMAT        "/usr/bin/nroff -man" /* command to format a manual page */
  71. #define    PAGER        "/usr/bin/more"    /* system command to page a file */
  72.  
  73. /* Don't play with these constants!! */
  74. #define    C_PROC        1
  75. #define    C_NPROC        2
  76.  
  77.  
  78. main(argc,argv)
  79. int argc;
  80. char *argv[];
  81. {
  82.     int    argno, section, kind, lookup();
  83.     char    command[20], pagename[MAXPATH];
  84.  
  85.     /* Process the command line arguments */
  86.  
  87.     switch(argc) {
  88.     case 2:  /* just the command name */
  89.         strncpy(command,argv[1],20);
  90.         section=0;
  91.         break;
  92.  
  93.     case 3:  /* the section and command name */
  94.         sscanf(argv[1], "%d", §ion);
  95.         strncpy(command,argv[2],20);
  96.         break;
  97.  
  98.     default:  /* invalid .. display the usage statement */
  99.         fprintf(stderr,"usage: %s [section] command\n", argv[0]);
  100.         exit(1);
  101.     }
  102.  
  103.     /*
  104.      * If the section is not specified explicitly, try to find
  105.      * the manual page in the first directory where it's encountered.
  106.      */
  107.  
  108.     if (section == 0) {
  109.         for (section=1; section<=8; section++)
  110.             if (lookup(command,section,pagename,&kind)) {
  111.                 fprintf(stderr,"%s: assuming %s from section %d\n",
  112.                     argv[0], command, section);
  113.                 printpage(pagename,kind);
  114.                 exit(0);
  115.             }
  116.         fprintf(stderr,"%s: cannot find %s in the manual\n",
  117.                 argv[0], command);
  118.         exit(2);
  119.     }
  120.  
  121.     /*
  122.      * If the user specified a section, then see if we can find it
  123.      * there .. if so, print the page
  124.      */
  125.  
  126.     if (lookup(command,section,pagename,&kind)) {
  127.         printpage(pagename,kind);
  128.         exit(0);
  129.     } else {
  130.         fprintf(stderr,"%s: cannot find %s in section %d\n",
  131.             argv[0], command, section);
  132.         exit(2);
  133.     }
  134. }
  135.  
  136.  
  137. /*
  138.  * Function lookup returns 0 on failure and 1 on success.  It will look
  139.  * through the directories for section and try to find the manual page
  140.  * for command.  If it finds it, the entire filename is returned as
  141.  * pagename.  "kind" passes along whether the name was found in the
  142.  * processed or unprocessed directory phases
  143.  */
  144.  
  145. int lookup(command,section,pagename,kind)
  146. char *command, *pagename;
  147. int section, *kind;
  148. {
  149.     int    passno, cmpman();
  150.     char    fullpath[MAXPATH];
  151.     DIR    *mdir;
  152.     struct dirent *dentry;
  153.  
  154.     /*
  155.      * Look through the formatted directory first to see if we
  156.      * can get one that's formatted.  The second pass gets
  157.      * the formatted directory.  This looks kludgy, but it's
  158.      * pretty neat nevertheless.
  159.      */
  160.  
  161.     for (passno=1; passno<=2; passno++) {
  162.         switch(passno) {
  163.         case 1:  /* check formatted directory */
  164.             sprintf(fullpath, "%s%d", PROCD, section);
  165.             *kind = C_PROC;
  166.             break;
  167.  
  168.         case 2:  /* check unformatted directory */
  169.             sprintf(fullpath, "%s%d", NPROCD, section);
  170.             *kind = C_NPROC;
  171.             break;
  172.         }
  173.  
  174.         if ((mdir=opendir(fullpath)) != NULL)
  175.             while ((dentry=readdir(mdir)) != NULL)
  176.                 if (cmpman(dentry->d_name,command) == 0) {
  177.                     closedir(mdir);
  178.                     sprintf(pagename, "%s/%s", fullpath,
  179.                         dentry->d_name);
  180.                     return(1);
  181.                 }
  182.  
  183.         closedir(mdir);
  184.     }
  185.     return(0);
  186. }
  187.  
  188.  
  189. /*
  190.  * Compare name with command and see if it matches before the period
  191.  * so we can crown it the matching manual page for command
  192.  */
  193.  
  194. int cmpman(name,command)
  195. char *name, *command;
  196. {
  197.     while ((*name == *command) && *name != '\0' && *command != '\0') {
  198.         name++;
  199.         command++;
  200.     }
  201.  
  202.     if (*name == '.' && *command == '\0') return(0);  /* OK */
  203.     if (*command == *name) return(0);  /* also OK */
  204.  
  205.     return(1);  /* all other cases fail */
  206. }
  207.  
  208.  
  209. /*
  210.  * Printpage prints a manual page.  It formats the page depending on
  211.  * where it comes from, and invokes the system pager depending on
  212.  * whether output is to a tty or a file/pipe
  213.  */
  214.  
  215. printpage(pageloc,form)
  216. char *pageloc;
  217. int form;
  218. {
  219.     int    compress, endstr, ttypage;
  220.     char    cmdline[512];
  221.  
  222.     /* See if we're dealing with a compressed file (.Z) */
  223.  
  224.     endstr=strlen(pageloc);
  225.     if (pageloc[endstr-2]=='.' && pageloc[endstr-1]=='Z')
  226.         compress=1;
  227.     else
  228.         compress=0;
  229.  
  230. #ifndef    TYPECOMP
  231.     if (compress) {
  232.         fprintf(stdout,"%s: compressed files not supported\n",
  233.                 argv[0]);
  234.         exit(2);
  235.     }
  236. #endif
  237.  
  238.     /* If we're a tty, page this using whatever our pager is */
  239.  
  240. #ifdef PAGER
  241.     if (isatty(1))
  242.         ttypage=1;
  243.     else
  244.         ttypage=0;
  245. #else
  246.     ttypage=0;
  247. #endif
  248.  
  249.     /*
  250.      * Setup command line.  This is some really sick code, but
  251.      * how else are we to do it?  I can think of only one way, but
  252.      * it's kind of wasteful of system resources...
  253.      */
  254.  
  255.     if (compress) {
  256.         if (form == C_NPROC)
  257.             sprintf(cmdline, "%s %s | %s", TYPECOMP, pageloc, FORMAT);
  258.         else
  259.             sprintf(cmdline, "%s %s", TYPECOMP, pageloc);
  260.     } else {
  261.         if (form == C_NPROC)
  262.             sprintf(cmdline, "%s %s", FORMAT, pageloc);
  263.         else
  264.             sprintf(cmdline, "/bin/cat %s", pageloc);
  265.     }
  266.  
  267.     if (ttypage) {
  268.         strcat(cmdline," | ");
  269.         strcat(cmdline,PAGER);
  270.     }
  271.  
  272.     /* Invoke command */
  273.  
  274.     system(cmdline);
  275. }
  276.