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