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*42051Sbostic static char sccsid[] = "@(#)apropos.c 5.10 (Berkeley) 05/15/90"; 2633054Sbostic #endif /* not lint */ 2731702Sbostic 2831702Sbostic #include <sys/param.h> 2931702Sbostic #include <stdio.h> 3031702Sbostic #include <ctype.h> 31*42051Sbostic #include <string.h> 3240389Sbostic #include "../man/pathnames.h" 3331702Sbostic 3440389Sbostic #define MAXLINELEN 256 /* max line handled */ 3531702Sbostic 3640389Sbostic int *found, foundman; 3740389Sbostic char *progname; 3840389Sbostic 3931702Sbostic main(argc, argv) 4033808Sbostic int argc; 4133808Sbostic char **argv; 4231702Sbostic { 4333808Sbostic extern char *optarg; 4433808Sbostic extern int optind; 4540389Sbostic register char **p; 4640389Sbostic int ch; 4740389Sbostic char *p_augment, *p_path, *config(), *getenv(), *malloc(); 4831702Sbostic 4940389Sbostic progname = "apropos"; 5040389Sbostic p_augment = p_path = NULL; 5140389Sbostic while ((ch = getopt(argc, argv, "M:m:P:")) != EOF) 5231702Sbostic switch((char)ch) { 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 7040389Sbostic if (!p_path && !(p_path = getenv("MANPATH"))) 7140389Sbostic p_path = config(); 7231702Sbostic 7331702Sbostic /*NOSTRICT*/ 7440389Sbostic if (!(found = (int *)malloc((u_int)argc))) 7540389Sbostic enomem(); 7633808Sbostic bzero((char *)found, argc * sizeof(int)); 7731702Sbostic 7835534Sbostic for (p = argv; *p; ++p) /* convert to lower-case */ 7935534Sbostic lowstr(*p, *p); 8040389Sbostic 8140389Sbostic if (p_augment) 8240389Sbostic apropos(argv, p_augment); 8340389Sbostic if (p_path) 8440389Sbostic apropos(argv, p_path); 8540389Sbostic if (!foundman) { 8640389Sbostic (void)fprintf(stderr, "apropos: no %s file found.\n", 8740389Sbostic _PATH_WHATIS); 8840389Sbostic exit(1); 8940389Sbostic } 9040389Sbostic for (p = argv; *p; ++p) 9140389Sbostic if (!found[p - argv]) 9240389Sbostic (void)printf("%s: nothing appropriate\n", *p); 9340389Sbostic } 9440389Sbostic 9540389Sbostic apropos(argv, path) 9640389Sbostic char **argv, *path; 9740389Sbostic { 9840389Sbostic register char *beg, *end, **p; 9940389Sbostic char fname[MAXPATHLEN + 1]; 10040389Sbostic char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1]; 10140389Sbostic 10240389Sbostic for (beg = path; beg; beg = end) { /* through path list */ 10331702Sbostic end = index(beg, ':'); 10431702Sbostic if (!end) 10540389Sbostic (void)sprintf(fname, "%s/%s", beg, _PATH_WHATIS); 10631702Sbostic else { 10740389Sbostic (void)sprintf(fname, "%.*s/%s", end - beg, beg, 10840389Sbostic _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);) { 11640389Sbostic if (!index(buf, '\n')) { 11740389Sbostic (void)fprintf(stderr, 11840389Sbostic "apropos: %s line too long.\n", fname); 11940389Sbostic exit(1); 12040389Sbostic } 12135534Sbostic lowstr(buf, wbuf); 12235534Sbostic for (p = argv; *p; ++p) 12335534Sbostic if (match(wbuf, *p)) { 12440389Sbostic (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 { 17840389Sbostic (void)fprintf(stderr, 17940389Sbostic "usage: apropos [-M path] [-m path] keyword ...\n"); 18031702Sbostic exit(1); 18131702Sbostic } 182