home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume2 / help / help.c next >
Encoding:
C/C++ Source or Header  |  1991-08-07  |  6.1 KB  |  223 lines

  1. /*
  2.  * Name:    help.c
  3.  * Purpose: display help about commands & system features
  4.  * Syntax:  help [cmd]
  5.  * Comment: Help displays help screens on all user commands
  6.  *          as set up in the file /usr/lib/helpfile.
  7.  *          It is particularly useful on systems with restricted 
  8.  *          diskspace, where it is not practical to keep the manuals
  9.  *          on-line.
  10.  *          The command is patterned after the MKS Toolkit command
  11.  *          of the same name. If no /usr/lib/helpindex file exists, or if
  12.  *          it is older than the helpfile, a new helpindex will be
  13.  *          created to allow faster access to the helpscreens by
  14.  *          means of fseek().
  15.  *          Desirable enhancements would include the possibility to
  16.  *          have help look in an environment variable HELPFILE for
  17.  *          an alternate or additional helpfile,
  18.  *              [ Done by John Plocher - uses HELPDIR to set the directory
  19.  *              where the help file and its index are.  It also uses HELPFILE
  20.  *              to give the name of the data file ($HELPFILE.idx is the index)
  21.  *              defaults are "/usr/lib" and "helpfile" ]
  22.  *          and/or to have help look in $HOME/.helpfile if a command
  23.  *          is not found in the default helpfile.
  24.  *          Another useful feature would be the possibility of using
  25.  *          a pager specified by $PAGER to output the help info, since
  26.  *          a few entries (stty, vi, ...) are longer than one screen.
  27.  *          No doubt the coding could be considerably improved, and
  28.  *          any suggestions would be more than welcome.
  29.  * Author:  Wolf Paul, ihnp4!killer!dcs!wnp
  30.  * Date:    Dec. 18, 1987
  31.  *
  32.  *    Revision Control Information
  33.  *
  34.  *    Last edited by:    $Author: plocher $
  35.  *            $Revision: 1.1 $
  36.  *    Last modified:    $Date: 87/12/26 23:34:50 $
  37.  *    Source is in:    $Source: /u/microport/src/help/RCS/help.c,v $
  38.  *
  39.  *    Release state:    $State: Posted $
  40.  *
  41.  * Modification Log
  42.  * ----------------
  43.  *
  44.  *    $Log:    help.c,v $
  45.  *    Revision 1.1  87/12/26  23:34:50  plocher
  46.  *    Added enviroment variables for HELPDIR and HELPFILE
  47.  *    
  48.  */
  49.  
  50. #ifndef lint
  51.     static char rcsid[] =
  52.      "$Header: help.c,v 1.1 87/12/26 23:34:50 plocher Posted $";
  53. #endif
  54.  
  55. #include <stdio.h>
  56. #include <ctype.h>
  57. #include <sys/types.h>
  58. #include <sys/stat.h>
  59.  
  60. #define MAXLINE     134
  61. #define HELPDIR        "/usr/lib"        /* Added by John Plocher */
  62. #define HELPFILE    "helpfile"        /* .. */
  63. #define INDEX        ".idx"            /* .. */
  64.  
  65. char helpfilename[128];        /* John Plocher */
  66. char helpidxname[128];        /* .. */
  67.  
  68. main(argc, argv)
  69. int argc;
  70. char **argv;
  71. {
  72.     struct
  73.     {
  74.         char name[15];
  75.         long offset;
  76.     } entry;                /* helpindex entries for each command */
  77.  
  78.     struct stat sbuf1, sbuf2;    /* stat buffers for helpfile & helpindex */
  79.     char *command, *line, Line[MAXLINE];
  80.     register char    *cp;        /* John Plocher */
  81.     extern char    *getenv();        /* .. */
  82.     int status;
  83.     FILE *ifp, *hfp;        /* file pointers for helpfile and helpindex */
  84.     
  85.     if ( argc == 1 )        /* If no arguments, ... */
  86.         command = "help";    /* ... default to "help help" */
  87.     else
  88.         command = argv[1];    /* else look for command in argv[1] */
  89.  
  90.  
  91.     /*        Added by John Plocher Sat Dec 26 22:02:09 CST 1987
  92.      * Look for:
  93.      *    getenv("HELPDIR") + getenv("HELPFILE")
  94.      *    getenv("HELPDIR") + "helpfile"
  95.      *    "/usr/lib"          + getenv("HELPFILE")
  96.      *    "/usr/lib"          + "helpfile"
  97.      */
  98.     if ((cp = getenv("HELPDIR")) != NULL)    /* if a dir is given, use it */
  99.         strcpy(helpidxname, cp);
  100.     else
  101.         strcpy(helpidxname, HELPDIR);
  102.     strcpy(helpfilename, helpidxname);
  103.     strcat(helpfilename, "/");
  104.  
  105.     if ((cp = getenv("HELPFILE")) != NULL)    /* if a filename is given, use it */
  106.         strcat(helpfilename, cp);
  107.     else
  108.         strcat(helpfilename, HELPFILE);
  109.  
  110.     strcpy(helpidxname, helpfilename);        /* make a name for the index file */
  111.     strcat(helpidxname, INDEX);
  112.  
  113.     stat(helpfilename, &sbuf1);    /* get mtime for helpfile */
  114.     status=access(helpidxname, 0);
  115.     if ( status == 0 )    /* if helpindex exists ... */
  116.     {
  117.         stat(helpidxname, &sbuf2);    /* get mtime for helpindex */
  118.     }
  119.     if ( (status != 0) ||             /* if there is no helpindex ... */
  120.         ((time_t)sbuf1.st_mtime > (time_t)sbuf2.st_mtime) )
  121.                                     /* or if it is older than helpfile */
  122.     {
  123.         buildindex();        /* build a new helpindex */
  124.     }
  125.  
  126.     if ( (ifp=fopen(helpidxname, "r")) == NULL )
  127.     {
  128.         fprintf(stderr, "Can't read %s\n", helpidxname);
  129.         exit(-1);
  130.     }
  131.     
  132.     while ( 1 )        /* look for index entry for "command" */
  133.     {
  134.         status=fread(&entry, sizeof(entry), 1, ifp);
  135.         if ( status==0 ) /* quit at end of index file */
  136.         {
  137.             fprintf(stderr, "No help for %s\n", command);
  138.             fclose(ifp);
  139.             exit(1);        }
  140.         if ( strcmp(entry.name, command) == 0 ) /* quit when we find it */
  141.         {
  142.             fclose(ifp);
  143.             break;
  144.         }
  145.     }
  146.  
  147.     if ((hfp=fopen(helpfilename, "r")) == NULL )
  148.     {
  149.         fprintf(stderr, "Can't open %s\n", helpfilename);
  150.         exit(-1);
  151.     }
  152.  
  153.     fseek(hfp, entry.offset, 0);    /* go to the help entry */
  154.  
  155.     while ( 1 )            /* just copy lines to stdout */
  156.     {
  157.         line = fgets(Line, MAXLINE, hfp);
  158.         if ( line == (char *) NULL || line[0] == '#' )
  159.                         /* until another entry starts */
  160.             break;
  161.         fputs(line,stdout);
  162.     }
  163.  
  164.     fclose(hfp);
  165. }
  166.  
  167. buildindex()
  168. {
  169.     FILE *hfp, *ifp;
  170.     struct {
  171.         char name[15];
  172.         long offset;
  173.     } entry;
  174.     char Line[MAXLINE];
  175.     char *line;
  176.     int i,j;
  177.  
  178.  
  179.     unlink(helpidxname); /* remove old index file */
  180.     if ( (hfp=fopen(helpfilename, "r")) == NULL )
  181.     {
  182.         fprintf(stderr,"buildindex: Can't read %s\n", helpfilename);
  183.         exit(-1);
  184.     }
  185.     if ( (ifp=fopen(helpidxname, "w")) == NULL )
  186.     {
  187.         fprintf(stderr, "buildindex: Can't write %s\n", helpidxname);
  188.         exit(-1);
  189.     }
  190.  
  191.     while (1)    /* Read thru helpfile ... */
  192.     {
  193.         entry.offset=(long) 0;
  194.         line = fgets(Line, MAXLINE, hfp);
  195.         if ( line == (char *) NULL ) break;
  196.         if ( line[0] == '#' )    /* and for each help entry ... */
  197.         {
  198.             line++;
  199.             while ( isspace(line[0]) ) line++;
  200.             i=j=0;
  201.             while ( line[i] != '\0' )
  202.             {
  203.                 if ( line[i] == '\n' ) break;
  204.                 while ( line[i] == ' ' || line[i] == ',' ) i++;
  205.                 while ( !isspace(line[i] ) &&
  206.                         line[i] != ',') /* save its name ... */
  207.                 {
  208.                     entry.name[j] = line[i];
  209.                     i++; j++;
  210.                 }
  211.                 while ( j < 15 )
  212.                     entry.name[j++] = '\0';
  213.                 j = 0;
  214.                 entry.offset=ftell(hfp);    /* and its offset ... */
  215.                 fwrite(&entry, sizeof(entry), 1, ifp);
  216.                                         /* and write it to indexfile */
  217.             }
  218.         }
  219.     }
  220.     fclose(hfp);
  221.     fclose(ifp);
  222. }
  223.