BSD 4 release
[unix-history] / usr / src / games / fortune / fortune.c
CommitLineData
31cef89c
BJ
1#ifdef UCB_SCCSID
2 char *sccsid = "@(#)fortune.c 2.6";
3#endif
4# include <stdio.h>
5# include "strfile.h"
6
7# define MINW 6 /* minimum wait if desired */
8# define CPERS 20 /* # of chars for each sec */
9# define SLEN 160 /* # of chars in short fortune */
10
11# define reg register
12
13short wflag = 0, /* wait desired after fortune */
14 sflag = 0, /* short fortune desired */
15 lflag = 0, /* long fortune desired */
16 oflag = 0, /* offensive fortunes only */
17 aflag = 0; /* any fortune allowed */
18
19char fortfile[100] = FORTFILE, /* fortune database */
20 *usage[] = {
21 "usage: fortune [ - ] [ -wsloa ] [ file ]",
22 " - - give this summary of usage",
23 " w - have program wait after printing message in order",
24 " to give time to read",
25 " s - short fortune only",
26 " l - long fortune only",
27 " o - offensive fortunes only",
28 " a - any fortune",
29 " Mail suggested fortunes to \"fortune\""
30 };
31
32long seekpts[2]; /* seek pointers to fortunes */
33
34main(ac, av)
35int ac;
36char *av[]; {
37
38 reg char c;
39 reg int nchar = 0;
40 reg FILE *inf;
41 int numforts, /* number of fortunes */
42 fortune; /* fortune number */
43 STRFILE tbl; /* input table */
44
45 getargs(ac, av);
46 srand(getpid());
47 if ((inf = fopen(fortfile, "r")) == NULL) {
48 perror(fortfile);
49 exit(-1);
50 }
51 fread(&tbl, (sizeof tbl), 1, inf);
52 numforts = tbl.str_numstr - 1; /* always a null string at the end */
53 if (tbl.str_longlen < SLEN && lflag) {
54 puts("Sorry, no long strings in this file");
55 exit(0);
56 }
57 if (tbl.str_shortlen > SLEN && sflag) {
58 puts("Sorry, no short strings in this file");
59 exit(0);
60 }
61 if (oflag)
62 numforts -= tbl.str_delims[0];
63 else if (!aflag)
64 numforts = tbl.str_delims[0];
65 do {
66 fortune = roll(1, numforts) - 1;
67 if (oflag && !aflag)
68 fortune += tbl.str_delims[0];
69 fseek(inf, (long)(sizeof seekpts[0]) * fortune + sizeof tbl, 0);
70 fread(seekpts, (sizeof seekpts[0]), 2, inf);
71 } while ((sflag && seekpts[1] - seekpts[0] > SLEN)
72 || (lflag && seekpts[1] - seekpts[0] < SLEN));
73 fseek(inf, seekpts[0], 0);
74 while (c = getc(inf)) {
75 nchar++;
76 putchar(c);
77 }
78 fflush(stdout);
79 if (wflag)
80 sleep(max((int) nchar/CPERS, MINW));
81}
82/*
83 * This routine evaluates the arguments on the command line
84 */
85getargs(ac, av)
86int ac;
87reg char *av[]; {
88
89 reg short bad = 0;
90 reg int i, j;
91
92 for (i = 1; i < ac; i++) {
93 if (av[i][0] != '-')
94 strcpy(fortfile, av[i]);
95 else
96 switch (av[i][1]) {
97 case '\0': /* give usage */
98 for (j = 0; j < sizeof usage / sizeof (char *); j++)
99 puts(usage[j]);
100 exit(0);
101 case 'w': /* give time to read */
102 wflag++;
103 break;
104 case 's': /* short ones only */
105 sflag++;
106 break;
107 case 'l': /* long ones only */
108 lflag++;
109 break;
110 case 'o': /* offensive ones only */
111 oflag++;
112 break;
113 case 'a': /* any fortune */
114 aflag++;
115 break;
116 default:
117 printf("unknown flag: '%c'\n", av[1][1]);
118 bad++;
119 break;
120 }
121 }
122 if (bad) {
123 printf("use \"%s -\" to get usage\n", av[0]);
124 exit(-1);
125 }
126}
127
128max(i, j)
129reg int i, j; {
130
131 return (i >= j ? i : j);
132}
133
134# ifndef vax
135# define MAXRAND 32767L
136
137roll(ndie, nsides)
138int ndie, nsides; {
139
140 reg long tot;
141 reg unsigned n, r;
142
143 tot = 0;
144 n = ndie;
145 while (n--)
146 tot += rand();
147 return (int) ((tot * (long) nsides) / ((long) MAXRAND + 1)) + ndie;
148}
149
150# else
151
152roll(ndie, nsides)
153reg int ndie, nsides; {
154
155 reg int tot, r;
156 reg double num_sides;
157
158 num_sides = nsides;
159 tot = 0;
160 while (ndie--)
161 tot += rand() * (num_sides / 017777777777) + 1;
162 return tot;
163}
164# endif
165
166