131702Sbostic /* 231702Sbostic * Copyright (c) 1987 Regents of the University of California. 331702Sbostic * All rights reserved. The Berkeley software License Agreement 431702Sbostic * specifies the terms and conditions for redistribution. 531702Sbostic */ 631702Sbostic 731702Sbostic #ifndef lint 831702Sbostic char copyright[] = 931702Sbostic "@(#) Copyright (c) 1987 Regents of the University of California.\n\ 1031702Sbostic All rights reserved.\n"; 1131702Sbostic #endif not lint 1231702Sbostic 1331702Sbostic #ifndef lint 14*31974Sbostic static char sccsid[] = "@(#)apropos.c 5.3 (Berkeley) 07/30/87"; 1531702Sbostic #endif not lint 1631702Sbostic 1731702Sbostic #include <sys/param.h> 1831702Sbostic #include <stdio.h> 1931702Sbostic #include <ctype.h> 2031702Sbostic 21*31974Sbostic #define DEF_PATH "/usr/man:/usr/new/man:/usr/local/man" 2231712Sbostic #define MAXLINELEN 1000 /* max line handled */ 2331702Sbostic #define NO 0 /* no/false */ 2431702Sbostic #define WHATIS "whatis" /* database name */ 2531702Sbostic #define YES 1 /* yes/true */ 2631702Sbostic 2731702Sbostic static char *myname; 2831702Sbostic 2931702Sbostic main(argc, argv) 3031702Sbostic int argc; 3131702Sbostic char **argv; 3231702Sbostic { 3331702Sbostic extern char *optarg; 3431702Sbostic extern int optind; 3531702Sbostic register char *beg, *end, **C; 3631702Sbostic int ch, foundman = NO, *found, isapropos, 3731702Sbostic a_match(), w_match(), (*match)(); 3831702Sbostic char *manpath = NULL, 3931702Sbostic buf[MAXLINELEN + 1], fname[MAXPATHLEN + 1], 4031702Sbostic wbuf[MAXLINELEN + 1], 4131702Sbostic *getenv(), *index(), *malloc(), *rindex(); 4231702Sbostic 4331702Sbostic myname = (beg = rindex(*argv, '/')) ? beg + 1 : *argv; 4431702Sbostic if (!strcmp(myname, "apropos")) { 4531702Sbostic isapropos = YES; 4631702Sbostic match = a_match; 4731702Sbostic } 4831702Sbostic else { 4931702Sbostic isapropos = NO; 5031702Sbostic match = w_match; 5131702Sbostic } 5231702Sbostic while ((ch = getopt(argc, argv, "M:P:")) != EOF) 5331702Sbostic switch((char)ch) { 5431702Sbostic case 'M': 5531702Sbostic case 'P': /* backward contemptible */ 5631702Sbostic manpath = optarg; 5731702Sbostic break; 5831702Sbostic case '?': 5931702Sbostic default: 6031702Sbostic usage(); 6131702Sbostic } 6231702Sbostic argv += optind; 6331702Sbostic argc -= optind; 6431702Sbostic if (argc < 1) 6531702Sbostic usage(); 6631702Sbostic 6731702Sbostic if (!(manpath = getenv("MANPATH"))) 6831702Sbostic manpath = DEF_PATH; 6931702Sbostic 7031702Sbostic /*NOSTRICT*/ 7131702Sbostic if (!(found = (int *)malloc((u_int)argc))) { 7231702Sbostic fprintf(stderr, "%s: out of space.\n", myname); 7331702Sbostic exit(1); 7431702Sbostic } 7531712Sbostic bzero((char *)found, argc * sizeof(int)); /* calloc is silly */ 7631702Sbostic 7731702Sbostic if (!isapropos) 7831712Sbostic for (C = argv; *C; ++C) { /* trim full paths */ 7931702Sbostic if (beg = rindex(*C, '/')) 8031702Sbostic *C = beg + 1; 8131702Sbostic } 8231702Sbostic for (C = argv; *C; ++C) /* convert to lower-case */ 8331702Sbostic lowstr(*C, *C); 8431702Sbostic 8531702Sbostic for (beg = manpath; beg; beg = end) { /* through path list */ 8631702Sbostic end = index(beg, ':'); 8731702Sbostic if (!end) 8831702Sbostic (void)sprintf(fname, "%s/%s", beg, WHATIS); 8931702Sbostic else { 9031702Sbostic (void)sprintf(fname, "%.*s/%s", end - beg, beg, WHATIS); 9131702Sbostic ++end; 9231702Sbostic } 9331702Sbostic /* for each file found */ 9431702Sbostic if (freopen(fname, "r", stdin)) { 9531702Sbostic foundman = YES; 9631702Sbostic while (gets(buf)) { /* read & convert to lcase */ 9731702Sbostic lowstr(buf, wbuf); 9831702Sbostic for (C = argv; *C; ++C) 9931702Sbostic if ((*match)(wbuf, *C)) { 10031702Sbostic puts(buf); 10131702Sbostic found[C - argv] = YES; 10231702Sbostic 10331702Sbostic /* only print line once */ 10431702Sbostic while (*++C) 10531702Sbostic if ((*match)(wbuf, *C)) 10631702Sbostic found[C - argv] = YES; 10731702Sbostic break; 10831702Sbostic } 10931702Sbostic } 11031702Sbostic } 11131702Sbostic } 11231702Sbostic if (!foundman) { 11331702Sbostic fprintf(stderr, "%s: no %s file found in %s.\n", myname, WHATIS, manpath); 11431702Sbostic exit(1); 11531702Sbostic } 11631702Sbostic for (C = argv; *C; C++) 11731702Sbostic if (!found[C - argv]) 11831702Sbostic printf("%s: %s\n", *C, isapropos ? "nothing appropriate" : "not found"); 11931702Sbostic } 12031702Sbostic 12131702Sbostic static 12231702Sbostic a_match(bp, str) 12331702Sbostic register char *bp, *str; 12431702Sbostic { 12531702Sbostic register char test, *Cs, *Cb; 12631702Sbostic 12731702Sbostic if (!*bp) 12831702Sbostic return(NO); 12931702Sbostic /* backward contemptible: everything matches empty string */ 13031702Sbostic if (!*str) 13131702Sbostic return(YES); 13231702Sbostic for (test = *str++; *bp;) 13331702Sbostic if (test == *bp++) { 13431702Sbostic Cs = str; 13531702Sbostic Cb = bp; 13631702Sbostic do { 13731702Sbostic if (!*Cs) 13831702Sbostic return(YES); 13931702Sbostic } while (*Cb++ == *Cs++); 14031702Sbostic } 14131702Sbostic return(NO); 14231702Sbostic } 14331702Sbostic 14431702Sbostic static 14531702Sbostic w_match(bp, str) 14631702Sbostic register char *bp, *str; 14731702Sbostic { 14831702Sbostic register char test, *Cs, *Cb; 14931702Sbostic 15031702Sbostic if (!*str || !*bp) 15131702Sbostic return(NO); 15231702Sbostic for (test = *str++; *bp;) 15331702Sbostic if (test == *bp++) { 15431702Sbostic for (Cs = str, Cb = bp; *Cs == *Cb; ++Cs, ++Cb); 15531702Sbostic if (!*Cs && (isspace(*Cb) || *Cb == '(' || *Cb == ',')) 15631702Sbostic return(YES); 15731702Sbostic } 15831702Sbostic return(NO); 15931702Sbostic } 16031702Sbostic 16131702Sbostic static 16231702Sbostic lowstr(from, to) 16331702Sbostic register char *from, *to; 16431702Sbostic { 16531702Sbostic for (; *from; ++from, ++to) 16631702Sbostic *to = isupper(*from) ? tolower(*from) : *from; 16731702Sbostic *to = '\0'; 16831702Sbostic } 16931702Sbostic 17031702Sbostic static 17131702Sbostic usage() 17231702Sbostic { 17331702Sbostic fprintf(stderr, "usage: %s [-M path] string ...\n", myname); 17431702Sbostic exit(1); 17531702Sbostic } 176