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*42403Sbostic static char sccsid[] = "@(#)apropos.c 5.11 (Berkeley) 05/27/90"; 2633054Sbostic #endif /* not lint */ 2731702Sbostic 2831702Sbostic #include <sys/param.h> 2931702Sbostic #include <stdio.h> 3031702Sbostic #include <ctype.h> 3142051Sbostic #include <string.h> 32*42403Sbostic #include <stdlib.h> 3340389Sbostic #include "../man/pathnames.h" 3431702Sbostic 3540389Sbostic #define MAXLINELEN 256 /* max line handled */ 3631702Sbostic 3740389Sbostic char *progname; 3840389Sbostic 39*42403Sbostic static int *found, foundman; 40*42403Sbostic 4131702Sbostic main(argc, argv) 4233808Sbostic int argc; 4333808Sbostic char **argv; 4431702Sbostic { 4533808Sbostic extern char *optarg; 4633808Sbostic extern int optind; 4740389Sbostic register char **p; 4840389Sbostic int ch; 49*42403Sbostic char *p_augment, *p_path, **getdb(); 5031702Sbostic 5140389Sbostic progname = "apropos"; 5240389Sbostic p_augment = p_path = NULL; 5340389Sbostic while ((ch = getopt(argc, argv, "M:m:P:")) != EOF) 5431702Sbostic switch((char)ch) { 5535534Sbostic case 'M': 5635534Sbostic case 'P': /* backward compatible */ 5740389Sbostic p_path = optarg; 5835534Sbostic break; 5940389Sbostic case 'm': 6040389Sbostic p_augment = optarg; 6140389Sbostic break; 6235534Sbostic case '?': 6335534Sbostic default: 6435534Sbostic usage(); 6531702Sbostic } 6631702Sbostic argv += optind; 6731702Sbostic argc -= optind; 6840389Sbostic 6931702Sbostic if (argc < 1) 7031702Sbostic usage(); 7131702Sbostic 7231702Sbostic /*NOSTRICT*/ 7340389Sbostic if (!(found = (int *)malloc((u_int)argc))) 7440389Sbostic enomem(); 75*42403Sbostic bzero((void *)found, argc * sizeof(int)); 7631702Sbostic 7735534Sbostic for (p = argv; *p; ++p) /* convert to lower-case */ 7835534Sbostic lowstr(*p, *p); 7940389Sbostic 8040389Sbostic if (p_augment) 81*42403Sbostic apropos(argv, p_augment, 1); 82*42403Sbostic if (p_path || (p_path = getenv("MANPATH"))) 83*42403Sbostic apropos(argv, p_path, 1); 84*42403Sbostic else 85*42403Sbostic for (p = getdb(); *p; ++p) 86*42403Sbostic apropos(argv, *p, 0); 87*42403Sbostic 8840389Sbostic if (!foundman) { 89*42403Sbostic (void)fprintf(stderr, 90*42403Sbostic "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 98*42403Sbostic apropos(argv, path, buildpath) 9940389Sbostic char **argv, *path; 100*42403Sbostic int buildpath; 10140389Sbostic { 102*42403Sbostic register char *end, *name, **p; 10340389Sbostic char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1]; 10440389Sbostic 105*42403Sbostic for (name = path; name; name = end) { /* through name list */ 106*42403Sbostic if (end = index(name, ':')) 107*42403Sbostic *end++ = '\0'; 108*42403Sbostic 109*42403Sbostic if (buildpath) { 110*42403Sbostic char hold[MAXPATHLEN + 1]; 111*42403Sbostic 112*42403Sbostic (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS); 113*42403Sbostic name = hold; 11431702Sbostic } 115*42403Sbostic 116*42403Sbostic if (!freopen(name, "r", stdin)) 11733808Sbostic continue; 11833808Sbostic 119*42403Sbostic foundman = 1; 120*42403Sbostic 12135534Sbostic /* for each file found */ 122*42403Sbostic while (fgets(buf, sizeof(buf), stdin)) { 12340389Sbostic if (!index(buf, '\n')) { 12440389Sbostic (void)fprintf(stderr, 125*42403Sbostic "apropos: %s line too long.\n", name); 12640389Sbostic exit(1); 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