xref: /csrg-svn/usr.bin/apropos/apropos.c (revision 65269)
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*65269Sbostic static char sccsid[] = "@(#)apropos.c	8.3 (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;
4240389Sbostic 	int ch;
43*65269Sbostic 	char *conffile, **p, *p_augment, *p_path;
4431702Sbostic 
45*65269Sbostic 	conffile = NULL;
4640389Sbostic 	p_augment = p_path = NULL;
47*65269Sbostic 	while ((ch = getopt(argc, argv, "C:M:m:P:")) != EOF)
4865268Sbostic 		switch (ch) {
49*65269Sbostic 		case 'C':
50*65269Sbostic 			conffile = optarg;
51*65269Sbostic 			break;
5235534Sbostic 		case 'M':
5335534Sbostic 		case 'P':		/* backward compatible */
5440389Sbostic 			p_path = optarg;
5535534Sbostic 			break;
5640389Sbostic 		case 'm':
5740389Sbostic 			p_augment = optarg;
5840389Sbostic 			break;
5935534Sbostic 		case '?':
6035534Sbostic 		default:
6135534Sbostic 			usage();
6231702Sbostic 		}
6331702Sbostic 	argv += optind;
6431702Sbostic 	argc -= optind;
6540389Sbostic 
6631702Sbostic 	if (argc < 1)
6731702Sbostic 		usage();
6831702Sbostic 
69*65269Sbostic 	if ((found = malloc((u_int)argc)) == NULL)
7065268Sbostic 		err(1, NULL);
7165268Sbostic 	memset(found, 0, argc * sizeof(int));
7231702Sbostic 
7335534Sbostic 	for (p = argv; *p; ++p)			/* convert to lower-case */
7435534Sbostic 		lowstr(*p, *p);
7540389Sbostic 
7640389Sbostic 	if (p_augment)
7742403Sbostic 		apropos(argv, p_augment, 1);
7842403Sbostic 	if (p_path || (p_path = getenv("MANPATH")))
7942403Sbostic 		apropos(argv, p_path, 1);
8065268Sbostic 	else {
81*65269Sbostic 		config(conffile);
8265268Sbostic 		ep = getlist("_whatdb");
8365268Sbostic 		if (ep != NULL)
8465268Sbostic 			ep = ep->list.qe_next;
8565268Sbostic 		for (; ep != NULL; ep = ep->list.qe_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 	}
9440389Sbostic 	for (p = argv; *p; ++p)
9540389Sbostic 		if (!found[p - argv])
9640389Sbostic 			(void)printf("%s: nothing appropriate\n", *p);
9740389Sbostic }
9840389Sbostic 
9942403Sbostic apropos(argv, path, buildpath)
10040389Sbostic 	char **argv, *path;
10142403Sbostic 	int buildpath;
10240389Sbostic {
10342403Sbostic 	register char *end, *name, **p;
10440389Sbostic 	char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
10540389Sbostic 
10642403Sbostic 	for (name = path; name; name = end) {	/* through name list */
10742403Sbostic 		if (end = index(name, ':'))
10842403Sbostic 			*end++ = '\0';
10942403Sbostic 
11042403Sbostic 		if (buildpath) {
11142403Sbostic 			char hold[MAXPATHLEN + 1];
11242403Sbostic 
11342403Sbostic 			(void)sprintf(hold, "%s/%s", name, _PATH_WHATIS);
11442403Sbostic 			name = hold;
11531702Sbostic 		}
11642403Sbostic 
11742403Sbostic 		if (!freopen(name, "r", stdin))
11833808Sbostic 			continue;
11933808Sbostic 
12042403Sbostic 		foundman = 1;
12142403Sbostic 
12235534Sbostic 		/* for each file found */
12342403Sbostic 		while (fgets(buf, sizeof(buf), stdin)) {
12440389Sbostic 			if (!index(buf, '\n')) {
12540389Sbostic 				(void)fprintf(stderr,
12642403Sbostic 				    "apropos: %s line too long.\n", name);
12751191Sbostic 				continue;
12840389Sbostic 			}
12935534Sbostic 			lowstr(buf, wbuf);
13035534Sbostic 			for (p = argv; *p; ++p)
13135534Sbostic 				if (match(wbuf, *p)) {
13240389Sbostic 					(void)printf("%s", buf);
13335534Sbostic 					found[p - argv] = 1;
13431702Sbostic 
13533808Sbostic 					/* only print line once */
13635534Sbostic 					while (*++p)
13735534Sbostic 						if (match(wbuf, *p))
13835534Sbostic 							found[p - argv] = 1;
13933808Sbostic 					break;
14033808Sbostic 				}
14131702Sbostic 		}
14231702Sbostic 	}
14331702Sbostic }
14431702Sbostic 
14533808Sbostic /*
14635534Sbostic  * match --
14735534Sbostic  *	match anywhere the string appears
14833808Sbostic  */
14935534Sbostic match(bp, str)
15033808Sbostic 	register char *bp, *str;
15131702Sbostic {
15233808Sbostic 	register int len;
15333808Sbostic 	register char test;
15431702Sbostic 
15531702Sbostic 	if (!*bp)
15635534Sbostic 		return(0);
15733808Sbostic 	/* backward compatible: everything matches empty string */
15831702Sbostic 	if (!*str)
15935534Sbostic 		return(1);
16033808Sbostic 	for (test = *str++, len = strlen(str); *bp;)
16133808Sbostic 		if (test == *bp++ && !strncmp(bp, str, len))
16235534Sbostic 			return(1);
16335534Sbostic 	return(0);
16431702Sbostic }
16531702Sbostic 
16633808Sbostic /*
16733808Sbostic  * lowstr --
16833808Sbostic  *	convert a string to lower case
16933808Sbostic  */
17033808Sbostic lowstr(from, to)
17133808Sbostic 	register char *from, *to;
17233808Sbostic {
17335534Sbostic 	register char ch;
17435534Sbostic 
17535534Sbostic 	while ((ch = *from++) && ch != '\n')
17635534Sbostic 		*to++ = isupper(ch) ? tolower(ch) : ch;
17735534Sbostic 	*to = '\0';
17833808Sbostic }
17933808Sbostic 
18033808Sbostic /*
18133808Sbostic  * usage --
18233808Sbostic  *	print usage message and die
18333808Sbostic  */
18431702Sbostic usage()
18531702Sbostic {
18640389Sbostic 	(void)fprintf(stderr,
187*65269Sbostic 	    "usage: apropos [-C file] [-M path] [-m path] keyword ...\n");
18831702Sbostic 	exit(1);
18931702Sbostic }
190