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*65268Sbostic static char sccsid[] = "@(#)apropos.c 8.2 (Berkeley) 01/02/94"; 1633054Sbostic #endif /* not lint */ 1731702Sbostic 1831702Sbostic #include <sys/param.h> 19*65268Sbostic #include <sys/queue.h> 20*65268Sbostic 21*65268Sbostic #include <ctype.h> 22*65268Sbostic #include <err.h> 2331702Sbostic #include <stdio.h> 24*65268Sbostic #include <stdlib.h> 2542051Sbostic #include <string.h> 26*65268Sbostic 27*65268Sbostic #include "../man/config.h" 2840389Sbostic #include "../man/pathnames.h" 2931702Sbostic 3051191Sbostic #define MAXLINELEN 1024 /* max line handled */ 3131702Sbostic 3240389Sbostic char *progname; 3340389Sbostic 3442403Sbostic static int *found, foundman; 3542403Sbostic 36*65268Sbostic int 3731702Sbostic main(argc, argv) 3833808Sbostic int argc; 39*65268Sbostic char *argv[]; 4031702Sbostic { 4133808Sbostic extern char *optarg; 4233808Sbostic extern int optind; 43*65268Sbostic ENTRY *ep; 4440389Sbostic int ch; 45*65268Sbostic char **p, *p_augment, *p_path; 4631702Sbostic 4740389Sbostic progname = "apropos"; 4840389Sbostic p_augment = p_path = NULL; 4940389Sbostic while ((ch = getopt(argc, argv, "M:m:P:")) != EOF) 50*65268Sbostic switch (ch) { 5135534Sbostic case 'M': 5235534Sbostic case 'P': /* backward compatible */ 5340389Sbostic p_path = optarg; 5435534Sbostic break; 5540389Sbostic case 'm': 5640389Sbostic p_augment = optarg; 5740389Sbostic break; 5835534Sbostic case '?': 5935534Sbostic default: 6035534Sbostic usage(); 6131702Sbostic } 6231702Sbostic argv += optind; 6331702Sbostic argc -= optind; 6440389Sbostic 6531702Sbostic if (argc < 1) 6631702Sbostic usage(); 6731702Sbostic 68*65268Sbostic if ((found = malloc((size_t)argc)) == NULL) 69*65268Sbostic err(1, NULL); 70*65268Sbostic memset(found, 0, argc * sizeof(int)); 7131702Sbostic 7235534Sbostic for (p = argv; *p; ++p) /* convert to lower-case */ 7335534Sbostic lowstr(*p, *p); 7440389Sbostic 7540389Sbostic if (p_augment) 7642403Sbostic apropos(argv, p_augment, 1); 7742403Sbostic if (p_path || (p_path = getenv("MANPATH"))) 7842403Sbostic apropos(argv, p_path, 1); 79*65268Sbostic else { 80*65268Sbostic config(); 81*65268Sbostic ep = getlist("_whatdb"); 82*65268Sbostic if (ep != NULL) 83*65268Sbostic ep = ep->list.qe_next; 84*65268Sbostic for (; ep != NULL; ep = ep->list.qe_next) 85*65268Sbostic apropos(argv, ep->s, 0); 86*65268Sbostic } 8742403Sbostic 8840389Sbostic if (!foundman) { 8942403Sbostic (void)fprintf(stderr, 90*65268Sbostic "apropos: no %s file found.\n", _PATH_WHATIS); 9140389Sbostic exit(1); 9240389Sbostic } 9340389Sbostic for (p = argv; *p; ++p) 9440389Sbostic if (!found[p - argv]) 9540389Sbostic (void)printf("%s: nothing appropriate\n", *p); 9640389Sbostic } 9740389Sbostic 9842403Sbostic apropos(argv, path, buildpath) 9940389Sbostic char **argv, *path; 10042403Sbostic int buildpath; 10140389Sbostic { 10242403Sbostic register char *end, *name, **p; 10340389Sbostic char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1]; 10440389Sbostic 10542403Sbostic for (name = path; name; name = end) { /* through name list */ 10642403Sbostic if (end = index(name, ':')) 10742403Sbostic *end++ = '\0'; 10842403Sbostic 10942403Sbostic if (buildpath) { 11042403Sbostic char hold[MAXPATHLEN + 1]; 11142403Sbostic 11242403Sbostic (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS); 11342403Sbostic name = hold; 11431702Sbostic } 11542403Sbostic 11642403Sbostic if (!freopen(name, "r", stdin)) 11733808Sbostic continue; 11833808Sbostic 11942403Sbostic foundman = 1; 12042403Sbostic 12135534Sbostic /* for each file found */ 12242403Sbostic while (fgets(buf, sizeof(buf), stdin)) { 12340389Sbostic if (!index(buf, '\n')) { 12440389Sbostic (void)fprintf(stderr, 12542403Sbostic "apropos: %s line too long.\n", name); 12651191Sbostic continue; 12740389Sbostic } 12835534Sbostic lowstr(buf, wbuf); 12935534Sbostic for (p = argv; *p; ++p) 13035534Sbostic if (match(wbuf, *p)) { 13140389Sbostic (void)printf("%s", buf); 13235534Sbostic found[p - argv] = 1; 13331702Sbostic 13433808Sbostic /* only print line once */ 13535534Sbostic while (*++p) 13635534Sbostic if (match(wbuf, *p)) 13735534Sbostic found[p - argv] = 1; 13833808Sbostic break; 13933808Sbostic } 14031702Sbostic } 14131702Sbostic } 14231702Sbostic } 14331702Sbostic 14433808Sbostic /* 14535534Sbostic * match -- 14635534Sbostic * match anywhere the string appears 14733808Sbostic */ 14835534Sbostic match(bp, str) 14933808Sbostic register char *bp, *str; 15031702Sbostic { 15133808Sbostic register int len; 15233808Sbostic register char test; 15331702Sbostic 15431702Sbostic if (!*bp) 15535534Sbostic return(0); 15633808Sbostic /* backward compatible: everything matches empty string */ 15731702Sbostic if (!*str) 15835534Sbostic return(1); 15933808Sbostic for (test = *str++, len = strlen(str); *bp;) 16033808Sbostic if (test == *bp++ && !strncmp(bp, str, len)) 16135534Sbostic return(1); 16235534Sbostic return(0); 16331702Sbostic } 16431702Sbostic 16533808Sbostic /* 16633808Sbostic * lowstr -- 16733808Sbostic * convert a string to lower case 16833808Sbostic */ 16933808Sbostic lowstr(from, to) 17033808Sbostic register char *from, *to; 17133808Sbostic { 17235534Sbostic register char ch; 17335534Sbostic 17435534Sbostic while ((ch = *from++) && ch != '\n') 17535534Sbostic *to++ = isupper(ch) ? tolower(ch) : ch; 17635534Sbostic *to = '\0'; 17733808Sbostic } 17833808Sbostic 17933808Sbostic /* 18033808Sbostic * usage -- 18133808Sbostic * print usage message and die 18233808Sbostic */ 18331702Sbostic usage() 18431702Sbostic { 18540389Sbostic (void)fprintf(stderr, 18640389Sbostic "usage: apropos [-M path] [-m path] keyword ...\n"); 18731702Sbostic exit(1); 18831702Sbostic } 189