1*31702Sbostic /* 2*31702Sbostic * Copyright (c) 1987 Regents of the University of California. 3*31702Sbostic * All rights reserved. The Berkeley software License Agreement 4*31702Sbostic * specifies the terms and conditions for redistribution. 5*31702Sbostic */ 6*31702Sbostic 7*31702Sbostic #ifndef lint 8*31702Sbostic char copyright[] = 9*31702Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 10*31702Sbostic All rights reserved.\n"; 11*31702Sbostic #endif not lint 12*31702Sbostic 13*31702Sbostic #ifndef lint 14*31702Sbostic static char sccsid[] = "@(#)apropos.c 5.1 (Berkeley) 06/29/87"; 15*31702Sbostic #endif not lint 16*31702Sbostic 17*31702Sbostic #include <sys/param.h> 18*31702Sbostic #include <stdio.h> 19*31702Sbostic #include <ctype.h> 20*31702Sbostic 21*31702Sbostic #define DEF_PATH "/usr/man" /* default man path */ 22*31702Sbostic #define MAXLINELEN 500 /* max line handled */ 23*31702Sbostic #define NO 0 /* no/false */ 24*31702Sbostic #define WHATIS "whatis" /* database name */ 25*31702Sbostic #define YES 1 /* yes/true */ 26*31702Sbostic 27*31702Sbostic static char *myname; 28*31702Sbostic 29*31702Sbostic main(argc, argv) 30*31702Sbostic int argc; 31*31702Sbostic char **argv; 32*31702Sbostic { 33*31702Sbostic extern char *optarg; 34*31702Sbostic extern int optind; 35*31702Sbostic register char *beg, *end, **C; 36*31702Sbostic int ch, foundman = NO, *found, isapropos, 37*31702Sbostic a_match(), w_match(), (*match)(); 38*31702Sbostic char *manpath = NULL, 39*31702Sbostic buf[MAXLINELEN + 1], fname[MAXPATHLEN + 1], 40*31702Sbostic wbuf[MAXLINELEN + 1], 41*31702Sbostic *getenv(), *index(), *malloc(), *rindex(); 42*31702Sbostic 43*31702Sbostic myname = (beg = rindex(*argv, '/')) ? beg + 1 : *argv; 44*31702Sbostic if (!strcmp(myname, "apropos")) { 45*31702Sbostic isapropos = YES; 46*31702Sbostic match = a_match; 47*31702Sbostic } 48*31702Sbostic else { 49*31702Sbostic isapropos = NO; 50*31702Sbostic match = w_match; 51*31702Sbostic } 52*31702Sbostic while ((ch = getopt(argc, argv, "M:P:")) != EOF) 53*31702Sbostic switch((char)ch) { 54*31702Sbostic case 'M': 55*31702Sbostic case 'P': /* backward contemptible */ 56*31702Sbostic manpath = optarg; 57*31702Sbostic break; 58*31702Sbostic case '?': 59*31702Sbostic default: 60*31702Sbostic usage(); 61*31702Sbostic } 62*31702Sbostic argv += optind; 63*31702Sbostic argc -= optind; 64*31702Sbostic if (argc < 1) 65*31702Sbostic usage(); 66*31702Sbostic 67*31702Sbostic if (!(manpath = getenv("MANPATH"))) 68*31702Sbostic manpath = DEF_PATH; 69*31702Sbostic 70*31702Sbostic /*NOSTRICT*/ 71*31702Sbostic if (!(found = (int *)malloc((u_int)argc))) { 72*31702Sbostic fprintf(stderr, "%s: out of space.\n", myname); 73*31702Sbostic exit(1); 74*31702Sbostic } 75*31702Sbostic bzero(found, argc * sizeof(int)); /* calloc is silly */ 76*31702Sbostic 77*31702Sbostic if (!isapropos) 78*31702Sbostic for (C = argv; *C; ++C) { /* trim full paths */ 79*31702Sbostic if (beg = rindex(*C, '/')) 80*31702Sbostic *C = beg + 1; 81*31702Sbostic } 82*31702Sbostic for (C = argv; *C; ++C) /* convert to lower-case */ 83*31702Sbostic lowstr(*C, *C); 84*31702Sbostic 85*31702Sbostic for (beg = manpath; beg; beg = end) { /* through path list */ 86*31702Sbostic end = index(beg, ':'); 87*31702Sbostic if (!end) 88*31702Sbostic (void)sprintf(fname, "%s/%s", beg, WHATIS); 89*31702Sbostic else { 90*31702Sbostic (void)sprintf(fname, "%.*s/%s", end - beg, beg, WHATIS); 91*31702Sbostic ++end; 92*31702Sbostic } 93*31702Sbostic /* for each file found */ 94*31702Sbostic if (freopen(fname, "r", stdin)) { 95*31702Sbostic foundman = YES; 96*31702Sbostic while (gets(buf)) { /* read & convert to lcase */ 97*31702Sbostic lowstr(buf, wbuf); 98*31702Sbostic for (C = argv; *C; ++C) 99*31702Sbostic if ((*match)(wbuf, *C)) { 100*31702Sbostic puts(buf); 101*31702Sbostic found[C - argv] = YES; 102*31702Sbostic 103*31702Sbostic /* only print line once */ 104*31702Sbostic while (*++C) 105*31702Sbostic if ((*match)(wbuf, *C)) 106*31702Sbostic found[C - argv] = YES; 107*31702Sbostic break; 108*31702Sbostic } 109*31702Sbostic } 110*31702Sbostic } 111*31702Sbostic } 112*31702Sbostic if (!foundman) { 113*31702Sbostic fprintf(stderr, "%s: no %s file found in %s.\n", myname, WHATIS, manpath); 114*31702Sbostic exit(1); 115*31702Sbostic } 116*31702Sbostic for (C = argv; *C; C++) 117*31702Sbostic if (!found[C - argv]) 118*31702Sbostic printf("%s: %s\n", *C, isapropos ? "nothing appropriate" : "not found"); 119*31702Sbostic } 120*31702Sbostic 121*31702Sbostic static 122*31702Sbostic a_match(bp, str) 123*31702Sbostic register char *bp, *str; 124*31702Sbostic { 125*31702Sbostic register char test, *Cs, *Cb; 126*31702Sbostic 127*31702Sbostic if (!*bp) 128*31702Sbostic return(NO); 129*31702Sbostic /* backward contemptible: everything matches empty string */ 130*31702Sbostic if (!*str) 131*31702Sbostic return(YES); 132*31702Sbostic for (test = *str++; *bp;) 133*31702Sbostic if (test == *bp++) { 134*31702Sbostic Cs = str; 135*31702Sbostic Cb = bp; 136*31702Sbostic do { 137*31702Sbostic if (!*Cs) 138*31702Sbostic return(YES); 139*31702Sbostic } while (*Cb++ == *Cs++); 140*31702Sbostic } 141*31702Sbostic return(NO); 142*31702Sbostic } 143*31702Sbostic 144*31702Sbostic static 145*31702Sbostic w_match(bp, str) 146*31702Sbostic register char *bp, *str; 147*31702Sbostic { 148*31702Sbostic register char test, *Cs, *Cb; 149*31702Sbostic 150*31702Sbostic if (!*str || !*bp) 151*31702Sbostic return(NO); 152*31702Sbostic for (test = *str++; *bp;) 153*31702Sbostic if (test == *bp++) { 154*31702Sbostic for (Cs = str, Cb = bp; *Cs == *Cb; ++Cs, ++Cb); 155*31702Sbostic if (!*Cs && (isspace(*Cb) || *Cb == '(' || *Cb == ',')) 156*31702Sbostic return(YES); 157*31702Sbostic } 158*31702Sbostic return(NO); 159*31702Sbostic } 160*31702Sbostic 161*31702Sbostic static 162*31702Sbostic lowstr(from, to) 163*31702Sbostic register char *from, *to; 164*31702Sbostic { 165*31702Sbostic for (; *from; ++from, ++to) 166*31702Sbostic *to = isupper(*from) ? tolower(*from) : *from; 167*31702Sbostic *to = '\0'; 168*31702Sbostic } 169*31702Sbostic 170*31702Sbostic static 171*31702Sbostic usage() 172*31702Sbostic { 173*31702Sbostic fprintf(stderr, "usage: %s [-M path] string ...\n", myname); 174*31702Sbostic exit(1); 175*31702Sbostic } 176*31702Sbostic 177