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