xref: /csrg-svn/usr.bin/apropos/apropos.c (revision 69226)
131702Sbostic /*
266644Spendry  * Copyright (c) 1987, 1993, 1994
362098Sbostic  *	The Regents of the University of California.  All rights reserved.
433054Sbostic  *
542741Sbostic  * %sccs.include.redist.c%
631702Sbostic  */
731702Sbostic 
831702Sbostic #ifndef lint
962098Sbostic static char copyright[] =
1066644Spendry "@(#) Copyright (c) 1987, 1993, 1994\n\
1162098Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1233054Sbostic #endif /* not lint */
1331702Sbostic 
1431702Sbostic #ifndef lint
15*69226Sbostic static char sccsid[] = "@(#)apropos.c	8.8 (Berkeley) 05/04/95";
1633054Sbostic #endif /* not lint */
1731702Sbostic 
1831702Sbostic #include <sys/param.h>
1965268Sbostic #include <sys/queue.h>
2065268Sbostic 
2165268Sbostic #include <ctype.h>
2265268Sbostic #include <err.h>
2366566Spendry #include <limits.h>
2431702Sbostic #include <stdio.h>
2565268Sbostic #include <stdlib.h>
2642051Sbostic #include <string.h>
27*69226Sbostic #include <unistd.h>
2865268Sbostic 
2965268Sbostic #include "../man/config.h"
3040389Sbostic #include "../man/pathnames.h"
3131702Sbostic 
3242403Sbostic static int *found, foundman;
3342403Sbostic 
3466566Spendry void apropos __P((char **, char *, int));
3566566Spendry void lowstr __P((char *, char *));
3666566Spendry int match __P((char *, char *));
3766566Spendry void usage __P((void));
3866566Spendry 
3965268Sbostic int
main(argc,argv)4031702Sbostic main(argc, argv)
4133808Sbostic 	int argc;
4265268Sbostic 	char *argv[];
4331702Sbostic {
4465268Sbostic 	ENTRY *ep;
4565271Sbostic 	TAG *tp;
4665270Sbostic 	int ch, rv;
4765269Sbostic 	char *conffile, **p, *p_augment, *p_path;
4831702Sbostic 
4965269Sbostic 	conffile = NULL;
5040389Sbostic 	p_augment = p_path = NULL;
5165269Sbostic 	while ((ch = getopt(argc, argv, "C:M:m:P:")) != EOF)
5265268Sbostic 		switch (ch) {
5365269Sbostic 		case 'C':
5465269Sbostic 			conffile = optarg;
5565269Sbostic 			break;
5635534Sbostic 		case 'M':
5735534Sbostic 		case 'P':		/* backward compatible */
5840389Sbostic 			p_path = optarg;
5935534Sbostic 			break;
6040389Sbostic 		case 'm':
6140389Sbostic 			p_augment = optarg;
6240389Sbostic 			break;
6335534Sbostic 		case '?':
6435534Sbostic 		default:
6535534Sbostic 			usage();
6631702Sbostic 		}
6731702Sbostic 	argv += optind;
6831702Sbostic 	argc -= optind;
6940389Sbostic 
7031702Sbostic 	if (argc < 1)
7131702Sbostic 		usage();
7231702Sbostic 
7365270Sbostic 	if ((found = malloc((u_int)argc * sizeof(int))) == NULL)
7465268Sbostic 		err(1, NULL);
7565268Sbostic 	memset(found, 0, argc * sizeof(int));
7631702Sbostic 
7735534Sbostic 	for (p = argv; *p; ++p)			/* convert to lower-case */
7835534Sbostic 		lowstr(*p, *p);
7940389Sbostic 
8040389Sbostic 	if (p_augment)
8142403Sbostic 		apropos(argv, p_augment, 1);
8242403Sbostic 	if (p_path || (p_path = getenv("MANPATH")))
8342403Sbostic 		apropos(argv, p_path, 1);
8465268Sbostic 	else {
8565269Sbostic 		config(conffile);
8665271Sbostic 		ep = (tp = getlist("_whatdb")) == NULL ?
8765271Sbostic 		    NULL : tp->list.tqh_first;
8865271Sbostic 		for (; ep != NULL; ep = ep->q.tqe_next)
8965268Sbostic 			apropos(argv, ep->s, 0);
9065268Sbostic 	}
9142403Sbostic 
9266566Spendry 	if (!foundman)
9366566Spendry 		errx(1, "no %s file found", _PATH_WHATIS);
9466566Spendry 
9565270Sbostic 	rv = 1;
9640389Sbostic 	for (p = argv; *p; ++p)
9765270Sbostic 		if (found[p - argv])
9865270Sbostic 			rv = 0;
9965270Sbostic 		else
10040389Sbostic 			(void)printf("%s: nothing appropriate\n", *p);
10165270Sbostic 	exit(rv);
10240389Sbostic }
10340389Sbostic 
10466566Spendry void
apropos(argv,path,buildpath)10542403Sbostic apropos(argv, path, buildpath)
10640389Sbostic 	char **argv, *path;
10742403Sbostic 	int buildpath;
10840389Sbostic {
10966566Spendry 	char *end, *name, **p;
11066566Spendry 	char buf[LINE_MAX + 1], wbuf[LINE_MAX + 1];
11140389Sbostic 
11242403Sbostic 	for (name = path; name; name = end) {	/* through name list */
11366566Spendry 		if (end = strchr(name, ':'))
11442403Sbostic 			*end++ = '\0';
11542403Sbostic 
11642403Sbostic 		if (buildpath) {
11742403Sbostic 			char hold[MAXPATHLEN + 1];
11842403Sbostic 
11942403Sbostic 			(void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
12042403Sbostic 			name = hold;
12131702Sbostic 		}
12242403Sbostic 
12342403Sbostic 		if (!freopen(name, "r", stdin))
12433808Sbostic 			continue;
12533808Sbostic 
12642403Sbostic 		foundman = 1;
12742403Sbostic 
12835534Sbostic 		/* for each file found */
12942403Sbostic 		while (fgets(buf, sizeof(buf), stdin)) {
13066566Spendry 			if (!strchr(buf, '\n')) {
13166566Spendry 				warnx("%s: line too long", name);
13251191Sbostic 				continue;
13340389Sbostic 			}
13435534Sbostic 			lowstr(buf, wbuf);
13535534Sbostic 			for (p = argv; *p; ++p)
13635534Sbostic 				if (match(wbuf, *p)) {
13740389Sbostic 					(void)printf("%s", buf);
13835534Sbostic 					found[p - argv] = 1;
13931702Sbostic 
14033808Sbostic 					/* only print line once */
14135534Sbostic 					while (*++p)
14235534Sbostic 						if (match(wbuf, *p))
14335534Sbostic 							found[p - argv] = 1;
14433808Sbostic 					break;
14533808Sbostic 				}
14631702Sbostic 		}
14731702Sbostic 	}
14831702Sbostic }
14931702Sbostic 
15033808Sbostic /*
15135534Sbostic  * match --
15235534Sbostic  *	match anywhere the string appears
15333808Sbostic  */
15466566Spendry int
match(bp,str)15535534Sbostic match(bp, str)
15666566Spendry 	char *bp, *str;
15731702Sbostic {
15866566Spendry 	int len;
15966566Spendry 	char test;
16031702Sbostic 
16131702Sbostic 	if (!*bp)
16266566Spendry 		return (0);
16333808Sbostic 	/* backward compatible: everything matches empty string */
16431702Sbostic 	if (!*str)
16566566Spendry 		return (1);
16633808Sbostic 	for (test = *str++, len = strlen(str); *bp;)
16733808Sbostic 		if (test == *bp++ && !strncmp(bp, str, len))
16866566Spendry 			return (1);
16966566Spendry 	return (0);
17031702Sbostic }
17131702Sbostic 
17233808Sbostic /*
17333808Sbostic  * lowstr --
17433808Sbostic  *	convert a string to lower case
17533808Sbostic  */
17666566Spendry void
lowstr(from,to)17733808Sbostic lowstr(from, to)
17866566Spendry 	char *from, *to;
17933808Sbostic {
18066566Spendry 	char ch;
18135534Sbostic 
18235534Sbostic 	while ((ch = *from++) && ch != '\n')
18335534Sbostic 		*to++ = isupper(ch) ? tolower(ch) : ch;
18435534Sbostic 	*to = '\0';
18533808Sbostic }
18633808Sbostic 
18733808Sbostic /*
18833808Sbostic  * usage --
18933808Sbostic  *	print usage message and die
19033808Sbostic  */
19166566Spendry void
usage()19231702Sbostic usage()
19331702Sbostic {
19466566Spendry 
19540389Sbostic 	(void)fprintf(stderr,
19665269Sbostic 	    "usage: apropos [-C file] [-M path] [-m path] keyword ...\n");
19731702Sbostic 	exit(1);
19831702Sbostic }
199