1 /* 2 * Copyright (c) 1987 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)apropos.c 5.12 (Berkeley) 06/01/90"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <stdio.h> 20 #include <ctype.h> 21 #include <string.h> 22 #include <stdlib.h> 23 #include "../man/pathnames.h" 24 25 #define MAXLINELEN 256 /* max line handled */ 26 27 char *progname; 28 29 static int *found, foundman; 30 31 main(argc, argv) 32 int argc; 33 char **argv; 34 { 35 extern char *optarg; 36 extern int optind; 37 register char **p; 38 int ch; 39 char *p_augment, *p_path, **getdb(); 40 41 progname = "apropos"; 42 p_augment = p_path = NULL; 43 while ((ch = getopt(argc, argv, "M:m:P:")) != EOF) 44 switch((char)ch) { 45 case 'M': 46 case 'P': /* backward compatible */ 47 p_path = optarg; 48 break; 49 case 'm': 50 p_augment = optarg; 51 break; 52 case '?': 53 default: 54 usage(); 55 } 56 argv += optind; 57 argc -= optind; 58 59 if (argc < 1) 60 usage(); 61 62 /*NOSTRICT*/ 63 if (!(found = (int *)malloc((u_int)argc))) 64 enomem(); 65 bzero((void *)found, argc * sizeof(int)); 66 67 for (p = argv; *p; ++p) /* convert to lower-case */ 68 lowstr(*p, *p); 69 70 if (p_augment) 71 apropos(argv, p_augment, 1); 72 if (p_path || (p_path = getenv("MANPATH"))) 73 apropos(argv, p_path, 1); 74 else 75 for (p = getdb(); *p; ++p) 76 apropos(argv, *p, 0); 77 78 if (!foundman) { 79 (void)fprintf(stderr, 80 "apropos: : no %s file found.\n", _PATH_WHATIS); 81 exit(1); 82 } 83 for (p = argv; *p; ++p) 84 if (!found[p - argv]) 85 (void)printf("%s: nothing appropriate\n", *p); 86 } 87 88 apropos(argv, path, buildpath) 89 char **argv, *path; 90 int buildpath; 91 { 92 register char *end, *name, **p; 93 char buf[MAXLINELEN + 1], wbuf[MAXLINELEN + 1]; 94 95 for (name = path; name; name = end) { /* through name list */ 96 if (end = index(name, ':')) 97 *end++ = '\0'; 98 99 if (buildpath) { 100 char hold[MAXPATHLEN + 1]; 101 102 (void)sprintf(hold, "%s/%s", name, _PATH_WHATIS); 103 name = hold; 104 } 105 106 if (!freopen(name, "r", stdin)) 107 continue; 108 109 foundman = 1; 110 111 /* for each file found */ 112 while (fgets(buf, sizeof(buf), stdin)) { 113 if (!index(buf, '\n')) { 114 (void)fprintf(stderr, 115 "apropos: %s line too long.\n", name); 116 exit(1); 117 } 118 lowstr(buf, wbuf); 119 for (p = argv; *p; ++p) 120 if (match(wbuf, *p)) { 121 (void)printf("%s", buf); 122 found[p - argv] = 1; 123 124 /* only print line once */ 125 while (*++p) 126 if (match(wbuf, *p)) 127 found[p - argv] = 1; 128 break; 129 } 130 } 131 } 132 } 133 134 /* 135 * match -- 136 * match anywhere the string appears 137 */ 138 match(bp, str) 139 register char *bp, *str; 140 { 141 register int len; 142 register char test; 143 144 if (!*bp) 145 return(0); 146 /* backward compatible: everything matches empty string */ 147 if (!*str) 148 return(1); 149 for (test = *str++, len = strlen(str); *bp;) 150 if (test == *bp++ && !strncmp(bp, str, len)) 151 return(1); 152 return(0); 153 } 154 155 /* 156 * lowstr -- 157 * convert a string to lower case 158 */ 159 lowstr(from, to) 160 register char *from, *to; 161 { 162 register char ch; 163 164 while ((ch = *from++) && ch != '\n') 165 *to++ = isupper(ch) ? tolower(ch) : ch; 166 *to = '\0'; 167 } 168 169 /* 170 * usage -- 171 * print usage message and die 172 */ 173 usage() 174 { 175 (void)fprintf(stderr, 176 "usage: apropos [-M path] [-m path] keyword ...\n"); 177 exit(1); 178 } 179