static char rcsid[] = "$Header:fortune.c 12.0$";
char	*sccsid = "@(#)fortune.c	1.4 (Berkeley) 2/11/83";

# include	<sys/types.h>
# include	<stdio.h>
# include	"strfile.h"

# define	MINW	6		/* minimum wait if desired	*/
# define	CPERS	20		/* # of chars for each sec	*/
# define	SLEN	160		/* # of chars in short fortune	*/

# define	reg	register

short	wflag		= 0,		/* wait desired after fortune	*/
	sflag		= 0,		/* short fortune desired	*/
	lflag		= 0,		/* long fortune desired		*/
	oflag		= 0,		/* offensive fortunes only	*/
	aflag		= 0;		/* any fortune allowed		*/

char	fortfile[100]	= FORTFILE,	/* fortune database		*/
	*usage[]	= {
       "usage:  fortune [ - ] [ -wsloa ] [ file ]",
       "	- - give this summary of usage",
       "	w - have program wait after printing message in order",
       "	    to give time to read",
       "	s - short fortune only",
       "	l - long fortune only",
       "	o - offensive fortunes only",
       "	a - any fortune",
       "		Mail suggested fortunes to \"fortune\""
	};

long	seekpts[2];			/* seek pointers to fortunes	*/

time_t	seed;

STRFILE	tbl;				/* input table			*/

time_t	time();

main(ac, av)
int	ac;
char	*av[]; {

	reg char	c;
	reg int		nchar = 0;
	reg FILE	*inf;
	reg int		numforts,	/* number of fortunes		*/
			fortune;	/* fortune number		*/
	reg time_t	tm;

	getargs(ac, av);
	if ((inf = fopen(fortfile, "r")) == NULL) {
		perror(fortfile);
		exit(-1);
	}
	fread(&tbl, (sizeof tbl), 1, inf);
	numforts = tbl.str_numstr - 1;	 /* always a null string at the end */
	if (tbl.str_longlen < SLEN && lflag) {
		puts("Sorry, no long strings in this file");
		exit(0);
	}
	if (tbl.str_shortlen > SLEN && sflag) {
		puts("Sorry, no short strings in this file");
		exit(0);
	}
	if (oflag)
		numforts -= tbl.str_delims[0];
	else if (!aflag)
		numforts = tbl.str_delims[0];
	tm = time(NULL);
	seed = tm + getpid();
	getfort(numforts, inf);
	if (sflag)
		while (seekpts[1] - seekpts[0] >= SLEN)
			getfort(numforts, inf);
	else if (lflag)
		while (seekpts[1] - seekpts[0] < SLEN)
			getfort(numforts, inf);
	fseek(inf, seekpts[0], 0);
	while (c = getc(inf)) {
		nchar++;
		putchar(c);
	}
	fflush(stdout);
	if (wflag)
		sleep(max((int) nchar/CPERS, MINW));
}

/*
 *	This routine evaluates the arguments on the command line
 */
getargs(ac, av)
int		ac;
reg char	*av[]; {

	reg short	bad = 0;
	reg int		i, j;

	for (i = 1; i < ac; i++)  {
		if (av[i][0] != '-')
			strcpy(fortfile, av[i]);
		else
			switch (av[i][1]) {
			  case '\0':	/* give usage			*/
				for (j = 0; j < sizeof usage / sizeof (char *); j++)
					puts(usage[j]);
				exit(0);
			  case 'w':	/* give time to read		*/
				wflag++;
				break;
			  case 's':	/* short ones only		*/
				sflag++;
				break;
			  case 'l':	/* long ones only		*/
				lflag++;
				break;
			  case 'o':	/* offensive ones only		*/
				oflag++;
				break;
			  case 'a':	/* any fortune			*/
				aflag++;
				break;
			  default:
				printf("unknown flag: '%c'\n", av[1][1]);
				bad++;
				break;
			}
	}
	if (bad) {
		printf("use \"%s -\" to get usage\n", av[0]);
		exit(-1);
	}
}

getfort(numforts, inf)
reg int		numforts;
reg FILE	*inf; {

	reg int		fortune;

	fortune = rnd(numforts);
	if (oflag && !aflag)
		fortune += tbl.str_delims[0];
	fseek(inf, (long)(sizeof seekpts[0]) * fortune + sizeof tbl, 0);
	fread(seekpts, (sizeof seekpts[0]), 2, inf);
}

max(i, j)
reg int	i, j; {

	return (i >= j ? i : j);
}

rnd(num)
int	num; {

	return ((seed = seed*11109+13849) & 0xffff) % num;
}
