|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.