|
|
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.