Annotation of 43BSDReno/games/fortune/fortune.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1986 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Ken Arnold.
                      7:  *
                      8:  * Redistribution and use in source and binary forms are permitted
                      9:  * provided that the above copyright notice and this paragraph are
                     10:  * duplicated in all such forms and that any documentation,
                     11:  * advertising materials, and other materials related to such
                     12:  * distribution and use acknowledge that the software was developed
                     13:  * by the University of California, Berkeley.  The name of the
                     14:  * University may not be used to endorse or promote products derived
                     15:  * from this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  */
                     20: 
                     21: #ifndef lint
                     22: char copyright[] =
                     23: "@(#) Copyright (c) 1986 The Regents of the University of California.\n\
                     24:  All rights reserved.\n";
                     25: #endif /* not lint */
                     26: 
                     27: #ifndef lint
                     28: static char sccsid[] = "@(#)fortune.c  5.12 (Berkeley) 12/15/89";
                     29: #endif /* not lint */
                     30: 
                     31: # include      <machine/endian.h>
                     32: # include      <sys/param.h>
                     33: # include      <sys/stat.h>
                     34: # include      <sys/dir.h>
                     35: # include      <stdio.h>
                     36: # include      <assert.h>
                     37: # include      "strfile.h"
                     38: # include      "pathnames.h"
                     39: 
                     40: #ifdef SYSV
                     41: # include      <dirent.h>
                     42: 
                     43: # define       NO_LOCK
                     44: # define       REGCMP
                     45: # ifdef        NO_REGEX
                     46: #      undef    NO_REGEX
                     47: # endif        /* NO_REGEX */
                     48: # define       index   strchr
                     49: # define       rindex  strrchr
                     50: #endif /* SYSV */
                     51: 
                     52: #ifndef NO_REGEX
                     53: # include      <ctype.h>
                     54: #endif /* NO_REGEX */
                     55: 
                     56: # ifndef NO_LOCK
                     57: # include      <sys/file.h>
                     58: # endif        /* NO_LOCK */
                     59: 
                     60: # ifndef F_OK
                     61: /* codes for access() */
                     62: # define       F_OK            0       /* does file exist */
                     63: # define       X_OK            1       /* is it executable by caller */
                     64: # define       W_OK            2       /* writable by caller */
                     65: # define       R_OK            4       /* readable by caller */
                     66: # endif        /* F_OK */
                     67: 
                     68: # define       TRUE    1
                     69: # define       FALSE   0
                     70: # define       bool    short
                     71: 
                     72: # define       MINW    6               /* minimum wait if desired */
                     73: # define       CPERS   20              /* # of chars for each sec */
                     74: # define       SLEN    160             /* # of chars in short fortune */
                     75: 
                     76: # define       POS_UNKNOWN     ((unsigned long) -1)    /* pos for file unknown */
                     77: # define       NO_PROB         (-1)            /* no prob specified for file */
                     78: 
                     79: # ifdef DEBUG
                     80: # define       DPRINTF(l,x)    if (Debug >= l) fprintf x; else
                     81: # undef                NDEBUG
                     82: # else /* DEBUG */
                     83: # define       DPRINTF(l,x)
                     84: # define       NDEBUG  1
                     85: # endif        /* DEBUG */
                     86: 
                     87: typedef struct fd {
                     88:        int             percent;
                     89:        int             fd, datfd;
                     90:        unsigned long   pos;
                     91:        FILE            *inf;
                     92:        char            *name;
                     93:        char            *path;
                     94:        char            *datfile, *posfile;
                     95:        bool            read_tbl;
                     96:        bool            was_pos_file;
                     97:        STRFILE         tbl;
                     98:        int             num_children;
                     99:        struct fd       *child, *parent;
                    100:        struct fd       *next, *prev;
                    101: } FILEDESC;
                    102: 
                    103: bool   Found_one;                      /* did we find a match? */
                    104: bool   Find_files      = FALSE;        /* just find a list of proper fortune files */
                    105: bool   Wait            = FALSE;        /* wait desired after fortune */
                    106: bool   Short_only      = FALSE;        /* short fortune desired */
                    107: bool   Long_only       = FALSE;        /* long fortune desired */
                    108: bool   Offend          = FALSE;        /* offensive fortunes only */
                    109: bool   All_forts       = FALSE;        /* any fortune allowed */
                    110: bool   Equal_probs     = FALSE;        /* scatter un-allocted prob equally */
                    111: #ifndef NO_REGEX
                    112: bool   Match           = FALSE;        /* dump fortunes matching a pattern */
                    113: #endif
                    114: #ifdef DEBUG
                    115: bool   Debug = FALSE;                  /* print debug messages */
                    116: #endif
                    117: 
                    118: char   *Fortbuf = NULL;                        /* fortune buffer for -m */
                    119: 
                    120: int    Fort_len = 0;
                    121: 
                    122: off_t  Seekpts[2];                     /* seek pointers to fortunes */
                    123: 
                    124: FILEDESC       *File_list = NULL,      /* Head of file list */
                    125:                *File_tail = NULL;      /* Tail of file list */
                    126: FILEDESC       *Fortfile;              /* Fortune file to use */
                    127: 
                    128: STRFILE                Noprob_tbl;             /* sum of data for all no prob files */
                    129: 
                    130: char   *do_malloc(), *copy(), *off_name();
                    131: 
                    132: FILEDESC       *pick_child(), *new_fp();
                    133: 
                    134: extern char    *malloc(), *index(), *rindex(), *strcpy(), *strcat();
                    135: 
                    136: extern time_t  time();
                    137: 
                    138: #ifndef NO_REGEX
                    139: char   *conv_pat();
                    140: #endif
                    141: 
                    142: #ifndef NO_REGEX
                    143: #ifdef REGCMP
                    144: # define       RE_COMP(p)      (Re_pat = regcmp(p, NULL))
                    145: # define       BAD_COMP(f)     ((f) == NULL)
                    146: # define       RE_EXEC(p)      regex(Re_pat, (p))
                    147: 
                    148: char   *Re_pat;
                    149: 
                    150: char   *regcmp(), *regex();
                    151: #else
                    152: # define       RE_COMP(p)      (p = re_comp(p))
                    153: # define       BAD_COMP(f)     ((f) != NULL)
                    154: # define       RE_EXEC(p)      re_exec(p)
                    155: 
                    156: char   *re_comp();
                    157: #ifdef SYSV
                    158: char   *re_exec();
                    159: #else
                    160: int    re_exec();
                    161: #endif
                    162: #endif
                    163: #endif
                    164: 
                    165: main(ac, av)
                    166: int    ac;
                    167: char   *av[];
                    168: {
                    169: #ifdef OK_TO_WRITE_DISK
                    170:        int     fd;
                    171: #endif /* OK_TO_WRITE_DISK */
                    172: 
                    173:        getargs(ac, av);
                    174: 
                    175: #ifndef NO_REGEX
                    176:        if (Match)
                    177:                exit(find_matches() != 0);
                    178: #endif
                    179: 
                    180:        init_prob();
                    181:        srandom((int)(time((time_t *) NULL) + getpid()));
                    182:        do {
                    183:                get_fort();
                    184:        } while ((Short_only && fortlen() > SLEN) ||
                    185:                 (Long_only && fortlen() <= SLEN));
                    186: 
                    187:        display(Fortfile);
                    188: 
                    189: #ifdef OK_TO_WRITE_DISK
                    190:        if ((fd = creat(Fortfile->posfile, 0666)) < 0) {
                    191:                perror(Fortfile->posfile);
                    192:                exit(1);
                    193:        }
                    194: #ifdef LOCK_EX
                    195:        /*
                    196:         * if we can, we exclusive lock, but since it isn't very
                    197:         * important, we just punt if we don't have easy locking
                    198:         * available.
                    199:         */
                    200:        (void) flock(fd, LOCK_EX);
                    201: #endif /* LOCK_EX */
                    202:        write(fd, (char *) &Fortfile->pos, sizeof Fortfile->pos);
                    203:        if (!Fortfile->was_pos_file)
                    204:                (void) chmod(Fortfile->path, 0666);
                    205: #ifdef LOCK_EX
                    206:        (void) flock(fd, LOCK_UN);
                    207: #endif /* LOCK_EX */
                    208: #endif /* OK_TO_WRITE_DISK */
                    209:        if (Wait) {
                    210:                if (Fort_len == 0)
                    211:                        (void) fortlen();
                    212:                sleep((unsigned int) max(Fort_len / CPERS, MINW));
                    213:        }
                    214:        exit(0);
                    215:        /* NOTREACHED */
                    216: }
                    217: 
                    218: display(fp)
                    219: FILEDESC       *fp;
                    220: {
                    221:        register char   *p, ch;
                    222:        char    line[BUFSIZ];
                    223: 
                    224:        open_fp(fp);
                    225:        (void) fseek(fp->inf, Seekpts[0], 0);
                    226:        for (Fort_len = 0; fgets(line, sizeof line, fp->inf) != NULL &&
                    227:            !STR_ENDSTRING(line, fp->tbl); Fort_len++) {
                    228:                if (fp->tbl.str_flags & STR_ROTATED)
                    229:                        for (p = line; ch = *p; ++p)
                    230:                                if (isupper(ch))
                    231:                                        *p = 'A' + (ch - 'A' + 13) % 26;
                    232:                                else if (islower(ch))
                    233:                                        *p = 'a' + (ch - 'a' + 13) % 26;
                    234:                fputs(line, stdout);
                    235:        }
                    236:        (void) fflush(stdout);
                    237: }
                    238: 
                    239: /*
                    240:  * fortlen:
                    241:  *     Return the length of the fortune.
                    242:  */
                    243: fortlen()
                    244: {
                    245:        register int    nchar;
                    246:        char            line[BUFSIZ];
                    247: 
                    248:        if (!(Fortfile->tbl.str_flags & (STR_RANDOM | STR_ORDERED)))
                    249:                nchar = (Seekpts[1] - Seekpts[0] <= SLEN);
                    250:        else {
                    251:                open_fp(Fortfile);
                    252:                (void) fseek(Fortfile->inf, Seekpts[0], 0);
                    253:                nchar = 0;
                    254:                while (fgets(line, sizeof line, Fortfile->inf) != NULL &&
                    255:                       !STR_ENDSTRING(line, Fortfile->tbl))
                    256:                        nchar += strlen(line);
                    257:        }
                    258:        Fort_len = nchar;
                    259:        return nchar;
                    260: }
                    261: 
                    262: /*
                    263:  *     This routine evaluates the arguments on the command line
                    264:  */
                    265: getargs(argc, argv)
                    266: register int   argc;
                    267: register char  **argv;
                    268: {
                    269:        register int    ignore_case;
                    270: # ifndef NO_REGEX
                    271:        register char   *pat;
                    272: # endif        /* NO_REGEX */
                    273:        extern char *optarg;
                    274:        extern int optind;
                    275:        int ch;
                    276: 
                    277:        ignore_case = FALSE;
                    278:        pat = NULL;
                    279: 
                    280: # ifdef DEBUG
                    281:        while ((ch = getopt(argc, argv, "aDefilm:osw")) != EOF)
                    282: #else
                    283:        while ((ch = getopt(argc, argv, "aefilm:osw")) != EOF)
                    284: #endif /* DEBUG */
                    285:                switch(ch) {
                    286:                case 'a':               /* any fortune */
                    287:                        All_forts++;
                    288:                        break;
                    289: # ifdef DEBUG
                    290:                case 'D':
                    291:                        Debug++;
                    292:                        break;
                    293: # endif /* DEBUG */
                    294:                case 'e':
                    295:                        Equal_probs++;  /* scatter un-allocted prob equally */
                    296:                        break;
                    297:                case 'f':               /* find fortune files */
                    298:                        Find_files++;
                    299:                        break;
                    300:                case 'l':               /* long ones only */
                    301:                        Long_only++;
                    302:                        Short_only = FALSE;
                    303:                        break;
                    304:                case 'o':               /* offensive ones only */
                    305:                        Offend++;
                    306:                        break;
                    307:                case 's':               /* short ones only */
                    308:                        Short_only++;
                    309:                        Long_only = FALSE;
                    310:                        break;
                    311:                case 'w':               /* give time to read */
                    312:                        Wait++;
                    313:                        break;
                    314: # ifdef        NO_REGEX
                    315:                case 'i':                       /* case-insensitive match */
                    316:                case 'm':                       /* dump out the fortunes */
                    317:                        (void) fprintf(stderr,
                    318:                            "fortune: can't match fortunes on this system (Sorry)\n");
                    319:                        exit(0);
                    320: # else /* NO_REGEX */
                    321:                case 'm':                       /* dump out the fortunes */
                    322:                        Match++;
                    323:                        pat = optarg;
                    324:                        break;
                    325:                case 'i':                       /* case-insensitive match */
                    326:                        ignore_case++;
                    327:                        break;
                    328: # endif        /* NO_REGEX */
                    329:                case '?':
                    330:                default:
                    331:                        usage();
                    332:                }
                    333:        argc -= optind;
                    334:        argv += optind;
                    335: 
                    336:        if (!form_file_list(argv, argc))
                    337:                exit(1);        /* errors printed through form_file_list() */
                    338: #ifdef DEBUG
                    339:        if (Debug >= 1)
                    340:                print_file_list();
                    341: #endif /* DEBUG */
                    342:        if (Find_files) {
                    343:                print_file_list();
                    344:                exit(0);
                    345:        }
                    346: 
                    347: # ifndef NO_REGEX
                    348:        if (pat != NULL) {
                    349:                if (ignore_case)
                    350:                        pat = conv_pat(pat);
                    351:                if (BAD_COMP(RE_COMP(pat))) {
                    352: #ifndef REGCMP
                    353:                        fprintf(stderr, "%s\n", pat);
                    354: #else  /* REGCMP */
                    355:                        fprintf(stderr, "bad pattern: %s\n", pat);
                    356: #endif /* REGCMP */
                    357:                }
                    358:        }
                    359: # endif        /* NO_REGEX */
                    360: }
                    361: 
                    362: /*
                    363:  * form_file_list:
                    364:  *     Form the file list from the file specifications.
                    365:  */
                    366: form_file_list(files, file_cnt)
                    367: register char  **files;
                    368: register int   file_cnt;
                    369: {
                    370:        register int    i, percent;
                    371:        register char   *sp;
                    372: 
                    373:        if (file_cnt == 0)
                    374:                if (Find_files)
                    375:                        return add_file(NO_PROB, FORTDIR, NULL, &File_list,
                    376:                                        &File_tail, NULL);
                    377:                else
                    378:                        return add_file(NO_PROB, "fortunes", FORTDIR,
                    379:                                        &File_list, &File_tail, NULL);
                    380:        for (i = 0; i < file_cnt; i++) {
                    381:                percent = NO_PROB;
                    382:                if (!isdigit(files[i][0]))
                    383:                        sp = files[i];
                    384:                else {
                    385:                        percent = 0;
                    386:                        for (sp = files[i]; isdigit(*sp); sp++)
                    387:                                percent = percent * 10 + *sp - '0';
                    388:                        if (percent > 100) {
                    389:                                fprintf(stderr, "percentages must be <= 100\n");
                    390:                                return FALSE;
                    391:                        }
                    392:                        if (*sp == '.') {
                    393:                                fprintf(stderr, "percentages must be integers\n");
                    394:                                return FALSE;
                    395:                        }
                    396:                        /*
                    397:                         * If the number isn't followed by a '%', then
                    398:                         * it was not a percentage, just the first part
                    399:                         * of a file name which starts with digits.
                    400:                         */
                    401:                        if (*sp != '%') {
                    402:                                percent = NO_PROB;
                    403:                                sp = files[i];
                    404:                        }
                    405:                        else if (*++sp == '\0') {
                    406:                                if (++i >= file_cnt) {
                    407:                                        fprintf(stderr, "percentages must precede files\n");
                    408:                                        return FALSE;
                    409:                                }
                    410:                                sp = files[i];
                    411:                        }
                    412:                }
                    413:                if (strcmp(sp, "all") == 0)
                    414:                        sp = FORTDIR;
                    415:                if (!add_file(percent, sp, NULL, &File_list, &File_tail, NULL))
                    416:                        return FALSE;
                    417:        }
                    418:        return TRUE;
                    419: }
                    420: 
                    421: /*
                    422:  * add_file:
                    423:  *     Add a file to the file list.
                    424:  */
                    425: add_file(percent, file, dir, head, tail, parent)
                    426: int            percent;
                    427: register char  *file;
                    428: char           *dir;
                    429: FILEDESC       **head, **tail;
                    430: FILEDESC       *parent;
                    431: {
                    432:        register FILEDESC       *fp;
                    433:        register int            fd;
                    434:        register char           *path, *offensive;
                    435:        register bool           was_malloc;
                    436:        register bool           isdir;
                    437: 
                    438:        if (dir == NULL) {
                    439:                path = file;
                    440:                was_malloc = FALSE;
                    441:        }
                    442:        else {
                    443:                path = do_malloc((unsigned int) (strlen(dir) + strlen(file) + 2));
                    444:                (void) strcat(strcat(strcpy(path, dir), "/"), file);
                    445:                was_malloc = TRUE;
                    446:        }
                    447:        if ((isdir = is_dir(path)) && parent != NULL) {
                    448:                if (was_malloc)
                    449:                        free(path);
                    450:                return FALSE;   /* don't recurse */
                    451:        }
                    452:        offensive = NULL;
                    453:        if (!isdir && parent == NULL && (All_forts || Offend) &&
                    454:            !is_off_name(path)) {
                    455:                offensive = off_name(path);
                    456:                was_malloc = TRUE;
                    457:                if (Offend) {
                    458:                        if (was_malloc)
                    459:                                free(path);
                    460:                        path = offensive;
                    461:                        file = off_name(file);
                    462:                }
                    463:        }
                    464: 
                    465:        DPRINTF(1, (stderr, "adding file \"%s\"\n", path));
                    466: over:
                    467:        if ((fd = open(path, 0)) < 0) {
                    468:                /*
                    469:                 * This is a sneak.  If the user said -a, and if the
                    470:                 * file we're given isn't a file, we check to see if
                    471:                 * there is a -o version.  If there is, we treat it as
                    472:                 * if *that* were the file given.  We only do this for
                    473:                 * individual files -- if we're scanning a directory,
                    474:                 * we'll pick up the -o file anyway.
                    475:                 */
                    476:                if (All_forts && offensive != NULL) {
                    477:                        path = offensive;
                    478:                        if (was_malloc)
                    479:                                free(path);
                    480:                        offensive = NULL;
                    481:                        was_malloc = TRUE;
                    482:                        DPRINTF(1, (stderr, "\ttrying \"%s\"\n", path));
                    483:                        file = off_name(file);
                    484:                        goto over;
                    485:                }
                    486:                if (dir == NULL && file[0] != '/')
                    487:                        return add_file(percent, file, FORTDIR, head, tail,
                    488:                                        parent);
                    489:                if (parent == NULL)
                    490:                        perror(path);
                    491:                if (was_malloc)
                    492:                        free(path);
                    493:                return FALSE;
                    494:        }
                    495: 
                    496:        DPRINTF(2, (stderr, "path = \"%s\"\n", path));
                    497: 
                    498:        fp = new_fp();
                    499:        fp->fd = fd;
                    500:        fp->percent = percent;
                    501:        fp->name = file;
                    502:        fp->path = path;
                    503:        fp->parent = parent;
                    504: 
                    505:        if ((isdir && !add_dir(fp)) ||
                    506:            (!isdir &&
                    507:             !is_fortfile(path, &fp->datfile, &fp->posfile, (parent != NULL))))
                    508:        {
                    509:                if (parent == NULL)
                    510:                        fprintf(stderr,
                    511:                                "fortune:%s not a fortune file or directory\n",
                    512:                                path);
                    513:                free((char *) fp);
                    514:                if (was_malloc)
                    515:                        free(path);
                    516:                do_free(fp->datfile);
                    517:                do_free(fp->posfile);
                    518:                do_free(offensive);
                    519:                return FALSE;
                    520:        }
                    521:        /*
                    522:         * If the user said -a, we need to make this node a pointer to
                    523:         * both files, if there are two.  We don't need to do this if
                    524:         * we are scanning a directory, since the scan will pick up the
                    525:         * -o file anyway.
                    526:         */
                    527:        if (All_forts && parent == NULL && !is_off_name(path))
                    528:                all_forts(fp, offensive);
                    529:        if (*head == NULL)
                    530:                *head = *tail = fp;
                    531:        else if (fp->percent == NO_PROB) {
                    532:                (*tail)->next = fp;
                    533:                fp->prev = *tail;
                    534:                *tail = fp;
                    535:        }
                    536:        else {
                    537:                (*head)->prev = fp;
                    538:                fp->next = *head;
                    539:                *head = fp;
                    540:        }
                    541: #ifdef OK_TO_WRITE_DISK
                    542:        fp->was_pos_file = (access(fp->posfile, W_OK) >= 0);
                    543: #endif /* OK_TO_WRITE_DISK */
                    544: 
                    545:        return TRUE;
                    546: }
                    547: 
                    548: /*
                    549:  * new_fp:
                    550:  *     Return a pointer to an initialized new FILEDESC.
                    551:  */
                    552: FILEDESC *
                    553: new_fp()
                    554: {
                    555:        register FILEDESC       *fp;
                    556: 
                    557:        fp = (FILEDESC *) do_malloc(sizeof *fp);
                    558:        fp->datfd = -1;
                    559:        fp->pos = POS_UNKNOWN;
                    560:        fp->inf = NULL;
                    561:        fp->fd = -1;
                    562:        fp->percent = NO_PROB;
                    563:        fp->read_tbl = FALSE;
                    564:        fp->next = NULL;
                    565:        fp->prev = NULL;
                    566:        fp->child = NULL;
                    567:        fp->parent = NULL;
                    568:        fp->datfile = NULL;
                    569:        fp->posfile = NULL;
                    570:        return fp;
                    571: }
                    572: 
                    573: /*
                    574:  * off_name:
                    575:  *     Return a pointer to the offensive version of a file of this name.
                    576:  */
                    577: char *
                    578: off_name(file)
                    579: char   *file;
                    580: {
                    581:        char    *new;
                    582: 
                    583:        new = copy(file, (unsigned int) (strlen(file) + 2));
                    584:        return strcat(new, "-o");
                    585: }
                    586: 
                    587: /*
                    588:  * is_off_name:
                    589:  *     Is the file an offensive-style name?
                    590:  */
                    591: is_off_name(file)
                    592: char   *file;
                    593: {
                    594:        int     len;
                    595: 
                    596:        len = strlen(file);
                    597:        return (len >= 3 && file[len - 2] == '-' && file[len - 1] == 'o');
                    598: }
                    599: 
                    600: /*
                    601:  * all_forts:
                    602:  *     Modify a FILEDESC element to be the parent of two children if
                    603:  *     there are two children to be a parent of.
                    604:  */
                    605: all_forts(fp, offensive)
                    606: register FILEDESC      *fp;
                    607: char                   *offensive;
                    608: {
                    609:        register char           *sp;
                    610:        register FILEDESC       *scene, *obscene;
                    611:        register int            fd;
                    612:        auto char               *datfile, *posfile;
                    613: 
                    614:        if (fp->child != NULL)  /* this is a directory, not a file */
                    615:                return;
                    616:        if (!is_fortfile(offensive, &datfile, &posfile, FALSE))
                    617:                return;
                    618:        if ((fd = open(offensive, 0)) < 0)
                    619:                return;
                    620:        DPRINTF(1, (stderr, "adding \"%s\" because of -a\n", offensive));
                    621:        scene = new_fp();
                    622:        obscene = new_fp();
                    623:        *scene = *fp;
                    624: 
                    625:        fp->num_children = 2;
                    626:        fp->child = scene;
                    627:        scene->next = obscene;
                    628:        obscene->next = NULL;
                    629:        scene->child = obscene->child = NULL;
                    630:        scene->parent = obscene->parent = fp;
                    631: 
                    632:        fp->fd = -1;
                    633:        scene->percent = obscene->percent = NO_PROB;
                    634: 
                    635:        obscene->fd = fd;
                    636:        obscene->inf = NULL;
                    637:        obscene->path = offensive;
                    638:        if ((sp = rindex(offensive, '/')) == NULL)
                    639:                obscene->name = offensive;
                    640:        else
                    641:                obscene->name = ++sp;
                    642:        obscene->datfile = datfile;
                    643:        obscene->posfile = posfile;
                    644:        obscene->read_tbl = FALSE;
                    645: #ifdef OK_TO_WRITE_DISK
                    646:        obscene->was_pos_file = (access(obscene->posfile, W_OK) >= 0);
                    647: #endif /* OK_TO_WRITE_DISK */
                    648: }
                    649: 
                    650: /*
                    651:  * add_dir:
                    652:  *     Add the contents of an entire directory.
                    653:  */
                    654: add_dir(fp)
                    655: register FILEDESC      *fp;
                    656: {
                    657:        register DIR            *dir;
                    658: #ifdef SYSV
                    659:        register struct dirent  *dirent;        /* NIH, of course! */
                    660: #else
                    661:        register struct direct  *dirent;
                    662: #endif
                    663:        auto FILEDESC           *tailp;
                    664:        auto char               *name;
                    665: 
                    666:        (void) close(fp->fd);
                    667:        fp->fd = -1;
                    668:        if ((dir = opendir(fp->path)) == NULL) {
                    669:                perror(fp->path);
                    670:                return FALSE;
                    671:        }
                    672:        tailp = NULL;
                    673:        DPRINTF(1, (stderr, "adding dir \"%s\"\n", fp->path));
                    674:        fp->num_children = 0;
                    675:        while ((dirent = readdir(dir)) != NULL) {
                    676:                if (dirent->d_namlen == 0)
                    677:                        continue;
                    678:                name = copy(dirent->d_name, dirent->d_namlen);
                    679:                if (add_file(NO_PROB, name, fp->path, &fp->child, &tailp, fp))
                    680:                        fp->num_children++;
                    681:                else
                    682:                        free(name);
                    683:        }
                    684:        if (fp->num_children == 0) {
                    685:                (void) fprintf(stderr,
                    686:                    "fortune: %s: No fortune files in directory.\n", fp->path);
                    687:                return FALSE;
                    688:        }
                    689:        return TRUE;
                    690: }
                    691: 
                    692: /*
                    693:  * is_dir:
                    694:  *     Return TRUE if the file is a directory, FALSE otherwise.
                    695:  */
                    696: is_dir(file)
                    697: char   *file;
                    698: {
                    699:        auto struct stat        sbuf;
                    700: 
                    701:        if (stat(file, &sbuf) < 0)
                    702:                return FALSE;
                    703:        return (sbuf.st_mode & S_IFDIR);
                    704: }
                    705: 
                    706: /*
                    707:  * is_fortfile:
                    708:  *     Return TRUE if the file is a fortune database file.  We try and
                    709:  *     exclude files without reading them if possible to avoid
                    710:  *     overhead.  Files which start with ".", or which have "illegal"
                    711:  *     suffixes, as contained in suflist[], are ruled out.
                    712:  */
                    713: /* ARGSUSED */
                    714: is_fortfile(file, datp, posp, check_for_offend)
                    715: char   *file;
                    716: char   **datp, **posp;
                    717: int    check_for_offend;
                    718: {
                    719:        register int    i;
                    720:        register char   *sp;
                    721:        register char   *datfile;
                    722:        static char     *suflist[] = {  /* list of "illegal" suffixes" */
                    723:                                "dat", "pos", "c", "h", "p", "i", "f",
                    724:                                "pas", "ftn", "ins.c", "ins,pas",
                    725:                                "ins.ftn", "sml",
                    726:                                NULL
                    727:                        };
                    728: 
                    729:        DPRINTF(2, (stderr, "is_fortfile(%s) returns ", file));
                    730: 
                    731:        /*
                    732:         * Preclude any -o files for offendable people, and any non -o
                    733:         * files for completely offensive people.
                    734:         */
                    735:        if (check_for_offend && !All_forts) {
                    736:                i = strlen(file);
                    737:                if (Offend ^ (file[i - 2] == '-' && file[i - 1] == 'o'))
                    738:                        return FALSE;
                    739:        }
                    740: 
                    741:        if ((sp = rindex(file, '/')) == NULL)
                    742:                sp = file;
                    743:        else
                    744:                sp++;
                    745:        if (*sp == '.') {
                    746:                DPRINTF(2, (stderr, "FALSE (file starts with '.')\n"));
                    747:                return FALSE;
                    748:        }
                    749:        if ((sp = rindex(sp, '.')) != NULL) {
                    750:                sp++;
                    751:                for (i = 0; suflist[i] != NULL; i++)
                    752:                        if (strcmp(sp, suflist[i]) == 0) {
                    753:                                DPRINTF(2, (stderr, "FALSE (file has suffix \".%s\")\n", sp));
                    754:                                return FALSE;
                    755:                        }
                    756:        }
                    757: 
                    758:        datfile = copy(file, (unsigned int) (strlen(file) + 4)); /* +4 for ".dat" */
                    759:        strcat(datfile, ".dat");
                    760:        if (access(datfile, R_OK) < 0) {
                    761:                free(datfile);
                    762:                DPRINTF(2, (stderr, "FALSE (no \".dat\" file)\n"));
                    763:                return FALSE;
                    764:        }
                    765:        if (datp != NULL)
                    766:                *datp = datfile;
                    767:        else
                    768:                free(datfile);
                    769: #ifdef OK_TO_WRITE_DISK
                    770:        if (posp != NULL) {
                    771:                *posp = copy(file, (unsigned int) (strlen(file) + 4)); /* +4 for ".dat" */
                    772:                (void) strcat(*posp, ".pos");
                    773:        }
                    774: #endif /* OK_TO_WRITE_DISK */
                    775:        DPRINTF(2, (stderr, "TRUE\n"));
                    776:        return TRUE;
                    777: }
                    778: 
                    779: /*
                    780:  * copy:
                    781:  *     Return a malloc()'ed copy of the string
                    782:  */
                    783: char *
                    784: copy(str, len)
                    785: char           *str;
                    786: unsigned int   len;
                    787: {
                    788:        char    *new, *sp;
                    789: 
                    790:        new = do_malloc(len + 1);
                    791:        sp = new;
                    792:        do {
                    793:                *sp++ = *str;
                    794:        } while (*str++);
                    795:        return new;
                    796: }
                    797: 
                    798: /*
                    799:  * do_malloc:
                    800:  *     Do a malloc, checking for NULL return.
                    801:  */
                    802: char *
                    803: do_malloc(size)
                    804: unsigned int   size;
                    805: {
                    806:        char    *new;
                    807: 
                    808:        if ((new = malloc(size)) == NULL) {
                    809:                (void) fprintf(stderr, "fortune: out of memory.\n");
                    810:                exit(1);
                    811:        }
                    812:        return new;
                    813: }
                    814: 
                    815: /*
                    816:  * do_free:
                    817:  *     Free malloc'ed space, if any.
                    818:  */
                    819: do_free(ptr)
                    820: char   *ptr;
                    821: {
                    822:        if (ptr != NULL)
                    823:                free(ptr);
                    824: }
                    825: 
                    826: /*
                    827:  * init_prob:
                    828:  *     Initialize the fortune probabilities.
                    829:  */
                    830: init_prob()
                    831: {
                    832:        register FILEDESC       *fp, *last;
                    833:        register int            percent, num_noprob, frac;
                    834: 
                    835:        /*
                    836:         * Distribute the residual probability (if any) across all
                    837:         * files with unspecified probability (i.e., probability of 0)
                    838:         * (if any).
                    839:         */
                    840: 
                    841:        percent = 0;
                    842:        num_noprob = 0;
                    843:        for (fp = File_tail; fp != NULL; fp = fp->prev)
                    844:                if (fp->percent == NO_PROB) {
                    845:                        num_noprob++;
                    846:                        if (Equal_probs)
                    847:                                last = fp;
                    848:                }
                    849:                else
                    850:                        percent += fp->percent;
                    851:        DPRINTF(1, (stderr, "summing probabilities:%d%% with %d NO_PROB's",
                    852:                    percent, num_noprob));
                    853:        if (percent > 100) {
                    854:                (void) fprintf(stderr,
                    855:                    "fortune: probabilities sum to %d%%!\n", percent);
                    856:                exit(1);
                    857:        }
                    858:        else if (percent < 100 && num_noprob == 0) {
                    859:                (void) fprintf(stderr,
                    860:                    "fortune: no place to put residual probability (%d%%)\n",
                    861:                    percent);
                    862:                exit(1);
                    863:        }
                    864:        else if (percent == 100 && num_noprob != 0) {
                    865:                (void) fprintf(stderr,
                    866:                    "fortune: no probability left to put in residual files\n");
                    867:                exit(1);
                    868:        }
                    869:        percent = 100 - percent;
                    870:        if (Equal_probs)
                    871:                if (num_noprob != 0) {
                    872:                        if (num_noprob > 1) {
                    873:                                frac = percent / num_noprob;
                    874:                                DPRINTF(1, (stderr, ", frac = %d%%", frac));
                    875:                                for (fp = File_list; fp != last; fp = fp->next)
                    876:                                        if (fp->percent == NO_PROB) {
                    877:                                                fp->percent = frac;
                    878:                                                percent -= frac;
                    879:                                        }
                    880:                        }
                    881:                        last->percent = percent;
                    882:                        DPRINTF(1, (stderr, ", residual = %d%%", percent));
                    883:                }
                    884:        else {
                    885:                DPRINTF(1, (stderr,
                    886:                            ", %d%% distributed over remaining fortunes\n",
                    887:                            percent));
                    888:        }
                    889:        DPRINTF(1, (stderr, "\n"));
                    890: 
                    891: #ifdef DEBUG
                    892:        if (Debug >= 1)
                    893:                print_file_list();
                    894: #endif
                    895: }
                    896: 
                    897: /*
                    898:  * get_fort:
                    899:  *     Get the fortune data file's seek pointer for the next fortune.
                    900:  */
                    901: get_fort()
                    902: {
                    903:        register FILEDESC       *fp;
                    904:        register int            choice;
                    905:        long random();
                    906: 
                    907:        if (File_list->next == NULL || File_list->percent == NO_PROB)
                    908:                fp = File_list;
                    909:        else {
                    910:                choice = random() % 100;
                    911:                DPRINTF(1, (stderr, "choice = %d\n", choice));
                    912:                for (fp = File_list; fp->percent != NO_PROB; fp = fp->next)
                    913:                        if (choice < fp->percent)
                    914:                                break;
                    915:                        else {
                    916:                                choice -= fp->percent;
                    917:                                DPRINTF(1, (stderr,
                    918:                                            "    skip \"%s\", %d%% (choice = %d)\n",
                    919:                                            fp->name, fp->percent, choice));
                    920:                        }
                    921:                        DPRINTF(1, (stderr,
                    922:                                    "using \"%s\", %d%% (choice = %d)\n",
                    923:                                    fp->name, fp->percent, choice));
                    924:        }
                    925:        if (fp->percent != NO_PROB)
                    926:                get_tbl(fp);
                    927:        else {
                    928:                if (fp->next != NULL) {
                    929:                        sum_noprobs(fp);
                    930:                        choice = random() % Noprob_tbl.str_numstr;
                    931:                        DPRINTF(1, (stderr, "choice = %d (of %d) \n", choice,
                    932:                                    Noprob_tbl.str_numstr));
                    933:                        while (choice >= fp->tbl.str_numstr) {
                    934:                                choice -= fp->tbl.str_numstr;
                    935:                                fp = fp->next;
                    936:                                DPRINTF(1, (stderr,
                    937:                                            "    skip \"%s\", %d (choice = %d)\n",
                    938:                                            fp->name, fp->tbl.str_numstr,
                    939:                                            choice));
                    940:                        }
                    941:                        DPRINTF(1, (stderr, "using \"%s\", %d\n", fp->name,
                    942:                                    fp->tbl.str_numstr));
                    943:                }
                    944:                get_tbl(fp);
                    945:        }
                    946:        if (fp->child != NULL) {
                    947:                DPRINTF(1, (stderr, "picking child\n"));
                    948:                fp = pick_child(fp);
                    949:        }
                    950:        Fortfile = fp;
                    951:        get_pos(fp);
                    952:        open_dat(fp);
                    953:        (void) lseek(fp->datfd,
                    954:                     (off_t) (sizeof fp->tbl + fp->pos * sizeof Seekpts[0]), 0);
                    955:        read(fp->datfd, Seekpts, sizeof Seekpts);
                    956:        Seekpts[0] = ntohl(Seekpts[0]);
                    957:        Seekpts[1] = ntohl(Seekpts[1]);
                    958: }
                    959: 
                    960: /*
                    961:  * pick_child
                    962:  *     Pick a child from a chosen parent.
                    963:  */
                    964: FILEDESC *
                    965: pick_child(parent)
                    966: FILEDESC       *parent;
                    967: {
                    968:        register FILEDESC       *fp;
                    969:        register int            choice;
                    970: 
                    971:        if (Equal_probs) {
                    972:                choice = random() % parent->num_children;
                    973:                DPRINTF(1, (stderr, "    choice = %d (of %d)\n",
                    974:                            choice, parent->num_children));
                    975:                for (fp = parent->child; choice--; fp = fp->next)
                    976:                        continue;
                    977:                DPRINTF(1, (stderr, "    using %s\n", fp->name));
                    978:                return fp;
                    979:        }
                    980:        else {
                    981:                get_tbl(parent);
                    982:                choice = random() % parent->tbl.str_numstr;
                    983:                DPRINTF(1, (stderr, "    choice = %d (of %d)\n",
                    984:                            choice, parent->tbl.str_numstr));
                    985:                for (fp = parent->child; choice >= fp->tbl.str_numstr;
                    986:                     fp = fp->next) {
                    987:                        choice -= fp->tbl.str_numstr;
                    988:                        DPRINTF(1, (stderr, "\tskip %s, %d (choice = %d)\n",
                    989:                                    fp->name, fp->tbl.str_numstr, choice));
                    990:                }
                    991:                DPRINTF(1, (stderr, "    using %s, %d\n", fp->name,
                    992:                            fp->tbl.str_numstr));
                    993:                return fp;
                    994:        }
                    995: }
                    996: 
                    997: /*
                    998:  * sum_noprobs:
                    999:  *     Sum up all the noprob probabilities, starting with fp.
                   1000:  */
                   1001: sum_noprobs(fp)
                   1002: register FILEDESC      *fp;
                   1003: {
                   1004:        static bool     did_noprobs = FALSE;
                   1005: 
                   1006:        if (did_noprobs)
                   1007:                return;
                   1008:        zero_tbl(&Noprob_tbl);
                   1009:        while (fp != NULL) {
                   1010:                get_tbl(fp);
                   1011:                sum_tbl(&Noprob_tbl, &fp->tbl);
                   1012:                fp = fp->next;
                   1013:        }
                   1014:        did_noprobs = TRUE;
                   1015: }
                   1016: 
                   1017: max(i, j)
                   1018: register int   i, j;
                   1019: {
                   1020:        return (i >= j ? i : j);
                   1021: }
                   1022: 
                   1023: /*
                   1024:  * open_fp:
                   1025:  *     Assocatiate a FILE * with the given FILEDESC.
                   1026:  */
                   1027: open_fp(fp)
                   1028: FILEDESC       *fp;
                   1029: {
                   1030:        if (fp->inf == NULL && (fp->inf = fdopen(fp->fd, "r")) == NULL) {
                   1031:                perror(fp->path);
                   1032:                exit(1);
                   1033:        }
                   1034: }
                   1035: 
                   1036: /*
                   1037:  * open_dat:
                   1038:  *     Open up the dat file if we need to.
                   1039:  */
                   1040: open_dat(fp)
                   1041: FILEDESC       *fp;
                   1042: {
                   1043:        if (fp->datfd < 0 && (fp->datfd = open(fp->datfile, 0)) < 0) {
                   1044:                perror(fp->datfile);
                   1045:                exit(1);
                   1046:        }
                   1047: }
                   1048: 
                   1049: /*
                   1050:  * get_pos:
                   1051:  *     Get the position from the pos file, if there is one.  If not,
                   1052:  *     return a random number.
                   1053:  */
                   1054: get_pos(fp)
                   1055: FILEDESC       *fp;
                   1056: {
                   1057: #ifdef OK_TO_WRITE_DISK
                   1058:        int     fd;
                   1059: #endif /* OK_TO_WRITE_DISK */
                   1060: 
                   1061:        assert(fp->read_tbl);
                   1062:        if (fp->pos == POS_UNKNOWN) {
                   1063: #ifdef OK_TO_WRITE_DISK
                   1064:                if ((fd = open(fp->posfile, 0)) < 0 ||
                   1065:                    read(fd, &fp->pos, sizeof fp->pos) != sizeof fp->pos)
                   1066:                        fp->pos = random() % fp->tbl.str_numstr;
                   1067:                else if (fp->pos >= fp->tbl.str_numstr)
                   1068:                        fp->pos %= fp->tbl.str_numstr;
                   1069:                if (fd >= 0)
                   1070:                        (void) close(fd);
                   1071: #else
                   1072:                fp->pos = random() % fp->tbl.str_numstr;
                   1073: #endif /* OK_TO_WRITE_DISK */
                   1074:        }
                   1075:        if (++(fp->pos) >= fp->tbl.str_numstr)
                   1076:                fp->pos -= fp->tbl.str_numstr;
                   1077:        DPRINTF(1, (stderr, "pos for %s is %d\n", fp->name, fp->pos));
                   1078: }
                   1079: 
                   1080: /*
                   1081:  * get_tbl:
                   1082:  *     Get the tbl data file the datfile.
                   1083:  */
                   1084: get_tbl(fp)
                   1085: FILEDESC       *fp;
                   1086: {
                   1087:        auto int                fd;
                   1088:        register FILEDESC       *child;
                   1089: 
                   1090:        if (fp->read_tbl)
                   1091:                return;
                   1092:        if (fp->child == NULL) {
                   1093:                if ((fd = open(fp->datfile, 0)) < 0) {
                   1094:                        perror(fp->datfile);
                   1095:                        exit(1);
                   1096:                }
                   1097:                if (read(fd, (char *) &fp->tbl, sizeof fp->tbl) != sizeof fp->tbl) {
                   1098:                        (void)fprintf(stderr,
                   1099:                            "fortune: %s corrupted\n", fp->path);
                   1100:                        exit(1);
                   1101:                }
                   1102:                /* fp->tbl.str_version = ntohl(fp->tbl.str_version); */
                   1103:                fp->tbl.str_numstr = ntohl(fp->tbl.str_numstr);
                   1104:                fp->tbl.str_longlen = ntohl(fp->tbl.str_longlen);
                   1105:                fp->tbl.str_shortlen = ntohl(fp->tbl.str_shortlen);
                   1106:                fp->tbl.str_flags = ntohl(fp->tbl.str_flags);
                   1107:                (void) close(fd);
                   1108:        }
                   1109:        else {
                   1110:                zero_tbl(&fp->tbl);
                   1111:                for (child = fp->child; child != NULL; child = child->next) {
                   1112:                        get_tbl(child);
                   1113:                        sum_tbl(&fp->tbl, &child->tbl);
                   1114:                }
                   1115:        }
                   1116:        fp->read_tbl = TRUE;
                   1117: }
                   1118: 
                   1119: /*
                   1120:  * zero_tbl:
                   1121:  *     Zero out the fields we care about in a tbl structure.
                   1122:  */
                   1123: zero_tbl(tp)
                   1124: register STRFILE       *tp;
                   1125: {
                   1126:        tp->str_numstr = 0;
                   1127:        tp->str_longlen = 0;
                   1128:        tp->str_shortlen = -1;
                   1129: }
                   1130: 
                   1131: /*
                   1132:  * sum_tbl:
                   1133:  *     Merge the tbl data of t2 into t1.
                   1134:  */
                   1135: sum_tbl(t1, t2)
                   1136: register STRFILE       *t1, *t2;
                   1137: {
                   1138:        t1->str_numstr += t2->str_numstr;
                   1139:        if (t1->str_longlen < t2->str_longlen)
                   1140:                t1->str_longlen = t2->str_longlen;
                   1141:        if (t1->str_shortlen > t2->str_shortlen)
                   1142:                t1->str_shortlen = t2->str_shortlen;
                   1143: }
                   1144: 
                   1145: #define        STR(str)        ((str) == NULL ? "NULL" : (str))
                   1146: 
                   1147: /*
                   1148:  * print_file_list:
                   1149:  *     Print out the file list
                   1150:  */
                   1151: print_file_list()
                   1152: {
                   1153:        print_list(File_list, 0);
                   1154: }
                   1155: 
                   1156: /*
                   1157:  * print_list:
                   1158:  *     Print out the actual list, recursively.
                   1159:  */
                   1160: print_list(list, lev)
                   1161: register FILEDESC      *list;
                   1162: int                    lev;
                   1163: {
                   1164:        while (list != NULL) {
                   1165:                fprintf(stderr, "%*s", lev * 4, "");
                   1166:                if (list->percent == NO_PROB)
                   1167:                        fprintf(stderr, "___%%");
                   1168:                else
                   1169:                        fprintf(stderr, "%3d%%", list->percent);
                   1170:                fprintf(stderr, " %s", STR(list->name));
                   1171:                DPRINTF(1, (stderr, " (%s, %s, %s)\n", STR(list->path),
                   1172:                            STR(list->datfile), STR(list->posfile)));
                   1173:                putc('\n', stderr);
                   1174:                if (list->child != NULL)
                   1175:                        print_list(list->child, lev + 1);
                   1176:                list = list->next;
                   1177:        }
                   1178: }
                   1179: 
                   1180: #ifndef        NO_REGEX
                   1181: /*
                   1182:  * conv_pat:
                   1183:  *     Convert the pattern to an ignore-case equivalent.
                   1184:  */
                   1185: char *
                   1186: conv_pat(orig)
                   1187: register char  *orig;
                   1188: {
                   1189:        register char           *sp;
                   1190:        register unsigned int   cnt;
                   1191:        register char           *new;
                   1192: 
                   1193:        cnt = 1;        /* allow for '\0' */
                   1194:        for (sp = orig; *sp != '\0'; sp++)
                   1195:                if (isalpha(*sp))
                   1196:                        cnt += 4;
                   1197:                else
                   1198:                        cnt++;
                   1199:        if ((new = malloc(cnt)) == NULL) {
                   1200:                fprintf(stderr, "pattern too long for ignoring case\n");
                   1201:                exit(1);
                   1202:        }
                   1203: 
                   1204:        for (sp = new; *orig != '\0'; orig++) {
                   1205:                if (islower(*orig)) {
                   1206:                        *sp++ = '[';
                   1207:                        *sp++ = *orig;
                   1208:                        *sp++ = toupper(*orig);
                   1209:                        *sp++ = ']';
                   1210:                }
                   1211:                else if (isupper(*orig)) {
                   1212:                        *sp++ = '[';
                   1213:                        *sp++ = *orig;
                   1214:                        *sp++ = tolower(*orig);
                   1215:                        *sp++ = ']';
                   1216:                }
                   1217:                else
                   1218:                        *sp++ = *orig;
                   1219:        }
                   1220:        *sp = '\0';
                   1221:        return new;
                   1222: }
                   1223: 
                   1224: /*
                   1225:  * find_matches:
                   1226:  *     Find all the fortunes which match the pattern we've been given.
                   1227:  */
                   1228: find_matches()
                   1229: {
                   1230:        Fort_len = maxlen_in_list(File_list);
                   1231:        DPRINTF(2, (stderr, "Maximum length is %d\n", Fort_len));
                   1232:        /* extra length, "%\n" is appended */
                   1233:        Fortbuf = do_malloc((unsigned int) Fort_len + 10);
                   1234: 
                   1235:        Found_one = FALSE;
                   1236:        matches_in_list(File_list);
                   1237:        return Found_one;
                   1238:        /* NOTREACHED */
                   1239: }
                   1240: 
                   1241: /*
                   1242:  * maxlen_in_list
                   1243:  *     Return the maximum fortune len in the file list.
                   1244:  */
                   1245: maxlen_in_list(list)
                   1246: FILEDESC       *list;
                   1247: {
                   1248:        register FILEDESC       *fp;
                   1249:        register int            len, maxlen;
                   1250: 
                   1251:        maxlen = 0;
                   1252:        for (fp = list; fp != NULL; fp = fp->next) {
                   1253:                if (fp->child != NULL) {
                   1254:                        if ((len = maxlen_in_list(fp->child)) > maxlen)
                   1255:                                maxlen = len;
                   1256:                }
                   1257:                else {
                   1258:                        get_tbl(fp);
                   1259:                        if (fp->tbl.str_longlen > maxlen)
                   1260:                                maxlen = fp->tbl.str_longlen;
                   1261:                }
                   1262:        }
                   1263:        return maxlen;
                   1264: }
                   1265: 
                   1266: /*
                   1267:  * matches_in_list
                   1268:  *     Print out the matches from the files in the list.
                   1269:  */
                   1270: matches_in_list(list)
                   1271: FILEDESC       *list;
                   1272: {
                   1273:        register char           *sp;
                   1274:        register FILEDESC       *fp;
                   1275:        int                     in_file;
                   1276: 
                   1277:        for (fp = list; fp != NULL; fp = fp->next) {
                   1278:                if (fp->child != NULL) {
                   1279:                        matches_in_list(fp->child);
                   1280:                        continue;
                   1281:                }
                   1282:                DPRINTF(1, (stderr, "searching in %s\n", fp->path));
                   1283:                open_fp(fp);
                   1284:                sp = Fortbuf;
                   1285:                in_file = FALSE;
                   1286:                while (fgets(sp, Fort_len, fp->inf) != NULL)
                   1287:                        if (!STR_ENDSTRING(sp, fp->tbl))
                   1288:                                sp += strlen(sp);
                   1289:                        else {
                   1290:                                *sp = '\0';
                   1291:                                if (RE_EXEC(Fortbuf)) {
                   1292:                                        printf("%c%c", fp->tbl.str_delim,
                   1293:                                            fp->tbl.str_delim);
                   1294:                                        if (!in_file) {
                   1295:                                                printf(" (%s)", fp->name);
                   1296:                                                Found_one = TRUE;
                   1297:                                                in_file = TRUE;
                   1298:                                        }
                   1299:                                        putchar('\n');
                   1300:                                        (void) fwrite(Fortbuf, 1, (sp - Fortbuf), stdout);
                   1301:                                }
                   1302:                                sp = Fortbuf;
                   1303:                        }
                   1304:        }
                   1305: }
                   1306: # endif        /* NO_REGEX */
                   1307: 
                   1308: usage()
                   1309: {
                   1310:        (void) fprintf(stderr, "fortune [-a");
                   1311: #ifdef DEBUG
                   1312:        (void) fprintf(stderr, "D");
                   1313: #endif /* DEBUG */
                   1314:        (void) fprintf(stderr, "f");
                   1315: #ifndef        NO_REGEX
                   1316:        (void) fprintf(stderr, "i");
                   1317: #endif /* NO_REGEX */
                   1318:        (void) fprintf(stderr, "losw]");
                   1319: #ifndef        NO_REGEX
                   1320:        (void) fprintf(stderr, " [-m pattern]");
                   1321: #endif /* NO_REGEX */
                   1322:        (void) fprintf(stderr, "[ [#%%] file/directory/all]\n");
                   1323:        exit(1);
                   1324: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.