home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / cfortune.zip / FORTUNE.C < prev    next >
C/C++ Source or Header  |  1989-05-25  |  6KB  |  253 lines

  1. /*
  2.  * Copyright (c) 1986 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char sccsid[] = "@(#)fortune.c    5.2 (Berkeley) 12/9/86";
  9. #endif not lint
  10.  
  11. # include    <sys/types.h>
  12. # include    <stdio.h>
  13. # include    <sys/file.h>
  14. # include    "strfile.h"
  15.  
  16. # define    TRUE    1
  17. # define    FALSE    0
  18. # define    bool    short
  19.  
  20. # define    MINW    6        /* minimum wait if desired */
  21. # define    CPERS    20        /* # of chars for each sec */
  22. # define    SLEN    160        /* # of chars in short fortune */
  23.  
  24. # define    FORTFILE    "/usr/games/lib/fortunes.dat"
  25.  
  26. bool    Wflag        = FALSE,    /* wait desired after fortune */
  27.     Sflag        = FALSE,    /* short fortune desired */
  28.     Lflag        = FALSE,    /* long fortune desired */
  29.     Oflag        = FALSE,    /* offensive fortunes only */
  30.     Aflag        = FALSE;    /* any fortune allowed */
  31.  
  32. char    *Fortfile    = FORTFILE,    /* fortune database */
  33.     *Usage[]    = {
  34.        "usage:  fortune [ - ] [ -wsloa ] [ file ]",
  35.        "    - - give this summary of usage",
  36.        "    w - have program wait after printing message in order",
  37.        "        to give time to read",
  38.        "    s - short fortune only",
  39.        "    l - long fortune only",
  40.        "    o - offensive fortunes only",
  41.        "    a - any fortune",
  42.        "        Mail suggested fortunes to \"fortune\"",
  43.     NULL
  44.     };
  45.  
  46. long    Seekpts[2];            /* seek pointers to fortunes */
  47.  
  48. FILE    *Inf;                /* input file */
  49.  
  50. STRFILE    Tbl;                /* input table */
  51.  
  52. time_t    time();
  53.  
  54. main(ac, av)
  55. int    ac;
  56. char    *av[];
  57. {
  58.     register char    c;
  59.     register int    nchar = 0;
  60.     register int    i;
  61.  
  62.     getargs(ac, av);
  63.     if ((Inf = fopen(Fortfile, "r+")) == NULL) {
  64.         perror(Fortfile);
  65.         exit(-1);
  66.     }
  67.     fread((char *) &Tbl, sizeof Tbl, 1, Inf);    /* NOSTRICT */
  68.     if (Tbl.str_longlen <= SLEN && Lflag) {
  69.         puts("Sorry, no long strings in this file");
  70.         exit(0);
  71.     }
  72.     if (Tbl.str_shortlen > SLEN && Sflag) {
  73.         puts("Sorry, no short strings in this file");
  74.         exit(0);
  75.     }
  76.  
  77.     /*
  78.      * initialize the pointer to the first -o fortune if need be.
  79.      */
  80.     if (Tbl.str_delims[2] == 0)
  81.         Tbl.str_delims[2] = Tbl.str_delims[0];
  82.  
  83.     for (;;) {
  84.         getfort();
  85.         if (Sflag && !is_short())
  86.             continue;
  87.         if (Lflag && !is_long())
  88.             continue;
  89.         break;
  90.     }
  91.  
  92.     fseek(Inf, Seekpts[0], 0);
  93.     while (c = getc(Inf)) {
  94.         nchar++;
  95.         putchar(c);
  96.     }
  97.     fflush(stdout);
  98.     fseek(Inf, 0L, 0);
  99. #ifdef    LOCK_EX
  100.     /*
  101.      * if we can, we exclusive lock, but since it isn't very
  102.      * important, we just punt if we don't have easy locking
  103.      * available.
  104.      */
  105.     flock(fileno(Inf), LOCK_EX);
  106. #endif    LOCK_EX
  107.     fwrite(&Tbl, 1, sizeof Tbl, Inf);
  108. #ifdef    LOCK_EX
  109.     flock(fileno(Inf), LOCK_UN);
  110. #endif    LOCK_EX
  111.     if (Wflag)
  112.         sleep(max((int) nchar / CPERS, MINW));
  113.     exit(0);
  114. }
  115.  
  116. /*
  117.  * is_short:
  118.  *    Return TRUE if fortune is "short".
  119.  */
  120. is_short()
  121. {
  122.     register int    nchar;
  123.  
  124.     if (!(Tbl.str_flags & (STR_RANDOM | STR_ORDERED)))
  125.         return (Seekpts[1] - Seekpts[0] <= SLEN);
  126.     fseek(Inf, Seekpts[0], 0);
  127.     nchar = 0;
  128.     while (getc(Inf))
  129.         nchar++;
  130.     return (nchar <= SLEN);
  131. }
  132.  
  133. /*
  134.  * is_long:
  135.  *    Return TRUE if fortune is "long".
  136.  */
  137. is_long()
  138. {
  139.     register int    nchar;
  140.  
  141.     if (!(Tbl.str_flags & (STR_RANDOM | STR_ORDERED)))
  142.         return (Seekpts[1] - Seekpts[0] > SLEN);
  143.     fseek(Inf, Seekpts[0], 0);
  144.     nchar = 0;
  145.     while (getc(Inf))
  146.         nchar++;
  147.     return (nchar > SLEN);
  148. }
  149.  
  150. /*
  151.  *    This routine evaluates the arguments on the command line
  152.  */
  153. getargs(ac, av)
  154. register int    ac;
  155. register char    *av[];
  156. {
  157.     register int    i;
  158.     register char    *sp;
  159.     register int    j;
  160.     register short    bad = 0;
  161.  
  162.     for (i = 1; i < ac; i++)  {
  163.         if (av[i][0] != '-') {
  164.             setuid(getuid());
  165.             setgid(getgid());
  166.             Fortfile = av[i];
  167.         }
  168.         else if (av[i][1] == '\0') {
  169.             j = 0;
  170.             while (Usage[j] != NULL)
  171.                 puts(Usage[j++]);
  172.             exit(0);
  173.             /* NOTREACHED */
  174.         }
  175.         else
  176.             for (sp = &av[i][1]; *sp != '\0'; sp++)
  177.                 switch (*sp) {
  178.                   case 'w':    /* give time to read */
  179.                     Wflag++;
  180.                     break;
  181.                   case 's':    /* short ones only */
  182.                     Sflag++;
  183.                     Lflag = 0;
  184.                     break;
  185.                   case 'l':    /* long ones only */
  186.                     Lflag++;
  187.                     Sflag = 0;
  188.                     break;
  189.                   case 'o':    /* offensive ones only */
  190.                     Oflag++;
  191.                     break;
  192.                   case 'a':    /* any fortune */
  193.                     Aflag++;
  194.                     /*
  195.                      * initialize the random number
  196.                      * generator; throw away the first
  197.                      * few numbers to avoid any non-
  198.                      * randomness in startup
  199.                      */
  200.                     srnd(time(NULL) + getpid());
  201.                     for (j = 0; j < 20; j++)
  202.                         (void) rnd(100);
  203.                     break;
  204.                   default:
  205.                     printf("unknown flag: '%c'\n", *sp);
  206.                     bad++;
  207.                     break;
  208.                 }
  209.     }
  210.     if (bad) {
  211.         printf("use \"%s -\" to get usage\n", av[0]);
  212.         exit(-1);
  213.     }
  214. }
  215.  
  216. /*
  217.  * getfort:
  218.  *    Get the fortune data file's seek pointer for the next fortune.
  219.  */
  220. getfort()
  221. {
  222.     register int    fortune;
  223.  
  224.     /*
  225.      * Make sure all values are in range.
  226.      */
  227.  
  228.     if (Tbl.str_delims[1] >= Tbl.str_delims[0])
  229.         Tbl.str_delims[1] = 0;
  230.     if (Tbl.str_delims[2] >= Tbl.str_numstr)
  231.         Tbl.str_delims[2] = Tbl.str_delims[0];
  232.  
  233.     if (Aflag) {
  234.         if (rnd(Tbl.str_numstr) < Tbl.str_delims[0])
  235.             fortune = Tbl.str_delims[1]++;
  236.         else
  237.             fortune = Tbl.str_delims[2]++;
  238.     }
  239.     else if (Oflag)
  240.         fortune = Tbl.str_delims[2]++;
  241.     else
  242.         fortune = Tbl.str_delims[1]++;
  243.  
  244.     fseek(Inf, (long)(sizeof Seekpts[0]) * fortune + sizeof Tbl, 0);
  245.     fread((char *) Seekpts, (sizeof Seekpts[0]), 2, Inf);
  246. }
  247.  
  248. max(i, j)
  249. register int    i, j;
  250. {
  251.     return (i >= j ? i : j);
  252. }
  253.