/*
 * cookie - The incredible fortune cookie system output program
 */

/* Version T1.00 - 01-Dec-86 - tmk - Initial portable version		*/
/* Version T1.01 - 06-Dec-86 - tmk - Fixup for VAX: Limit printf to 511
				     bytes, don't look past end of argv
				     area, use curses for video mode out-
				     put. For PC: fix null pointer prob-
				     lem in sleep(), add q to exit from
				     continuous cookie mode, interrogate
				     environment for COOKIE if all else
				     fails to find the file. General:
				     clean up code.			*/
/* Version T1.02 - 07-Dec-86 - tmk - Fix -f name eating next argument,
				     add video modes for PDP, fix problem
				     on PC and PDP of improper line wrap
				     in ANSI video modes		*/
/* Version T1.03 - 30-Mar-87 - tmk - Add setting of environment variable
				     LASTCOOKIE on PC versions, -e option
				     to inhibit same			*/
/* Version T1.04 - 18-Apr-87 - tmk - Set LASTCOOKIE on VAX version, cleanup
				     by lint				*/
/* Version T1.05 - 17-May-87 - tmk - Clean up debugging information	*/
/* Version T1.06 - 27-May-87 - tmk - Cleanup, add DECtalk support	*/
/* Version T1.07 - 05-Jun-87 - tmk - Modify header structure, expand -i
				     text, clean up messages		*/
/* Version T1.08 - 24-Jun-87 - tmk - Change file format, long swap code	*/
/* Version T1.09 - 02-Jul-87 - tmk - Add support for Turbo C		*/
/* Version T1.10 - 04-Jul-87 - tmk - Set LASTCOOKIE on RSTS version	*/
/* Version T1.11 - 14-Jul-87 - tmk - Change version no. to indicate mods
				     to ASMCLS in PC versions		*/
/* Version T1.12 - 16-Jul-87 - tmk - Test for keypress during DOALL out-
				     put of cookies on PC version, emit
				     %% before first cookie in DOALL mode,
				     add range (-r) option		*/
/* Version T1.13 - 15-Aug-87 - tmk - Support DECtalk on RSTS/E KB's via
				     the BUGFIX.C add-on (DECUS C bugs),
				     allow operation on real RT-11, polish
				     DECtalk output routines		*/
/* Version T1.14 - 15-Nov-87 - tmk - Change random number generator for
				     better values, add option to test
				     generator, proving all cookies will
				     eventually be displayed		*/
/* Version T1.15 - 27-Nov-87 - tmk - Fixups for MSC 5.0, make help fit on
				     one screen again, add function pro-
				     totypes, speed up -vx opt combo	*/
/* Version T1.16 - 15-Jul-88 - tmk - Display correct 'most popular cookie'
				     in -x test (1- vs. 0-based)	*/
/* Version T1.17 - 18-Jul-88 - tmk - Make file I/O errors fatal, set error
				     level on MS-DOS			*/
/* Version T1.18 - 23-Jul-88 - tmk - Fix so that leading %'s no longer
				     suppress the cookie (short circuit in
				     expression evaluator), make -a and -r
				     imply -e (for MS-DOS batch files)	*/
/* Version V1.20 - 24-Jul-88 - tmk - Official release version (finally)	*/
/* Version V1.21 - 22-Dec-89 - tmk - Add support for DEC PDP-11 C V1.0	*/
/* Version V1.22 - 17-Jul-90 - tmk - Update for PDP-11 C V1.1		*/
/* Version V1.23 - 19-Nov-90 - tmk - Add support for 2.10BSD Unix	*/
/* Version V1.24 - 01-Sep-91 - tmk - Look in /usr/games/lib on Unix, add
				     "ctx=stm" for VMS to make it more tol-
				     erant of file characteristics, 2BSD
				     doesn't need byte swaps		*/

#define VERSION		"V1.24 01-Sep-91 - tmk"

/*
 * Define module ID for VMS (must go for Turbo C and Unix, else bogus error)
 */
/*ifdef Pseudo-ifdef for Turbo C and Unix */
#ifdef	vms
#ifdef	__DECC
#pragma	module	cookie	VERSION
#else
#module	cookie	VERSION
#endif	/* __DECC */
#endif	/* vms */
/*ifdef Pseudo-ifdef for Turbo C and Unix */
#ifdef	__pdp11c
#pragma list title VERSION
#endif	/* __pdp11c */

/*
 * Convince Turbo C it's running under MS-DOS (it isn't sure)
 */
#ifdef	__TURBOC__
#define	MSDOS		1
#endif	/* __TURBOC__ */

/*
 * Grab lots of header files
 */
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#ifdef unix
#include <curses.h>
#endif	/* unix */
#ifdef __pdp11c
#include <signal.h>	/* I won't ask why sleep() lives in signal.h */
#endif
#ifdef __DECC
#include <signal.h>	/* ... but apparently it's contagious */
#endif
#ifndef	decus
#ifndef unix
#include <stdlib.h>
#ifndef	vms
#ifndef __pdp11c
#include <conio.h>
#endif	/* __pdp11c */
#endif	/* vms */
#include <string.h>
#endif	/* unix */
#endif	/* decus */
#ifdef	MSDOS
#ifndef	__TURBOC__
#include <malloc.h>
#else
#include <alloc.h>
#endif	/* __TURBOC__ */
#include <dos.h>
#endif	/* MSDOS */
#ifdef	vms
#include <curses.h>
#include <descrip.h>
#endif	/* vms */

/*
 * Have a fight about function declarations, names, and file modes
 */
#ifdef	__TURBOC__
#define	cmpi		stricmp
#else
#define	cmpi		strcmpi
#endif	/* __TURBOC__ */
#ifdef	decus
#define	R_MODE	"rn"
#define	void
#define	gotfget
#define gotrsts
#define badprintf
#else
#define R_MODE	"rb"
#endif	/* decus */
#ifdef	vms
#define	gotfget
#define	gotcurses
#endif	/* vms */
#ifdef	__pdp11c
#define	gotrsts
#define	gotfget
#endif	/* __pdp11c */
#ifdef	unix
#define	gotcurses
#define badprintf
#endif	/* unix */

/*
 * Define some constants
 */
#define	EOS	0
#ifndef	unix
#define	TRUE	1
#define	FALSE	0
#endif	/* unix */
#ifdef	decus
#define	SC_VT52	(64+1)
#define	EMT	0104000
#define	DOCCL	EMT+0367
#endif	/* decus */
#ifdef	vms
#define	IO_SUC	65535
#define	IO_ERR	65535
#else
#define	IO_SUC	0
#define	IO_ERR	1
#endif	/* vms */

/*
 * Define some externals
 */
#ifdef	decus
extern	int	$$rsts;
extern	long	rand();
extern	long	seed;
extern	long	time();
#endif	/* decus */
#ifdef	__pdp11c
int	$$rsts		= 0;
#endif	/* __pdp11c */
#ifdef	__DECC
extern int	decc$gprintw();
#endif	/* __DECC */

/*
 * Global variables
 */
int	doall		= 0;		/* Show all cookies		*/
long	first		= 0;		/* First cookie of range	*/
long	last		= 0;		/* Last cookie of range		*/
int	video		= 0;		/* Utilize video mode		*/
int	noenvset	= 0;		/* Don't set the LASTCOOKIE sym	*/
#ifdef	MSDOS
int	ansivideo	= 0;		/* Use ANSI.SYS instead of BIOS	*/
int	comport		= 0;		/* Comm. port for DECtalk	*/
#endif	/* MSDOS */
#ifdef	decus
int	isvt52		= 0;		/* VT-52 vs. VT-100 flag	*/
#endif	/* decus */
int	notLong		= 0;		/* No Lazarus Long cookies	*/
int	continuous	= 0;		/* Show 'em continuously	*/
int	debug		= 0;		/* Are we showing debug info?	*/
int	disp_version	= 0;		/* Display version of coofile	*/
int	no_sleep        = 1;		/* Don't pause between cookies	*/
int	offensive       = 0;		/* Don't show offensive cookies	*/
int	long_sleep	= 0;		/* If sleeping, how long (secs)	*/
int	linecount	= 0;		/* Number of lines in fortune	*/
char	temp_text[81];			/* Temporary text buffer	*/
char	envstr[32];			/* Holds the LASTCOOKIE string	*/
static	int	nvoice;
static	char	voices[] = "pbhfkrudw";	/* Voices for DECtalk		*/
#ifdef	MSDOS
char	envnam[128];			/* Stores SET COOKIE= string	*/
#endif	/* MSDOS */
unsigned rndflg		= 0;		/* Randomness test mode flag	*/
int	*rndtab;			/* Randomizer test table	*/
char	*namptr;
FILE	*cookfd		= NULL;		/* Cookie file			*/
FILE	*extrafd	= NULL;		/* First output file		*/
#ifdef	decus
int	talkfn		= 0;		/* DECtalk output channel	*/
#else
FILE	*talkfd		= NULL;		/* DECtalk output file		*/
#endif	/* decus */
#ifdef	unix
FILE	*lastfd		= NULL;		/* LASTCOOKIE value		*/
char	lastfn[128];			/* filename of above 		*/
#endif	/* unix */
char	*cookfile[] = {			/* Cookie search list		*/
	"cookie.fil",			/* Current directory first	*/
	"c:\\system\\cookie.fil",	/* PC-DOS system directory	*/
	"sys$manager:cookie.fil",	/* Default cookie directory	*/
	"public:cookie.fil",		/* Various			*/
	"pub:cookie.fil",		/*   public			*/
	"sys$public:cookie.fil",	/*     directories		*/
	"games:cookie.fil",		/* Some				*/
	"game:cookie.fil",		/*   games			*/
	"sys$games:cookie.fil",		/*     directories		*/
	"$cookie.fil",			/* Explicit [1,2] for PDP-11 C	*/
	"/usr/games/lib/cookie.fil",	/* Unix systems			*/
	NULL,
};

char	*coobfile[] = {			/* Cookie search list		*/
	"cookob.fil",			/* Current directory first	*/
	"c:\\system\\cookob.fil",	/* PC-DOS system directory	*/
	"sys$manager:cookob.fil",	/* Default cookie directory	*/
	"public:cookob.fil",		/* Various			*/
	"pub:cookob.fil",		/*   public			*/
	"sys$public:cookob.fil",	/*     directories		*/
	"games:cookob.fil",		/* Some				*/
	"game:cookob.fil",		/*   games			*/
	"sys$games:cookob.fil",		/*     directories		*/
	"$cookob.fil",			/* Explicit [1,2] for PDP-11 C	*/
	"/usr/games/lib/cookob.fil",	/* Unix systems			*/
	NULL,
};

struct header {
#ifdef	vms
	short	coover;			/* Version of CAM structure	*/
	short	spare;			/* Spare value (was password)	*/
	long	ncookie;		/* Number of cookies		*/
	short	bcookie;		/* Size of largest cookie	*/
	short	nindex;			/* Dimension of index[]		*/
	short	subindex;		/* Number of subindex entries	*/
	short	sindex;			/* Sizeof index for alloc	*/
#else
	int	coover;			/* Version of CAM structure	*/
	int	spare;			/* Spare value (was password)	*/
	long	ncookie;		/* Number of cookies		*/
	int	bcookie;		/* Size of largest cookie	*/
	int	nindex;			/* Dimension of index[]		*/
	int	subindex;		/* Number of subindex entries	*/
	int	sindex;			/* Sizeof index for alloc	*/
#endif	/* vms */
	char	date[28];		/* Date cookie file built	*/
} header;

#define	NCOOKIES	(header.ncookie)
#define	TEXTSIZE	4096
#define	INDEXMAX	(TEXTSIZE / sizeof(long))

union {
	char text[TEXTSIZE];		/* Cookies stored here		*/
	long index[INDEXMAX];		/* Cookie sub index entries	*/
} t;

#ifdef	MSDOS
union REGS inreg,outreg;		/* Processor registers		*/
#endif	/* MSDOS */

/*
 * If only one cookie is needed, topindex[] can be overlayed over t.index[]
 */

long	topindex[INDEXMAX];		/* Top index entries		*/

/*
 * Grab some PDP-11 C specific definitions
 */

#ifdef	__pdp11c
typedef	struct	{
			 short	xrlen;
			 short	xrbc;
			 short	xrloc;
		unsigned char	xrci;
		unsigned char	xrblkm;
			 short	xrblk;
			 short	xrtime;
			 short	xrmod;
		} XRB;

#define	RSTS$XRB   ((XRB *)  (0442)) /* Absolute address of the XRB	*/

#define	RSTS$CLRXRB	$CLXRB
extern void $CLXRB(void);			/* Clear the XRB	*/

#define RSTS$CCL	C$CCL			/* Check for CCL cmd	*/
extern void C$CCL(void);

#endif	/* __pdp11c */

/*
 * For 'modern' compilers (all except decus), supply function prototypes
 */
#ifndef	decus
#ifdef	unix
extern  int  main();
extern  void init();
extern  void setup_cookie();
extern  void rndchk();
extern  int  tbldun();
extern  void rerror();
extern  void docookie();
extern  int  isLong();
extern  void antiheinlein();
extern  void output();
extern  void speak();
extern  void spit();
extern  void startoutput();
extern  void endoutput();
extern  void vtcurse();
extern  void erpage();
extern  void vtout();
extern  void hswap();
extern  void swaplb();
extern  long swapl();
#else
extern  int  main(int, char **);
extern  void init(void);
extern  void setup_cookie(void);
extern  void rndchk(int, char *);
extern  int  tbldun(int);
extern  void rerror(int, int, char *);
extern  void docookie(long);
extern  int  isLong(char *);
extern  void antiheinlein(long);
extern  void output(long, char *);
extern  void speak(char *);
extern  void spit(int);
extern  void startoutput(long);
extern  void endoutput(void);
extern  void vtcurse(int, int);
extern  void erpage(void);
extern  void vtout(int, int, char *);
#ifdef	MSDOS
#ifndef	__TURBOC__
extern  void sleep(int);
#endif	/* __TURBOC__ */
extern  void kbtest(void);
extern  void comwait(int);
extern  int  comrdy(int);
extern  int  comsta(int);
extern  int  cominp(int);
extern  void comout(int ,int);
extern	void EXEC2E(char *);
extern	void ASMCLS(void);
#endif	/* MSDOS */
extern  void hswap(void);
extern  void swaplb(long *);
extern  long swapl(long);
#endif	/* unix */
#endif	/* decus */

/*
 * Actual code starts here
 */
int main(argc, argv)
int		argc;
char		*argv[];
{
	register int	howmany;	/* How many to do		*/
	register char	*ap;
	long		which;
	long		atol();
#ifdef	__pdp11c
	unsigned long	howlong;	/* How long to sleep		*/
#else
	int		howlong;	/* How long to sleep		*/
#endif	/* __pdp11c */

#ifdef	__pdp11c
	if (strcmp(getenv("OPSYS"), "RSTS") == 0)
	    $$rsts = 1;
	else
	    $$rsts = 0;
#endif	/* __pdp11c */
	which = 0;
	while (argc > 1) {
	    ap = argv[1];
	    if (isdigit(*ap) || (*ap == '-' && isdigit(ap[1]))) {
		which = atol(ap);
		continuous = 0;
	    }
	    else if (*ap != '-') {
		fprintf(stderr, "?Unknown command \"%s\"\n", ap);
#ifdef	unix
		fprintf(stderr, "  do COOKIE -z for help.\n\n\n");
#else
		fprintf(stderr, "  do COOKIE -? for help.\n\n\n");
#endif	/* unix */
	    }
	    else for (ap++; *ap; ap++) {
#ifdef	unix
		switch (isupper(*ap) ? tolower(*ap) : *ap) {
#else
		switch (tolower(*ap)) {
#endif	/* unix */
		case 'a':		/* Do all cookies		*/
		    doall++;
		    noenvset++;
		    break;

#ifdef	MSDOS
		case 'b':		/* Use ANSI.SYS for video	*/
		    ansivideo++;
		    break;
#endif	/* MSDOS */

		case 'c':		/* Display continuously		*/
		    continuous++;
		    break;

		case 'd':		/* Display seek addresses	*/
		    debug++;
		    break;

		case 'e':		/* Don't set LASTCOOKIE var.	*/
		    noenvset++;
		    break;

		case 'f':		/* Use different cookie file	*/
		    if (isgraph(ap[1]) != 0) {
#ifndef	gotfget
			namptr = &ap[1];
#endif	/* gotfget */
#ifdef	vms
			if ((cookfd = fopen(&ap[1], R_MODE, "ctx=stm")) == NULL) {
#else
			if ((cookfd = fopen(&ap[1], R_MODE)) == NULL) {
#endif	/* vms */
			    perror(&ap[1]);
			    exit(IO_ERR);
			}
		    }
		    else if (argc > 2) {
#ifndef	gotfget
			namptr = argv[2];
#endif	/* gotfget */
#ifdef	vms
			if ((cookfd = fopen(argv[2], R_MODE, "ctx=stm")) == NULL) {
#else
			if ((cookfd = fopen(argv[2], R_MODE)) == NULL) {
#endif	/* vms */
			    perror(argv[2]);
			    exit(IO_ERR);
			}
			argv++;
			argc--;
		    }
		    else {
			break;
		    }
		    goto next_arg;

		case 'h':		/* No Lazarus Long cookies	*/
		    notLong++;
		    break;

		case 'i':		/* Display version of file	*/
		    disp_version++;
		    break;

                case 'o':		/* offensive cookie		*/
                    offensive++;
                    break;

		case 'r':		/* Show range of cookies	*/
		    if ( argc > 2 && isdigit(ap[1]) && isdigit(argv[2][0])) {
			doall++;
			noenvset++;
			first = atol(&ap[1]);
			last = atol(argv[2]);
			argv++;		/* Skip next argument		*/
			argc--;		/* too.				*/
		    }
		    else if (argc > 3 && isdigit(argv[2][0]) &&
			isdigit(argv[3][0])) {
			doall++;
			noenvset++;
			first = atol(argv[2]);
		        last = atol(argv[3]);
			argv += 2;	/* Skip next two argument	*/
			argc -= 2;	/* too.				*/
		    }
		    else {
			fprintf(stderr, "?Must specify start and end values \
for range.\n");
			break;
		    }
		    goto next_arg;

		case 's':		/* Sleep between cookies	*/
		    continuous++;
                    no_sleep--;
		    if (isdigit(ap[1])) {
			long_sleep = atoi(&ap[1]);
		    }
		    else if (argc > 2 && isdigit(argv[2][0])) {
			long_sleep = atoi(argv[2]);
			argv++;		/* Skip next argument		*/
			argc--;		/* too.				*/
		    }
		    else {
			long_sleep = 0;
			break;
		    }
		    goto next_arg;

		case 't':		/* Output to DECtalk		*/
		    if (isgraph(ap[1]) != 0) {
#ifdef	MSDOS
			if (cmpi(&ap[1], "COM1") == 0)
			    comport = 1;
			if (cmpi(&ap[1], "COM2") == 0)
			    comport = 2;
#endif	/* MSDOS */
#ifndef	decus
			if ((talkfd = fopen(&ap[1], "wn")) == NULL) {
#else
			if ((talkfn = kb_open(&ap[1])) == NULL) {
#endif	/* decus */
			    perror(&ap[1]);
			    exit(IO_ERR);
			}
		    }
		    else if (argc > 2) {
#ifdef	MSDOS
			if (cmpi(argv[2], "COM1") == 0)
			    comport = 1;
			if (cmpi(argv[2], "COM2") == 0)
			    comport = 2;
#endif	/* MSDOS */
#ifndef	decus
			if ((talkfd = fopen(argv[2], "wn")) == NULL) {
#else
			if ((talkfn = kb_open(argv[2])) == NULL) {	
#endif	/* decus */
			    perror(argv[2]);
			    exit(IO_ERR);
			}
			argv++;
			argc--;
		    }
		    else {
			break;
		    }
		    goto next_arg;

		case 'v':		/* Output in video mode		*/
		    video = 1;
#ifdef	decus
		    if ($$rsts) {
                	if (((isvt52 = sctype()) & 64) == 0) {
			    fprintf(stderr, "?Unknown video %d\n", sctype());
			    video = 0;	/* So don't do it		*/
			}
			else
			    isvt52 = (isvt52 == SC_VT52);
		    }
		    else
			isvt52 = 0;
#endif	/* decus */
                    break;

		case 'w':		/* Write output to file		*/
		    if (isgraph(ap[1]) != 0) {
			if ((extrafd = fopen(&ap[1], "a")) == NULL) {
			    perror(&ap[1]);
			    exit(IO_ERR);
			}
		    }
		    else if (argc > 2) {
			if ((extrafd = fopen(argv[2], "a")) == NULL) {
			    perror(argv[2]);
			    exit(IO_ERR);
			}
			argv++;
			argc--;
		    }
		    else {
			break;
		    }
		    goto next_arg;

                case 'x':		/* exercise rand() function	*/
                    rndflg++;
                    break;

#ifdef	unix
		case 'z':		/* Display help message		*/
#else
		case '?':		/* Display help message		*/
#endif	/* unix */
		    printf("COOKIE %s",VERSION);
#ifdef	unix
		    printf("\n\nUsage is: cookie option option...\n");
#else
		    printf("\n\nUsage is: COOKIE option option...\n");
#endif	/* unix */
		    printf("Options: n      Display cookie N\n");
		    printf("         -n     Display N random cookies\n");
		    printf("         -a     Print all cookies in order\n");
#ifdef	MSDOS
		    printf("         -b     Use ANSI.SYS instead of BIOS video\n");
#endif	/* MSDOS */
		    printf("         -c     Print random cookies continuously\n");
		    printf("         -d     Enable debugging output\n");
#ifdef	gotrsts
		    if ($$rsts)
#endif	/* gotrsts */
		    printf("         -e     Don't set LASTCOOKIE in environment\n");
		    printf("         -f fn  Get cookies from file FN\n");
		    printf("         -h     Suppress Heinlein quotations\n");
		    printf("         -i     Print version ID of cookie file\n");
		    printf("         -o     Print an offensive cookie ");
		    printf("(May be disabled on your system)\n");
		    printf("         -r m n Print cookies M through N in order\n");
		    printf("         -s n   Sleep N seconds between cookies ");
		    printf("- if N is omitted, delay is\n");
		    printf("                 proportional to the size of the ");
		    printf("cookie\n");
		    printf("         -t fn  Write cookies to DECtalk on file FN ");
		    printf("as well as to terminal\n");
		    printf("         -v     Output cookies in video mode\n");
		    printf("         -w fn  Write cookies to file FN as well as ");
		    printf("to terminal\n");
		    printf("         -x     Run randomness tests on random num");
		    printf("ber generator (slow)\n");
#ifdef	unix
		    printf("         -z     Print this message\n");
#else
		    printf("         -?     Print this message\n");
#endif	/* unix */
		    exit(IO_SUC);
		    break;

		default:
		    fprintf(stderr, "?Unknown option '%c'\n", *ap);
#ifdef	unix
		    fprintf(stderr, "  do COOKIE -z for help.\n\n\n");
#else
		    fprintf(stderr, "  do COOKIE -? for help.\n\n\n");
#endif	/* unix */
		}
	    }
	    next_arg:
	    argc--;
	    argv++;
	}
	init();				/* Setup random number		*/
	setup_cookie();			/* Open file, check versions...	*/
	if (rndflg) {
	    rndflg=(int) NCOOKIES;
	    rndtab=(int *) calloc(rndflg, sizeof(int));
	    if (rndtab == NULL) {
		fprintf(stderr,"?Insufficient memory to hold table\n");
#ifdef	__pdp11c
		fprintf(stderr,"  Try re-linking with /CODE=DATA\n");
#endif	/* __pdp11c */
		exit(IO_ERR);
	    }
	    printf("\nThis may take a while...\n");
	    rndchk(0, "sequential");	/* Go exercise randomness	*/
	    rndchk(1, "iterative");
	    exit(IO_SUC);		/* And exit			*/
	}
	if (video) {
#ifdef	gotcurses
	    initscr();			/* Init C Curses library	*/
#endif	/* gotcurses */
	    erpage();
	}
	if (doall) {
	    printf("%s", (doall > 1) ? "%%\n" : "");
	    if ((first == 0) && (last == 0)) {
		first = 1;
		last = NCOOKIES;
	    }
	    if (first == 0)
		first = 1;
	    if (last == 0)
		last = 1;
	    for (which = first; which < last; which++) {
		docookie(which);
#ifdef	MSDOS
		kbtest();
#endif	/* MSDOS */
	    }
	}
	if (continuous)
	    which = -1;
	if (which > 0) {
	    if (which > NCOOKIES) {
		sprintf(t.text, "Misfortune: there are only %ld cookies.\n",
		    NCOOKIES);
		output(which, t.text);
	    }
	    else
		docookie(which);
	}
	else {
	    if ((howmany = -which) == 0)
		howmany = 1;
	    while (howmany-- > 0) {
		which = rand() % NCOOKIES;
		docookie(which + 1);
		if (continuous) {
		    howmany = 1;
#ifdef	MSDOS
		    kbtest();
#endif	/* MSDOS */
		}
		if (howmany > 0) {
		    if (no_sleep == 0) {
			if (long_sleep > 0)
			    howlong = long_sleep;
			else
			    howlong = (linecount + 1) * 2;
			if (howlong != 0)
			    sleep(howlong);
		    }
		}
	    }
	}
        if (extrafd != NULL)
	    fclose(extrafd);
#ifndef	decus
	if (talkfd != NULL)
	    fclose(talkfd);
#else
	if (talkfn != 0)
	    kb_close(talkfn);
#endif	/* decus */
#ifdef	decus
	if (!noenvset && $$rsts)
	    rtemt(DOCCL, &envstr);	/* Set LASTCOOKIE on RSTS	*/
#endif	/* decus */
#ifdef	__pdp11c
	if (!noenvset && $$rsts) {
	    RSTS$CLRXRB();
	    RSTS$XRB->xrlen = strlen(envstr);
	    RSTS$XRB->xrbc = strlen(envstr);
	    RSTS$XRB->xrloc = (short)envstr;
	    RSTS$CCL();
	}
#endif	/* __pdp11c */
#ifdef	unix
	if (!noenvset) {
	    strcpy(lastfn, (char *)getenv("HOME"));
	    strcat(lastfn, "/.lastcookie");
	    if ((lastfd = fopen(lastfn, "w")) == NULL) {
		perror("~.lastcookie");
		exit(IO_ERR);
	    }
	fprintf(lastfd, "%s\n", envstr);
	fclose(lastfd);
	}
#endif	/* unix */
	exit(IO_SUC);
}

void init()
/*
 * Initialize random number generator
 */
{
#ifdef	decus
	seed=time(NULL);		/* decus - set seed		*/
#else
#ifdef	unix
	srand(time(NULL) + getpid());	/* Unix - use function		*/
#else
	srand(time(NULL));		/* others - use function	*/
#endif	/* unix */
#endif	/* decus */
	rand();				/* always toss the first one	*/
}

void setup_cookie()
/*
 * Initialize cookie file, finding it in the search list
 */
{
	register char	**namep;
	register int	temp, p;
		 char	dummy[9];

	if (cookfd == NULL) {
	    if (offensive == 0) {
		for (namep = cookfile; *namep != NULL; namep++) {
#ifdef	vms
		    if ((cookfd = fopen(*namep, R_MODE, "ctx=stm")) != NULL)
#else
		    if ((cookfd = fopen(*namep, R_MODE)) != NULL)
#endif	/* vms */
			break;
		}
	    }
	    else { 
		for (namep = coobfile; *namep != NULL; namep++) {
#ifdef	vms
		    if ((cookfd = fopen(*namep, R_MODE, "ctx=stm")) != NULL)
#else
		    if ((cookfd = fopen(*namep, R_MODE)) != NULL)
#endif	/* vms */
			break;
		}
	    }
#ifndef	gotfget
	    namptr = *namep;
#endif	/* gotfget */
#ifdef	MSDOS
	    if (cookfd == NULL) {	/* Try for environment		*/
		strcpy(envnam, (char *)getenv("COOKIE"));
		if (envnam[strlen(envnam)-1] != '\\')
		    strcat(envnam, "\\");
		if (offensive == 0)
		    strcat(envnam, cookfile[0]);
		else
		    strcat(envnam, coobfile[0]);
		if (debug)
		    printf("environment-generated name is %s\n",envnam);
		cookfd = fopen(envnam, R_MODE);
		namptr = (char *)envnam;
	    }
#endif	/* MSDOS */
	    if (cookfd == NULL) {
		fprintf(stderr, "?Can't open cookie file\n");
		exit(IO_ERR);
	    }
	}
	if (debug)
	    printf("before normalize, first=%ld, last=%ld\n",first,last);
	fread(dummy, 9, 1, cookfd);
	if (strncmp(dummy, "555-2368", 8) != 0) {
	    fprintf(stderr, "?Bad magic number in cookie file\n");
	    exit(IO_ERR);
	}
	if ((temp = fread(&header, sizeof(header), 1, cookfd)) != 1)
	    rerror(sizeof(header), temp, "Reading header file");
#ifndef	decus
#ifndef	unix
	hswap();			/* Swap from PDP-11 format	*/
#endif	/* unix */
#endif	/* decus */
	if (header.coover != 102) {
	    fprintf(stderr, "?Unknown revision level %d in cookie file\n",
		header.coover);
	    exit(IO_ERR);
	}
#ifdef	gotfget
	namptr = fgetname(cookfd, temp_text);
#endif	/* gotfget */
	if (first > NCOOKIES)
	    first = NCOOKIES;
	if (last > NCOOKIES)
	    last = NCOOKIES;
	if (debug)
	    printf("after normalize, first=%ld, last=%ld\n",first,last);
	if (disp_version) {
#ifndef	badprintf
	    p = sprintf(t.text, "Cookie file %s, built on %s",
		namptr, header.date);
	    p--;			/* Eat newline character	*/
	    p += sprintf(t.text+p,", contains %ld cookies. The largest is %d ",
		header.ncookie, header.bcookie);
	    p += sprintf(t.text+p, "bytes long. %d index levels were used. ",
		header.nindex+1);
	    p += sprintf(t.text+p, "The revision level is %d.%02d.",
		header.coover / 100, header.coover % 100);
	    for (p = 64; p < strlen(t.text); p += 64) {
		while (t.text[p] != ' ')
		    p++;		/* Break into 64-char lines	*/
		t.text[p] = '\n';
	    }
	    printf("%s\n", t.text);
#else
	    printf("Cookie file %s, built on %s",
		namptr, header.date);
	    printf("contains %ld cookies. The largest is %d ",
		header.ncookie, header.bcookie);
	    printf("bytes long. %d\nindex levels were used. ",
		header.nindex+1);
	    printf("The revision level is %d.%02d.\n",
		header.coover / 100, header.coover % 100);
#endif	/* badprintf */
	    exit(IO_SUC);
	}
	if ((temp = fread(topindex, header.sindex, 1, cookfd)) != 1)
		rerror(header.sindex, temp, "Reading top-level index");
#ifndef	decus
#ifndef	unix
	swaplb(topindex);		/* Swap from PDP-11 format	*/
#endif	/* unix */
#endif	/* decus */
}

void rndchk(pass, type)
int	pass;				/* Pass number (0 or 1)		*/
char	*type;				/* Pass type			*/
/*
 * Verify random number generator
 */
{
	long	i, k, m;
	int	j, l;

	printf("\nBeginning %s test, %ld cookies.\n",type, NCOOKIES);
	k=0, l=0;			/* initialize # of tries	*/
	m=rand();			/* initialize pseudo-seed	*/
	for (i=0; i<NCOOKIES; i++)
	    rndtab[i]=0;		/* initialize table		*/
#ifdef	MSDOS
	while(((l = tbldun(l)) !=0) && !kbhit()) {
#else
	while((l = tbldun(l)) !=0) {
#endif	/* MSDOS */
	    for (i=0; i<l; i++) {	/* repeat until all cookies set	*/
		if (pass) {
#ifndef	decus
		    srand(m+=5);	/* Simulate multiple invoca-	*/
#else
		    m+=5;
		    seed=m;		/* Simulate multiple invoca-	*/
#endif	/* decus */
		    rand();		/*  tions at 5 second intervals	*/
		}
		j = rand() % NCOOKIES;
		k++;			/* say another random requested	*/
		rndtab[j]++;		/* turn on bit for this cookie	*/
	    }
	}
#ifdef	MSDOS
	kbtest();			/* eat possible keystroke	*/
#endif	/* MSDOS */
	l=NCOOKIES-tbldun(l);
	printf("  Took %ld tries for %d cookies.\n",k, l);
	k=0;
	l=0;				/* clear max and number		*/
	for (i=0; i<NCOOKIES; i++) {
	    if (rndtab[i] > k) {
		k=rndtab[i];		/* set new maximum		*/
		l=i;			/* and the cookie number	*/
	    }
	}
	l++;				/* adjust for 1-based numbering	*/
	printf("  Naximum hits was %ld, on cookie %d.\n",k, l);
}

int tbldun(l)
int		l;
/*
 * Return number of missing cookie elements
 */
{
	register int i, j;

	j=0;
	for (i=0; i<NCOOKIES; i++) {
	    if (rndtab[i] == 0)
		j++;
	}
	if ((video) && l != j) {
	    printf("  %5d left to go\r",j);
#ifdef	__pdp11c
	    fflush(stdout);
#endif	/* __pdp11c */
	    }
	return (j);
}

void rerror(expected, got, why)
int		expected;		/* Bytes in item		*/
int		got;			/* Unexpectedly isn't == 1	*/
char		*why;
/*
 * Fatal read error
 */
{
	perror(why);
	fprintf(stderr, "expected 1 item of %d bytes, read %d items\n",
			expected, got);
	exit(IO_ERR);			/* Had better leave		*/
}

void docookie(which)
long		which;
/*
 * Read and output the Nth cookie.  Note: 1-origin addressing
 */
{
	long		index;
	long		temp;
	register int	bytect;
#ifdef	__DECC
	int		i;
#else
	register int	i;
#endif	/* __DECC */
	register char	*tp;

#ifdef	__DECC
	extern int	LIB$SET_SYMBOL();
#endif	/* __DECC */

#ifdef	MSDOS
	if (!noenvset) {
	    sprintf(envstr,"\x14SET LASTCOOKIE=%ld\r",which);
	    *envstr = strlen(envstr+1)-1;
	    EXEC2E(envstr);		/* Set environment variable	*/
	}
#endif	/* MSDOS */
#ifdef	gotrsts
	if (!noenvset && $$rsts)
	    sprintf(envstr,"$LASTCOOKIE==%ld",which);
#endif	/* gotrsts */
#ifdef	unix
	if (!noenvset)
	    sprintf(envstr,"%ld",which);
#endif	/* unix */
#ifdef	vms
	/* Hello boys and girls... Can *you* say "contortionist"? Glenn
	   knew you could.						*/

	static	$DESCRIPTOR(symnam,"LASTCOOKIE");
	static	struct	dsc$descriptor_s	symval;

	if (!noenvset) {
	    sprintf(envstr,"%ld",which);
	    symval.dsc$w_length = strlen(envstr);
	    symval.dsc$a_pointer = envstr;
	    symval.dsc$b_class = DSC$K_CLASS_S;
	    symval.dsc$b_dtype = DSC$K_DTYPE_T;
	    i = 2;			/* Store in global table	*/
	    LIB$SET_SYMBOL(&symnam, &symval, &i);
	}
#endif	/* vms */
	which--;
	temp = header.nindex;
	temp = which / temp;
	i = temp;
	if (i >= header.subindex)
	    fprintf(stderr, "Bug: Gone too far, index = %d, max = %d\n",
		    i, header.subindex);
	index = topindex[i];
	if (debug) {
	    printf("requested cookie %ld+1\n",which);
	    printf("fseek to subindex at %ld\n",index);
	}
	if (fseek(cookfd, index, 0) != 0)
	    fprintf(stderr, "Can't seek to top-index at %ld\n",
		    index);
	if ((bytect = fread(t.index, header.sindex, 1, cookfd)) != 1) {
	    fprintf(stderr, "seek to sub-index %d, %ld.\n",
		    i, index);
	    rerror(header.sindex, bytect, "Can't read sub-index");
	}
#ifndef	decus
#ifndef	unix
	swaplb(t.index);		/* Swap from PDP-11 format	*/
#endif	/* unix */
#endif	/* decus */
	temp = header.nindex;
	temp = which % temp;
	i = temp;
	index = t.index[i];
#ifdef	MSDOS
	rewind(cookfd);			/* fseek() bug in Microsoft 4.0	*/
#endif	/* MSDOS */
	if (debug)
	    printf("fseek to cookie at %ld\n",index);
	if (fseek(cookfd, index, 0) != 0) {
	    fprintf(stderr, "Can't seek to cookie at %ld: ",
		    index);
	    perror("minor index seek");
	    printf("Requesting cookie %ld, max = %ld\n",
		    which, header.ncookie);
	    exit(IO_ERR);
	}
	if (debug)
	    printf("ftell of cookie is %ld\n",ftell(cookfd));
	tp = &t.text[0];
	while (fgets(tp, (sizeof(t.text)) - (tp - t.text), cookfd) != NULL
	 && !feof(cookfd)
	 && !(tp[0] == '%' & tp[1] == '%')) {
	    tp += strlen(tp);		/* Compiler torture test above	*/
	}
	*tp = EOS;			/* Remove trailing %%		*/
	if (feof(cookfd)) {
	    rerror(tp - t.text, tp - t.text, "Can't read cookie");
	}
	if (notLong && isLong(t.text))
	    antiheinlein(which + 1);
	else
	    output(which + 1, t.text);
}

static char *anti1[] = {
	"A Heinlein Cookie you do disdain,\n\
I'll say no more to soothe your brain.\n",
	"I'd rather drink a gallon of overage Rhine wine,\n\
Than read a quote by Robert A. Heinlein.\n",
	"I'd rather bite boils from an elephant's behind,\n\
Than read more quotes by Robert A. Heinlein.\n",
	"*I'd rather a tax audit found me wrong,\n",
	"*I'd rather be dribbled by old King Kong,\n",
	"*I'd rather find paraquat in my bong,\n",
	"*I'd rather Chuck Barris used me as the gong,\n",
	"*I'd rather do updates to Atari Pong,\n",
	"*I'd rather write a \"User's Guide to Pong\",\n",
};

static char *anti2[] = {
	"Than read another quote by Lazarus Long.\n",
	"Than have to read more of Lazarus Long.\n",
	"Than be forced to consider more Lazarus Long.\n",
};

int isLong(text)
register char	*text;
/*
 * Return TRUE if the text contains "Heinlein" or "Lazarus Long"
 */
{
	register char	c;

	while ((c = *text++) != EOS) {
	    switch (c) {
	    case 'H':
		if (strncmp(text, "einlein",7)==0)
		    return (TRUE);
		break;

	    case 'L':
		if (strncmp(text, "azarus Long",11)==0)
		    return (TRUE);
		break;
	    }
	}
	return (FALSE);
}

static	char	antibuffer[257];

void antiheinlein(which)
long		which;
/*
 * Output a non-Heinlein cookie
 */
{
	register char	*tp;


	tp = anti1[(rand() & 32767) % (sizeof(anti1)) / (sizeof(char *))];
	if (*tp == '*') {
	    strcpy(antibuffer, tp + 1);
	    strcat(antibuffer,
	    anti2[(rand() & 32767) % (sizeof(anti2)) / (sizeof(char *))]);
	}
	else {
	    strcpy(antibuffer, tp);
	}
	output(which, antibuffer);
}

void output(which, out_text)
long		which;
char		*out_text;
/*
 * Output one cookie
 */
{
	register char	*tp, *te;
	register char	tc;

	startoutput(which);
	te = out_text + strlen(out_text);
	for ( tp = out_text; tp < te; tp += 511) {
	    if (tp+511 < te) {		/* More than 511, break up 	*/
		tc = *(tp+511);
		*(tp+511) = '\0';
#ifdef	gotcurses
		if (video) {
		    printw("%s", tp);
		    refresh();
		}
		else
		    printf("%s", tp);
#else
		printf("%s", tp);
#endif	/* gotcurses */
		if (extrafd != NULL)
		    fprintf(extrafd, "%s", tp);
		*(tp+511) = tc;
	    }
	    else {
#ifdef	gotcurses
		if (video) {
		    printw("%s%s\n", tp, (doall > 1) ? "%%" : "");
		    refresh();
		}
		else
		    printf("%s%s\n", tp, (doall > 1) ? "%%" : "");
#else
		printf("%s%s\n", tp, (doall > 1) ? "%%" : "");
#endif	/* gotcurses */
		if (extrafd != NULL)
		    fprintf(extrafd, "%s%s\n", tp, (doall > 1) ? "%%" : "");
	    }
	}
#ifndef	decus
	if (talkfd != NULL)		/* Should we mumble?		*/
#else
	if (talkfn != 0)		/* Should we mumble?		*/
#endif	/* decus */
	    speak(out_text);
	linecount = 1;
	tp = out_text; 
	while ((tp = (char *)strchr(tp, '\n')) != NULL) {
	    linecount++;
	    tp++;
	}
	endoutput();
}

void speak(out_text)
char		*out_text;
/*
 * Drive DECtalk
 */
{
	register char	*tp;
	register int	c;

	nvoice = (rand() & 32767 % 9);
	spit('[');			/* Voice header			*/
	spit(':');
	spit('n');
	spit(voices[nvoice]);
	spit(']');
	for (tp = out_text; (c = *tp++) != EOS;) {
	    switch (c) {
	    case '-':			/* hy-\nphen => hyphen		*/
		if (*tp == '\n') {
		    tp++;
		    while ((c = *tp) == ' ')
			tp++;
		}
		else
		   spit('-');
		break;
	
	    case '+':			/* Errosols, part 1 of 2	*/
		if ((*tp == '-') && (tp[1] == '-')) {
		    while (*tp != '+')
			tp++;
		    tp++;
		    c = *tp;
		}
		else
		    spit('+');
		break;

	    case '|':			/* Errosols, part 2 of 2	*/
		if ((tp[-2] != '\n') && (*tp != '\n'))
		    spit('|');
		break;

	    case ',':
		spit(',');
		if (!isspace(*tp))
		    spit(' ');
		break;

	    case '[':			/* [ => (			*/
		spit('(');
		break;

	    case ']':
		spit(')');		/* ] => )			*/
		break;

	    case '(':			/* (c.a. => ( c.a.		*/
		if (isalpha(*tp) && tp[1] == '.') {
		    spit(c);
		    c = ' ';
		}
		spit(c);
		break;

	    case ')':			/* (44-22 BC)? =>		*/
		if (tp > &out_text[1]	/* (44-22 BC)			*/
		 && !isalpha(tp[-2])
		 && *tp == '?') {
		    spit(c);
		    c = ' ';
		    tp++;
		}
		spit(c);
		break;

	    case '.':
		if (tp > &out_text[3]	/* H. L. Menken =>		*/
		 && isupper(tp[-2])	/* H L Menken			*/
		 && isspace(tp[-3])	/* so DECtalk doesn't		*/
		 && isspace(*tp))	/* pause.			*/
		    continue;
		if (tp > &out_text[2]	/* ...foo => ... foo		*/
		 && tp[-2] == '.'
		 && isalpha(*tp)) {
		    spit(c);
		    c = ' ';
		}
		spit(c);
		break;

	    case '?':
		if (tp > &out_text[2]
		 && isalpha(tp[-2])
		 && isspace(*tp))
		    spit(c);
		break;

	    default:
		spit(c);
		if (isdigit(c) && !isdigit(*tp)) {
		    switch (*tp) {
		    case '?':		/* 1900?-1980			*/
			if (tp[1] != '-')
			    break;
			tp++;		/* Skip ?			*/

		    case '-':		/* 1900-1910			*/
			spit(',');
			spit(' ');
			tp++;
			if (*tp == '?' && tp[1] == ')')
			    tp += 2;	/* 1900-?)			*/
			break;
		    }
		}
	    }
	}
#ifdef	gotrsts
	spit(($$rsts) ? '\233' : '\33');
#else
	spit('\33');
#endif	/* gotrsts */
	spit('P');
	spit('0');
	spit(';');
	spit('1');
	spit('1');
	spit('z');
#ifdef	gotrsts
	spit(($$rsts) ? '\233' : '\33');
#else
	spit('\33');
#endif	/* gotrsts */
	spit('\\');
}

void spit(what)				/* Emit character to DECtalk	*/
int	what;
{
#ifdef	MSDOS
	if (comport == 0)		/* Messy case			*/
	    putc(what, talkfd);		/* If not to COMn		*/
	else {
	    if ((comsta(comport-1) & 0x0030) != 0x0030) {
		fprintf(stderr, "?Error writing device COM%d:\n", comport);
		exit(IO_ERR);
	    }
	    comout(comport-1, what);	/* Otherwise send the byte	*/
	    comwait(comport-1);		/* And play at flow control	*/
	}
#else
#ifdef	decus
	kb_spit(talkfn, what);		/* Simple-minded case		*/
#else
	putc(what, talkfd);		/* Simple case			*/
#endif	/* decus */
#endif	/* MSDOS */
}

void startoutput(which)
long	which;
/*
 * Initialize output
 */
{

	register char	*timebuf;
#ifdef	__DECC
	unsigned long	tvec;
#else
	long		tvec;
#endif	/* __DECC */

	if (video) {
	    sprintf(temp_text, "%ld", which);
	    time(&tvec);
	    timebuf = ctime(&tvec);
	    erpage();
	    vtout(1, 27, timebuf);
	    vtout(3, 36, temp_text);
	    vtout(4, 1, "\n");		/* Force new line for some OS's	*/
	}
}

void endoutput()
/*
 * Clear the rest of the screen
 */
{
	if (video) {
	    fflush(stdout);
	}
}

void vtcurse(row, col)
int		row, col;
{
	if (row == 0)
	    return;
#ifdef	MSDOS
	if (ansivideo)
	    printf("\033[%d;%dH",row, col);
	else {
	    inreg.h.ah = 15;		/* Get current video page	*/
	    int86(0x10, &inreg, &outreg);
	    inreg.h.ah = 2;		/* Position cursor on it	*/
	    inreg.h.dh = --row;
	    inreg.h.dl = --col;
	    inreg.h.bh = outreg.h.bh;
	    int86(0x10, &inreg, &outreg);
	}
#endif	/* MSDOS */
#ifdef	decus
	if (isvt52)
	    printf(($$rsts) ? "\233Y%c%c" : "\033Y%c%c", row + 037, col + 037);
	else
	    printf(($$rsts) ? "\233[%d;%dH" : "\033[%d;%dH", row, col);
#endif	/* decus */
#ifdef	__pdp11c
	printf(($$rsts) ? "\233[%d;%dH" : "\033[%d;%dH", row, col);
#endif	/* __pdp11c */
#ifdef	gotcurses
	move(row, col);	
#endif	/* gotcurses */
}

void erpage()
{
	vtcurse(1, 1);
#ifdef	MSDOS
	if (ansivideo)
	    fputs("\033[J", stdout);
	else
	    ASMCLS();
#endif	/* MSDOS */
#ifdef	decus
	if (isvt52)
	    fputs(($$rsts) ? "\233J" : "\033J", stdout);
	else
	    fputs(($$rsts) ? "\233[J" : "\033[J", stdout);
#endif	/* decus */
#ifdef	__pdp11c
	fputs(($$rsts) ? "\233[J" : "\033[J", stdout);
#endif	/* __pdp11c */
#ifdef	gotcurses
	clear();
	refresh();
#endif	/* gotcurses */
}

void vtout(row, col, text)
int		row, col;
char		*text;
{
	vtcurse(row, col);
#ifdef	gotcurses
	printw("%s", text);
	refresh();
#else
	fputs(text, stdout);
#endif	/* gotcurses */
}

#ifdef	MSDOS
#ifndef	__TURBOC__
void sleep(howlong)
int	howlong;
{
long	basetime, curtime;

	basetime = time(NULL);
	curtime = time(NULL);
	while((curtime < basetime + howlong) && !kbhit())
	    curtime = time(NULL);
	kbtest();			/* See if key was hit and exit	*/

}
#endif	/* __TURBOC__ */

void kbtest()
{
int	quitchr=0;

	if (kbhit()) {
	    quitchr = getch();
	    quitchr = tolower(quitchr);
	    if (quitchr == 113)
	        exit(IO_SUC);
	}
}
#endif	/* MSDOS */

#ifdef	MSDOS
void comwait(port)
int	port;				/* Desired port (0, 1)		*/
{
	int	byte;

	while ( comrdy(port) != 0) {	/* If there is a byte waiting	*/
	    byte = cominp(port);	/* Get it			*/
	    if (byte == 0x13) {		/* If ^S, await matching ^Q	*/
		while (cominp(port) != 0x11) {
		}
	    }
	}
	return;
}

int comrdy(port)			/* Return input ready status	*/
int	port;
{
	return ((comsta(port) & 0x0100) >> 8);
}

int comsta(port)			/* Return all status		*/
int	port;
{
	inreg.x.dx = port;
	inreg.h.ah = 3;
	int86(0x14, &inreg, &outreg);
	return (outreg.x.ax);
}

int cominp(port)			/* Return character		*/
int	port;
{
	inreg.x.dx = port;
	inreg.h.ah = 2;
	int86(0x14, &inreg, &outreg);
	return (outreg.h.al & 0x7f);
}

void comout(port,data)			/* Send character		*/
int	port, data;
{
	inreg.x.dx = port;
	inreg.h.ah = 1;
	inreg.h.al = data;
	int86(0x14, &inreg, &outreg);
}
#endif	/* MSDOS */

#ifndef	decus
#ifndef	unix
void hswap()
/*
 * Swap the header.xxx components to/from PDP-11 format
 */
{
	header.ncookie  = swapl(header.ncookie);
}

void swaplb(indextable)
long	indextable[];
/*
 * Swap an index table to/from universal format
 */
{
	register int i;

	for (i=0; i < header.nindex; i++)
	    indextable[i] = swapl(indextable[i]);
}

long swapl(l)				/* With thanks to Dennis Bednar	*/
long	l;
{
	register char *sp, *dp;
		 long r;

	sp = (char *) &l;
	dp = (char *) &r;

	*dp++ = sp[2];			/* PDP-11 stores bytes 2,3,0,1	*/
	*dp++ = sp[3];
	*dp++ = sp[0];
	*dp   = sp[1];
	return (r);
}
#endif	/* unix */
#endif	/* decus */
