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