131702Sbostic /* 231702Sbostic * Copyright (c) 1987 Regents of the University of California. 333054Sbostic * All rights reserved. 433054Sbostic * 5*42741Sbostic * %sccs.include.redist.c% 631702Sbostic */ 731702Sbostic 831702Sbostic #ifndef lint 931702Sbostic char copyright[] = 1031702Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 1131702Sbostic All rights reserved.\n"; 1233054Sbostic #endif /* not lint */ 1331702Sbostic 1431702Sbostic #ifndef lint 15*42741Sbostic static char sccsid[] = "@(#)apropos.c 5.12 (Berkeley) 06/01/90"; 1633054Sbostic #endif /* not lint */ 1731702Sbostic 1831702Sbostic #include <sys/param.h> 1931702Sbostic #include <stdio.h> 2031702Sbostic #include <ctype.h> 2142051Sbostic #include <string.h> 2242403Sbostic #include <stdlib.h> 2340389Sbostic #include "../man/pathnames.h" 2431702Sbostic 2540389Sbostic #define MAXLINELEN 256 /* max line handled */ 2631702Sbostic 2740389Sbostic char *progname; 2840389Sbostic 2942403Sbostic static int *found, foundman; 3042403Sbostic 3131702Sbostic main(argc, argv) 3233808Sbostic int argc; 3333808Sbostic char **argv; 3431702Sbostic { 3533808Sbostic extern char *optarg; 3633808Sbostic extern int optind; 3740389Sbostic register char **p; 3840389Sbostic int ch; 3942403Sbostic char *p_augment, *p_path, **getdb(); 4031702Sbostic 4140389Sbostic progname = "apropos"; 4240389Sbostic p_augment = p_path = NULL; 4340389Sbostic while ((ch = getopt(argc, argv, "M:m:P:")) != EOF) 4431702Sbostic switch((char)ch) { 4535534Sbostic case 'M': 4635534Sbostic case 'P': /* backward compatible */ 4740389Sbostic p_path = optarg; 4835534Sbostic break; 4940389Sbostic case 'm': 5040389Sbostic p_augment = optarg; 5140389Sbostic break; 5235534Sbostic case '?': 5335534Sbostic default: 5435534Sbostic usage(); 5531702Sbostic } 5631702Sbostic argv += optind; 5731702Sbostic argc -= optind; 5840389Sbostic 5931702Sbostic if (argc < 1) 6031702Sbostic usage(); 6131702Sbostic 6231702Sbostic /*NOSTRICT*/ 6340389Sbostic if (!(found = (int *)malloc((u_int)argc))) 6440389Sbostic enomem(); 6542403Sbostic bzero((void *)found, argc * sizeof(int)); 6631702Sbostic 6735534Sbostic for (p = argv; *p; ++p) /* convert to lower-case */ 6835534Sbostic lowstr(*p, *p); 6940389Sbostic 7040389Sbostic if (p_augment) 7142403Sbostic apropos(argv, p_augment, 1); 7242403Sbostic if (p_path || (p_path = getenv("MANPATH"))) 7342403Sbostic apropos(argv, p_path, 1); 7442403Sbostic else 7542403Sbostic for (p = getdb(); *p; ++p) 7642403Sbostic apropos(argv, *p, 0); 7742403Sbostic 7840389Sbostic if (!foundman) { 7942403Sbostic (void)fprintf(stderr, 8042403Sbostic "apropos: : no %s file found.\n", _PATH_WHATIS); 8140389Sbostic exit(1); 8240389Sbostic } 8340389Sbostic for (p = argv; *p; ++p) 8440389Sbostic if (!found[p - argv]) 8540389Sbostic (void)printf("%s: nothing appropriate\n", *p); 8640389Sbostic } 8740389Sbostic 8842403Sbostic apropos(argv, path, buildpath) 8940389Sbostic char **argv, *path; 9042403Sbostic int buildpath; 9140389Sbostic { 9242403Sbostic register char *end, *name, **p; 9340389Sbostic char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1]; 9440389Sbostic 9542403Sbostic for (name = path; name; name = end) { /* through name list */ 9642403Sbostic if (end = index(name, ':')) 9742403Sbostic *end++ = '\0'; 9842403Sbostic 9942403Sbostic if (buildpath) { 10042403Sbostic char hold[MAXPATHLEN + 1]; 10142403Sbostic 10242403Sbostic (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS); 10342403Sbostic name = hold; 10431702Sbostic } 10542403Sbostic 10642403Sbostic if (!freopen(name, "r", stdin)) 10733808Sbostic continue; 10833808Sbostic 10942403Sbostic foundman = 1; 11042403Sbostic 11135534Sbostic /* for each file found */ 11242403Sbostic while (fgets(buf, sizeof(buf), stdin)) { 11340389Sbostic if (!index(buf, '\n')) { 11440389Sbostic (void)fprintf(stderr, 11542403Sbostic "apropos: %s line too long.\n", name); 11640389Sbostic exit(1); 11740389Sbostic } 11835534Sbostic lowstr(buf, wbuf); 11935534Sbostic for (p = argv; *p; ++p) 12035534Sbostic if (match(wbuf, *p)) { 12140389Sbostic (void)printf("%s", buf); 12235534Sbostic found[p - argv] = 1; 12331702Sbostic 12433808Sbostic /* only print line once */ 12535534Sbostic while (*++p) 12635534Sbostic if (match(wbuf, *p)) 12735534Sbostic found[p - argv] = 1; 12833808Sbostic break; 12933808Sbostic } 13031702Sbostic } 13131702Sbostic } 13231702Sbostic } 13331702Sbostic 13433808Sbostic /* 13535534Sbostic * match -- 13635534Sbostic * match anywhere the string appears 13733808Sbostic */ 13835534Sbostic match(bp, str) 13933808Sbostic register char *bp, *str; 14031702Sbostic { 14133808Sbostic register int len; 14233808Sbostic register char test; 14331702Sbostic 14431702Sbostic if (!*bp) 14535534Sbostic return(0); 14633808Sbostic /* backward compatible: everything matches empty string */ 14731702Sbostic if (!*str) 14835534Sbostic return(1); 14933808Sbostic for (test = *str++, len = strlen(str); *bp;) 15033808Sbostic if (test == *bp++ && !strncmp(bp, str, len)) 15135534Sbostic return(1); 15235534Sbostic return(0); 15331702Sbostic } 15431702Sbostic 15533808Sbostic /* 15633808Sbostic * lowstr -- 15733808Sbostic * convert a string to lower case 15833808Sbostic */ 15933808Sbostic lowstr(from, to) 16033808Sbostic register char *from, *to; 16133808Sbostic { 16235534Sbostic register char ch; 16335534Sbostic 16435534Sbostic while ((ch = *from++) && ch != '\n') 16535534Sbostic *to++ = isupper(ch) ? tolower(ch) : ch; 16635534Sbostic *to = '\0'; 16733808Sbostic } 16833808Sbostic 16933808Sbostic /* 17033808Sbostic * usage -- 17133808Sbostic * print usage message and die 17233808Sbostic */ 17331702Sbostic usage() 17431702Sbostic { 17540389Sbostic (void)fprintf(stderr, 17640389Sbostic "usage: apropos [-M path] [-m path] keyword ...\n"); 17731702Sbostic exit(1); 17831702Sbostic } 179