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*66566Spendry static char sccsid[] = "@(#)apropos.c 8.6 (Berkeley) 04/01/94"; 1633054Sbostic #endif /* not lint */ 1731702Sbostic 1831702Sbostic #include <sys/param.h> 1965268Sbostic #include <sys/queue.h> 2065268Sbostic 2165268Sbostic #include <ctype.h> 2265268Sbostic #include <err.h> 23*66566Spendry #include <limits.h> 2431702Sbostic #include <stdio.h> 2565268Sbostic #include <stdlib.h> 2642051Sbostic #include <string.h> 2765268Sbostic 2865268Sbostic #include "../man/config.h" 2940389Sbostic #include "../man/pathnames.h" 3031702Sbostic 3142403Sbostic static int *found, foundman; 3242403Sbostic 33*66566Spendry void apropos __P((char **, char *, int)); 34*66566Spendry void lowstr __P((char *, char *)); 35*66566Spendry int match __P((char *, char *)); 36*66566Spendry void usage __P((void)); 37*66566Spendry 3865268Sbostic int 3931702Sbostic main(argc, argv) 4033808Sbostic int argc; 4165268Sbostic char *argv[]; 4231702Sbostic { 4365268Sbostic ENTRY *ep; 4465271Sbostic TAG *tp; 4565270Sbostic int ch, rv; 4665269Sbostic char *conffile, **p, *p_augment, *p_path; 4731702Sbostic 4865269Sbostic conffile = NULL; 4940389Sbostic p_augment = p_path = NULL; 5065269Sbostic while ((ch = getopt(argc, argv, "C:M:m:P:")) != EOF) 5165268Sbostic switch (ch) { 5265269Sbostic case 'C': 5365269Sbostic conffile = optarg; 5465269Sbostic break; 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 7265270Sbostic if ((found = malloc((u_int)argc * sizeof(int))) == NULL) 7365268Sbostic err(1, NULL); 7465268Sbostic memset(found, 0, argc * sizeof(int)); 7531702Sbostic 7635534Sbostic for (p = argv; *p; ++p) /* convert to lower-case */ 7735534Sbostic lowstr(*p, *p); 7840389Sbostic 7940389Sbostic if (p_augment) 8042403Sbostic apropos(argv, p_augment, 1); 8142403Sbostic if (p_path || (p_path = getenv("MANPATH"))) 8242403Sbostic apropos(argv, p_path, 1); 8365268Sbostic else { 8465269Sbostic config(conffile); 8565271Sbostic ep = (tp = getlist("_whatdb")) == NULL ? 8665271Sbostic NULL : tp->list.tqh_first; 8765271Sbostic for (; ep != NULL; ep = ep->q.tqe_next) 8865268Sbostic apropos(argv, ep->s, 0); 8965268Sbostic } 9042403Sbostic 91*66566Spendry if (!foundman) 92*66566Spendry errx(1, "no %s file found", _PATH_WHATIS); 93*66566Spendry 9465270Sbostic rv = 1; 9540389Sbostic for (p = argv; *p; ++p) 9665270Sbostic if (found[p - argv]) 9765270Sbostic rv = 0; 9865270Sbostic else 9940389Sbostic (void)printf("%s: nothing appropriate\n", *p); 10065270Sbostic exit(rv); 10140389Sbostic } 10240389Sbostic 103*66566Spendry void 10442403Sbostic apropos(argv, path, buildpath) 10540389Sbostic char **argv, *path; 10642403Sbostic int buildpath; 10740389Sbostic { 108*66566Spendry char *end, *name, **p; 109*66566Spendry char buf[LINE_MAX + 1], wbuf[LINE_MAX + 1]; 11040389Sbostic 11142403Sbostic for (name = path; name; name = end) { /* through name list */ 112*66566Spendry if (end = strchr(name, ':')) 11342403Sbostic *end++ = '\0'; 11442403Sbostic 11542403Sbostic if (buildpath) { 11642403Sbostic char hold[MAXPATHLEN + 1]; 11742403Sbostic 11842403Sbostic (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS); 11942403Sbostic name = hold; 12031702Sbostic } 12142403Sbostic 12242403Sbostic if (!freopen(name, "r", stdin)) 12333808Sbostic continue; 12433808Sbostic 12542403Sbostic foundman = 1; 12642403Sbostic 12735534Sbostic /* for each file found */ 12842403Sbostic while (fgets(buf, sizeof(buf), stdin)) { 129*66566Spendry if (!strchr(buf, '\n')) { 130*66566Spendry warnx("%s: line too long", name); 13151191Sbostic continue; 13240389Sbostic } 13335534Sbostic lowstr(buf, wbuf); 13435534Sbostic for (p = argv; *p; ++p) 13535534Sbostic if (match(wbuf, *p)) { 13640389Sbostic (void)printf("%s", buf); 13735534Sbostic found[p - argv] = 1; 13831702Sbostic 13933808Sbostic /* only print line once */ 14035534Sbostic while (*++p) 14135534Sbostic if (match(wbuf, *p)) 14235534Sbostic found[p - argv] = 1; 14333808Sbostic break; 14433808Sbostic } 14531702Sbostic } 14631702Sbostic } 14731702Sbostic } 14831702Sbostic 14933808Sbostic /* 15035534Sbostic * match -- 15135534Sbostic * match anywhere the string appears 15233808Sbostic */ 153*66566Spendry int 15435534Sbostic match(bp, str) 155*66566Spendry char *bp, *str; 15631702Sbostic { 157*66566Spendry int len; 158*66566Spendry char test; 15931702Sbostic 16031702Sbostic if (!*bp) 161*66566Spendry return (0); 16233808Sbostic /* backward compatible: everything matches empty string */ 16331702Sbostic if (!*str) 164*66566Spendry return (1); 16533808Sbostic for (test = *str++, len = strlen(str); *bp;) 16633808Sbostic if (test == *bp++ && !strncmp(bp, str, len)) 167*66566Spendry return (1); 168*66566Spendry return (0); 16931702Sbostic } 17031702Sbostic 17133808Sbostic /* 17233808Sbostic * lowstr -- 17333808Sbostic * convert a string to lower case 17433808Sbostic */ 175*66566Spendry void 17633808Sbostic lowstr(from, to) 177*66566Spendry char *from, *to; 17833808Sbostic { 179*66566Spendry char ch; 18035534Sbostic 18135534Sbostic while ((ch = *from++) && ch != '\n') 18235534Sbostic *to++ = isupper(ch) ? tolower(ch) : ch; 18335534Sbostic *to = '\0'; 18433808Sbostic } 18533808Sbostic 18633808Sbostic /* 18733808Sbostic * usage -- 18833808Sbostic * print usage message and die 18933808Sbostic */ 190*66566Spendry void 19131702Sbostic usage() 19231702Sbostic { 193*66566Spendry 19440389Sbostic (void)fprintf(stderr, 19565269Sbostic "usage: apropos [-C file] [-M path] [-m path] keyword ...\n"); 19631702Sbostic exit(1); 19731702Sbostic } 198