Commit | Line | Data |
---|---|---|
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 | ||
13 | short 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 | ||
19 | char 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 | ||
32 | long seekpts[2]; /* seek pointers to fortunes */ | |
33 | ||
34 | main(ac, av) | |
35 | int ac; | |
36 | char *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 | */ | |
85 | getargs(ac, av) | |
86 | int ac; | |
87 | reg 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 | ||
128 | max(i, j) | |
129 | reg int i, j; { | |
130 | ||
131 | return (i >= j ? i : j); | |
132 | } | |
133 | ||
134 | # ifndef vax | |
135 | # define MAXRAND 32767L | |
136 | ||
137 | roll(ndie, nsides) | |
138 | int 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 | ||
152 | roll(ndie, nsides) | |
153 | reg 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 |