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