home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
utility
/
whatis20.zoo
/
apropos.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-13
|
8KB
|
434 lines
#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);
}