/*% cc -O -K -i -s -o fortune % */ /* * Fetch a fortune from the Fortunes file by randomly seeking * within that file and then searching for the Nth next fortune, * ( 0 <= N <= 15). If EOF is reached, rewind and continue. * This two step process minimizes file i/o while making the frequency * of each fortune realtively independent of the size of its predecessors. * * Display the selected fortune, replacing @ characters with newlines. * This format (single line fortunes) allows foreign fortunes to be * merged into a local file with common lines deleted by sort -u * * If called with any argument, repeat until killed. * */ #include #include #include char *Fortunes = "fortunes"; #define LEN 2048 char line[LEN]; main(argc, argv) char **argv; { long p; register l; register char *q; time_t t; FILE *f; struct stat sbuf; char *fortenv; if ( (fortenv = getenv ("FORTUNES")) != NULL ) Fortunes = fortenv; if (argc >= 3 && !strcmp(argv[1], "-f")) { Fortunes = argv[2]; argv += 2; argc -= 2; } f = fopen(Fortunes, "r"); if (f == NULL) { write(1,"Memory fault -- core dumped\n", 29); exit(1); } time(&t); srand(getpid() ^ (int)((t>>16) ^ t)); fstat(fileno(f), &sbuf); do { p = rand() % sbuf.st_size; fseek(f, p, 0); for (l=((rand())&07); l-- >= 0; ) { fgets(line, LEN, f); if (fgets(line, LEN, f) == NULL || line[0] == 0) { rewind(f); fgets(line, LEN, f); } } for(q = line; *q++;) if ( *q == '@') *q = '\n'; l = (q - line) -1; write(1, line, l); } while (argc > 1); exit(0); } char * fgets(s, n, f) register char *s; register n; FILE *f; { register c; register char *p; p=s; while (--n>0) { if ((c = getc(f)) == EOF) break; if ((*s++ = c) == '\n') break; } *s = 0; if (p == s) return NULL; return p; }