home *** CD-ROM | disk | FTP | other *** search
- #undef DEBUG
-
- /*
- * apropos - find pertinent on-line documentation
- *
- * apropos name ...
- */
-
- static char *rcsid_apropos_c = "$Id: apropos.c,v 2.0 1992/09/13 05:02:44 rosenkra Exp $";
- /*
- * $Log: apropos.c,v $
- * Revision 2.0 1992/09/13 05:02:44 rosenkra
- * total rewrite. this if first rev of this file.
- *
- *
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
-
-
- #include "whatis.h"
-
-
- /*
- * we only need one record here. we read a record and check all the
- * command line args against it for a match
- */
- struct rec r;
-
- char *libpath = MANPATH; /* path to database files (-P) */
- int debugging = 0; /* for -d */
-
-
- /*
- * fcn prototypes
- */
- void apropos (int, int, int, char **);
- int match_up (char *, char *);
- int advance (char *, char *);
- int cmp_ign_case (int, int);
- void usage (int);
- int parse_record (char *, struct rec *);
- void print_record (int, struct rec *);
- #ifdef CHECK_MAGIC
- int check_magic (void);
- #endif
-
-
-
-
- /*------------------------------*/
- /* main */
- /*------------------------------*/
- void main (int argc, char *argv[])
- {
- int sect = -1;
- int verbose = 0;
- char *lpath;
- char *ps;
-
-
-
- /*
- * see if there is MANPATH in env. use it over default...
- */
- if ((lpath = getenv ("MANPATH")) != (char *) NULL)
- libpath = lpath;
- else if ((lpath = getenv ("MANDIR")) != (char *) NULL)
- libpath = lpath;
- #ifdef DEBUG
- else
- fprintf (stderr, "apropos: environment variable MANPATH not set, using default\n");
- #endif
-
-
- /*
- * parse args
- */
- for (argc--, argv++; argc && **argv == '-'; argc--, argv++)
- {
- switch (*(*argv+1))
- {
- case 'P': /* path for db */
- case 'M':
- argc--, argv++;
- if (argc < 1)
- usage (1);
- libpath = *argv;
- break;
-
- case 's': /* specific section */
- argc--, argv++;
- if (argc < 1)
- usage (1);
- sect = **argv;
- break;
-
- case 'd': /* debug mode */
- debugging = 1;
- break;
-
- case 'h': /* help */
- usage (0);
- /* NOTREACHED */
- }
- }
-
-
-
- /*
- * apropos what?
- */
- if (argc == 0)
- {
- fprintf (stderr,
- "apropos: you must specify an argument. consider using whatisin.\n");
- usage (1);
- }
-
-
-
- /*
- * not documented: if first arg is a number, use it for section...
- */
- if (isdigit(**argv))
- {
- sect = **argv;
- argc--, argv++;
- }
-
-
-
- /*
- * do it. if specific section, search it only. else search all
- * sections
- */
- if (sect != -1)
- {
- apropos (verbose, sect, argc, argv);
- }
- else
- {
- for (ps = SECTIONS; *ps; ps++)
- {
- sect = *ps;
- apropos (verbose, sect, argc, argv);
- }
- }
-
-
- exit (0);
- }
-
-
-
- /*------------------------------*/
- /* apropos */
- /*------------------------------*/
- void apropos (int verbose, int sect, int argc, char **argv)
- {
- #define MAX_ARGS 100
-
- char dbname[256];
- char buf[REC_SIZE];
- char srch[REC_SIZE];
- register char **vp;
- int notfound[MAX_ARGS];
- int i, j;
-
-
-
- /*
- * FIXME: we should allocate space for the notfound list.
- */
- if (argc > MAX_ARGS)
- argc = MAX_ARGS;
-
-
-
- /*
- * set up db name. section is really a single ascii char, not an
- * int. this is so we can have whatis for local, new, etc.
- */
- if (sect == -1)
- /* orig behavior (just single "whatis" file, never used here) */
- sprintf (dbname, "%s%s%s", libpath, SLASH, WHATIS);
- else
- /* new: whatis._[0-9lno]_ */
- sprintf (dbname, "%s%s%s._%c_", libpath, SLASH, WHATIS, sect);
-
-
-
- /*
- * reopen stdin as this file...
- */
- if (debugging)
- fprintf (stderr, "checking database file %s...\n", dbname);
- if (freopen (dbname, "r", stdin) == (FILE *) NULL)
- {
- /* if (verbose || debugging)*/
- if (debugging)
- fprintf (stderr,
- "apropos: could not access file %s\n", dbname);
-
- return;
- }
-
-
-
-
- #ifdef CHECK_MAGIC
- /*
- * check file's magic
- */
- if (check_magic ())
- {
- fprintf (stderr,
- "whatis: magic number is wrong for file %s\n",
- dbname);
-
- return;
- }
- #endif
-
-
-
-
- /*
- * read file and compare. first assume we will not find anything
- * and flag list...
- */
- for (i = 0; i < MAX_ARGS; i++)
- notfound[i] = 1;
- while (1)
- {
- /*
- * get raw record from file
- */
- fgets (buf, REC_SIZE-1, stdin);
- if (feof (stdin))
- break;
- if (debugging)
- fprintf (stderr, "%s", buf);
-
-
-
- /*
- * skip comment or blank lines
- */
- if (buf[0] == '#' || buf[0] == '\0' || buf[0] == '\n')
- continue;
-
-
-
- /*
- * parse the record and store in r
- */
- parse_record (buf, &r);
-
- if (debugging)
- {
- fprintf (stderr, "name: %s\n", r.name ? r.name : "(NULL)");
- fprintf (stderr, "section: %s\n", r.section ? r.section : "(NULL)");
- fprintf (stderr, "subsect: %s\n", r.subsect ? r.subsect : "(NULL)");
- fprintf (stderr, "desc: %s\n", r.desc ? r.desc : "(NULL)");
- }
-
-
-
- /*
- * compare record's name field to all args from orig
- * command line. if we find one, flag notfound list
- */
- for (i = 0, vp = argv; i < argc && *vp; vp++, i++)
- {
- /*
- * make a long list of things to search
- */
- srch[0] = '\0';
- if (r.name)
- {
- strcat (srch, r.name);
- strcat (srch, " ");
- }
- if (r.desc)
- {
- strcat (srch, r.desc);
- strcat (srch, " ");
- }
- for (j = 0; j < MAX_ALIAS; j++)
- {
- if (r.alias[j] == NULL)
- break;
- strcat (srch, r.alias[j]);
- strcat (srch, " ");
- }
- for (j = 0; j < MAX_KEYW; j++)
- {
- if (r.keyw[j] == NULL)
- break;
- strcat (srch, r.keyw[j]);
- strcat (srch, " ");
- }
-
-
-
- /*
- * check for a match...
- */
- if (match_up (srch, *vp))
- {
- print_record (verbose, &r);
- notfound[i] = 0;
- }
- }
- }
-
-
-
- /*
- * print a message if we didn't find anything for the cmdline arg
- */
- if (verbose)
- {
- for (i = 0; i < argc; i++)
- {
- if (notfound[i])
- {
- printf ("nothing appropriate in section %c for %s\n",
- sect, argv[i]);
- }
- }
- }
-
- return;
- }
-
-
-
-
- /*------------------------------*/
- /* match_up */
- /*------------------------------*/
- int match_up (char *buf, char *str)
- {
-
- /*
- * search for string in str from a list contained in buf. this part
- * just advances a ptr to buf and calls a lower level routine. ret 1
- * if there is a match, else 0.
- */
-
- register char *pbuf;
-
- for (pbuf = buf; *pbuf; pbuf++)
- if (advance (pbuf, str))
- return (1);
-
- return (0);
- }
-
-
-
-
- /*------------------------------*/
- /* advance */
- /*------------------------------*/
- int advance (char *s1, char *s2)
- {
-
- /*
- * main matching driver. advances along each string. cmp_ign_case does
- * theactual char match. ret 1 if match, else 0. search is finished when
- * s2 is at EOS.
- */
-
- while (*s1 && *s2
- && ((*s1 == *s2) || cmp_ign_case ((int) (*s1), (int) (*s2))))
- s1++, s2++;
-
- if (*s2 == 0)
- return (1);
-
- return (0);
- }
-
-
-
-
- /*------------------------------*/
- /* cmp_ign_case */
- /*------------------------------*/
- int cmp_ign_case (int c1, int c2)
- {
-
- /*
- * char matching part. ignores case. must be alpha chars only! if
- * chars match, ret 1, else 0. c1 should probably always be alpha,
- * but check anyway. c2 comes from user. check it first for possible
- * quick exit. compare in lower case (since that is more probable
- * and the tolower could be skipped).
- *
- * consider inlining this...
- */
-
- if (!isalpha (c2) || !isalpha (c1)) return (0);
- if (isupper (c1)) c1 = tolower (c1);
- if (isupper (c2)) c2 = tolower (c2);
-
- return (c1 == c2);
- }
-
-
-
-
- /*------------------------------*/
- /* usage */
- /*------------------------------*/
- void usage (int excode)
- {
- #define U(x) fprintf(stderr,x);
-
- U("usage: apropos [-P path] [-s section] name ...\n");
- U(" -P path alternative path to databases (MANPATH)\n");
- U(" -s section limit search to single section, not all\n");
- U(" name name of a keyword (any single word).\n");
-
- exit (excode);
- }
-
-