xref: /csrg-svn/usr.bin/apropos/apropos.c (revision 31974)
131702Sbostic /*
231702Sbostic  * Copyright (c) 1987 Regents of the University of California.
331702Sbostic  * All rights reserved.  The Berkeley software License Agreement
431702Sbostic  * specifies the terms and conditions for redistribution.
531702Sbostic  */
631702Sbostic 
731702Sbostic #ifndef lint
831702Sbostic char copyright[] =
931702Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\
1031702Sbostic  All rights reserved.\n";
1131702Sbostic #endif not lint
1231702Sbostic 
1331702Sbostic #ifndef lint
14*31974Sbostic static char sccsid[] = "@(#)apropos.c	5.3 (Berkeley) 07/30/87";
1531702Sbostic #endif not lint
1631702Sbostic 
1731702Sbostic #include <sys/param.h>
1831702Sbostic #include <stdio.h>
1931702Sbostic #include <ctype.h>
2031702Sbostic 
21*31974Sbostic #define	DEF_PATH	"/usr/man:/usr/new/man:/usr/local/man"
2231712Sbostic #define	MAXLINELEN	1000			/* max line handled */
2331702Sbostic #define	NO		0			/* no/false */
2431702Sbostic #define	WHATIS		"whatis"		/* database name */
2531702Sbostic #define	YES		1			/* yes/true */
2631702Sbostic 
2731702Sbostic static char	*myname;
2831702Sbostic 
2931702Sbostic main(argc, argv)
3031702Sbostic 	int	argc;
3131702Sbostic 	char	**argv;
3231702Sbostic {
3331702Sbostic 	extern char	*optarg;
3431702Sbostic 	extern int	optind;
3531702Sbostic 	register char	*beg, *end, **C;
3631702Sbostic 	int	ch, foundman = NO, *found, isapropos,
3731702Sbostic 		a_match(), w_match(), (*match)();
3831702Sbostic 	char	*manpath = NULL,
3931702Sbostic 		buf[MAXLINELEN + 1], fname[MAXPATHLEN + 1],
4031702Sbostic 		wbuf[MAXLINELEN + 1],
4131702Sbostic 		*getenv(), *index(), *malloc(), *rindex();
4231702Sbostic 
4331702Sbostic 	myname = (beg = rindex(*argv, '/')) ? beg + 1 : *argv;
4431702Sbostic 	if (!strcmp(myname, "apropos")) {
4531702Sbostic 		isapropos = YES;
4631702Sbostic 		match = a_match;
4731702Sbostic 	}
4831702Sbostic 	else {
4931702Sbostic 		isapropos = NO;
5031702Sbostic 		match = w_match;
5131702Sbostic 	}
5231702Sbostic 	while ((ch = getopt(argc, argv, "M:P:")) != EOF)
5331702Sbostic 		switch((char)ch) {
5431702Sbostic 			case 'M':
5531702Sbostic 			case 'P':		/* backward contemptible */
5631702Sbostic 				manpath = optarg;
5731702Sbostic 				break;
5831702Sbostic 			case '?':
5931702Sbostic 			default:
6031702Sbostic 				usage();
6131702Sbostic 		}
6231702Sbostic 	argv += optind;
6331702Sbostic 	argc -= optind;
6431702Sbostic 	if (argc < 1)
6531702Sbostic 		usage();
6631702Sbostic 
6731702Sbostic 	if (!(manpath = getenv("MANPATH")))
6831702Sbostic 		manpath = DEF_PATH;
6931702Sbostic 
7031702Sbostic 	/*NOSTRICT*/
7131702Sbostic 	if (!(found = (int *)malloc((u_int)argc))) {
7231702Sbostic 		fprintf(stderr, "%s: out of space.\n", myname);
7331702Sbostic 		exit(1);
7431702Sbostic 	}
7531712Sbostic 	bzero((char *)found, argc * sizeof(int));	/* calloc is silly */
7631702Sbostic 
7731702Sbostic 	if (!isapropos)
7831712Sbostic 		for (C = argv; *C; ++C) {		/* trim full paths */
7931702Sbostic 			if (beg = rindex(*C, '/'))
8031702Sbostic 				*C = beg + 1;
8131702Sbostic 		}
8231702Sbostic 	for (C = argv; *C; ++C)			/* convert to lower-case */
8331702Sbostic 		lowstr(*C, *C);
8431702Sbostic 
8531702Sbostic 	for (beg = manpath; beg; beg = end) {	/* through path list */
8631702Sbostic 		end = index(beg, ':');
8731702Sbostic 		if (!end)
8831702Sbostic 			(void)sprintf(fname, "%s/%s", beg, WHATIS);
8931702Sbostic 		else {
9031702Sbostic 			(void)sprintf(fname, "%.*s/%s", end - beg, beg, WHATIS);
9131702Sbostic 			++end;
9231702Sbostic 		}
9331702Sbostic 						/* for each file found */
9431702Sbostic 		if (freopen(fname, "r", stdin)) {
9531702Sbostic 			foundman = YES;
9631702Sbostic 			while (gets(buf)) {	/* read & convert to lcase */
9731702Sbostic 				lowstr(buf, wbuf);
9831702Sbostic 				for (C = argv; *C; ++C)
9931702Sbostic 					if ((*match)(wbuf, *C)) {
10031702Sbostic 						puts(buf);
10131702Sbostic 						found[C - argv] = YES;
10231702Sbostic 
10331702Sbostic 						/* only print line once */
10431702Sbostic 						while (*++C)
10531702Sbostic 							if ((*match)(wbuf, *C))
10631702Sbostic 								found[C - argv] = YES;
10731702Sbostic 						break;
10831702Sbostic 					}
10931702Sbostic 			}
11031702Sbostic 		}
11131702Sbostic 	}
11231702Sbostic 	if (!foundman) {
11331702Sbostic 		fprintf(stderr, "%s: no %s file found in %s.\n", myname, WHATIS, manpath);
11431702Sbostic 		exit(1);
11531702Sbostic 	}
11631702Sbostic 	for (C = argv; *C; C++)
11731702Sbostic 		if (!found[C - argv])
11831702Sbostic 			printf("%s: %s\n", *C, isapropos ? "nothing appropriate" : "not found");
11931702Sbostic }
12031702Sbostic 
12131702Sbostic static
12231702Sbostic a_match(bp, str)
12331702Sbostic 	register char	*bp, *str;
12431702Sbostic {
12531702Sbostic 	register char	test, *Cs, *Cb;
12631702Sbostic 
12731702Sbostic 	if (!*bp)
12831702Sbostic 		return(NO);
12931702Sbostic 	/* backward contemptible: everything matches empty string */
13031702Sbostic 	if (!*str)
13131702Sbostic 		return(YES);
13231702Sbostic 	for (test = *str++; *bp;)
13331702Sbostic 		if (test == *bp++) {
13431702Sbostic 			Cs = str;
13531702Sbostic 			Cb = bp;
13631702Sbostic 			do {
13731702Sbostic 				if (!*Cs)
13831702Sbostic 					return(YES);
13931702Sbostic 			} while (*Cb++ == *Cs++);
14031702Sbostic 		}
14131702Sbostic 	return(NO);
14231702Sbostic }
14331702Sbostic 
14431702Sbostic static
14531702Sbostic w_match(bp, str)
14631702Sbostic 	register char	*bp, *str;
14731702Sbostic {
14831702Sbostic 	register char	test, *Cs, *Cb;
14931702Sbostic 
15031702Sbostic 	if (!*str || !*bp)
15131702Sbostic 		return(NO);
15231702Sbostic 	for (test = *str++; *bp;)
15331702Sbostic 		if (test == *bp++) {
15431702Sbostic 			for (Cs = str, Cb = bp; *Cs == *Cb; ++Cs, ++Cb);
15531702Sbostic 			if (!*Cs && (isspace(*Cb) || *Cb == '(' || *Cb == ','))
15631702Sbostic 				return(YES);
15731702Sbostic 		}
15831702Sbostic 	return(NO);
15931702Sbostic }
16031702Sbostic 
16131702Sbostic static
16231702Sbostic lowstr(from, to)
16331702Sbostic 	register char	*from, *to;
16431702Sbostic {
16531702Sbostic 	for (; *from; ++from, ++to)
16631702Sbostic 		*to = isupper(*from) ? tolower(*from) : *from;
16731702Sbostic 	*to = '\0';
16831702Sbostic }
16931702Sbostic 
17031702Sbostic static
17131702Sbostic usage()
17231702Sbostic {
17331702Sbostic 	fprintf(stderr, "usage: %s [-M path] string ...\n", myname);
17431702Sbostic 	exit(1);
17531702Sbostic }
176