karl@sugar.hackercorp.com (Karl Lehenbauer) (10/21/90)
Cookie is a program to randomly retrieve cookies from a fortune cookie file. Each cookie can contain an arbitrary number of lines of text. By generating a small "hash" file containing the addresses of each cookie in the cookie file, cookie has a high-performance way to look up cookies, plus it is "fair," which is to say that short cookies are equally as likely to be selected as long ones. The code is again released into the public domain without restriction. #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # If this archive is complete, you will see the following message at the end: # "End of shell archive." # Contents: README cookie.1 Makefile cookie.h cookie.c cookhash.c # Wrapped by karl@sugar on Sat Oct 20 13:06:08 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(3858 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X XThe third release of "cookie" 20-Oct-1990 X------------------------------------------- X XCookie is a program to randomly retrieve cookies from a fortune cookie file. XEach cookie can contain an arbitrary number of lines of text. By generating Xa small "hash" file containing the addresses of each cookie in the cookie Xfile, cookie has a high-performance way to look up cookies, plus it is "fair," Xwhich is to say that short cookies are equally as likely to be selected as Xlong ones. (The technique of simply randomly seeking into the cookie file Xand looking backwards and forwards from there to find the beginning and Xend of the cookie text would bias the cookie program toward large cookies.) X XThis is the same code as in my second release, but it's been almost two years Xsince that release and I've gotten numerous requests for the program, plus XI'm about to pump out a batch of new cookies, plus there wern't alt.sources Xarchives (that I'm aware of) then, plus there's a manpage now, blah blah Xblah. Flames via email or alt.sources.d if you must... X XThe code is again released into the public domain without restriction. XI ask that you retain my name in the source code if you redistribute this stuff, Xand that you redistribute source along with binaries. X XNo warranties are expressed or implied -- this is free code. We do not have Xa contract. X XThe code is written for System V but the only area of incompatibility should be Xthe rand() function. Only minor hacking should be necessary to port to BSD, Xfor example. (If someone gets the urge, please make a version that works Xwith #ifdefs for both, test the BSD version and forward it back to me, OK?) X XIt should be possible to make cookie work pretty painlessly on MS-DOS, Minix, Xetc. Tested updates for popular and not-overwhelmingly-twisted systems, with X#ifdefs, are solicited. I seem to recall that cookie works as-is on the Amiga. X XTo use, unshar this archive and do a 'make' to compile 'cookie' and 'cookhash'. X XThen collect a bunch of cookies. Eric Townsend just posted quite a few to Xalt.sources. I will be posting a couple of new batches. I hope to post Xinformation soon to alt.sources.d as to where an archive site for all my Xcookies (pushing 500 KB) can be found. X XCookies are separated by lines containing two percent-signs and nothing Xelse, for example: X X"I just thought of something funny, your mother." X-- Cheech Marin X%% X"He can shout, don't hear you." X-- The Firesign Theatre X%% X X...and so forth. X XThe include file "cookie.h" defines the location of the cookie file as being X"/usr/local/lib/sayings". If you want to put it elsewhere, change cookie.h Xand rebuild 'cookie'. X XCookie needs a hash file for the cookie file, by default called X"/usr/local/lib/sayhash". This is created by the 'cookhash' program. XCookhash is simply a filter that reads a cookie file in as stdin and writes Xa cookie hash file to stdout. Thus, if you've moved the cookie file to X/usr/local/lib, 'cd' there and do a "cookhash <sayings >sayhash" to create the Xhash file. X XAfter that, 'cookie' should produce a cookie. Cookie can also be executed Xwith two arguments, the name of a cookie file followed by the name of Xits hash file, useful for creating aliases for alternate cookie files so Xyou can get just Zippy the Pinhead quotes, for example. X XIf you find quotes in the file that are unattributed and you know the Xattributions, please mail them to karl@sugar.hackercorp.com or Xuunet!sugar!karl X XI also collect cookies. If you see good ones, please forward them. (If you Xgot them from me, please don't!) X XA lot of people think it's fun to get a cookie every time they log in, so Xthey put "cookie" in their .profile or .login file. X XRegards, XKarl (karl@sugar.hackercorp.com) @ The Hacker's Haven, Missouri City, Texas X(The name will be changing because hacker has lost its old meaning -- sigh) END_OF_FILE if test 3858 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'cookie.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cookie.1'\" else echo shar: Extracting \"'cookie.1'\" \(1033 characters\) sed "s/^X//" >'cookie.1' <<'END_OF_FILE' X.TH COOKIE 6 X.SH NAME Xcookie \- show a fortune cookie X.SH SYNOPSIS X.B cookie X[ cookie-file hash-file ] X.sp X.B /usr/local/lib/cookhash X< sayings > hash-file X.SH DESCRIPTION X.I Cookie Xshows the user a randomly chosen quote from a file containing Xfortune cookies, sayings, jokes, aphorisms, quotes and so on. X.P XCookie can also be executed with two arguments, the name of a cookie file Xfollowed by the name of its hash file. X.P XTo create the hash file, use X.I /usr/local/lib/cookhash Xwhich reads the sayings from standard input and writes the hash values to Xstandard output. (The hash file contains the ASCII-formatted addresses of Xthe cookies found in the cookie file. It is used by X.I cookie Xto look up cookies quickly and to help to insure that all cookies are Xequally likely to be chosen.) X.P XSayings within the input file are separated by lines containing X.B %% . X.SH SEE ALSO Xfortune(6) X.SH FILES X/usr/local/lib/sayings, /usr/local/lib/sayhash X.SH AUTHOR XKarl Lehenbauer (karl@sugar.hackercorp.com), XMissouri City, Texas, USA X END_OF_FILE if test 1033 -ne `wc -c <'cookie.1'`; then echo shar: \"'cookie.1'\" unpacked with wrong size! fi # end of 'cookie.1' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(200 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# makefile for karl's PD fortune cookie program X Xall: cookie cookhash X Xcookie: cookie.h X cc -O -o cookie cookie.c X Xcookhash: X cc -O -o cookhash cookhash.c X Xinstall: X cp cookie cookhash /usr/local/bin END_OF_FILE if test 200 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'cookie.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cookie.h'\" else echo shar: Extracting \"'cookie.h'\" \(263 characters\) sed "s/^X//" >'cookie.h' <<'END_OF_FILE' X/* cookie.h - include file for karl's PD fortune cookie program X * by Karl Lehenbauer (karl@sugar.uu.net, uunet!sugar!karl) X * cookie.h 1.1 1/12/89 X */ X X#define COOKIEFILE "/usr/local/lib/sayings" X#define HASHFILE "/usr/local/lib/sayhash" X X/* end of cookie.h */ END_OF_FILE if test 263 -ne `wc -c <'cookie.h'`; then echo shar: \"'cookie.h'\" unpacked with wrong size! fi # end of 'cookie.h' fi if test -f 'cookie.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cookie.c'\" else echo shar: Extracting \"'cookie.c'\" \(2702 characters\) sed "s/^X//" >'cookie.c' <<'END_OF_FILE' X/* cookie - print out an entry from the sayings file X * by Karl Lehenbauer (karl@sugar.uu.net, uunet!sugar!karl) X * cookie.c 1.1 1/12/89 X */ X X#include <stdio.h> X#include "cookie.h" X X#define ENTSIZE 7L X#define METACHAR '%' X#define YES 1 X#define NO 0 X Xchar *sccs_id = "@(#) fortune cookie program 1.1 1/12/89 by K. Lehenbauer"; X Xextern long lseek(), time(); Xextern int rand(); X Xchar *cookiename = COOKIEFILE; Xchar *hashname = HASHFILE; X X/* really_random - insure a good random return for a range, unlike an arbitrary X * random() % n, thanks to Ken Arnold, Unix Review, October 1987 X * ...likely needs a little hacking to run under Berkely X */ X#define RANDOM_RANGE ((1 << 15) - 1) Xint really_random(my_range) Xint my_range; X{ X int max_multiple, rnum; X X max_multiple = RANDOM_RANGE / my_range; X max_multiple *= my_range; X while ((rnum = rand()) >= max_multiple) X continue; X return(rnum % my_range); X} X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int nentries, oneiwant, c, sawmeta = 0; X FILE *hashf, *cookief; X long cookiepos; X X /* if we got exactly three arguments, use the cookie and hash X * files specified X */ X if (argc == 3) X { X cookiename = argv[1]; X hashname = argv[2]; X } X /* otherwise if argc isn't one (no arguments, specifying the X * default cookie file), barf X */ X else if (argc != 1) X { X fputs("usage: cookie cookiefile hashfile\n",stderr); X exit(1); X } X X /* open the cookie file for read */ X if ((cookief = fopen(cookiename,"r")) == NULL) X { X perror(cookiename); X exit(2); X } X X /* open the hash file for read */ X if ((hashf = fopen(hashname,"r")) == NULL) X { X perror(hashname); X exit(2); X } X X /* compute number of cookie addresses in the hash file by X * dividing the file length by the size of a cookie address X */ X if (fseek(hashf,0L,2) != 0) X { X perror(hashname); X exit(3); X } X nentries = ftell(hashf) / 7L; X X /* seed the random number generator with time in seconds plus X * the program's process ID - it yields a pretty good seed X * again, thanks to Ken Arnold X */ X srand(getpid() + time(NULL)); X X /* generate a not really random number */ X oneiwant = really_random(nentries); X X /* locate the one I want in the hash file and read the X * address found there X */ X fseek(hashf,(long)oneiwant * ENTSIZE, 0); X fscanf(hashf,"%lx",&cookiepos); X X /* seek cookie file to cookie starting at address read from hash */ X fseek(cookief,cookiepos,0); X X /* get characters from the cookie file and write them out X * until finding the end-of-fortune sequence, '%%' X */ X while ((c = fgetc(cookief)) != EOF && sawmeta < 2) X { X if (c != METACHAR) X { X if (sawmeta) X putchar(METACHAR); X putchar(c); X sawmeta = 0; X } X else X sawmeta++; X } X exit(0); X} X X/* end of cookie.c */ END_OF_FILE if test 2702 -ne `wc -c <'cookie.c'`; then echo shar: \"'cookie.c'\" unpacked with wrong size! fi # end of 'cookie.c' fi if test -f 'cookhash.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cookhash.c'\" else echo shar: Extracting \"'cookhash.c'\" \(943 characters\) sed "s/^X//" >'cookhash.c' <<'END_OF_FILE' X/* cookhash - read a sayings file and generate an index file X * by Karl Lehenbauer (karl@sugar.uu.net, uunet!sugar!karl) X * cookhash.c 1.1 1/12/89 X */ X X#include <stdio.h> X X#define YES 1 X#define NO 0 X#define METACHAR '%' X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int c, sawmeta; X long charpos = 0; X X if (argc != 1) X { X fprintf(stderr,"usage: cookhash <cookiefile >hashfile\n"); X exit(1); X } X X /* write out the "address" of the first cookie */ X puts("000000"); X X /* read the cookie until the end, X * whenever the end-of-cookie ("%%") sequence is found, X * the "address" (file position) of the first byte following X * it (start of next cookie) is written to the index (hash) file X */ X while ((c = getchar()) != EOF) X { X if (c == METACHAR) X { X if (sawmeta) X { X printf("%06lx\n",charpos+2); X sawmeta = NO; X } X else X sawmeta = YES; X } X else X sawmeta = NO; X charpos++; X } X exit(0); X} X X/* end of cookhash.c */ END_OF_FILE if test 943 -ne `wc -c <'cookhash.c'`; then echo shar: \"'cookhash.c'\" unpacked with wrong size! fi # end of 'cookhash.c' fi echo shar: End of shell archive. exit 0 -- -- uunet!sugar!karl -- Usenet access: (713) 438-5018