/* cookie - print out an entry from the sayings file
 * by Karl Lehenbauer (karl@sugar.uu.net, uunet!sugar!karl)
 *  cookie.c  1.1  1/12/89
 *            ^^^^^^^^^^^^
 *            obsolete; see below
 */

/*
 * 1995-04-19 [JöG] changed the random number generation a bit
 *                  didn't bump revision though
 *
 * 1995-04-27 [JöG] different cookie file format now; there are
 *                  as many cookies now as there are entries in
 *                  the hash file
 *                  version bumped to cookie 2.0 due to the changed
 *                  format and the lexified 'cookhash'
 *
 * 1995-08-22 [JöG] still, the random number generation/seeding/
 *                  ranging wasn't good enough. Incorporated
 *                  a PD version of the R250 algorithm, which seems
 *                  to work just fine.
 *                  Cookie version 2, revision 1.
 *
 */

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <proto/exec.h>

#include "r250.h"

#include "cookie.h"

#define ENTSIZE 7L
#define METACHAR '%'
#define YES 1
#define NO 0

/*
 * char *sccs_id = "@(#) fortune cookie program 1.1 1/12/89 by K. Lehenbauer";
 */

static char verstring[] = "$" "VER: cookie 2.1 (22.8.95) "
							"Lehenbauer/Kirchwitz/Grahn";

char *cookiename = COOKIEFILE;
char *hashname = HASHFILE;

#ifdef ORIGINALRAND
/* really_random - insure a good random return for a range, unlike an arbitrary
 * random() % n, thanks to Ken Arnold, Unix Review, October 1987
 * ...likely needs a little hacking to run under Berkely
 */
#define RANDOM_RANGE ((1 << 15) - 1)
static int really_random(int my_range)
{
	int max_multiple, rnum;

	max_multiple = RANDOM_RANGE / my_range;
	max_multiple *= my_range;
	while ((rnum = rand()) >= max_multiple)
		continue;
	return(rnum % my_range);
}
#endif /*ORIGINALRAND*/

main(int argc,char *argv[])
{
	int nentries, oneiwant, c, sawmeta = 0;
	FILE *hashf, *cookief;
	long cookiepos;

	/* if we got exactly three arguments, use the cookie and hash
	 * files specified
	 */
	if (argc == 3)
	{
		cookiename = argv[1];
		hashname = argv[2];
	}
	/* otherwise if argc isn't one (no arguments, specifying the
	 * default cookie file), barf
	 */
	else if (argc != 1)
	{
		fputs("usage: cookie cookiefile hashfile\n",stderr);
		exit(1);
	}

	/* open the cookie file for read */
	if ((cookief = fopen(cookiename,"r")) == NULL)
	{
		perror(cookiename);
		exit(2);
	}

	/* open the hash file for read */
	if ((hashf = fopen(hashname,"r")) == NULL)
	{
		perror(hashname);
		exit(2);
	}

	/* compute number of cookie addresses in the hash file by
	 * dividing the file length by the size of a cookie address
	 * and subtract 1 (after the last %% is no cookie)
	 * Yes there is! [JöG]
	 *
	 */
	if (fseek(hashf,0L,2) != 0)
	{
		perror(hashname);
		exit(3);
	}
	nentries = (ftell(hashf) / ENTSIZE) - 1 + 1;

	/*
	 * I Left the original (pre-2.1) random code in
	 * for compeleness. Define ORIGINALRAND if
	 * you want it.
	 *
	 */
#ifdef ORIGINALRAND
	/* seed the random number generator with time in seconds plus
	 * the program's process ID - it yields a pretty good seed
	 * again, thanks to Ken Arnold
	 * AMK: FindTask()
	 */
	srand((long)FindTask(NULL) + time(NULL));

	/*
	 * AMK: get a dummy value
	 */
	rand();

#if 1
	/* generate a not really random number */
	/* this was the original unix s5r4 version, too sophisticated */
	   oneiwant = really_random(nentries);
#else
	/* this is version seems to be random enough ;-) (AMK) */
	oneiwant = rand() % nentries;
#endif
#else /* ORIGINALRAND */
	r250_init((unsigned short)FindTask(NULL) ^ (unsigned short)time(NULL));

	oneiwant = r250n(nentries);
#endif /* ORIGINALRAND */

	/* locate the one I want in the hash file and read the
	 * address found there
	 */
	fseek(hashf,(long)oneiwant * ENTSIZE, 0);
	fscanf(hashf,"%lx",&cookiepos);

	/* seek cookie file to cookie starting at address read from hash */
	fseek(cookief,cookiepos,0);

	/* get characters from the cookie file and write them out
	 * until finding the end-of-fortune sequence, '%%'
	 */
	while ((c = fgetc(cookief)) != EOF && sawmeta < 2)
	{
		if (c != METACHAR)
		{
			if (sawmeta)
				putchar(METACHAR);
			putchar(c);
			sawmeta = 0;
		}
		else
			sawmeta++;
	}
	exit(0);
}

/* end of cookie.c */
