xref: /csrg-svn/usr.bin/apropos/apropos.c (revision 65271)
131702Sbostic /*
262098Sbostic  * Copyright (c) 1987, 1993
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[] =
1062098Sbostic "@(#) Copyright (c) 1987, 1993\n\
1162098Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1233054Sbostic #endif /* not lint */
1331702Sbostic 
1431702Sbostic #ifndef lint
15*65271Sbostic static char sccsid[] = "@(#)apropos.c	8.5 (Berkeley) 01/02/94";
1633054Sbostic #endif /* not lint */
1731702Sbostic 
1831702Sbostic #include <sys/param.h>
1965268Sbostic #include <sys/queue.h>
2065268Sbostic 
2165268Sbostic #include <ctype.h>
2265268Sbostic #include <err.h>
2331702Sbostic #include <stdio.h>
2465268Sbostic #include <stdlib.h>
2542051Sbostic #include <string.h>
2665268Sbostic 
2765268Sbostic #include "../man/config.h"
2840389Sbostic #include "../man/pathnames.h"
2931702Sbostic 
3051191Sbostic #define	MAXLINELEN	1024			/* max line handled */
3131702Sbostic 
3242403Sbostic static int *found, foundman;
3342403Sbostic 
3465268Sbostic int
3531702Sbostic main(argc, argv)
3633808Sbostic 	int argc;
3765268Sbostic 	char *argv[];
3831702Sbostic {
3933808Sbostic 	extern char *optarg;
4033808Sbostic 	extern int optind;
4165268Sbostic 	ENTRY *ep;
42*65271Sbostic 	TAG *tp;
4365270Sbostic 	int ch, rv;
4465269Sbostic 	char *conffile, **p, *p_augment, *p_path;
4531702Sbostic 
4665269Sbostic 	conffile = NULL;
4740389Sbostic 	p_augment = p_path = NULL;
4865269Sbostic 	while ((ch = getopt(argc, argv, "C:M:m:P:")) != EOF)
4965268Sbostic 		switch (ch) {
5065269Sbostic 		case 'C':
5165269Sbostic 			conffile = optarg;
5265269Sbostic 			break;
5335534Sbostic 		case 'M':
5435534Sbostic 		case 'P':		/* backward compatible */
5540389Sbostic 			p_path = optarg;
5635534Sbostic 			break;
5740389Sbostic 		case 'm':
5840389Sbostic 			p_augment = optarg;
5940389Sbostic 			break;
6035534Sbostic 		case '?':
6135534Sbostic 		default:
6235534Sbostic 			usage();
6331702Sbostic 		}
6431702Sbostic 	argv += optind;
6531702Sbostic 	argc -= optind;
6640389Sbostic 
6731702Sbostic 	if (argc < 1)
6831702Sbostic 		usage();
6931702Sbostic 
7065270Sbostic 	if ((found = malloc((u_int)argc * sizeof(int))) == NULL)
7165268Sbostic 		err(1, NULL);
7265268Sbostic 	memset(found, 0, argc * sizeof(int));
7331702Sbostic 
7435534Sbostic 	for (p = argv; *p; ++p)			/* convert to lower-case */
7535534Sbostic 		lowstr(*p, *p);
7640389Sbostic 
7740389Sbostic 	if (p_augment)
7842403Sbostic 		apropos(argv, p_augment, 1);
7942403Sbostic 	if (p_path || (p_path = getenv("MANPATH")))
8042403Sbostic 		apropos(argv, p_path, 1);
8165268Sbostic 	else {
8265269Sbostic 		config(conffile);
83*65271Sbostic 		ep = (tp = getlist("_whatdb")) == NULL ?
84*65271Sbostic 		    NULL : tp->list.tqh_first;
85*65271Sbostic 		for (; ep != NULL; ep = ep->q.tqe_next)
8665268Sbostic 			apropos(argv, ep->s, 0);
8765268Sbostic 	}
8842403Sbostic 
8940389Sbostic 	if (!foundman) {
9042403Sbostic 		(void)fprintf(stderr,
9165268Sbostic 		    "apropos: no %s file found.\n", _PATH_WHATIS);
9240389Sbostic 		exit(1);
9340389Sbostic 	}
9465270Sbostic 	rv = 1;
9540389Sbostic 	for (p = argv; *p; ++p)
9665270Sbostic 		if (found[p - argv])
9765270Sbostic 			rv = 0;
9865270Sbostic 		else
9940389Sbostic 			(void)printf("%s: nothing appropriate\n", *p);
10065270Sbostic 	exit(rv);
10140389Sbostic }
10240389Sbostic 
10342403Sbostic apropos(argv, path, buildpath)
10440389Sbostic 	char **argv, *path;
10542403Sbostic 	int buildpath;
10640389Sbostic {
10742403Sbostic 	register char *end, *name, **p;
10840389Sbostic 	char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
10940389Sbostic 
11042403Sbostic 	for (name = path; name; name = end) {	/* through name list */
11142403Sbostic 		if (end = index(name, ':'))
11242403Sbostic 			*end++ = '\0';
11342403Sbostic 
11442403Sbostic 		if (buildpath) {
11542403Sbostic 			char hold[MAXPATHLEN + 1];
11642403Sbostic 
11742403Sbostic 			(void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
11842403Sbostic 			name = hold;
11931702Sbostic 		}
12042403Sbostic 
12142403Sbostic 		if (!freopen(name, "r", stdin))
12233808Sbostic 			continue;
12333808Sbostic 
12442403Sbostic 		foundman = 1;
12542403Sbostic 
12635534Sbostic 		/* for each file found */
12742403Sbostic 		while (fgets(buf, sizeof(buf), stdin)) {
12840389Sbostic 			if (!index(buf, '\n')) {
12940389Sbostic 				(void)fprintf(stderr,
13042403Sbostic 				    "apropos: %s line too long.\n", name);
13151191Sbostic 				continue;
13240389Sbostic 			}
13335534Sbostic 			lowstr(buf, wbuf);
13435534Sbostic 			for (p = argv; *p; ++p)
13535534Sbostic 				if (match(wbuf, *p)) {
13640389Sbostic 					(void)printf("%s", buf);
13735534Sbostic 					found[p - argv] = 1;
13831702Sbostic 
13933808Sbostic 					/* only print line once */
14035534Sbostic 					while (*++p)
14135534Sbostic 						if (match(wbuf, *p))
14235534Sbostic 							found[p - argv] = 1;
14333808Sbostic 					break;
14433808Sbostic 				}
14531702Sbostic 		}
14631702Sbostic 	}
14731702Sbostic }
14831702Sbostic 
14933808Sbostic /*
15035534Sbostic  * match --
15135534Sbostic  *	match anywhere the string appears
15233808Sbostic  */
15335534Sbostic match(bp, str)
15433808Sbostic 	register char *bp, *str;
15531702Sbostic {
15633808Sbostic 	register int len;
15733808Sbostic 	register char test;
15831702Sbostic 
15931702Sbostic 	if (!*bp)
16035534Sbostic 		return(0);
16133808Sbostic 	/* backward compatible: everything matches empty string */
16231702Sbostic 	if (!*str)
16335534Sbostic 		return(1);
16433808Sbostic 	for (test = *str++, len = strlen(str); *bp;)
16533808Sbostic 		if (test == *bp++ && !strncmp(bp, str, len))
16635534Sbostic 			return(1);
16735534Sbostic 	return(0);
16831702Sbostic }
16931702Sbostic 
17033808Sbostic /*
17133808Sbostic  * lowstr --
17233808Sbostic  *	convert a string to lower case
17333808Sbostic  */
17433808Sbostic lowstr(from, to)
17533808Sbostic 	register char *from, *to;
17633808Sbostic {
17735534Sbostic 	register char ch;
17835534Sbostic 
17935534Sbostic 	while ((ch = *from++) && ch != '\n')
18035534Sbostic 		*to++ = isupper(ch) ? tolower(ch) : ch;
18135534Sbostic 	*to = '\0';
18233808Sbostic }
18333808Sbostic 
18433808Sbostic /*
18533808Sbostic  * usage --
18633808Sbostic  *	print usage message and die
18733808Sbostic  */
18831702Sbostic usage()
18931702Sbostic {
19040389Sbostic 	(void)fprintf(stderr,
19165269Sbostic 	    "usage: apropos [-C file] [-M path] [-m path] keyword ...\n");
19231702Sbostic 	exit(1);
19331702Sbostic }
194