xref: /csrg-svn/usr.bin/apropos/apropos.c (revision 40389)
131702Sbostic /*
231702Sbostic  * Copyright (c) 1987 Regents of the University of California.
333054Sbostic  * All rights reserved.
433054Sbostic  *
533054Sbostic  * Redistribution and use in source and binary forms are permitted
634886Sbostic  * provided that the above copyright notice and this paragraph are
734886Sbostic  * duplicated in all such forms and that any documentation,
834886Sbostic  * advertising materials, and other materials related to such
934886Sbostic  * distribution and use acknowledge that the software was developed
1034886Sbostic  * by the University of California, Berkeley.  The name of the
1134886Sbostic  * University may not be used to endorse or promote products derived
1234886Sbostic  * from this software without specific prior written permission.
1334886Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434886Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534886Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1631702Sbostic  */
1731702Sbostic 
1831702Sbostic #ifndef lint
1931702Sbostic char copyright[] =
2031702Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\
2131702Sbostic  All rights reserved.\n";
2233054Sbostic #endif /* not lint */
2331702Sbostic 
2431702Sbostic #ifndef lint
25*40389Sbostic static char sccsid[] = "@(#)apropos.c	5.9 (Berkeley) 03/11/90";
2633054Sbostic #endif /* not lint */
2731702Sbostic 
2831702Sbostic #include <sys/param.h>
2931702Sbostic #include <stdio.h>
3031702Sbostic #include <ctype.h>
3133808Sbostic #include <strings.h>
32*40389Sbostic #include "../man/pathnames.h"
3331702Sbostic 
34*40389Sbostic #define	MAXLINELEN	256			/* max line handled */
3531702Sbostic 
36*40389Sbostic int *found, foundman;
37*40389Sbostic char *progname;
38*40389Sbostic 
3931702Sbostic main(argc, argv)
4033808Sbostic 	int argc;
4133808Sbostic 	char **argv;
4231702Sbostic {
4333808Sbostic 	extern char *optarg;
4433808Sbostic 	extern int optind;
45*40389Sbostic 	register char **p;
46*40389Sbostic 	int ch;
47*40389Sbostic 	char *p_augment, *p_path, *config(), *getenv(), *malloc();
4831702Sbostic 
49*40389Sbostic 	progname = "apropos";
50*40389Sbostic 	p_augment = p_path = NULL;
51*40389Sbostic 	while ((ch = getopt(argc, argv, "M:m:P:")) != EOF)
5231702Sbostic 		switch((char)ch) {
5335534Sbostic 		case 'M':
5435534Sbostic 		case 'P':		/* backward compatible */
55*40389Sbostic 			p_path = optarg;
5635534Sbostic 			break;
57*40389Sbostic 		case 'm':
58*40389Sbostic 			p_augment = optarg;
59*40389Sbostic 			break;
6035534Sbostic 		case '?':
6135534Sbostic 		default:
6235534Sbostic 			usage();
6331702Sbostic 		}
6431702Sbostic 	argv += optind;
6531702Sbostic 	argc -= optind;
66*40389Sbostic 
6731702Sbostic 	if (argc < 1)
6831702Sbostic 		usage();
6931702Sbostic 
70*40389Sbostic 	if (!p_path && !(p_path = getenv("MANPATH")))
71*40389Sbostic 		p_path = config();
7231702Sbostic 
7331702Sbostic 	/*NOSTRICT*/
74*40389Sbostic 	if (!(found = (int *)malloc((u_int)argc)))
75*40389Sbostic 		enomem();
7633808Sbostic 	bzero((char *)found, argc * sizeof(int));
7731702Sbostic 
7835534Sbostic 	for (p = argv; *p; ++p)			/* convert to lower-case */
7935534Sbostic 		lowstr(*p, *p);
80*40389Sbostic 
81*40389Sbostic 	if (p_augment)
82*40389Sbostic 		apropos(argv, p_augment);
83*40389Sbostic 	if (p_path)
84*40389Sbostic 		apropos(argv, p_path);
85*40389Sbostic 	if (!foundman) {
86*40389Sbostic 		(void)fprintf(stderr, "apropos: no %s file found.\n",
87*40389Sbostic 		    _PATH_WHATIS);
88*40389Sbostic 		exit(1);
89*40389Sbostic 	}
90*40389Sbostic 	for (p = argv; *p; ++p)
91*40389Sbostic 		if (!found[p - argv])
92*40389Sbostic 			(void)printf("%s: nothing appropriate\n", *p);
93*40389Sbostic }
94*40389Sbostic 
95*40389Sbostic apropos(argv, path)
96*40389Sbostic 	char **argv, *path;
97*40389Sbostic {
98*40389Sbostic 	register char *beg, *end, **p;
99*40389Sbostic 	char fname[MAXPATHLEN + 1];
100*40389Sbostic 	char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1];
101*40389Sbostic 
102*40389Sbostic 	for (beg = path; beg; beg = end) {	/* through path list */
10331702Sbostic 		end = index(beg, ':');
10431702Sbostic 		if (!end)
105*40389Sbostic 			(void)sprintf(fname, "%s/%s", beg, _PATH_WHATIS);
10631702Sbostic 		else {
107*40389Sbostic 			(void)sprintf(fname, "%.*s/%s", end - beg, beg,
108*40389Sbostic 			    _PATH_WHATIS);
10931702Sbostic 			++end;
11031702Sbostic 		}
11133808Sbostic 		if (!freopen(fname, "r", stdin))
11233808Sbostic 			continue;
11333808Sbostic 
11435534Sbostic 		/* for each file found */
11535534Sbostic 		for (foundman = 1; fgets(buf, sizeof(buf), stdin);) {
116*40389Sbostic 			if (!index(buf, '\n')) {
117*40389Sbostic 				(void)fprintf(stderr,
118*40389Sbostic 				    "apropos: %s line too long.\n", fname);
119*40389Sbostic 				exit(1);
120*40389Sbostic 			}
12135534Sbostic 			lowstr(buf, wbuf);
12235534Sbostic 			for (p = argv; *p; ++p)
12335534Sbostic 				if (match(wbuf, *p)) {
124*40389Sbostic 					(void)printf("%s", buf);
12535534Sbostic 					found[p - argv] = 1;
12631702Sbostic 
12733808Sbostic 					/* only print line once */
12835534Sbostic 					while (*++p)
12935534Sbostic 						if (match(wbuf, *p))
13035534Sbostic 							found[p - argv] = 1;
13133808Sbostic 					break;
13233808Sbostic 				}
13331702Sbostic 		}
13431702Sbostic 	}
13531702Sbostic }
13631702Sbostic 
13733808Sbostic /*
13835534Sbostic  * match --
13935534Sbostic  *	match anywhere the string appears
14033808Sbostic  */
14135534Sbostic match(bp, str)
14233808Sbostic 	register char *bp, *str;
14331702Sbostic {
14433808Sbostic 	register int len;
14533808Sbostic 	register char test;
14631702Sbostic 
14731702Sbostic 	if (!*bp)
14835534Sbostic 		return(0);
14933808Sbostic 	/* backward compatible: everything matches empty string */
15031702Sbostic 	if (!*str)
15135534Sbostic 		return(1);
15233808Sbostic 	for (test = *str++, len = strlen(str); *bp;)
15333808Sbostic 		if (test == *bp++ && !strncmp(bp, str, len))
15435534Sbostic 			return(1);
15535534Sbostic 	return(0);
15631702Sbostic }
15731702Sbostic 
15833808Sbostic /*
15933808Sbostic  * lowstr --
16033808Sbostic  *	convert a string to lower case
16133808Sbostic  */
16233808Sbostic lowstr(from, to)
16333808Sbostic 	register char *from, *to;
16433808Sbostic {
16535534Sbostic 	register char ch;
16635534Sbostic 
16735534Sbostic 	while ((ch = *from++) && ch != '\n')
16835534Sbostic 		*to++ = isupper(ch) ? tolower(ch) : ch;
16935534Sbostic 	*to = '\0';
17033808Sbostic }
17133808Sbostic 
17233808Sbostic /*
17333808Sbostic  * usage --
17433808Sbostic  *	print usage message and die
17533808Sbostic  */
17631702Sbostic usage()
17731702Sbostic {
178*40389Sbostic 	(void)fprintf(stderr,
179*40389Sbostic 	    "usage: apropos [-M path] [-m path] keyword ...\n");
18031702Sbostic 	exit(1);
18131702Sbostic }
182