V10/history/v8arch

From research!mcvax!ukc!eagle.ukc.ac.uk!cheviot.newcastle.ac.uk!andy  Thu Sep  5 21:18:15 1985
Received: by mcvax.UUCP; Thu, 5 Sep 85 21:18:15 +0200 (MET)
Message-Id: <8509051918.AA13165@mcvax.UUCP>
Received: from [nedaftp] by ukc.AC.UK id a029579; 5 Sep 85 17:00 BST
From: Andy Linton (andy@cheviot.UUCP) <mcvax!andy@cheviot.newcastle.ac.uk>
Date: Thu, 5 Sep 85 17:00:13 bst
To: research!v8news
Subject: Conversion of Blits to 250 volts

Here is a message from the keyboard of the first Blit we have converted.

It was not as straightforward as the data sheet would have one believe.
There is an additional jumper which needs changed to complete the job.
This one is on the power supply behind the screen and on the left as you 
face the screen. On some of the models we got there are two plugs which
can be interchanged - one is marked 120 and the other is marked 220.

Needless to say we chose one of the Blits which did not have this  to
commence conversions with. For this one we needed to change the
male connector plug as shown below:

Original setup
**************
	O--+
	   |  
	   |
	O--|--+------------ Blackto logic Power supply
	   |  |
	   |  |
	O--+--------------- White to logic Power supply
	      |
	      |
	O-----+


220V setup
**********

	O------------------ White to logic Power supply


	O--+
	   |  
	   |
	   |
	O--+
	
	
	O------------------ Black to logic Power supply


We have not yet received our V8 tape and I am using the Blit as a
dumb terminal. Is there a proper termcap entry for it - I am using
oblit from the Berkeley termcap file but it doesn't clear the screen
properly. Any hints?
Thanks.
andy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SENDER 	: Andy Linton		PHONE	: +44 632 329233
POST	: Computing Lab, University of Newcastle upon Tyne, UK, NE1 7RU
ARPA	: andy%cheviot.newcastle.ac.uk@ucl-cs.ARPA)
JANET	: andy@uk.ac.newcastle.cheviot
UUCP	: <UK>!ukc!cheviot!andy

***  Ni fui moran beagan d'aon rud, ach is fui moran beagan ceille.  ***





From research!acsnet!basser!boyd Sat Sep  7 21:29:36 1985
To: v8news@research
Cc: v8
Subject: 4.1 chroot bug etc...
Full-name: Boyd Roberts

At Sydney Uni we also had the 4.1 chroot bug.  If you chroot,
your system crashes.  Yuk.  To get around it we just took our
4.1 pack, read in our V8 root file-system onto another partition.
We made a V8 kernel on our standard system (ie. non 4.1)
and put it in the soon to be V8 /.

THe V8 / was dumped it to tape (using 4.1 dump) and was restored the
on top of the 4.1 root file-system.  Now we had a clean V8 root file-system.
>From there we made our /usr file-system.  We then had a minimal V8 system.

Without a clean (ie. no 4.1 crud on it) V8 root file-system life
is very interesting.  We tried a different approach at one stage
and it was a nightmare.

But, we have some more difficult problems.  As we run a system
(for the sake of argument we'll call it 32V) that has a 512 byte
block file-system.  Nothing on V8 understands it, and nothing on
32V understands V8.  We were facing the prospect of dumping and
restoring our existing file-systems with tar.  But, our
calculations showed that we may run out of disk space.

Our solution was to implement a new file-system type.  We could then
use all our 32V file-system things to manipulate our old file-systems.
The true beauty of the idea was that we could always return to 32V.
Should we convert all our file-systems to V8, we were then stuck with it.
We hoped to bring up V8 with minimal disruption as our machine
is very heavily relied on.

One other major problem was that we couldn't backup the V8 file-systems
as there wasn't a dump that really understood them.  One of our programmers
is working on a dump that will understand all three file-systems.  Other minor
problems included what to do with our ``special'' files (i.e. named pipes,
locking and autolocking files).  The new file-system type solved all of
the problems.

I've implemented the new file-system type.  It is not really
a ``type'' in it's own right, but is more like a type 0 file system
with a different block size.  pjw's 4k file system code made it easy.
It's slow, but it works!  Slowly we will convert to 1k or 4k.

I'll just add a few lines on some of the minor V8 bugs we've found.

    dev/ht.c:
		> hpattach() should return 1
		> change all mba device register to 16 bit assignments
		  to assign to 32 bit quantities

    dev/hp.c:
		> hpread() and hpwrite() should be fixed to
		  correctly select the unit number out of the
		  ``dev'' argument.  otherwise you can't read
		  or write 4k file-system devices except through
		  the block device interface.

    sys/machdep.c:
    sys/prf.c:
    sys/locore.s:
		> the printf message buffer allocation and use
		  should be fixed.  currently it is allocated
		  via pte's.  if you get a trap that causes
		  a printf, before the pte's are valid, then
		  a trap loop will ensue until a stack invalid
		  halt stops it.  yuk.  soon i will fix it here.


Boyd Roberts

From acsnet!basser!john Sat Sep 21 10:34:42 1985
>From john Sat Sep 21 10:34:42 1985 remote from acsnet!basser
Message-ID: <15958.221.496110881.basser@Basser>
To: v8news@research
Subject: device drivers

There comes a time when you want to drive some devices.  I've
written a DMF32 (asynch part only) driver; it has been tested
on Able VMZ's and Emulex CS32's and works fine on both.  Piers
has done a stream driver using QBIGB for the LP11 line printer
interface (we were surprised to find the distributed one was
still a 4.1 driver).  It has been lightly exercised and looks OK.

I am going to do a DZ11 driver that uses a KMC to do dma output.
At the moment I am trying to get the ht driver not to give lots
of hard errors with our SI tape controller (it works fine with
a real DEC TM03).  If anyone thinks they might know something
about that, or wants anything I've mentioned, please mail me.

John Mackin	seismo!munnari!basser.oz!john	john%basser.oz@SEISMO.CSS.GOV

From dmr Sat Sep 21 02:34 EDT 1985
Subject: new source
To: v8news

Ah, some action!  We would be happy to distribute source for drivers
or other things that people develop, such as the DMF32 and LP11 code
that John and Piers did.  However, it might be best to avoid dumping
it in people's mailboxes, so I have set up an alternate distribution
channel,
 	research!v8source
Right now it is a copy of v8news, and goes to the same places.
If you might want a DMF32 driver, but not one tossed in your lap,
send me another address to direct it to.

	Dennis

From mcvax!ukc!mmdf  Fri Oct 18 16:18:21 1985
>From ukc!mmdf  Fri Oct 18 16:18:21 1985 remote from mcvax
Received: by mcvax.UUCP; Fri, 18 Oct 85 16:18:21 +0100 (MET)
Message-Id: <8510181518.AA21670@mcvax.UUCP>
Received: from [nedaftp] by ukc.AC.UK id a022127; 18 Oct 85 14:24 BST
From: Andy Linton <mcvax!cheviot!andy>, mcvax!ndy@cheviot.newcastle.ac.uk
Mmdf-Warning:  Parse error in original version of preceding line at Ukc.AC.UK
Date: Fri, 18 Oct 85 14:25:03 bst
To: research!v8news
Subject: Lack of traffic across the Atlantic.


We may have lost some items addressed to v8news.
Apart from one from Newcastle the headers of those
we hjave received are below. Have we missed much?
Can we have what we  missed? Have there been any
articles for v8sources?
Thanks
andy

	From: dmr%research@mcvax.uucp
	Message-Id: <8509050921.AA05459@mcvax.UUCP>
	Subject: welcome to the eighth edition Unix system

	From: mcvax.uucp!research!acsnet!basser!boyd
	Message-Id: <8509071547.AA08323@mcvax.UUCP>
	To: mcvax.uucp!research!acsnet!basser!research!v8news
	Cc: v8@mcvax.uucp
	Subject: 4.1 chroot bug etc...

	From: mcvax.uucp!research!acsnet!basser!john
	Message-Id: <15958.221.496110881.basser@Basser>
	To: mcvax.uucp!research!acsnet!basser!research!v8news
	Subject: device drivers

From princeton!down!honey  Sat Oct 19 08:33:45 1985
>From down!honey  Sat Oct 19 08:33:45 1985 remote from princeton
Date: 19 Oct 1985 08:31-EDT
To: research!v8sources
Subject: v8 net fs server, tcp

# To unbundle, sh this file
echo makefile 1>&2
sed 's/^-//' >makefile <<'//GO.SYSIN DD makefile'
YFLAGS=-D
CFLAGS=-g
LDFLAGS=-g
HDR=fserv.h
SRC=	tcpstuff.c tcpmain.c ps.y perm.c start.c sub.c sys.c work.c profit.c
CSRC=	tcpstuff.c tcpmain.c ps.c perm.c start.c sub.c sys.c work.c profit.c
OBJ=	tcpstuff.o tcpmain.o ps.o perm.o sys.o start.o sub.o work.o profit.o

fshare:	$(OBJ) profit.o
	$(CC) -o fshare $(LDFLAGS) $(OBJ) profit.o -lin -ljobs

$(OBJ):	fserv.h

ps.c:	ps.y
	yacc $(FLAGS) ps.y
	sed < y.tab.c > ps.c '/^# line/d'

clean:
	rm -f a.out core jim.errs $(OBJ) y.tab.c ps.c fshare

bundle:
	@bundle makefile fserv.h neta.h $(SRC)

lint:
	lint $(CSRC)

tags:
	ctags -w $(SRC) fserv.h neta.h
//GO.SYSIN DD makefile
echo fserv.h 1>&2
sed 's/^-//' >fserv.h <<'//GO.SYSIN DD fserv.h'
#include "sys/param.h"
#include "sys/dir.h"
#include "sys/stat.h"
#define xread read
#define xwrite write
extern int errno;
extern char *malloc();

int dbgfd;	/* for debugging output, shared with children */
int cntlfd;	/* fd for new service requests */
int ackfd;	/* for responding to network */
fd_set active;	/* bit map of active channels for select */
int myfd;	/* sole argument to children */
int silent;	/* debugging level */
#define NORMAN NOFILE
struct {
	int pid;	/* pid of child, if it exists */
	int fd;		/* fd of channel to client (duplicates index) */
	int flags;	/* status */
	int dtime;	/* time difference */
	int dev;	/* client's idea of the root */
	long lastheard;	/* for time outs */
	char *who;	/* client's name, for trapping loops */
	int host;	/* correlates with permissions table */
	int silent;
} children[NORMAN];		/* one-one with fd's */
#define CONN	1
#define SPLIT	2
#define UNINIT	3

#define NDEV 10
extern struct tdev {
	int ours, his;
} devtab[NDEV];
extern int ndev;

typedef struct aa {
	long tag;
	int dev;	/* his dev */
	int ino;
	char *name;	/* some name */
	struct stat statb;	/* cached */
	short fd;	/* the precious handle */
	char how;	/* how opened */
} netf;

extern netf *getnetf(), *gettag(), *newnetf(), *oldnetf();
#define ftype(p) (p->statb.st_mode & S_IFMT)
/* 1 for cmnd outline, 2 for cmnd detail, 4 for permissions */
#define debug1 if(silent & 1) xdebug
#define debug2 if(silent & 2) xdebug
#define debug3 if(silent & 3) xdebug
#define debug4 if(silent & 4) xdebug
#define NDBG 200
int dptr;
char debugbuf[NDBG][128];

/*
 *	From V8.
 *
 *	Set of fds used with the select system call.
 *	The macros depend on NBPW, NBBY, & NOFILE from sys/param.h.
 */
#define FDWORDS		(NOFILE+NBPW*NBBY-1)/(NBPW*NBBY)
/*typedef struct		fd_set { unsigned long fds_bits[FDWORDS]; } fd_set;*/
#define FD_SET(n,s)	(s).fds_bits[(n)/(NBPW*NBBY)] |= 1<<((n)%(NBPW*NBBY))
#define FD_CLR(n,s)	(s).fds_bits[(n)/(NBPW*NBBY)] &= ~(1<<((n)%(NBPW*NBBY)))
#define FD_ISSET(n,s)	((s).fds_bits[(n)/(NBPW*NBBY)] & (1<<((n)%(NBPW*NBBY))))
#define FD_ZERO(s)	{int i; for(i=0;i<FDWORDS;i++)s.fds_bits[i]=0; }
//GO.SYSIN DD fserv.h
echo neta.h 1>&2
sed 's/^-//' >neta.h <<'//GO.SYSIN DD neta.h'
#define NETVERSION	1	/* protocol variant */

#define NSTAT	1
#define NWRT	2
#define NREAD	3
#define NFREE	4
#define NTRUNC	5
#define NUPDAT	6
#define NGET	7
#define NNAMI	8
#define NPUT	9
#define NROOT	10
#define NDEL	11
#define NLINK	12
#define NCREAT	13
#define NOMATCH	14
#define NSTART	15
#define NIOCTL	16

struct senda {	/* not space efficient */
	char version;
	char cmd;
	char flags;	/* now only for nami */
	char rsvd;
	long trannum;
	short uid;
	short gid;
	short dev;	/* server may be using several */
	long tag;
	long mode;
	short newuid;	/* for updat */
	short newgid;
	long ino;
	long count;
	long offset;
	char *buf;
	time_t ta;
	time_t tm;
};

struct rcva {	/* not space efficient either */
	long trannum;
	char errno;
	char flags;	/* NROOT for nami */
	short dev;
	long size;
	short mode;
	short uid;
	short gid;
	long tag;
	short nlink;
	short rsvd;
	long ino;	/* back from nami */
	long count;	/* count or loc for nami to use */
	time_t tm[3];
};

extern long trannum;
//GO.SYSIN DD neta.h
echo tcpstuff.c 1>&2
sed 's/^-//' >tcpstuff.c <<'//GO.SYSIN DD tcpstuff.c'
#include "fserv.h"
#include <sys/ioctl.h>
#include <signal.h>
#include <errno.h>
#include <sys/inet/tcp_user.h>
#include <sys/neta.h>

#if 0
struct mesg {
	short	type;
	short	size;
};

#define	M_DATA	0		/* regular data (not ctl) */
#define	M_DELIM	03		/* data delimiter */
#define	M_YDEL	012		/* stream has started generating delims */
typedef u_short v8ino_t, v8d_ino;
#define	V8DIRSIZ	14

struct	v8direct
{
	v8ino_t	d_ino;
	char	d_name[V8DIRSIZ];
};
#endif

announce()
{	int fd;
	struct in_service *sp, *in_service();

	sp = in_service("fshare", "tcp", 0);
	if (sp == 0) {
		debug("fshare: unknown service\n");
		return;
	}

	fd = tcp_sock();
	if (fd < 0) {
		perror("fshare: socket");
		exit(1);
	}
	if (tcp_listen(fd, sp->port, 0, 0) != 0) {
		perror("fshare: listen");
		exit(1);
	}
	cntlfd = fd;
	FD_SET(fd, active);
	return;
}

newone()
{	int n, i, fd, dev;
	extern int rmesg_ld;
	char	*hp, *in_host();
	in_addr	from;
	tcp_port	fport;

	fd = tcp_accept(cntlfd, &from, &fport, &dev);	/* timeout?  non-block? */
	if (fd < 0)
		return;
	hp = in_host(from);
	if (hp == 0) {
		debug("fshare: %s: no such host\n", in_ntoa(from));
		(void) close(fd);
		return;
	}

	if (!(n = isfriend(hp))) {
		debug("fshare: %s not friend\n", hp);
		(void) close(fd);
		return;
	}
	if (ioctl(fd, FIOPUSHLD, &rmesg_ld) < 0) {
		debug("fshare: cannot push rmesg_ld for %s");
		(void) close(fd);
		return;
	}
	for(i = 0; i < NOFILE; i++)
		if(children[i].who && strcmp(children[i].who, hp) == 0) {
			debug("fshare: %s already attached\n", hp);
			free(children[i].who);
			children[i].who = 0;
			/* some more? */
			kill(children[i].pid, SIGKILL);	/* who did we kill?*/
			break;
		}
	if(children[fd].flags) {
		debug("opened %s twice", hp);
		debug("pid %d fd %d flags %d %s\n", children[fd].pid,
			children[fd].fd, children[fd].flags,
			children[fd].who);
		/* who should we believe?  the new one */
		if(children[fd].pid != 0)
			kill(children[fd].pid, SIGKILL);
		/* did that pid exist, and was it us? */
	}
	children[fd].pid = 0;
	children[fd].fd = fd;
	children[fd].flags = UNINIT;
	children[fd].host = n;
	children[fd].lastheard = time(0);
	children[fd].who = malloc(strlen(hp) + 1);
	strcpy(children[fd].who, hp);
	debug("ok, %s (%d) on fd %d", hp, n, fd);
	FD_SET(fd, active);
}

#if 0
/* yuck -- simulate rmesg ld */
#define RMESG(f, b, l) \
	if ((nread = read((f), (b), (l))) != (l)) { \
		fprintf("xread %d, expected %d\n", nread, (l)); \
		return(-1); \
	}
int
xread(f, b, l)
char *b;
{
	struct mesg mesg;
	static char base[8192], *rptr;
	static int count;
	int rval = 0, nread;

	if (l > 8192) {
		debug("xread %d is too much\n", l);
		return(-1);
	}

	if (count != 0) {	/* screw -- he can have this */
		int n = MIN(count, l);
		strncpy(b, rptr, n);
		count -= n;
		if (count > 0)
			rptr += n;
		else {
			count = 0;
			rptr = base;
		}
		return(n);
	}
	RMESG(f, &mesg, sizeof(mesg));
	while (mesg.type != M_DELIM) {
		if (mesg.type != M_DATA) {	/* ignore it */
			if (mesg.size != 0)
				RMESG(f, b, mesg.size);
			goto nxtmesg;
		}
		if (mesg.size > 8192) {
			fprintf("xread wants %d\n", mesg.size);
			return(-1);
		}

		if (mesg.size <= l) {
			RMESG(f, b, mesg.size);
			rval += mesg.size;
			b += mesg.size;
			l -= mesg.size;
			goto nxtmesg;
		}
		/* mesg.size > l */
		if (l > 0) {
			RMESG(f, b, l);
			rval += l;
			b += l;
			RMESG(f, rptr, mesg.size - l);
			rptr += mesg.size - l;
			count += l;
			l = 0;
		}
nxtmesg:
		/* this should be delim ... */
		RMESG(f, &mesg, sizeof(mesg));
	}
	if (mesg.size != 0) {
		debug("no delim\n");
		return(-1);
	}
	return(rval);
}

/* this sucks -- 4 bytes then data then 4 bytes.  slowness. */
int
xwrite(f, b, l)
char *b;
{
	struct mesg mesg;
	int rval;

	mesg.type = M_DATA;
	mesg.size = l;
	if (write(f, &mesg, sizeof(mesg)) != sizeof(mesg))
		return(-1);
	rval = write(f, b, l);

	mesg.type = M_DELIM;
	mesg.size = 0;
	if (write(f, &mesg, sizeof(mesg)) != sizeof(mesg))
		return(-1);
	return(rval);
}
#endif
//GO.SYSIN DD tcpstuff.c
echo tcpmain.c 1>&2
sed 's/^-//' >tcpmain.c <<'//GO.SYSIN DD tcpmain.c'
/* file service */
#include "fserv.h"
#include "errno.h"
#include "neta.h"
#include <time.h>

int lflag;	/* means /-prefixed symbolic links are interpreted by server */
char me[16];
char cmdbuf[256];
struct rcva y, nilrcv;
struct stat statb, rootstat;
int intrcnt, timecnt, okcnt;
fd_set svrdmask;

main(argc, argv)
char **argv;
{	int n, i;
	fd_set rdmask;

	if(argc > 1 && strcmp(argv[1], "-l") == 0)
		lflag = 1;
	dbgfd = 2;
	close(0);
	close(1);
	whoami();
	umask(0);
	perminit();
	signals();
	(void) stat("/", &rootstat);
	statb = rootstat;
	announce();
loop:
	if(cntlfd < 0) {	/* socket died */
		debug("announcing");
		for(i = 0; i < 32; i++)
			if(i != dbgfd)
				close(i);
		announce();
	}
	reapchild();
	errno = 0;
	rdmask = active;
	debug2("selecting x%x", rdmask);
	n = select(NOFILE, &rdmask, 0, 20000);
	if(n == -1 && errno == EINTR) {
		intrcnt++;
		goto loop;
	}
	else if(n == -1) {
		perror("select");
		goto loop;		/* probably an infinite loop? */
	}
	else if(n == 0) {
		debug2("timeout");
		timecnt++;
		permredo();
		goto timer;		/* nothing's going on? */
	}
	else {
		okcnt++;
		svrdmask = rdmask;
		debug2("got rdmask %lx", rdmask);
	}
	for(i = NOFILE - 1; i >= 0; i--)
		if(FD_ISSET(i, rdmask))
			if(i == cntlfd)
				newone();
			else {
				children[i].lastheard = time(0);
				serve(i, argv[0]);
			}
timer:
	for(i = 0; i < NOFILE; i++)
		if(FD_ISSET(i, active)) {
			if(i == cntlfd)
				continue;
			if(children[i].lastheard + 500 > time(0))
				continue;
			debug("%s 500 seconds", children[i].who);
			/*close(children[i].fd);
			children[i].fd = children[i].flags = 0;
			if(children[i].who)
				free(children[i].who);
			children[i].who = 0;
			FD_CLR(i, active);
			*/
			children[i].lastheard = time(0);
		}
	goto loop;
}

char dbgbuf[128];
/*VARARGS*/
debug(s, a, b, c, d, e, f)
	char *s;
{	/* no buffering, shared fd with children */
	long x;
	extern char *ctime();
	x = time(0);
	sprintf(dbgbuf, s, a, b, c, d, e, f);
	strcat(dbgbuf, " ");
	strcat(dbgbuf, ctime(&x));
	write(dbgfd, dbgbuf, strlen(dbgbuf));
}

whoami()
{	int fd, n;
	dbgfd = 2;	/* until logging starts */
	fd = open("/etc/whoami", 0);
	if(fd < 0) {
foof:
		perror("/etc/whoami");
		exit(1);
	}
	if((n = read(fd, me, sizeof(me))) == -1)
		goto foof;
	if(n >= sizeof(me)) {
		debug("/etc/whoami too long");
		exit(1);
	}
	close(fd);
	if(me[n - 1] == '\n')
		me[n - 1] = 0;
}

extern int sys_nerr;
extern char *sys_errlist[];
perror(s)
char *s;
{	register char *c;
	c = "Unknown error";
	if(0 < errno && errno < sys_nerr)
		c = sys_errlist[errno];
	debug("%s: %s (%d)", s, c, errno);
}


/* we expect one byte of version number followed by a senda with 
 * initialization stuff */
doinit(n)
{	struct senda *x;
	int i;

	i = xread(children[n].fd, cmdbuf, 1);
	x = (struct senda *)cmdbuf;
	debug("doinit read %d on %d for %d", i, children[n].fd, n);
	if(i != 1 || x->version != NETVERSION) {
		debug("read %d chars [0x%x] for child %d on fd %d",
			i, x->version, n, children[n].fd);
		goto awful;
	}
	i = xread(children[n].fd, cmdbuf, sizeof(struct senda));
	debug("doinit read %d on %d for %d", i, children[n].fd, n);
	if(i != sizeof(struct senda) || x->version != NETVERSION) {
		if(x->version != NETVERSION) {
			y.trannum = -1;
			xwrite(children[n].fd, (char *)&y, sizeof(struct rcva));
			debug("got version %d for %s", x->version, NETVERSION);
		}
		else
			debug("doinit, read %d on %d", i, children[n].fd);
awful:
		/* panic, we may get an endless stream */
		respond(0);
		close(children[n].fd);
		FD_CLR(children[n].fd, active);
		return;
	}
	children[n].dtime = x->ta - time(&children[n].lastheard);
	children[n].dev = x->dev;
	children[n].silent = x->uid;
	y.trannum = x->trannum;
	myfd = children[n].fd;
	respond(0);
	children[n].flags = CONN;
	debug("%s dev %d silent %d", children[n].who, children[n].dev / 256,
		children[n].silent);
}

respond(n)
{
	if((y.errno = n) && silent) {
		errno = n;
		perror("respond");
	}
	(void) xwrite(children[myfd].fd, (char *)&y, sizeof(y));
}

debugreset()
{
	dptr = 0;
}

/*VARARGS*/
xdebug(s, a, b, c, d, e, f, g)
	char *s;
{	sprintf(debugbuf[dptr], s, a, b, c, d, e, f, g);
	dptr++;
	if(dptr >= NDBG) {
		debugreset();
		xdebug("buffer wrapped");
	}
}
//GO.SYSIN DD tcpmain.c
echo ps.y 1>&2
sed 's/^-//' >ps.y <<'//GO.SYSIN DD ps.y'
%token MACHINE
%token LP RP NUMBER
%{
#include "stdio.h"
FILE *infd;
%}
%%
file:
	| machine_list ;
machine_list:	machine
	| machine_list machine
	;
machine:	MACHINE perm_list
	;
perm_list:
	| perm
	| perm_list perm
	;
perm:	LP client host RP
	;
client:	uid
		{ doclient($1, -1); }
	| LP uid gid RP
		{ doclient($2, $3); }
	;
host:	uid
		{ dohost($1, -1); }
	| LP uid gid RP
		{ dohost($2, $3); }
	;
uid:	NUMBER ;
gid:	NUMBER ;
%%
int lineno = 1;
yyerror(s)
char *s;
{	char buf[128];
	sprintf(buf, "%s line %d", s, lineno);
	perror(buf);
}

pparse(fd)
FILE *fd;
{
	infd = fd;
	yyparse();
}

yylex()
{	int c;
again:
	c = getc(infd);
	if(c == '\n')
		lineno++;
loop:
	if(c == EOF)
		return(0);
	if(c == '#') {
		do {
			c = getc(infd);
		} while(c != '\n' && c != EOF);
		if(c == '\n')
			lineno++;
		goto loop;
	}
	if(c == ' ' || c == ',' || c == '\n' || c == '\t')
		goto again;
	if(c == '(')
		return(LP);
	if(c == ')')
		return(RP);
	if(c == '+' || c == '-' || c >= '0' && c <= '9') {
		donumber(c);
		return(NUMBER);
	}
	if(c >= 'a' && c <= 'z' || c == '/') {
		domachine(c);
		lineno++;
		return(MACHINE);
	}
	debug("bad char in people (%c) 0%o ignored\n", c, c);
	goto again;
}

donumber(c)
int c;
{
	int n, sign;

	n = 0;
	sign = 1;
	if(c == '-')
		sign = -1;
	else if(c != '+')
		n = c - '0';
	for(c = getc(infd); c >= '0' && c <= '9'; c = getc(infd))
		n = 10 * n + c - '0';
	ungetc(c, infd);
	yylval = sign * n;
}

static char nmbuf[128];
domachine(c)
{	char *p = nmbuf;
	*p++ = c;
	for(c = getc(infd); (c >= 'a' && c <= 'z' || c == '/') && p < nmbuf + 127; c=getc(infd))
		*p++ = c;
	*p = 0;
	newhost(nmbuf);
}
//GO.SYSIN DD ps.y
echo perm.c 1>&2
sed 's/^-//' >perm.c <<'//GO.SYSIN DD perm.c'
#include "stdio.h"
#include "fserv.h"
#include "neta.h"
extern int host;
/* keep all the perm space here, to redo on file change */

typedef struct {
	unsigned short cuid;
	short cgid;
	unsigned short huid;
	short hgid;
} pe;
typedef struct {
	char *name;	/* eg mh/astro/seki */
	short ix;	/* its index > 0 */
	short cnt;	/* number of entries */
	pe *tab;	/* the entries */
	pe *inv;	/* host->client index */
} ps;
ps *prm;
int nprm, prmlen;
short *ptemp;
int ptnum, ptlen;
long lastlooked;

perminit()
{	FILE *fd;
	int i;
	fd = fopen("/usr/net/people", "r");
	if(fd == NULL) {
		fd = fopen("/etc/net/people", "r");
		if(fd == NULL) {
			perror("people");
			exit(1);
		}
	}
	for(i = 0; i < nprm; i++) {
		if(prm[i].name)
			free(prm[i].name);
		if(prm[i].tab)
			free((char *)prm[i].tab);
		if(prm[i].inv)
			free((char *)prm[i].inv);
	}
	nprm = 0;
	ptnum = 0;
	pparse(fd);
	newhost(0);
	fclose(fd);
	lastlooked = time(0);
	for(i = 0; i < nprm; i++)
		psort(prm + i);
}

permredo()
{	struct stat stb;
	int i;
	if(stat("/usr/net/people", &stb) == -1 || stb.st_mtime <= lastlooked)
		return;
	for(i = 0; i < nprm; i++) {
		free(prm[i].name);
		free(prm[i].tab);
		free(prm[i].inv);
	}
	nprm = 0;
	ptnum = 0;
	perminit();
}

newhost(s)
char *s;
{	ps *p;
	short *x;
	int i;
	if(nprm > 0) {	/* clean up after last one */
		p = prm + nprm - 1;
		p->tab = (pe *)malloc(ptnum * sizeof(short));
		x = (short *)p->tab;
		for(i = 0; i < ptnum; i++)
			*x++ = ptemp[i];
		p->cnt = ptnum / 4;	/* 4 = #shorts / pe */
		p->inv = (pe *)malloc(ptnum * sizeof(short));
		ptnum = 0;
	}
	if(s == 0)
		return;
	if(nprm >= prmlen) {
		if(nprm == 0) {
			prm = (ps *)malloc(5 * sizeof(ps));
			prmlen = 5;
		}
		else {
			prmlen *= 2;
			prm = (ps *)realloc((char *)prm, prmlen * sizeof(ps));
		}
	}
	p = prm + nprm++;
	p->name = malloc(strlen(s) + 1);
	strcpy(p->name, s);
	p->ix = nprm;
}

doclient(uid, gid)
{
	if(ptnum + 1 >= ptlen) {
		if(ptnum == 0) {
			ptemp = (short *)malloc(20 * sizeof(short));
			ptlen = 20;
		}
		else {
			ptlen *= 2;
			ptemp = (short *)realloc((char *)ptemp, ptlen * sizeof(short));
		}
	}
	ptemp[ptnum++] = uid;
	ptemp[ptnum++] = gid;
}

dohost(uid, gid)
{
	doclient(uid, gid);
}

ccmp(a, b)
pe *a, *b;
{
	if(a->cuid != b->cuid)
		return(a->cuid - b->cuid);
	else
		return(a->cgid - b->cgid);
}

hcmp(a, b)
pe *a, *b;
{
	if(a->huid != b->huid)
		return(a->huid - b->huid);
	else
		return(a->hgid - b->hgid);
}
psort(p)
ps *p;
{	int i;
	pe *x, *y;
	qsort((char *)p->tab, p->cnt, sizeof(pe), ccmp);
	for(i = 0; i < p->cnt; i++)
		p->inv[i] = p->tab[i];
	qsort((char *)p->inv, p->cnt, sizeof(pe), hcmp);
}

isfriend(s)
char *s;
{	int i;
	for(i = 0; i < nprm; i++)
		if(strcmp(prm[i].name, s) == 0)
			return(prm[i].ix);
	return(0);
}

pe *
hsearch(h, u, g)
{	pe *x;
	int lo, hi, j;
	h--;		/* change from ix to loc in array */
	debug4("hsearch(%s,%d,%d)", prm[h].name, u, g);
	lo = 0;
	hi = prm[h].cnt;
	x = prm[h].inv + (j = (lo + hi)/2);
	while(j > lo) {
		if(x->huid > u)
			hi = j;
		else
			lo = j;
		j = (lo + hi) / 2;
		x = prm[h].inv + j;
	}
	if(x->huid != u)
		return(0);
	for(; x >= prm[h].inv && x->huid == u; x--)
		if(x->hgid == g)
			return(x);
	if(x->huid != u)
		x++;
	return(x);
}
			

hostuid(s)
struct stat *s;
{	pe *x;
	x = hsearch(host, s->st_uid, s->st_gid);
	if(x)
		return(x->cuid);
	else
		return(-1);
}

hostgid(s)
struct stat *s;
{	pe *x;
	x = hsearch(host, s->st_uid, s->st_gid);
	if(x)
		return(x->cgid);
	else
		return(-1);
}

pe *
csearch(h, u, g)
{	pe *x;
	int lo, hi, j;
	h--;		/* change from ix to loc in array */
	debug4("csearch(%s,%d,%d)", prm[h].name, u, g);
	lo = 0;
	hi = prm[h].cnt;
	x = prm[h].tab + (j = (lo + hi)/2);
	while(j > lo) {
		if(x->cuid > u)
			hi = j;
		else
			lo = j;
		j = (lo + hi) / 2;
		x = prm[h].tab + j;
	}
	if(x->cuid != u)
		return(0);
	for(; x >= prm[h].tab && x->cuid == u; x--)
		if(x->cgid == g)
			return(x);
	if(x->cuid != u)
		x++;
	return(x);
}

myuid(u, g)
{	pe *x;
	x = csearch(host, u, g);
	if(x == 0)
		return(-1);
	else
		return(x->huid);
}

mygid(u, g)
{	pe *x;
	x = csearch(host, u, g);
	if(x == 0)
		return(-1);
	else
		return(x->hgid);
}

isowner(x, sbuf)
struct senda *x;
struct stat *sbuf;
{
	/* local file is owned by user */
	if((sbuf->st_mode & S_IFMT) == S_IFCHR || (sbuf->st_mode & S_IFMT) == S_IFBLK)
		return(0);
	if(sbuf->st_uid != -1 && myuid(x->uid, x->gid) == sbuf->st_uid)
		return(1);
	if(x->uid == 0)		/* cheat, not the whole story */
		return(1);
	return(0);
}
noaccess(x, sbuf, how)
struct senda *x;
struct stat *sbuf;
{	int n;
	n = myuid(x->uid, x->gid);
	if(n == -1 && x->uid == 0) {
		if(how == S_IEXEC)
			goto other;
		if(x->flags == NCREAT && (sbuf->st_mode & S_IFMT) == S_IFDIR)
			return(0);
		if(x->flags == NDEL && (sbuf->st_mode & S_IFMT) == S_IFDIR)
			return(0);
		if(x->flags == NLINK)
			return(0);
	}		
	if(n == -1)
		return(1);
	if((n == sbuf->st_uid) && (sbuf->st_mode & how))
		return(0);
	if((mygid(x->uid, x->gid) == sbuf->st_gid) && (sbuf->st_mode & (how >> 3)))
		return(0);
other:
	if(sbuf->st_mode & (how >> 6))
		return(0);
	return(1);
}
//GO.SYSIN DD perm.c
echo start.c 1>&2
sed 's/^-//' >start.c <<'//GO.SYSIN DD start.c'
#include "fserv.h"
#include "neta.h"

char cmdbuf[256];
int alive, rdcnt, wrcnt, dtime;
int rdnum;
extern struct rcva y, nilrcv;
int host;

work()
{	int n;
	struct senda *x;
	dtime = children[myfd].dtime;
	host = children[myfd].host;
	silent = children[myfd].silent;
	debugreset();
	do {
		/* would select be better? */
		n = xread(myfd, cmdbuf, sizeof(struct senda));
		if(n < 0) {
			debug("read -1 on %d for %s", myfd, children[myfd].who);
			leave(2);
		}
		if(n != sizeof(struct senda)) {
			debug("read %d wanted %d for %s", n, sizeof(struct senda),
				children[myfd].who);
			leave(3);
		}
		rdnum++;
		if(rdnum % 20 == 4)
			permredo();	/* every 10 minutes when idle */
		x = (struct senda *)cmdbuf;
		errno = 0;
		y = nilrcv;
		prcmd(x);
		switch(x->cmd) {
		default:
			debug("unk cmnd %d for %s", n, children[myfd].who);
			leave(4);
		case NSTAT:
			dostat(x);
			break;
		case NWRT:
			dowrite(x);
			break;
		case NREAD:
			doread(x);
			break;
		case NFREE:
			dofree(x);
			break;
		case NTRUNC:
			dotrunc(x);
			break;
		case NUPDAT:
			doupdat(x);
			break;
		case NGET:
			doget(x);
			break;
		case NNAMI:
			donami(x);
			break;
		case NPUT:
			doput(x);
			break;
		}
	} while(alive > 0);
	leave(0);
}

leave(n)
{	int i;
	debug("leaving(%d)", n);
	for(i = 0; i < dptr; i++) {
		strcat(debugbuf[i], "\n");
		write(dbgfd, debugbuf[i], strlen(debugbuf[i]));
	}
	exit(n);
}

extern netf netftab[];
extern int nnetf;
dumpstate()
{	struct senda *x = (struct senda *)cmdbuf;
	netf *p;
	int i;
	debug("\tmesg: ver %d flags %d trannum %d\n\tuid %d gid %d dev 0x%x tag %d mode 0%o",
	x->version, x->flags, x->trannum, x->uid, x->gid, x->dev, x->tag, x->mode);
	debug("\t\tino %d count %d offset %d", x->ino, x->count, x->offset);
	prcmd(x);
	debug("\t%s: fl %d dtime %d dev 0x%x host %d",
		children[myfd].who, children[myfd].flags, children[myfd].dtime,
		children[myfd].dev, children[myfd].host);
	for(i = 0; i < ndev; i++)
		debug("\tdev: ours 0x%x his 0x%x", devtab[i].ours,
			devtab[i].his);
	for(p = netftab, i = 0; i < nnetf; i++, p++) {
		debug("\tnetf %d dev 0x%x ino %d how %d fd %d %s",
			p->tag, p->dev, p->ino, p->how, p->fd,
			p->name? p->name: "(null)");
		debug("\tstat dev 0x%x ino %d mode 0%o nlink %d size %d",
			p->statb.st_dev, p->statb.st_ino, p->statb.st_mode,
			p->statb.st_nlink, p->statb.st_size);
		debug("\t\tuid %d gid %d ctime %s\t\t", p->statb.st_uid,
			p->statb.st_gid, ctime(&p->statb.st_ctime));
	}
}
//GO.SYSIN DD start.c
echo sub.c 1>&2
sed 's/^-//' >sub.c <<'//GO.SYSIN DD sub.c'
#include "fserv.h"
#include "errno.h"
#include "neta.h"

extern char *realloc();
/* temporary static alloc of devtab */

struct tdev devtab[NDEV];
struct stat rootstat;
int ndev, dev;
extern int alive;
char *cmdnames[] = {"0?", "stat", "wrt", "read", "free", "trunc", "updat",
	"get", "nami", "put", "10?"};
char *buf, *nbuf;
int buflen, nbuflen;

#define NF	100
/* temporary static alloc of netftab */
netf netftab[NF];
int nnetf;

#define MASK	0x0

ourdev(n)
{	int i;
	for(i = 0; i < ndev; i++)
		if(devtab[i].his == n)
			return(devtab[i].ours);
	return(-1);
}

hisdev(n)
{	int i;
	for(i = 0; i < ndev; i++)
		if(devtab[i].ours == n)
			return(devtab[i].his);
	return(-1);
}

newdev(n)
{	struct tdev *p;
	p = devtab + ndev++;
	p->ours = n;
	p->his = dev++;
	debug1("\tnewdev %d %d", p->ours, p->his);
}

netf *
gettag(n)
long n;
{	int i;
	for(i = 0; i < nnetf; i++)
		if(netftab[i].tag == n)
			return(netftab + i);
	errno = ENOENT;
	return(0);
}

netf *
getnetf(d, i)	/* either root of netfs, or in the table */
{	int j;
	netf *p;
	if(i == 0) {
		errno = ENOENT;
		return(0);
	}
	for(j = 0; j < nnetf; j++)
		if(netftab[j].ino == i && netftab[j].dev == d)
			return(netftab + j);
	debug2("\tgetnetf(%d,%d)", d, i);
	for(p = netftab, j = 0; j < nnetf; j++, p++) {
		debug2("\t%d %d %d %s", p->tag, p->dev, p->ino, p->name?p->name:"");
	}
	return(0);
}
netf *
oldnetf(s)	/* special case for nami/NDEL */
char *s;
{	netf *p;
	struct stat stb;
	if(xstat(s, &stb) < 0)
		return(0);
	if(p = getnetf(hisdev(stb.st_dev), stb.st_ino)) {
		p->statb = stb;
		return(p);
	}
	return(0);
}

netf *
newnetf(s, fd, how)
char *s;
{	int i;
	netf *p;
	struct stat stb;
	if(xstat(s, &stb) < 0)
		return(0);
	if(p = getnetf(hisdev(stb.st_dev), stb.st_ino)) {
		p->statb = stb;
		return(p);
	}
	for(i = 0; i < nnetf; i++)
		if(netftab[i].ino == 0)
			goto found;
	i = nnetf++;
	if(nnetf > NF) {
		errno = ENOMEM;
		return(0);
	}
found:
	alive++;
	p = netftab + i;
	p->name = malloc(strlen(s) + 1);
	strcpy(p->name, s);
	p->statb = stb;
	if(fd < 0) {
		if(ftype(p) != S_IFLNK && ftype(p) != S_IFCHR && ftype(p) != S_IFBLK)
			p->fd = open(p->name, 0);	/* this better work */
		else
			p->fd = -1;
		p->how = 0;
	}
	else {
		p->fd = fd;
		p->how = how;
	}
	p->dev = hisdev(p->statb.st_dev);
	if(p->dev == -1) {
		newdev(p->statb.st_dev);
		p->dev = hisdev(p->statb.st_dev);
	}
	p->ino = p->statb.st_ino;
	p->tag = (p->dev << 16) ^ p->ino ^ MASK;
	debug2("\tnew %d %d %s", p->dev, p->ino, p->name);
	debug2("\tnew 0%o %d %d", p->statb.st_mode, p->statb.st_uid, p->statb.st_gid);
	debug2("\tnew %d", nnetf);
	return(p);
}

clrnetf(n)
{	netf *p;
	p = gettag(n);
	if(p == 0) {
		debug("\tclr net got 0 (x%x)", n);
		dumpstate();
		leave(8);	/* shut it down */
		return;
	}
	if(p->ino == 2 && p->dev == devtab[0].his)
		return;		/* hold on to the root */
	if(p->tag != n) {
		debug("\tclr weird %d %d", n, p->tag);
		errno = EIO;
		dumpstate();
		return;
	}
	debug1("\tclear %d %s", p->tag, p->name);
	if(p->fd != -1) {
		close(p->fd);
		p->fd = -1;
		p->how = 0;
	}
	p->tag = p->dev = p->ino = 0;
	if(p->name)
		free(p->name);
	p->name = 0;
	alive--;
}

opennf(p, fl)	/* fl: 0-read, 1-write, 2-trunc */
netf *p;
{	int i;
	if(p->fd != -1 && p->how == fl)
		return(0);
	if(fl == 2) {
		errno = EPERM;
		return(1);
	}
	i = open(p->name, fl);
	if(p->fd != -1)
		close(p->fd);
	p->fd = i;
	debug1("\topennf %s %d", p->name, p->fd);
	if(p->fd == -1)
		return(1);
	p->how = fl;
	return(0);
}

truncnf(n)
long n;
{	netf *p;
	int fd;
	p = gettag(n);
	if(p == 0) {
		debug("\ttrunc %d", n);
		errno = EIO;
		dumpstate();
		return;
	}
	if(p->fd != -1)
		close(p->fd);
	fd = creat(p->name, 0);
	p->fd = fd;
	p->how = 1;
}

isroot(p)
netf *p;
{
	debug2("\tisroot(dev=%d ino=%d), ourde=%d", p->dev, p->ino, ourdev(p->dev));
	return(p->ino == rootstat.st_ino && ourdev(p->dev) == rootstat.st_dev);
}

prcmd(x)
struct senda *x;
{
	debug1("got %s %d %d %d", cmdnames[x->cmd], major(x->dev), minor(x->dev), x->ino);
}

getbuf(n)
{
	if(n < buflen)
		return;
	if(buflen == 0)
		buf = malloc(buflen = n);
	else
		buf = realloc(buf, buflen = n);
	if(buf)
		return;
	debug("getbuf failed");
	leave(6);
}

getnbuf(n)
long n;
{
	if(n < nbuflen)
		return;
	if(nbuflen == 0)
		nbuf = malloc(nbuflen = n);
	else
		nbuf = realloc(nbuf, nbuflen = n);
	if(nbuf)
		return;
	debug("nbuf failed");
	leave(7);
}
/* the current name is a full path name, buf contains another component */
fixnbuf(name, count, buf, flag)
char *name, *buf;
{	int i, n;
	for(i = 0; i < count && buf[i]; i++)
		;
	count = i;
	n = strlen(name);
	getnbuf(n + count + 2);
	strcpy(nbuf, name);
	if(count > 2 || flag == NLINK || flag == NDEL) {
ok:
		nbuf[n++] = '/';
		for(i = 0; i < count; i++)
			nbuf[n++] = *buf++;
		nbuf[n] = 0;
		return;
	}
	if(count == 0)
		return;
	if(count == 1)
		if(buf[0] == '.')
			return;	/* do we know that name is a directory? */
		else
			goto ok;
	if(buf[0] != '.' || buf[1] != '.')
		goto ok;
	while(n > 0 && nbuf[n] != '/')
		n--;
	nbuf[n] = 0;
	if(nbuf[0] != '/')
		strcpy(nbuf, "/..");
}
//GO.SYSIN DD sub.c
echo sys.c 1>&2
sed 's/^-//' >sys.c <<'//GO.SYSIN DD sys.c'
#include "stdio.h"
#include "fserv.h"
#include "signal.h"
#include "wait.h"
#include "errno.h"

extern int dev;
extern struct stat statb;
extern char *ctime();
extern char *buf, *nbuf;

dummy()
{
	signal(SIGCHLD, dummy);
}

hup()
{
	signal(SIGHUP, hup);
	fprintf(stderr, "hup %d\n", getpid());
}

signals()
{	extern int profit();
	hup();
	signal(SIGINT, SIG_IGN);
	signal(SIGCHLD, dummy);
	signal(SIGTERM, profit);
	signal(SIGPIPE, SIG_IGN);
	setpgrp(0, getpid());
}

reapchild()
{	int pid, i;
	int status;
	pid = wait3(&status, WNOHANG, 0);
	if(pid <= 0)
		return;
	for(i = 0; i < NORMAN; i++)
		if(children[i].pid == pid) {
			children[i].pid = 0;
			if(status) {	/* bye bye */
				debug("child fd %d status 0x%x", i, status);
				close(children[i].fd);
				children[i].fd = 0;
				children[i].flags = 0;
				if(children[i].who)
					free(children[i].who);
				children[i].who = 0;
				return;
			}
			children[i].flags = CONN;
			children[i].lastheard = time(0);
			FD_SET(i, active);
			debug("wait got %d %s", pid, children[i].who);
			return;
		}
	debug("wait got pid %d, not found", pid);
}

serve(n, argp)	/* ok child[n] */
char *argp;	/* for ps */
{	int i;
	long now;
	if(children[n].flags == UNINIT) {
		doinit(n);
		return;
	}
	myfd = n;
	children[n].pid = fork();
	if(children[n].pid == -1) {	/*can't fork, what a pain*/
		perror(children[n].who);
		debug("couldn't fork, bye");
		return;	/* not enough */
	}
	if(children[n].pid == 0) {
		for(i = 0; i < NOFILE-1; i++)
			if(i != myfd && i != dbgfd)
				close(i);
		debug("child %d started for %s", getpid(), children[n].who);
		dev = children[n].dev;
		newdev(statb.st_dev);
		(void) newnetf("/", -1, 0);
		for(i = 0; argp[i]; i++)
			argp[i] = children[n].who[i];
		work();
	}
	FD_CLR(n, active);
	/* should close n, but how would we know who to kill? */
}

xstat(s, b)
char *s;
struct stat *b;
{	int i;
	i = lstat(s, b);
	if(i < 0)
		return(i);
	if((b->st_mode & S_IFMT) == S_IFCHR || (b->st_mode & S_IFMT) == S_IFBLK)
		b->st_mode &= ~0777;
	if(isremote(b->st_dev)) {
		errno = ELOOP;
		return(-1);
	}
	return(i);
}

isremote(n)	/* temporary, maybe should read /etc/net/friends, or ask sys */
{
	/*if(((n>>8) & 0xff) >= 48)
		return(1);*/	/* let's see what happens with it off */
	return(0);
}

lcllink(q)
netf *q;
{
	getbuf(q->statb.st_size + 1);
	readlink(q->name, buf, q->statb.st_size);
	if(buf[0] != '/')
		return(0);
	buf[q->statb.st_size] = 0;
	getnbuf(q->statb.st_size + 1);
	clrnetf(q->tag);
	strcpy(nbuf, buf);
	return(1);
}
//GO.SYSIN DD sys.c
echo work.c 1>&2
sed 's/^-//' >work.c <<'//GO.SYSIN DD work.c'
#include "fserv.h"
#include "errno.h"
#include "neta.h"
extern char *buf, *nbuf;
extern int dtime, myfd, wrcnt, rdcnt, lflag;
extern struct rcva y, nilrcv;

doput(x)
struct senda *x;
{
	y.trannum = x->trannum;
	if(x->tag == 0) {
		debug("\tput got 0");
		respond(EIO);
		dumpstate();
		leave(9);
	}
	clrnetf(x->tag);
	respond(errno);
}

doget(x)
struct senda *x;
{	netf *p;
	y.trannum = x->trannum;
	p = getnetf(x->dev, x->ino);
	if(p == 0) {
		debug("\tget didn't %d %d", x->dev, x->ino);
		respond(errno);
		dumpstate();
		return;
	}
	if(p->fd == -1 && xstat(p->name, &p->statb) < 0
		|| p->fd != -1 && fstat(p->fd, &p->statb) < 0) {
		respond(errno);
		return;
	}
	debug2("\tget %d %d 0%o %d %d %s\n", p->dev, p->ino,
		p->statb.st_mode, p->statb.st_uid, p->statb.st_gid, p->name);
	y.mode = p->statb.st_mode;
	y.tag = p->tag;
	y.nlink = p->statb.st_nlink;
	y.uid = hostuid(&p->statb);
	y.gid = hostgid(&p->statb);
	y.size = p->statb.st_size;
	respond(0);
}

dofree(x)		/* means rmt thinks nlink == 0 */
struct senda *x;
{
	y.trannum = x->trannum;
	respond(0);
}

doupdat(x)
struct senda *x;
{	netf *p;
	int i;
	y.trannum = x->trannum;
	p = gettag(x->tag);
	if(p == 0) {
		respond(errno);
		return;
	}
	debug2("\tupdat 0%o %d %d\n", p->statb.st_mode, p->statb.st_uid, p->statb.st_gid);
	debug2("\t\t0%o %d %d\n", x->mode, x->uid, x->gid);
	x->ta += dtime;
	x->tm += dtime;
	if(p->name == 0) {	/* of course this can't happen */
		debug("\tname 0 tag %d\n", p->tag);
		respond(EIO);
		dumpstate();
		return;
	}
	debug2("\t%s\n", p->name);
	if(x->ta == dtime)
		x->ta = p->statb.st_atime;
	if(x->tm == dtime)
		x->tm = p->statb.st_mtime;
	utime(p->name, &x->ta);
	errno = 0;	/* p->name may be wrong, so times off [bug] */
	if(x->mode != p->statb.st_mode) {
		i = 1;
		if(isowner(x, &p->statb))
			fchmod(p->fd, x->mode);
		else
			errno = EPERM;
		perror("\tfchmod");
	}
	if(x->uid == 0 && (hostuid(&p->statb) != x->newuid
		|| hostgid(&p->statb) != x->newgid)) {
		i = 1;
		if(isowner(x, &p->statb))
			fchown(p->fd, myuid(x->newuid, x->newgid),
				mygid(x->newuid, x->newgid));
		else
			errno = EPERM;
		if(errno)
			perror("\tfchown");
		debug1("\tupdat %d %d\n", p->statb.st_uid, p->statb.st_gid);
	}
	if(i)
		fstat(p->fd, &p->statb);
	y.mode = p->statb.st_mode;
	y.nlink = p->statb.st_nlink;
	y.uid = hostuid(&p->statb);
	y.gid = hostgid(&p->statb);
	y.size =  p->statb.st_size;
	if(hisdev(p->statb.st_dev) != p->dev || p->ino != p->statb.st_ino) {
		debug("\tdev oops\n");
		dumpstate();
	}
	respond(errno);
}

doread(x)
struct senda *x;
{	netf *p;
	int n, offset = 0;
	y.trannum = x->trannum;
	p = gettag(x->tag);
	if(p == 0) {
		if(errno == 0)
			errno = EIO;
		respond(errno);
		return;
	}
	if(ftype(p) == S_IFLNK) {
		n = readlink(p->name, buf, x->count);
		offset = x->offset;
		debug2("readlink %s %d %d\n", p->name, n, x->count);
		offset = x->offset;
		if(n < offset)
			offset = n;
	}
	else {
		if(opennf(p, 0)) {
			respond(errno);
			return;
		}
		if(lseek(p->fd, x->offset, 0) < 0)
			perror("\tread lseek");
		getbuf(x->count);
		n = read(p->fd, buf, x->count);
	}
	debug1("\tread got %d wanted %d\n", n, x->count);
	if(n < 0) {
		y.errno = errno;
		y.count = n;
		respond(0);
		return;
	}
	y.count = n - offset;
	respond(0);
	(void) xwrite(myfd, buf + offset, (unsigned) n - offset);
	wrcnt += n;
}

dowrite(x)
struct senda *x;
{	netf *p;
	int n;
	y.trannum = x->trannum;
	if(x->count == 0)
		respond(0);
	getbuf(x->count);
	if((n = xread(myfd, buf, x->count)) != x->count) {
		debug("\twrite expected %d got %d\n", x->count, n);
		rdcnt += n;
		if(errno == 0)
			errno = EIO;
		respond(errno);
		dumpstate();
		return;
	}
	wrcnt += n;
	debug1("\twrite %d\n", x->count);
	p = gettag(x->tag);
	if(p == 0) {
		respond(errno);
		return;
	}
	if(opennf(p, 1)) {
		respond(errno);
		return;
	}
	n = lseek(p->fd, x->offset, 0);
	if(n < 0) {
		debug("\twrite lseek %d\n", errno);
		dumpstate();
	}
	if((n = write(p->fd, buf, x->count)) != x->count) {
		debug("\twrite failed %d %d\n", n, p->fd);
		if(errno == 0)
			errno = EIO;
		dumpstate();
	}
	respond(errno);
}

dotrunc(x)
struct senda *x;
{
	y.trannum = x->trannum;
	truncnf(x->tag);
	respond(errno);
}

dostat(x)
struct senda *x;
{	netf *p;
	y.trannum = x->trannum;
	debug2("\tstat %d\n", x->tag);
	p = gettag(x->tag);
	if(p == 0) {
		respond(errno);
		return;
	}
	debug2("\tlstat %s ", p->name);
	if(p->fd == -1 && xstat(p->name, &p->statb) < 0
		|| p->fd != -1 && fstat(p->fd, &p->statb) < 0) {
		respond(errno);
		return;
	}
	debug2("0%o %d %d\n", p->statb.st_mode, p->statb.st_uid, p->statb.st_gid);
	y.mode = p->statb.st_mode;
	y.nlink = p->statb.st_nlink;
	y.uid = hostuid(&p->statb);
	y.gid = hostgid(&p->statb);
	debug2("\thostuid(%d) = %d\n", p->statb.st_uid, y.uid);
	debug2("\tgid %d\n", y.gid);
	y.size = p->statb.st_size;
	y.tm[0] = p->statb.st_atime;
	y.tm[1] = p->statb.st_mtime;
	y.tm[2] = p->statb.st_ctime;
	if(hisdev(p->statb.st_dev) != p->dev || p->ino != p->statb.st_ino) {
		debug("\toops dev or ino\n");
		dumpstate();
	}
	respond(0);
}

donami(x)
struct senda *x;
{	netf *p, *q;
	int fd, i, nlink = 0;
	y.trannum = x->trannum;
	getbuf(x->count);
	if((i = xread(myfd, buf, x->count)) != x->count) {
		rdcnt += i;
		if(errno == 0)
			errno = EIO;
		respond(errno);
		return;
	}
	rdcnt += i;
	p = gettag(x->tag);
	if(p == 0) {
		respond(errno);
		return;
	}
	debug1("\tcdir %s 0%o %d %d\n", p->name, p->statb.st_mode,
		p->statb.st_uid, p->statb.st_gid);
	if(ftype(p) != S_IFDIR) {
		respond(ENOTDIR);
		return;
	}
	if(noaccess(x, &p->statb, S_IEXEC)) {
		respond(EACCES);
		return;
	}
	fixnbuf(p->name, x->count, buf, x->flags);
	debug2("\tnami %s (%d)\n", nbuf, x->flags);
again:
	q = 0;
	if(x->flags == NDEL)
		q = oldnetf(nbuf);
	if(q == 0)
		q = newnetf(nbuf, -1, 0);
	if(q != 0) {
		debug2("\tfound\n");
		errno = 0;
		if(/*lflag && */ftype(q) == S_IFLNK)
			if(lcllink(q)) {
				if(nlink++ > 4) {
					errno = ELOOP;
					goto bad;
				}
				goto again;
			}
		y.ino = q->ino;
		y.tag = q->tag;
		y.dev = q->dev;
		y.mode = q->statb.st_mode;
		y.nlink = q->statb.st_nlink;
		y.uid = hostuid(&q->statb);
		y.gid = hostgid(&q->statb);
		y.size = q->statb.st_size;
		if(isroot(q) && strncmp(buf, ".", x->count)) {
			debug2("NROOT %s\n", buf);
			y.flags = NROOT;
		}
		if(x->flags == NDEL) {
			if(noaccess(x, &p->statb, S_IWRITE)) {
				debug1("\tnodelete\n");
				respond(EPERM);
				return;
			}
			if(y.dev != x->dev)
				errno = EBUSY;
			if(y.flags == NROOT)
				errno = EPERM;
			(void) unlink(nbuf);
			debug1("\tunlink %s %d\n", nbuf, errno);
		}
		if(x->flags == NCREAT && noaccess(x, &q->statb, S_IWRITE)) {
			debug1("\tnocreat\n");
			respond(EPERM);
			return;
		}
		respond(errno);
		return;
	}
	else {
		y.flags = NOMATCH;
		if(x->flags == NLINK) {
			if(noaccess(x, &p->statb, S_IWRITE)) {
				debug1("\tnolink %d %d %d\n", x->uid,
					p->statb.st_uid, p->statb.st_gid);
				respond(EPERM);
				return;
			}
			q = gettag(x->tag);
			p = getnetf(x->dev, x->ino);
			if(q == 0 || p == 0) {
				debug1("\tno link p 0x%x q 0x%x", p, q);
				respond(EXDEV);
				return;
			}
			debug1("\tlink %d %d %d %s %s",
				x->dev, x->ino, q->dev, p->name, nbuf);
			if(q->dev != p->dev)
				errno = EXDEV;
			i = link(p->name, nbuf);
			if(i != -1)
				errno = 0;
			else
				debug("\tlink %d", errno);
		}
		else if(x->flags == NCREAT) {
			debug1("\tnami creat 0%o %s\n", x->mode, nbuf);
			if(noaccess(x, &p->statb, S_IWRITE)) {
				debug1("\tnoaccess\n");
				respond(EACCES);
				return;
			}
			switch(x->mode & S_IFMT) {
			case 0:
			case S_IFREG:
				fd = creat(nbuf, x->mode);
				if(fd != -1) {
					q = newnetf(nbuf, fd, 1);
					y.ino = q->ino;
					y.dev = q->dev;
					errno = 0;
					chown(nbuf, myuid(x->uid, x->gid),
						mygid(x->uid, x->gid));
					debug1("\tchown %d %d\n",
						myuid(x->uid, x->gid),
						mygid(x->uid, x->gid));
					(void) fstat(fd, &q->statb);
				}
				break;
			case S_IFDIR:
				if(x->uid != 0) {
					debug1("\tsuser %d\n", x->uid);
					respond(EPERM);
					return;
				}
				i = mknod(nbuf, x->mode, 0);
				if(i != -1) {
					q = newnetf(nbuf, -1, 0);
					y.ino = q->ino;
					y.dev = q->dev;
					errno = 0;
					chown(nbuf, myuid(x->uid, x->gid),
						mygid(x->uid, x->gid));
					(void) fstat(q->fd, &q->statb);
					debug1("\tmknod 0%o %d %d\n",
						q->statb.st_mode, q->statb.st_uid, q->statb.st_gid);
				}
				else
					debug1("\tmknod\n");
				break;
			case S_IFLNK:
				errno = 0;
				fd = creat(nbuf, 0777);
				if(fd < 0)
					break;
				chown(nbuf, myuid(x->uid, x->gid),
					mygid(x->uid, x->gid));
				i = fchmod(fd, x->mode | S_IFLNK);
				debug1("\tfchmod(%s) %d errno %d\n", nbuf, i, errno);
				if(errno == 0) {
					debug2("\tfd = %d\n", fd);
					q = newnetf(nbuf, fd, 1);
					y.ino = q->ino;
					y.dev = q->dev;
				}
				break;
			default:
				errno = EPERM;
				break;
			}
		}
	}
bad:
	y.tag = q->tag;
	y.nlink = q->statb.st_nlink;
	y.size = q->statb.st_size;
	y.uid = hostuid(&q->statb);
	y.gid = hostuid(&q->statb);
	respond(errno);
}
//GO.SYSIN DD work.c
echo profit.c 1>&2
sed 's/^-//' >profit.c <<'//GO.SYSIN DD profit.c'
#include "stdio.h"
#include "signal.h"
struct rec {
	long len;
	struct rec *next;
	char *fname;
	long cnt[1];
} *proFptr = (struct rec *)-1;	/* end of list marker */
profit()
{	int i;
	FILE *fd;
	struct rec *x = proFptr;
	fd = fopen("/etc/net/prof.out", "w");
	if(fd == NULL)
		fd = fopen("/usr/net/prof.out", "w");
	while(x != (struct rec *)-1) {
		fprintf(fd, "%s\n", x->fname);
		for(i = 3; i < x->len; i++)
			fprintf(fd, "%d\n", x->cnt[i-3]);
		x = x->next;
	}
	fflush(fd);
	fclose(fd);
	signal(SIGTERM, profit);
}
//GO.SYSIN DD profit.c
exit


From princeton!down!honey  Sat Oct 19 08:34:37 1985
>From down!honey  Sat Oct 19 08:34:37 1985 remote from princeton
Date: 19 Oct 1985 08:32-EDT
To: research!v8sources
Subject: 4.2 net fs server, tcp

bundle makefile fserv.h neta.h tcpstuff.c fserv.h tcpmain.c ps.y perm.c start.c sub.c sys.c work.c profit.c


From princeton!down!honey  Sat Oct 19 08:37:28 1985
>From down!honey  Sat Oct 19 08:37:28 1985 remote from princeton
Date: 19 Oct 1985 08:37-EDT
To: research!v8news
Subject: netfs stuff for tcp

i just posted 3 packages to v8sources:
	netfs server for v8 side
	netfs server for 4.2 side
	netfs client for v8 side
all use tcp instead of datakit.  there are bugs here, e.g., it gets
out of synch, doesn't handle pwd right, and forgets to close files
somewhere.  so the job isn't completely done, but the 90% i did will
help whoever takes on the task of finishing it.

i have more buggy code -- a v8 deuna driver that embarrasses me that
i'll mail on request.

	peter


From princeton!down!honey  Sat Oct 19 09:26:44 1985
>From down!honey  Sat Oct 19 09:26:44 1985 remote from princeton
Date: 19 Oct 1985 09:25-EDT
To: research!v8source
Subject: v8 netfs client, tcp

# To unbundle, sh this file
echo makefile 1>&2
sed 's/^-//' >makefile <<'//GO.SYSIN DD makefile'
CC=cc -g
tcpsetup:	tcpsetup.o
	$(CC) -o tcpsetup tcpsetup.o -lin

tcpsetup.o: fserv.h

print:
	imprint tags makefile /usr/include/sys/neta.h fserv.h tcpsetup.c perm.c profit.c setup.c start.c sub.c sys.c tcpmain.c tcpstuff.c work.c ps.y 

bundle:
	@bundle makefile fserv.h tcpsetup.c
//GO.SYSIN DD makefile
echo fserv.h 1>&2
sed 's/^-//' >fserv.h <<'//GO.SYSIN DD fserv.h'
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/stat.h>
extern int errno;
extern char *malloc();

int dbgfd;	/* for debugging output, shared with children */
int cntlfd;	/* fd for new service requests */
int ackfd;	/* for responding to network */
int active;	/* bit map of active channels for select */
int myfd;	/* sole argument to children */
int silent;	/* debugging level */
#define NORMAN 30
struct {
	int pid;	/* pid of child, if it exists */
	int fd;		/* fd of channel to client (duplicates index) */
	int flags;	/* status */
	int dtime;	/* time difference */
	int dev;	/* client's idea of the root */
	long lastheard;	/* for time outs */
	char *who;	/* client's name, for trapping loops */
	int host;	/* correlates with permissions table */
	int silent;
} children[NORMAN];		/* one-one with fd's */
#define CONN	1
#define SPLIT	2
#define UNINIT	3

#define NDEV 10
extern struct tdev {
	int ours, his;
} devtab[NDEV];
extern int ndev;

typedef struct aa {
	long tag;
	int dev;	/* his dev */
	int ino;
	char *name;	/* some name */
	struct stat statb;	/* cached */
	short fd;	/* the precious handle */
	DIR *dirp;	/* seems to be the best way */
	long	diroffset;	/* ditto, sadly */
	char how;	/* how opened */
} netf;

extern netf *getnetf(), *gettag(), *newnetf(), *oldnetf();
#define ftype(p) (p->statb.st_mode & S_IFMT)
/* 1 for cmnd outline, 2 for cmnd detail, 4 for permissions */
#define debug1 if(silent & 1) xdebug
#define debug2 if(silent & 2) xdebug
#define debug3 if(silent & 3) xdebug
#define debug4 if(silent & 4) xdebug
#define NDBG 200
int dptr;
char debugbuf[NDBG][128];
//GO.SYSIN DD fserv.h
echo tcpsetup.c 1>&2
sed 's/^-//' >tcpsetup.c <<'//GO.SYSIN DD tcpsetup.c'
#include "stdio.h"
#include "sys/param.h"
#include "sys/stat.h"
#include "sys/neta.h"
#include "errno.h"
#include "sys/ioctl.h"
#include "signal.h"
#include "setjmp.h"
#include "sys/inet/in.h"

#define RMFSTYP 1	/* file system type for remote file system */

struct friend {
	char *who;
	char *mount;
	int dev;
	int silent;
	int status;
	int chan;
} friends[NOFILE];
int nfriends;
#define DEAD	0
#define OK	1
#define PROBE	2
#define KILL 	3

char *states[] = { "dead", "ok", "probe", "kill", "?"};

struct senda x;
struct rcva y;
extern int errno;
extern char *ctime();
extern char *malloc();
struct stat stb;
long looked;
jmp_buf jmpbuf;

main()
{	int i;
/* any signal but SIGALRM (14) will start it over.  SIGALRM is used to
 * interrupt hung reads.  SIGCHLD is ignored too */
	sigalrm(0);
	if(setjmp(jmpbuf) == 1)
		rdfile();
	else
		sigcatch();
	probe();
}
sigalrm(n)
{
	fprintf(stderr, "sigalrm %d\n", n);
	fflush(stderr);
	if(n == SIGALRM || n == 0)	/* otherwise might get SIGCHLD in sleep */
		signal(SIGALRM, sigalrm);
	signal(SIGCHLD, sigalrm);
}
sigcatch(n)
{	int i;
	for(i = 1; i < NSIG; i++)
		if(i != SIGALRM && i != SIGCHLD)	/* alarm and tdkdial */
			(void) signal(i, sigcatch);
	fprintf(stderr, "sigcatch %d\n", n);
	fflush(stderr);
	switch(i) {
	case SIGILL: case SIGBUS: case SIGSEGV:
		restart();
	}
	longjmp(jmpbuf, 1);
}
restart()
{
	fprintf(stderr, "execing\n");
	fflush(stderr);
	execl("/etc/net/setup", "setup", 0);
	execl("/usr/net/setup", "setup", 0);
	/* if that doesn't work */
	fprintf(stderr, "oops, calling main\n");
	fflush(stderr);
	main();		/* ho ho */
}
probe()
{	int i;
	static int lastdone;
	long now;
loop:
	if(lastdone >= nfriends) {
		lastdone = 0;
		sleep(30);
		if(stat("/etc/net/friends", &stb) == 0 && stb.st_mtime > looked)
			rdfile();
		if(stat("/usr/net/friends", &stb) == 0 && stb.st_mtime > looked)
			rdfile();
		if(time((long *)0) > looked + 1200)
			rdfile();
	}
	i = lastdone++;
	switch(friends[i].status) {
	default:
		break;
	case PROBE:
	case OK:
		friends[i].status++;
		doprobe(friends + i);
		if(friends[i].status != OK) {
			now = time(0);
			fprintf(stderr, "hmm %s %s %s\n", friends[i].who,
				states[friends[i].status], ctime(&now));
		}
		break;
	case KILL:	/* over the limit */
		now = time(0);
		fprintf(stderr, "%s timed out %s 0x%x %s", friends[i].who,
			states[friends[i].status], friends[i].chan, ctime(&now));
		errno = 0;
		gmount(RMFSTYP, friends[i].dev, 1, 0, 0);
		if(errno == 0 || errno == EINVAL) {
			friends[i].status = DEAD;
			fprintf(stderr, "dead now\n");
		}
		else
			perror("xmount");
		break;
	}
	goto loop;
}	
doprobe(x)
struct friend *x;
{	struct stat stb;
	if(stat(x->mount, &stb) == 0 && stb.st_dev == x->dev)
		x->status = OK;
}
startup(p)
struct friend *p;
{	int fd, i;
	char version;
	fd = callfs(p->who);
	if(fd < 0) {
		fprintf(stderr, "callfs %s failed\n", p->who);
		return;
	}
	(void) fstat(fd, &stb);
	fprintf(stderr, "starting %s (0x%x)", p->who, stb.st_rdev);
	gmount(RMFSTYP, p->dev, 1, 0, 0);	/* just in case */
	perror("xunmount");
	x.trannum = 0;
	version = x.version = NETVERSION;
	x.cmd = NSTART;
	x.uid = p->silent;
	x.dev = p->dev;
	alarm(30);
	x.ta = time(0);
	if((write(fd, &version, 1) != 1) || write(fd, (char *)&x, sizeof(x))
		!= sizeof(x)) {
			perror("write in setup");
			fprintf(stderr, "%s\n", p->who);
			close(fd);
			alarm(0);
			return;
	}
	if((i = read(fd, (char *)&y, sizeof(y))) != sizeof(y)) {
		if(y.trannum == -1)
			fprintf(stderr, "version mismatch %s\n", p->who);
		else {
			fprintf(stderr, "read %d chars for %s\n", i, p->who);
			perror((char *)&y);
		}
		close(fd);
		return;
	}
	alarm(0);
	if(y.errno != 0) {
		errno = y.errno;
		perror("nak in setup");
		close(fd);
		return;
	}
	if(gmount(RMFSTYP, p->dev, 0, fd, p->mount) != 0) {
		perror("xmount");
		fprintf(stderr, "unmounting it\n");	/* garbage collection*/
		gmount(RMFSTYP, p->dev, 1, 0, 0);
		perror("xunmount");
		close(fd);
		/* and try again later */
		return;
	}
	p->status = OK;
	fprintf(stderr, "started %s on %s dev %d silent %d chan 0x%x\n", p->who,
		p->mount, p->dev/256, p->silent, p->chan = stb.st_rdev);
	close(fd);
}

#define skip for(; *p == ' ' || *p == '\t'; p++)
#define note for(s = p; *p != ' ' && *p != '\t' && *p != '\n'; p++)
struct friend *
cnvt(s)
char *s;
{	static struct friend x;
	char *p;
	s[strlen(s)] = '\n';
	p = s;
	skip;
	if(*p == '\n') {
		x.who = "#";
		return(&x);
	}
	note;
	if(*p == '\n')
		return(0);
	*p++ = 0;
	x.who = malloc(strlen(s) + 1);
	strcpy(x.who, s);
	s = p;
	skip;
	note;
	if(*p == '\n')
		return(0);
	*p++ = 0;
	x.mount = malloc(strlen(s) + 1);
	strcpy(x.mount, s);
	s = p;
	skip;
	note;
	if(*p == '\n')
		return(0);
	*p++ = 0;
	x.dev = 256 * atoi(s);
	s = p;
	skip;
	note;
	*p++ = 0;
	x.silent = atoi(s);
	x.status = DEAD;
	return(&x);
}

rdfile()
{	FILE *fd;
	int i;
	char line[128];
	struct friend *p;
	alarm(0);		/* disable the sleep in probe */
	fd = fopen("/etc/net/friends", "r");
	if(fd == NULL) {
		fd = fopen("/usr/net/friends","r");
		if(fd == NULL) {
			perror("friends");
			exit(1);
		}
	}
	for(;;) {
onward:
		(void) fgets(line, sizeof(line), fd);
		if(feof(fd))
			break;
		p = cnvt(line);
		if(p == 0) {
			fprintf(stderr, "weird friends line %s\n", line);
			continue;
		}
		if(p->who[0] == '#')
			continue;
		for(i = 0; i < nfriends; i++) {
			if(strcmp(p->who, friends[i].who))
				continue;
			if(friends[i].status != OK) {
				looked = time(0);
				fprintf(stderr, "\nrdfile %s (%s) %s",
					states[friends[i].status],
					friends[i].who, ctime(&looked));
				/* off the mother */
				if(friends[i].status != DEAD) {
					friends[i].status = KILL;
					fprintf(stderr, "bye %s\n", friends[i].who);
				}
			}
			if(friends[i].status != DEAD)
				goto onward;
			/* one could free the space */
			fprintf(stderr, "new friend %s\n", p->who);
			friends[i] = *p;
			startup(friends + i);
			goto onward;
		}
		for(i = 0; i < nfriends; i++)
			if(friends[i].status == DEAD) {
				friends[i] = *p;
				fprintf(stderr, "new friend %s\n", p->who);
				startup(friends + i);
				goto onward;
			}
		if(i < nfriends)
			continue;
		if(nfriends >= NOFILE) {
			fprintf(stderr, "friends overflow\n");
			abort();
		}
		fprintf(stderr, "new friend %s\n", p->who);
		friends[nfriends++] = *p;
		startup(friends + nfriends - 1);
	}
	fclose(fd);
	looked = time(0);
	fprintf(stderr, "ok %s", ctime(&looked));
}

callfs(srvr)
char *srvr;
{
	int rem, v;
	extern int rmesg_ld;
	long x;

	alarm(30);
	x = time(0);
	fprintf(stderr, "%d tcpdial %s %s", getpid(), srvr, ctime(&x));
	fflush(stderr);
	rem = tcpdial(srvr);
	x = time(0);
	alarm(0);
	if (rem < 0) {
		fprintf(stderr, " %d can't rexec err = %d\n", getpid(), errno);
		fflush(stderr);
		return(-1);
	}
	else
		fprintf(stderr, "tcpdial ok %s", ctime(&x));
	if (ioctl(rem, FIOPUSHLD, &rmesg_ld) < 0) {
		perror("rmesg_ld");
		(void) close(rem);
		return(-1);
	}

	x = time(0);
	return(rem);
}

int
tcpdial(host)
char	*host;
{
	int	fd;
	in_addr faddr, in_address();
	struct in_service *fport, *in_service();

	/*
	 * connect to server.
	 */
	faddr = in_address(host);
	if(faddr == 0) {
		fprintf(stderr, "fshare: %s: no such host\n", host);
		return(-1);
	}
	fport = in_service("fshare", "tcp", 0);
	if (fport < 0) {
		fprintf(stderr, "fshare: no such service\n", host);
		return(-1);
	}
	fd = tcp_sock();
	if(fd < 0) {
		fprintf(stderr, "fshare: no socket\n", host);
		return(-1);
	}
	if(tcp_connect(fd, 0, faddr, fport->port) < 0) {
		close(fd);
		fprintf(stderr, "fshare: can't connect\n", host);
		return(-1);
	}
	return(fd);
}
//GO.SYSIN DD tcpsetup.c
exit


From princeton!down!honey  Sat Oct 19 09:31:21 1985
>From down!honey  Sat Oct 19 09:31:21 1985 remote from princeton
Date: 19 Oct 1985 09:29-EDT
To: research!v8source
Subject: 4.2 net fs server, tcp

# To unbundle, sh this file
echo makefile 1>&2
sed 's/^-//' >makefile <<'//GO.SYSIN DD makefile'
YFLAGS=-D
CFLAGS=-g
LDFLAGS=-g
SOURCE=tcpstuff.c fserv.h tcpmain.c ps.y perm.c start.c sub.c sys.c work.c profit.c
OBJ=tcpmain.o ps.o perm.o sys.o start.o sub.o work.o tcpstuff.o profit.o

fshare:	$(OBJ) profit.o
	$(CC) -o fshare $(LDFLAGS) $(OBJ) profit.o

$(OBJ):	fserv.h

ps.c:	ps.y
	yacc $(FLAGS) ps.y
	sed < y.tab.c > ps.c '/^# line/d'

clean:
	rm -f a.out core jim.errs $(OBJ) y.tab.c ps.c fshare

bundle:
	@bundle makefile fserv.h neta.h $(SOURCE)
//GO.SYSIN DD makefile
echo fserv.h 1>&2
sed 's/^-//' >fserv.h <<'//GO.SYSIN DD fserv.h'
#include "sys/param.h"
#include "sys/dir.h"
#include "sys/stat.h"
extern int errno;
extern char *malloc();

int dbgfd;	/* for debugging output, shared with children */
int cntlfd;	/* fd for new service requests */
int ackfd;	/* for responding to network */
fd_set active;	/* bit map of active channels for select */
int myfd;	/* sole argument to children */
int silent;	/* debugging level */
#define NORMAN NOFILE
struct {
	int pid;	/* pid of child, if it exists */
	int fd;		/* fd of channel to client (duplicates index) */
	int flags;	/* status */
	int dtime;	/* time difference */
	int dev;	/* client's idea of the root */
	long lastheard;	/* for time outs */
	char *who;	/* client's name, for trapping loops */
	int host;	/* correlates with permissions table */
	int silent;
} children[NORMAN];		/* one-one with fd's */
#define CONN	1
#define SPLIT	2
#define UNINIT	3

#define NDEV 10
extern struct tdev {
	int ours, his;
} devtab[NDEV];
extern int ndev;

typedef struct aa {
	long tag;
	int dev;	/* his dev */
	int ino;
	char *name;	/* some name */
	struct stat statb;	/* cached */
	short fd;	/* the precious handle */
	DIR *dirp;	/* seems to be the best way */
	long	diroffset;	/* ditto, sadly */
	char how;	/* how opened */
} netf;

extern netf *getnetf(), *gettag(), *newnetf(), *oldnetf();
#define ftype(p) (p->statb.st_mode & S_IFMT)
/* 1 for cmnd outline, 2 for cmnd detail, 4 for permissions */
#define debug1 if(silent & 1) xdebug
#define debug2 if(silent & 2) xdebug
#define debug3 if(silent & 3) xdebug
#define debug4 if(silent & 4) xdebug
#define NDBG 200
int dptr;
char debugbuf[NDBG][128];

/*
 *	From V8.
 *
 *	Set of fds used with the select system call.
 *	The macros depend on NBPW, NBBY, & NOFILE from sys/param.h.
 */
#define FDWORDS		(NOFILE+NBPW*NBBY-1)/(NBPW*NBBY)
/*typedef struct		fd_set { unsigned long fds_bits[FDWORDS]; } fd_set;*/
#define FD_SET(n,s)	(s).fds_bits[(n)/(NBPW*NBBY)] |= 1<<((n)%(NBPW*NBBY))
#define FD_CLR(n,s)	(s).fds_bits[(n)/(NBPW*NBBY)] &= ~(1<<((n)%(NBPW*NBBY)))
#define FD_ISSET(n,s)	((s).fds_bits[(n)/(NBPW*NBBY)] & (1<<((n)%(NBPW*NBBY))))
#define FD_ZERO(s)	{int i; for(i=0;i<FDWORDS;i++)s.fds_bits[i]=0; }
//GO.SYSIN DD fserv.h
echo neta.h 1>&2
sed 's/^-//' >neta.h <<'//GO.SYSIN DD neta.h'
#define NETVERSION	1	/* protocol variant */

#define NSTAT	1
#define NWRT	2
#define NREAD	3
#define NFREE	4
#define NTRUNC	5
#define NUPDAT	6
#define NGET	7
#define NNAMI	8
#define NPUT	9
#define NROOT	10
#define NDEL	11
#define NLINK	12
#define NCREAT	13
#define NOMATCH	14
#define NSTART	15
#define NIOCTL	16

struct senda {	/* not space efficient */
	char version;
	char cmd;
	char flags;	/* now only for nami */
	char rsvd;
	long trannum;
	short uid;
	short gid;
	short dev;	/* server may be using several */
	long tag;
	long mode;
	short newuid;	/* for updat */
	short newgid;
	long ino;
	long count;
	long offset;
	char *buf;
	time_t ta;
	time_t tm;
};

struct rcva {	/* not space efficient either */
	long trannum;
	char errno;
	char flags;	/* NROOT for nami */
	short dev;
	long size;
	short mode;
	short uid;
	short gid;
	long tag;
	short nlink;
	short rsvd;
	long ino;	/* back from nami */
	long count;	/* count or loc for nami to use */
	time_t tm[3];
};

extern long trannum;
//GO.SYSIN DD neta.h
echo tcpstuff.c 1>&2
sed 's/^-//' >tcpstuff.c <<'//GO.SYSIN DD tcpstuff.c'
#include "fserv.h"
#include "sys/ioctl.h"
#include "signal.h"
#include "errno.h"
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include "neta.h"

struct sockaddr_in sin;

struct mesg {
	short	type;
	short	size;
};

#define	M_DATA	0		/* regular data (not ctl) */
#define	M_DELIM	03		/* data delimiter */
#define	M_YDEL	012		/* stream has started generating delims */
typedef u_short v8ino_t, v8d_ino;
#define	V8DIRSIZ	14

struct	v8direct
{
	v8ino_t	d_ino;
	char	d_name[V8DIRSIZ];
};


announce()
{
	int fd;
	struct servent *getservbyname();
	static struct servent *sp;

	if (sp == 0) {
		sp = getservbyname("fshare", "tcp");
		if (sp == 0) {
			debug("fshare: unknown service\n");
			return;
		}
	}
	sin.sin_family = AF_INET;
	sin.sin_port = sp->s_port;

	fd = socket(AF_INET, SOCK_STREAM, 0);
	if (fd < 0) {
		perror("fshare: socket");
		exit(1);
	}
	if (bind(fd, &sin, sizeof (sin), 0) < 0) {
		perror("fshare: bind");
		exit(1);
	}
	if (listen(fd, 10) != 0) {
		perror("fshare: listen");
		exit(1);
	}
	cntlfd = fd;
	active |= (1 << fd);
	return;
}

newone()
{
	int n, i, fd;
	char *inet_ntoa();
	struct sockaddr_in from;
	int len = sizeof(from);
	struct hostent *hp;

	fd = accept(cntlfd, &from, &len);	/* needs timeout?  non-block? */
	if (fd < 0)
		return;
	hp = gethostbyaddr(&(from.sin_addr), sizeof(struct in_addr), from.sin_family);
	if (hp == 0) {
		debug("fshare: %s: no such host\n", inet_ntoa(from.sin_addr));
		(void) close(fd);
		return;
	}

	if (!(n = isfriend(hp->h_name))) {
		debug("fshare: %s not friend\n", hp->h_name);
		(void) close(fd);
		return;
	}
	for(i = 0; i < NOFILE; i++)
		if(children[i].who && strcmp(children[i].who, hp->h_name) == 0) {
			debug("fshare: %s already attached\n", hp->h_name);
			free(children[i].who);
			children[i].who = 0;
			/* some more? */
			kill(children[i].pid, SIGKILL);	/* who did we kill?*/
			break;
		}
	if(children[fd].flags) {
		debug("opened %s twice", hp->h_name);
		debug("pid %d fd %d flags %d %s\n", children[fd].pid,
			children[fd].fd, children[fd].flags,
			children[fd].who);
		/* who should we believe?  the new one */
		if(children[fd].pid != 0)
			kill(children[fd].pid, SIGKILL);
		/* did that pid exist, and was it us? */
	}
	children[fd].pid = 0;
	children[fd].fd = fd;
	children[fd].flags = UNINIT;
	children[fd].host = n;
	children[fd].lastheard = time(0);
	children[fd].who = malloc(strlen(hp->h_name) + 1);
	strcpy(children[fd].who, hp->h_name);
	debug("ok, %s (%d) on fd %d", hp->h_name, n, fd);
	active |= (1 << fd);
}
/* yuck -- simulate rmesg ld */
#define RMESG(f, b, l) \
	if ((nread = read((f), (b), (l))) != (l)) { \
		fprintf("xread %d, expected %d\n", nread, (l)); \
		return(-1); \
	}
int
xread(f, b, l)
char *b;
{
	struct mesg mesg;
	static char base[8192], *rptr, *lim;
	static int count, size = 8192;
	int rval = 0, nread;

	if (l > 8192) {
bad:		debug("xread %d is too much\n", l);
		return(-1);
	}

	if (count != 0) {	/* screw -- he can have this */
		int n = MIN(count, l);
		strncpy(b, rptr, n);
		count -= n;
		if (count > 0)
			rptr += n;
		else {
			count = 0;
			rptr = base;
		}
		return(n);
	}
	RMESG(f, &mesg, sizeof(mesg));
	while (mesg.type != M_DELIM) {
		if (mesg.type != M_DATA) {	/* ignore it */
			if (mesg.size != 0)
				RMESG(f, b, mesg.size);
			goto nxtmesg;
		}
		if (mesg.size > 8192) {
			fprintf("xread wants %d\n", mesg.size);
			return(-1);
		}

		if (mesg.size <= l) {
			RMESG(f, b, mesg.size);
			rval += mesg.size;
			b += mesg.size;
			l -= mesg.size;
			goto nxtmesg;
		}
		/* mesg.size > l */
		if (l > 0) {
			RMESG(f, b, l);
			rval += l;
			b += l;
			RMESG(f, rptr, mesg.size - l);
			rptr += mesg.size - l;
			count += l;
			l = 0;
		}
nxtmesg:
		/* this should be delim ... */
		RMESG(f, &mesg, sizeof(mesg));
	}
	if (mesg.size != 0) {
		debug("no delim\n");
		return(-1);
	}
	return(rval);
}

/* this sucks -- 4 bytes then data then 4 bytes.  slowness. */
int
xwrite(f, b, l)
char *b;
{
	struct mesg mesg;
	int rval;

	mesg.type = M_DATA;
	mesg.size = l;
	if (write(f, &mesg, sizeof(mesg)) != sizeof(mesg))
		return(-1);
	rval = write(f, b, l);

	mesg.type = M_DELIM;
	mesg.size = 0;
	if (write(f, &mesg, sizeof(mesg)) != sizeof(mesg))
		return(-1);
	return(rval);
}

xreaddir(p, buf, x)
netf *p;
char *buf;
struct senda *x;
{
	struct direct *dp;
	struct v8direct *bp;
	int i;
	extern int buflen;

	if (x->offset == 0)
		rewinddir(p->dirp);
	else
		seekdir(p->dirp, p->diroffset);
	
	getbuf(x->count);
	bzero(buf, buflen);	/* seems prudent ... */
	bp = (struct v8direct *) buf;
	for (i = x->count/sizeof(struct v8direct); i > 0; --i) {
		/* ignore loooong file names -- they don't exist */
		do
			dp = readdir(p->dirp);
		while (dp && dp->d_namlen > V8DIRSIZ);
		if (dp == 0)
			break;
#ifdef VAX
		bp->d_ino = dp->d_ino;
#else !VAX thus SUN
		bp->d_ino = ((dp->d_ino & 0xff) << 8)		/* lsb */
			  | ((dp->d_ino & 0xff00) >> 8);	/* msb */
#endif VAX
		strncpy(bp->d_name, dp->d_name, MIN(dp->d_namlen, V8DIRSIZ));
		bp++;
	}
	p->diroffset = telldir(p->dirp);
	return(((char *) bp) - buf);
}
//GO.SYSIN DD tcpstuff.c
echo fserv.h 1>&2
sed 's/^-//' >fserv.h <<'//GO.SYSIN DD fserv.h'
#include "sys/param.h"
#include "sys/dir.h"
#include "sys/stat.h"
extern int errno;
extern char *malloc();

int dbgfd;	/* for debugging output, shared with children */
int cntlfd;	/* fd for new service requests */
int ackfd;	/* for responding to network */
fd_set active;	/* bit map of active channels for select */
int myfd;	/* sole argument to children */
int silent;	/* debugging level */
#define NORMAN NOFILE
struct {
	int pid;	/* pid of child, if it exists */
	int fd;		/* fd of channel to client (duplicates index) */
	int flags;	/* status */
	int dtime;	/* time difference */
	int dev;	/* client's idea of the root */
	long lastheard;	/* for time outs */
	char *who;	/* client's name, for trapping loops */
	int host;	/* correlates with permissions table */
	int silent;
} children[NORMAN];		/* one-one with fd's */
#define CONN	1
#define SPLIT	2
#define UNINIT	3

#define NDEV 10
extern struct tdev {
	int ours, his;
} devtab[NDEV];
extern int ndev;

typedef struct aa {
	long tag;
	int dev;	/* his dev */
	int ino;
	char *name;	/* some name */
	struct stat statb;	/* cached */
	short fd;	/* the precious handle */
	DIR *dirp;	/* seems to be the best way */
	long	diroffset;	/* ditto, sadly */
	char how;	/* how opened */
} netf;

extern netf *getnetf(), *gettag(), *newnetf(), *oldnetf();
#define ftype(p) (p->statb.st_mode & S_IFMT)
/* 1 for cmnd outline, 2 for cmnd detail, 4 for permissions */
#define debug1 if(silent & 1) xdebug
#define debug2 if(silent & 2) xdebug
#define debug3 if(silent & 3) xdebug
#define debug4 if(silent & 4) xdebug
#define NDBG 200
int dptr;
char debugbuf[NDBG][128];

/*
 *	From V8.
 *
 *	Set of fds used with the select system call.
 *	The macros depend on NBPW, NBBY, & NOFILE from sys/param.h.
 */
#define FDWORDS		(NOFILE+NBPW*NBBY-1)/(NBPW*NBBY)
/*typedef struct		fd_set { unsigned long fds_bits[FDWORDS]; } fd_set;*/
#define FD_SET(n,s)	(s).fds_bits[(n)/(NBPW*NBBY)] |= 1<<((n)%(NBPW*NBBY))
#define FD_CLR(n,s)	(s).fds_bits[(n)/(NBPW*NBBY)] &= ~(1<<((n)%(NBPW*NBBY)))
#define FD_ISSET(n,s)	((s).fds_bits[(n)/(NBPW*NBBY)] & (1<<((n)%(NBPW*NBBY))))
#define FD_ZERO(s)	{int i; for(i=0;i<FDWORDS;i++)s.fds_bits[i]=0; }
//GO.SYSIN DD fserv.h
echo tcpmain.c 1>&2
sed 's/^-//' >tcpmain.c <<'//GO.SYSIN DD tcpmain.c'
/* file service */
#include "fserv.h"
#include "errno.h"
#include "neta.h"
#include <sys/time.h>

int lflag;	/* means /-prefixed symbolic links are interpreted by server */
char me[16];
char *service;
char cmdbuf[256];
struct rcva y, nilrcv;
struct stat statb, rootstat;
int intrcnt, timecnt, okcnt;
fd_set svrdmask;

main(argc, argv)
char **argv;
{	int n, i;
	fd_set rdmask;
	struct timeval twentysec;

	if(argc > 1 && strcmp(argv[1], "-l") == 0)
		lflag = 1;
	dbgfd = 2;
	close(0);
	close(1);
	n = open("/dev/tty", 2);
	if (n >= 0) {
		ioctl(n, TIOCNOTTY, (char *) 0);
		(void) close(n);
	}
	whoami();
	umask(0);
	twentysec.tv_sec = 20;
	perminit();
	signals();
	(void) stat("/", &rootstat);
	statb = rootstat;
	announce();
loop:
	if(cntlfd < 0) {	/* socket died */
		debug("announcing");
		for(i = 0; i < 32; i++)
			if(i != dbgfd)
				close(i);
		announce();
	}
	reapchild();
	errno = 0;
	rdmask = active;
	debug2("selecting x%x", rdmask);
	n = select(NOFILE, &rdmask, (int *) 0, (int *) 0, &twentysec);
	if(n == -1 && errno == EINTR) {
		intrcnt++;
		goto loop;
	}
	else if(n == -1) {
		perror("select");
		goto loop;		/* probably an infinite loop? */
	}
	else if(n == 0) {
		debug2("timeout");
		timecnt++;
		permredo();
		goto timer;		/* nothing's going on? */
	}
	else {
		okcnt++;
		svrdmask = rdmask;
		debug2("got rdmask %lx", rdmask);
	}
	for(i = NOFILE - 1; i >= 0; i--)
		if(FD_ISSET(i, rdmask))
			if(i == cntlfd)
				newone();
			else {
				children[i].lastheard = time(0);
				serve(i, argv[0]);
			}
timer:
	for(i = 0; i < NOFILE; i++)
		if(FD_ISSET(i, active)) {
			if(i == cntlfd)
				continue;
			if(children[i].lastheard + 500 > time(0))
				continue;
			debug("%s 500 seconds", children[i].who);
			/*close(children[i].fd);
			children[i].fd = children[i].flags = 0;
			if(children[i].who)
				free(children[i].who);
			children[i].who = 0;
			FD_CLR(i, active);
			*/
			children[i].lastheard = time(0);
		}
	goto loop;
}

char dbgbuf[128];
/*VARARGS*/
debug(s, a, b, c, d, e, f)
{	/* no buffering, shared fd with children */
	long x;
	extern char *ctime();
	x = time(0);
	sprintf(dbgbuf, s, a, b, c, d, e, f);
	strcat(dbgbuf, " ");
	strcat(dbgbuf, ctime(&x));
	write(dbgfd, dbgbuf, strlen(dbgbuf));
}

whoami()
{
	gethostname(me, sizeof(me));
	me[sizeof(me)] = 0;
}

extern int sys_nerr;
extern char *sys_errlist[];
perror(s)
char *s;
{	register char *c;
	c = "Unknown error";
	if(0 < errno && errno < sys_nerr)
		c = sys_errlist[errno];
	debug("%s: %s (%d)", s, c, errno);
}


/* we expect one byte of version number followed by a senda with 
 * initialization stuff */
doinit(n)
{	struct senda *x;
	int i;

	i = xread(children[n].fd, cmdbuf, 1);
	x = (struct senda *)cmdbuf;
	debug("doinit read %d on %d for %d", i, children[n].fd, n);
	if(i != 1 || x->version != NETVERSION) {
		debug("read %d chars [0x%x] for child %d on fd %d",
			i, x->version, n, children[n].fd);
		goto awful;
	}
	i = xread(children[n].fd, cmdbuf, sizeof(struct senda));
	debug("doinit read %d on %d for %d", i, children[n].fd, n);
	if(i != sizeof(struct senda) || x->version != NETVERSION) {
		if(x->version != NETVERSION) {
			y.trannum = -1;
			xwrite(children[n].fd, (char *)&y, sizeof(struct rcva));
			debug("got version %d for %s", x->version, NETVERSION);
		}
		else
			debug("doinit, read %d on %d", i, children[n].fd);
awful:
		/* panic, we may get an endless stream */
		respond(0);
		close(children[n].fd);
		FD_CLR(children[n].fd, active);
		return;
	}
	children[n].dtime = x->ta - time(&children[n].lastheard);
	children[n].dev = x->dev;
	children[n].silent = x->uid;
	y.trannum = x->trannum;
	myfd = children[n].fd;
	respond(0);
	children[n].flags = CONN;
	debug("%s dev %d silent %d", children[n].who, children[n].dev / 256,
		children[n].silent);
}

respond(n)
{
	if((y.errno = n) && silent) {
		errno = n;
		perror("respond");
	}
	(void) xwrite(children[myfd].fd, (char *)&y, sizeof(y));
}

debugreset()
{
	dptr = 0;
}

xdebug(s, a, b, c, d, e, f, g)
{
	sprintf(debugbuf[dptr], s, a, b, c, d, e, f, g);
	dptr++;
	if(dptr >= NDBG) {
		debugreset();
		xdebug("buffer wrapped");
	}
}
//GO.SYSIN DD tcpmain.c
echo ps.y 1>&2
sed 's/^-//' >ps.y <<'//GO.SYSIN DD ps.y'
%token MACHINE
%token LP RP NUMBER
%{
#include "stdio.h"
FILE *infd;
%}
%%
file:
	| machine_list ;
machine_list:	machine
	| machine_list machine
	;
machine:	MACHINE perm_list
	;
perm_list:
	| perm
	| perm_list perm
	;
perm:	LP client host RP
	;
client:	uid
		{ doclient($1, -1); }
	| LP uid gid RP
		{ doclient($2, $3); }
	;
host:	uid
		{ dohost($1, -1); }
	| LP uid gid RP
		{ dohost($2, $3); }
	;
uid:	NUMBER ;
gid:	NUMBER ;
%%
int lineno = 1;
yyerror(s)
char *s;
{	char buf[128];
	sprintf(buf, "%s line %d", s, lineno);
	perror(buf);
}

pparse(fd)
FILE *fd;
{
	infd = fd;
	yyparse();
}

yylex()
{	int c;
again:
	c = getc(infd);
	if(c == '\n')
		lineno++;
loop:
	if(c == EOF)
		return(0);
	if(c == '#') {
		do {
			c = getc(infd);
		} while(c != '\n' && c != EOF);
		if(c == '\n')
			lineno++;
		goto loop;
	}
	if(c == ' ' || c == ',' || c == '\n' || c == '\t')
		goto again;
	if(c == '(')
		return(LP);
	if(c == ')')
		return(RP);
	if(c == '+' || c == '-' || c >= '0' && c <= '9') {
		donumber(c);
		return(NUMBER);
	}
	if(c >= 'a' && c <= 'z' || c == '/') {
		domachine(c);
		lineno++;
		return(MACHINE);
	}
	debug("bad char in people (%c) 0%o ignored\n", c, c);
	goto again;
}

donumber(c)
int c;
{
	int n, sign;

	n = 0;
	sign = 1;
	if(c == '-')
		sign = -1;
	else if(c != '+')
		n = c - '0';
	for(c = getc(infd); c >= '0' && c <= '9'; c = getc(infd))
		n = 10 * n + c - '0';
	ungetc(c, infd);
	yylval = sign * n;
}

static char nmbuf[128];
domachine(c)
{	char *p = nmbuf;
	*p++ = c;
	for(c = getc(infd); (c >= 'a' && c <= 'z' || c == '/') && p < nmbuf + 127; c=getc(infd))
		*p++ = c;
	*p = 0;
	newhost(nmbuf);
}
//GO.SYSIN DD ps.y
echo perm.c 1>&2
sed 's/^-//' >perm.c <<'//GO.SYSIN DD perm.c'
#include "stdio.h"
#include "fserv.h"
#include "neta.h"
extern int host;
/* keep all the perm space here, to redo on file change */

typedef struct {
	unsigned short cuid;
	short cgid;
	unsigned short huid;
	short hgid;
} pe;
typedef struct {
	char *name;	/* eg mh/astro/seki */
	short ix;	/* its index > 0 */
	short cnt;	/* number of entries */
	pe *tab;	/* the entries */
	pe *inv;	/* host->client index */
} ps;
ps *prm;
int nprm, prmlen;
short *ptemp;
int ptnum, ptlen;
long lastlooked;

perminit()
{	FILE *fd;
	int i;
	fd = fopen("/usr/net/people", "r");
	if(fd == NULL) {
		fd = fopen("/etc/net/people", "r");
		if(fd == NULL) {
			perror("people");
			exit(1);
		}
	}
	for(i = 0; i < nprm; i++) {
		if(prm[i].name)
			free(prm[i].name);
		if(prm[i].tab)
			free((char *)prm[i].tab);
		if(prm[i].inv)
			free((char *)prm[i].inv);
	}
	nprm = 0;
	ptnum = 0;
	pparse(fd);
	newhost(0);
	fclose(fd);
	lastlooked = time(0);
	for(i = 0; i < nprm; i++)
		psort(prm + i);
}

permredo()
{	struct stat stb;
	int i;
	if(stat("/usr/net/people", &stb) == -1 || stb.st_mtime <= lastlooked)
		return;
	for(i = 0; i < nprm; i++) {
		free(prm[i].name);
		free(prm[i].tab);
		free(prm[i].inv);
	}
	nprm = 0;
	ptnum = 0;
	perminit();
}

newhost(s)
char *s;
{	ps *p;
	short *x;
	int i;
	if(nprm > 0) {	/* clean up after last one */
		p = prm + nprm - 1;
		p->tab = (pe *)malloc(ptnum * sizeof(short));
		x = (short *)p->tab;
		for(i = 0; i < ptnum; i++)
			*x++ = ptemp[i];
		p->cnt = ptnum / 4;	/* 4 = #shorts / pe */
		p->inv = (pe *)malloc(ptnum * sizeof(short));
		ptnum = 0;
	}
	if(s == 0)
		return;
	if(nprm >= prmlen) {
		if(nprm == 0) {
			prm = (ps *)malloc(5 * sizeof(ps));
			prmlen = 5;
		}
		else {
			prmlen *= 2;
			prm = (ps *)realloc((char *)prm, prmlen * sizeof(ps));
		}
	}
	p = prm + nprm++;
	p->name = malloc(strlen(s) + 1);
	strcpy(p->name, s);
	p->ix = nprm;
}

doclient(uid, gid)
{
	if(ptnum + 1 >= ptlen) {
		if(ptnum == 0) {
			ptemp = (short *)malloc(20 * sizeof(short));
			ptlen = 20;
		}
		else {
			ptlen *= 2;
			ptemp = (short *)realloc((char *)ptemp, ptlen * sizeof(short));
		}
	}
	ptemp[ptnum++] = uid;
	ptemp[ptnum++] = gid;
}

dohost(uid, gid)
{
	doclient(uid, gid);
}

ccmp(a, b)
pe *a, *b;
{
	if(a->cuid != b->cuid)
		return(a->cuid - b->cuid);
	else
		return(a->cgid - b->cgid);
}

hcmp(a, b)
pe *a, *b;
{
	if(a->huid != b->huid)
		return(a->huid - b->huid);
	else
		return(a->hgid - b->hgid);
}
psort(p)
ps *p;
{	int i;
	pe *x, *y;
	qsort((char *)p->tab, p->cnt, sizeof(pe), ccmp);
	for(i = 0; i < p->cnt; i++)
		p->inv[i] = p->tab[i];
	qsort((char *)p->inv, p->cnt, sizeof(pe), hcmp);
}

isfriend(s)
char *s;
{	int i;
	for(i = 0; i < nprm; i++)
		if(strcmp(prm[i].name, s) == 0)
			return(prm[i].ix);
	return(0);
}

pe *
hsearch(h, u, g)
{	pe *x;
	int lo, hi, j;
	h--;		/* change from ix to loc in array */
	debug4("hsearch(%s,%d,%d)", prm[h].name, u, g);
	lo = 0;
	hi = prm[h].cnt;
	x = prm[h].inv + (j = (lo + hi)/2);
	while(j > lo) {
		if(x->huid > u)
			hi = j;
		else
			lo = j;
		j = (lo + hi) / 2;
		x = prm[h].inv + j;
	}
	if(x->huid != u)
		return(0);
	for(; x >= prm[h].inv && x->huid == u; x--)
		if(x->hgid == g)
			return(x);
	if(x->huid != u)
		x++;
	return(x);
}
			

hostuid(s)
struct stat *s;
{	pe *x;
	x = hsearch(host, s->st_uid, s->st_gid);
	if(x)
		return(x->cuid);
	else
		return(-1);
}

hostgid(s)
struct stat *s;
{	pe *x;
	x = hsearch(host, s->st_uid, s->st_gid);
	if(x)
		return(x->cgid);
	else
		return(-1);
}

pe *
csearch(h, u, g)
{	pe *x;
	int lo, hi, j;
	h--;		/* change from ix to loc in array */
	debug4("csearch(%s,%d,%d)", prm[h].name, u, g);
	lo = 0;
	hi = prm[h].cnt;
	x = prm[h].tab + (j = (lo + hi)/2);
	while(j > lo) {
		if(x->cuid > u)
			hi = j;
		else
			lo = j;
		j = (lo + hi) / 2;
		x = prm[h].tab + j;
	}
	if(x->cuid != u)
		return(0);
	for(; x >= prm[h].tab && x->cuid == u; x--)
		if(x->cgid == g)
			return(x);
	if(x->cuid != u)
		x++;
	return(x);
}

myuid(u, g)
{	pe *x;
	x = csearch(host, u, g);
	if(x == 0)
		return(-1);
	else
		return(x->huid);
}

mygid(u, g)
{	pe *x;
	x = csearch(host, u, g);
	if(x == 0)
		return(-1);
	else
		return(x->hgid);
}

isowner(x, sbuf)
struct senda *x;
struct stat *sbuf;
{
	/* local file is owned by user */
	if((sbuf->st_mode & S_IFMT) == S_IFCHR || (sbuf->st_mode & S_IFMT) == S_IFBLK)
		return(0);
	if(sbuf->st_uid != -1 && myuid(x->uid, x->gid) == sbuf->st_uid)
		return(1);
	if(x->uid == 0)		/* cheat, not the whole story */
		return(1);
	return(0);
}
noaccess(x, sbuf, how)
struct senda *x;
struct stat *sbuf;
{	int n;
	n = myuid(x->uid, x->gid);
	if(n == -1 && x->uid == 0) {
		if(how == S_IEXEC)
			goto other;
		if(x->flags == NCREAT && (sbuf->st_mode & S_IFMT) == S_IFDIR)
			return(0);
		if(x->flags == NDEL && (sbuf->st_mode & S_IFMT) == S_IFDIR)
			return(0);
		if(x->flags == NLINK)
			return(0);
	}		
	if(n == -1)
		return(1);
	if((n == sbuf->st_uid) && (sbuf->st_mode & how))
		return(0);
	if((mygid(x->uid, x->gid) == sbuf->st_gid) && (sbuf->st_mode & (how >> 3)))
		return(0);
other:
	if(sbuf->st_mode & (how >> 6))
		return(0);
	return(1);
}
//GO.SYSIN DD perm.c
echo start.c 1>&2
sed 's/^-//' >start.c <<'//GO.SYSIN DD start.c'
#include "fserv.h"
#include "neta.h"

char cmdbuf[256];
int alive, rdcnt, wrcnt, dtime;
int rdnum;
extern struct rcva y, nilrcv;
int host;

work()
{	int n;
	struct senda *x;
	dtime = children[myfd].dtime;
	host = children[myfd].host;
	silent = children[myfd].silent;
	debugreset();
	do {
		/* would select be better? */
		n = xread(myfd, cmdbuf, sizeof(struct senda));
		if(n < 0) {
			debug("read -1 on %d for %s", myfd, children[myfd].who);
			leave(2);
		}
		if(n != sizeof(struct senda)) {
			debug("read %d wanted %d for %s", n, sizeof(struct senda),
				children[myfd].who);
			leave(3);
		}
		rdnum++;
		if(rdnum % 20 == 4)
			permredo();	/* every 10 minutes when idle */
		x = (struct senda *)cmdbuf;
		errno = 0;
		y = nilrcv;
		prcmd(x);
		switch(x->cmd) {
		default:
			debug("unk cmnd %d for %s", n, children[myfd].who);
			leave(4);
		case NSTAT:
			dostat(x);
			break;
		case NWRT:
			dowrite(x);
			break;
		case NREAD:
			doread(x);
			break;
		case NFREE:
			dofree(x);
			break;
		case NTRUNC:
			dotrunc(x);
			break;
		case NUPDAT:
			doupdat(x);
			break;
		case NGET:
			doget(x);
			break;
		case NNAMI:
			donami(x);
			break;
		case NPUT:
			doput(x);
			break;
		}
	} while(alive > 0);
	leave(0);
}

leave(n)
{	int i;
	debug("leaving(%d)", n);
	for(i = 0; i < dptr; i++) {
		strcat(debugbuf[i], "\n");
		write(dbgfd, debugbuf[i], strlen(debugbuf[i]));
	}
	exit(n);
}

extern netf netftab[];
extern int nnetf;
dumpstate()
{	struct senda *x = (struct senda *)cmdbuf;
	netf *p;
	int i;
	debug("\tmesg: ver %d flags %d trannum %d\n\tuid %d gid %d dev 0x%x tag %d mode 0%o",
	x->version, x->flags, x->trannum, x->uid, x->gid, x->dev, x->tag, x->mode);
	debug("\t\tino %d count %d offset %d", x->ino, x->count, x->offset);
	prcmd(x);
	debug("\t%s: fl %d dtime %d dev 0x%x host %d",
		children[myfd].who, children[myfd].flags, children[myfd].dtime,
		children[myfd].dev, children[myfd].host);
	for(i = 0; i < ndev; i++)
		debug("\tdev: ours 0x%x his 0x%x", devtab[i].ours,
			devtab[i].his);
	for(p = netftab, i = 0; i < nnetf; i++, p++) {
		debug("\tnetf %d dev 0x%x ino %d how %d fd %d %s",
			p->tag, p->dev, p->ino, p->how, p->fd,
			p->name? p->name: "(null)");
		debug("\tstat dev 0x%x ino %d mode 0%o nlink %d size %d",
			p->statb.st_dev, p->statb.st_ino, p->statb.st_mode,
			p->statb.st_nlink, p->statb.st_size);
		debug("\t\tuid %d gid %d ctime %s\t\t", p->statb.st_uid,
			p->statb.st_gid, ctime(&p->statb.st_ctime));
	}
}
//GO.SYSIN DD start.c
echo sub.c 1>&2
sed 's/^-//' >sub.c <<'//GO.SYSIN DD sub.c'
#include "fserv.h"
#include "errno.h"
#include "neta.h"

extern char *realloc();
/* temporary static alloc of devtab */

struct tdev devtab[NDEV];
struct stat rootstat;
int ndev, dev;
extern int alive;
char *cmdnames[] = {"0?", "stat", "wrt", "read", "free", "trunc", "updat",
	"get", "nami", "put", "10?"};
char *buf, *nbuf;
int buflen, nbuflen;

#define NF	100
/* temporary static alloc of netftab */
netf netftab[NF];
int nnetf;

#define MASK	0x0

ourdev(n)
{	int i;
	for(i = 0; i < ndev; i++)
		if(devtab[i].his == n)
			return(devtab[i].ours);
	return(-1);
}

hisdev(n)
{	int i;
	for(i = 0; i < ndev; i++)
		if(devtab[i].ours == n)
			return(devtab[i].his);
	return(-1);
}

newdev(n)
{	struct tdev *p;
	p = devtab + ndev++;
	p->ours = n;
	p->his = dev++;
	debug1("\tnewdev %d %d", p->ours, p->his);
}

netf *
gettag(n)
long n;
{	int i;
	for(i = 0; i < nnetf; i++)
		if(netftab[i].tag == n)
			return(netftab + i);
	errno = ENOENT;
	return(0);
}

netf *
getnetf(d, i)	/* either root of netfs, or in the table */
{	int j;
	netf *p;
	if(i == 0) {
		errno = ENOENT;
		return(0);
	}
	for(j = 0; j < nnetf; j++)
		if(netftab[j].ino == i && netftab[j].dev == d)
			return(netftab + j);
	debug2("\tgetnetf(%d,%d)", d, i);
	for(p = netftab, j = 0; j < nnetf; j++, p++) {
		debug2("\t%d %d %d %s", p->tag, p->dev, p->ino, p->name?p->name:"");
	}
	return(0);
}
netf *
oldnetf(s)	/* special case for nami/NDEL */
char *s;
{	netf *p;
	struct stat stb;
	if(xstat(s, &stb) < 0)
		return(0);
	if(p = getnetf(hisdev(stb.st_dev), stb.st_ino)) {
		p->statb = stb;
		return(p);
	}
	return(0);
}

netf *
newnetf(s, fd, how)
char *s;
{	int i;
	netf *p;
	struct stat stb;
	if(xstat(s, &stb) < 0)
		return(0);
	if(p = getnetf(hisdev(stb.st_dev), stb.st_ino)) {
		p->statb = stb;
		return(p);
	}
	for(i = 0; i < nnetf; i++)
		if(netftab[i].ino == 0)
			goto found;
	i = nnetf++;
	if(nnetf > NF) {
		errno = ENOMEM;
		return(0);
	}
found:
	alive++;
	p = netftab + i;
	p->name = malloc(strlen(s) + 1);
	strcpy(p->name, s);
	p->statb = stb;
	if(fd < 0) {
		if(ftype(p) == S_IFLNK || ftype(p) == S_IFCHR || ftype(p) == S_IFBLK)
			p->fd = -1;
		else if (ftype(p) == S_IFDIR) {
			if((p->dirp = opendir(p->name)) != 0) {
				p->diroffset = telldir(p->dirp);
				p->fd = p->dirp->dd_fd;
			} else {
				p->fd = -1;
				perror(p->name);
			}
		} else
			p->fd = open(p->name, 0);	/* this better work */
		p->how = 0;
	}
	else {
		p->fd = fd;
		p->how = how;
	}
	p->dev = hisdev(p->statb.st_dev);
	if(p->dev == -1) {
		newdev(p->statb.st_dev);
		p->dev = hisdev(p->statb.st_dev);
	}
	p->ino = p->statb.st_ino;
	p->tag = (p->dev << 16) ^ p->ino ^ MASK;
	debug2("\tnew %d %d %s", p->dev, p->ino, p->name);
	debug2("\tnew 0%o %d %d", p->statb.st_mode, p->statb.st_uid, p->statb.st_gid);
	debug2("\tnew %d", nnetf);
	return(p);
}

clrnetf(n)
{	netf *p;
	p = gettag(n);
	if(p == 0) {
		debug("\tclr net got 0 (x%x)", n);
		dumpstate();
		leave(8);	/* shut it down */
		return;
	}
	if(p->ino == 2 && p->dev == devtab[0].his)
		return;		/* hold on to the root */
	if(p->tag != n) {
		debug("\tclr weird %d %d", n, p->tag);
		errno = EIO;
		dumpstate();
		return;
	}
	debug1("\tclear %d %s", p->tag, p->name);
	if(p->fd != -1) {
		close(p->fd);
		p->fd = -1;
		p->how = 0;
	}
	p->tag = p->dev = p->ino = 0;
	if(p->name)
		free(p->name);
	p->name = 0;
	alive--;
}

opennf(p, fl)	/* fl: 0-read, 1-write, 2-trunc */
netf *p;
{	struct stat stb;

	if(p->fd != -1 && p->how == fl)
		return(0);
	if(fl == 2) {
		errno = EPERM;
		return(1);
	}
	if(xstat(p->name, &stb) < 0)
		return(0);
	p->statb = stb;
	if (ftype(p) != S_IFDIR)
		p->fd = open(p->name, fl);
	else {
		if (fl != 0) {
			errno = EISDIR;
			return(1);
		}
		p->dirp = opendir(p->name);
		if (p->dirp != 0)
			p->fd = p->dirp->dd_fd;
	}
	debug1("\topennf %s %d", p->name, p->fd);
	if(p->fd == -1)
		return(1);
	p->how = fl;
	return(0);
}

truncnf(n)
long n;
{	netf *p;
	int fd;
	p = gettag(n);
	if(p == 0) {
		debug("\ttrunc %d", n);
		errno = EIO;
		dumpstate();
		return;
	}
	if(p->fd != -1)
		close(p->fd);
	fd = creat(p->name, 0);
	p->fd = fd;
	p->how = 1;
}

isroot(p)
netf *p;
{
	debug2("\tisroot(dev=%d ino=%d), ourde=%d", p->dev, p->ino, ourdev(p->dev));
	return(p->ino == rootstat.st_ino && ourdev(p->dev) == rootstat.st_dev);
}

prcmd(x)
struct senda *x;
{
	debug1("got %s %d %d %d", cmdnames[x->cmd], major(x->dev), minor(x->dev), x->ino);
}

getbuf(n)
{
	if(n < buflen)
		return;
	if(buflen == 0)
		buf = malloc(buflen = n);
	else
		buf = realloc(buf, buflen = n);
	if(buf)
		return;
	debug("getbuf failed");
	leave(6);
}

getnbuf(n)
long n;
{
	if(n < nbuflen)
		return;
	if(nbuflen == 0)
		nbuf = malloc(nbuflen = n);
	else
		nbuf = realloc(nbuf, nbuflen = n);
	if(nbuf)
		return;
	debug("nbuf failed");
	leave(7);
}
/* the current name is a full path name, buf contains another component */
fixnbuf(name, count, buf, flag)
char *name, *buf;
{	int i, n;
	for(i = 0; i < count && buf[i]; i++)
		;
	count = i;
	n = strlen(name);
	getnbuf(n + count + 2);
	strcpy(nbuf, name);
	if(count > 2 || flag == NLINK || flag == NDEL) {
ok:
		nbuf[n++] = '/';
		for(i = 0; i < count; i++)
			nbuf[n++] = *buf++;
		nbuf[n] = 0;
		return;
	}
	if(count == 0)
		return;
	if(count == 1)
		if(buf[0] == '.')
			return;	/* do we know that name is a directory? */
		else
			goto ok;
	if(buf[0] != '.' || buf[1] != '.')
		goto ok;
	while(n > 0 && nbuf[n] != '/')
		n--;
	nbuf[n] = 0;
	if(nbuf[0] != '/')
		strcpy(nbuf, "/..");
}
//GO.SYSIN DD sub.c
echo sys.c 1>&2
sed 's/^-//' >sys.c <<'//GO.SYSIN DD sys.c'
#include "stdio.h"
#include "fserv.h"
#include "signal.h"
#include "sys/wait.h"
#include "errno.h"

extern int dev;
extern struct stat statb;
extern char *ctime();
extern char *buf, *nbuf;

dummy()
{
	signal(SIGCHLD, dummy);
}

hup()
{
	signal(SIGHUP, hup);
	fprintf(stderr, "hup %d\n", getpid());
}

signals()
{	extern int profit();
	hup();
	signal(SIGINT, SIG_IGN);
	signal(SIGCHLD, dummy);
	signal(SIGTERM, profit);
	signal(SIGPIPE, SIG_IGN);
	setpgrp(0, getpid());
}

reapchild()
{	int pid, i;
	int status;
	pid = wait3(&status, WNOHANG, 0);
	if(pid <= 0)
		return;
	for(i = 0; i < NORMAN; i++)
		if(children[i].pid == pid) {
			children[i].pid = 0;
			if(status) {	/* bye bye */
				debug("child fd %d status 0x%x", i, status);
				close(children[i].fd);
				children[i].fd = 0;
				children[i].flags = 0;
				if(children[i].who)
					free(children[i].who);
				children[i].who = 0;
				return;
			}
			children[i].flags = CONN;
			children[i].lastheard = time(0);
			FD_SET(i, active);
			debug("wait got %d %s", pid, children[i].who);
			return;
		}
	debug("wait got pid %d, not found", pid);
}

serve(n, argp)	/* ok child[n] */
char *argp;	/* for ps */
{	int i;
	long now;
	if(children[n].flags == UNINIT) {
		doinit(n);
		return;
	}
	myfd = n;
	children[n].pid = fork();
	if(children[n].pid == -1) {	/*can't fork, what a pain*/
		perror(children[n].who);
		debug("couldn't fork, bye");
		return;	/* not enough */
	}
	if(children[n].pid == 0) {
		for(i = 0; i < NOFILE-1; i++)
			if(i != myfd && i != dbgfd)
				close(i);
		debug("child %d started for %s", getpid(), children[n].who);
		dev = children[n].dev;
		newdev(statb.st_dev);
		(void) newnetf("/", -1, 0);
		for(i = 0; argp[i]; i++)
			argp[i] = children[n].who[i];
		work();
	}
	FD_CLR(n, active);
	/* should close n, but how would we know who to kill? */
}

xstat(s, b)
char *s;
struct stat *b;
{	int i;
	i = lstat(s, b);
	if(i < 0)
		return(i);
	if((b->st_mode & S_IFMT) == S_IFCHR || (b->st_mode & S_IFMT) == S_IFBLK)
		b->st_mode &= ~0777;
	if(isremote(b->st_dev)) {
		errno = ELOOP;
		return(-1);
	}
	return(i);
}

isremote(n)	/* temporary, maybe should read /etc/net/friends, or ask sys */
{
	/*if(((n>>8) & 0xff) >= 48)
		return(1);*/	/* let's see what happens with it off */
	return(0);
}

lcllink(q)
netf *q;
{
	getbuf(q->statb.st_size + 1);
	readlink(q->name, buf, q->statb.st_size);
	if(buf[0] != '/')
		return(0);
	buf[q->statb.st_size] = 0;
	getnbuf(q->statb.st_size + 1);
	clrnetf(q->tag);
	strcpy(nbuf, buf);
	return(1);
}
//GO.SYSIN DD sys.c
echo work.c 1>&2
sed 's/^-//' >work.c <<'//GO.SYSIN DD work.c'
#include "fserv.h"
#include "errno.h"
#include "neta.h"
extern char *buf, *nbuf;
extern int dtime, myfd, wrcnt, rdcnt, lflag;
extern struct rcva y, nilrcv;

doput(x)
struct senda *x;
{
	y.trannum = x->trannum;
	if(x->tag == 0) {
		debug("\tput got 0");
		respond(EIO);
		dumpstate();
		leave(9);
	}
	clrnetf(x->tag);
	respond(errno);
}

doget(x)
struct senda *x;
{	netf *p;
	y.trannum = x->trannum;
	p = getnetf(x->dev, x->ino);
	if(p == 0) {
		debug("\tget didn't %d %d", x->dev, x->ino);
		respond(errno);
		dumpstate();
		return;
	}
	if(p->fd == -1 && xstat(p->name, &p->statb) < 0
		|| p->fd != -1 && fstat(p->fd, &p->statb) < 0) {
		respond(errno);
		return;
	}
	debug2("\tget %d %d 0%o %d %d %s\n", p->dev, p->ino,
		p->statb.st_mode, p->statb.st_uid, p->statb.st_gid, p->name);
	y.mode = p->statb.st_mode;
	y.tag = p->tag;
	y.nlink = p->statb.st_nlink;
	y.uid = hostuid(&p->statb);
	y.gid = hostgid(&p->statb);
	y.size = p->statb.st_size;
	respond(0);
}

dofree(x)		/* means rmt thinks nlink == 0 */
struct senda *x;
{
	y.trannum = x->trannum;
	respond(0);
}

doupdat(x)
struct senda *x;
{	netf *p;
	int i;
	y.trannum = x->trannum;
	p = gettag(x->tag);
	if(p == 0) {
		respond(errno);
		return;
	}
	debug2("\tupdat 0%o %d %d\n", p->statb.st_mode, p->statb.st_uid, p->statb.st_gid);
	debug2("\t\t0%o %d %d\n", x->mode, x->uid, x->gid);
	x->ta += dtime;
	x->tm += dtime;
	if(p->name == 0) {	/* of course this can't happen */
		debug("\tname 0 tag %d\n", p->tag);
		respond(EIO);
		dumpstate();
		return;
	}
	debug2("\t%s\n", p->name);
	if(x->ta == dtime)
		x->ta = p->statb.st_atime;
	if(x->tm == dtime)
		x->tm = p->statb.st_mtime;
	utime(p->name, &x->ta);
	errno = 0;	/* p->name may be wrong, so times off [bug] */
	if(x->mode != p->statb.st_mode) {
		i = 1;
		if(isowner(x, &p->statb))
			fchmod(p->fd, x->mode);
		else
			errno = EPERM;
		perror("\tfchmod");
	}
	if(x->uid == 0 && (hostuid(&p->statb) != x->newuid
		|| hostgid(&p->statb) != x->newgid)) {
		i = 1;
		if(isowner(x, &p->statb))
			fchown(p->fd, myuid(x->newuid, x->newgid),
				mygid(x->newuid, x->newgid));
		else
			errno = EPERM;
		if(errno)
			perror("\tfchown");
		debug1("\tupdat %d %d\n", p->statb.st_uid, p->statb.st_gid);
	}
	if(i)
		fstat(p->fd, &p->statb);
	y.mode = p->statb.st_mode;
	y.nlink = p->statb.st_nlink;
	y.uid = hostuid(&p->statb);
	y.gid = hostgid(&p->statb);
	y.size =  p->statb.st_size;
	if(hisdev(p->statb.st_dev) != p->dev || p->ino != p->statb.st_ino) {
		debug("\tdev oops\n");
		dumpstate();
	}
	respond(errno);
}

doread(x)
struct senda *x;
{	netf *p;
	int n, offset = 0;
	y.trannum = x->trannum;
	p = gettag(x->tag);
	if(p == 0) {
		if(errno == 0)
			errno = EIO;
		respond(errno);
		return;
	}
	if(ftype(p) == S_IFLNK) {
		n = readlink(p->name, buf, x->count);
		offset = x->offset;
		debug2("readlink %s %d %d\n", p->name, n, x->count);
		offset = x->offset;
		if(n < offset)
			offset = n;
	}
	else {
		if(opennf(p, 0)) {
			respond(errno);
			return;
		}
		getbuf(x->count);
		if (ftype(p) == S_IFDIR)
			n = xreaddir(p, buf, x);
		else {
			if(lseek(p->fd, x->offset, 0) < 0)
				perror("\tread lseek");
			n = read(p->fd, buf, x->count);
		}
	}
	debug1("\tread got %d wanted %d\n", n, x->count);
	if(n < 0) {
		y.errno = errno;
		y.count = n;
		respond(0);
		return;
	}
	y.count = n - offset;
	respond(0);
	(void) xwrite(myfd, buf + offset, (unsigned) n - offset);
	wrcnt += n;
}

dowrite(x)
struct senda *x;
{	netf *p;
	int n;
	y.trannum = x->trannum;
	if(x->count == 0)
		respond(0);
	getbuf(x->count);
	if((n = xread(myfd, buf, x->count)) != x->count) {
		debug("\twrite expected %d got %d\n", x->count, n);
		rdcnt += n;
		if(errno == 0)
			errno = EIO;
		respond(errno);
		dumpstate();
		return;
	}
	wrcnt += n;
	debug1("\twrite %d\n", x->count);
	p = gettag(x->tag);
	if(p == 0) {
		respond(errno);
		return;
	}
	if(opennf(p, 1)) {
		respond(errno);
		return;
	}
	n = lseek(p->fd, x->offset, 0);
	if(n < 0) {
		debug("\twrite lseek %d\n", errno);
		dumpstate();
	}
	if((n = write(p->fd, buf, x->count)) != x->count) {
		debug("\twrite failed %d %d\n", n, p->fd);
		if(errno == 0)
			errno = EIO;
		dumpstate();
	}
	respond(errno);
}

dotrunc(x)
struct senda *x;
{
	y.trannum = x->trannum;
	truncnf(x->tag);
	respond(errno);
}

dostat(x)
struct senda *x;
{	netf *p;
	y.trannum = x->trannum;
	debug2("\tstat %d\n", x->tag);
	p = gettag(x->tag);
	if(p == 0) {
		respond(errno);
		return;
	}
	debug2("\tlstat %s ", p->name);
	if(p->fd == -1 && xstat(p->name, &p->statb) < 0
		|| p->fd != -1 && fstat(p->fd, &p->statb) < 0) {
		respond(errno);
		return;
	}
	debug2("0%o %d %d\n", p->statb.st_mode, p->statb.st_uid, p->statb.st_gid);
	y.mode = p->statb.st_mode;
	y.nlink = p->statb.st_nlink;
	y.uid = hostuid(&p->statb);
	y.gid = hostgid(&p->statb);
	debug2("\thostuid(%d) = %d\n", p->statb.st_uid, y.uid);
	debug2("\tgid %d\n", y.gid);
	y.size = p->statb.st_size;
	y.tm[0] = p->statb.st_atime;
	y.tm[1] = p->statb.st_mtime;
	y.tm[2] = p->statb.st_ctime;
	if(hisdev(p->statb.st_dev) != p->dev || p->ino != p->statb.st_ino) {
		debug("\toops dev or ino\n");
		dumpstate();
	}
	respond(0);
}

donami(x)
struct senda *x;
{	netf *p, *q;
	int fd, i, nlink = 0;
	y.trannum = x->trannum;
	getbuf(x->count);
	if((i = xread(myfd, buf, x->count)) != x->count) {
		rdcnt += i;
		if(errno == 0)
			errno = EIO;
		respond(errno);
		return;
	}
	rdcnt += i;
	p = gettag(x->tag);
	if(p == 0) {
		respond(errno);
		return;
	}
	debug1("\tcdir %s 0%o %d %d\n", p->name, p->statb.st_mode,
		p->statb.st_uid, p->statb.st_gid);
	if(ftype(p) != S_IFDIR) {
		respond(ENOTDIR);
		return;
	}
	if(noaccess(x, &p->statb, S_IEXEC)) {
		respond(EACCES);
		return;
	}
	fixnbuf(p->name, x->count, buf, x->flags);
	debug2("\tnami %s (%d)\n", nbuf, x->flags);
again:
	q = 0;
	if(x->flags == NDEL)
		q = oldnetf(nbuf);
	if(q == 0)
		q = newnetf(nbuf, -1, 0);
	if(q != 0) {
		debug2("\tfound\n");
		errno = 0;
		if(/*lflag && */ftype(q) == S_IFLNK)
			if(lcllink(q)) {
				if(nlink++ > 4) {
					errno = ELOOP;
					goto bad;
				}
				goto again;
			}
		y.ino = q->ino;
		y.tag = q->tag;
		y.dev = q->dev;
		y.mode = q->statb.st_mode;
		y.nlink = q->statb.st_nlink;
		y.uid = hostuid(&q->statb);
		y.gid = hostgid(&q->statb);
		y.size = q->statb.st_size;
		if(isroot(q) && strncmp(buf, ".", x->count)) {
			debug2("NROOT %s\n", buf);
			y.flags = NROOT;
		}
		if(x->flags == NDEL) {
			if(noaccess(x, &p->statb, S_IWRITE)) {
				debug1("\tnodelete\n");
				respond(EPERM);
				return;
			}
			if(y.dev != x->dev)
				errno = EBUSY;
			if(y.flags == NROOT)
				errno = EPERM;
			(void) unlink(nbuf);
			debug1("\tunlink %s %d\n", nbuf, errno);
		}
		if(x->flags == NCREAT && noaccess(x, &q->statb, S_IWRITE)) {
			debug1("\tnocreat\n");
			respond(EPERM);
			return;
		}
		respond(errno);
		return;
	}
	else {
		y.flags = NOMATCH;
		if(x->flags == NLINK) {
			if(noaccess(x, &p->statb, S_IWRITE)) {
				debug1("\tnolink %d %d %d\n", x->uid,
					p->statb.st_uid, p->statb.st_gid);
				respond(EPERM);
				return;
			}
			q = gettag(x->tag);
			p = getnetf(x->dev, x->ino);
			if(q == 0 || p == 0) {
				debug1("\tno link p 0x%x q 0x%x", p, q);
				respond(EXDEV);
				return;
			}
			debug1("\tlink %d %d %d %s %s",
				x->dev, x->ino, q->dev, p->name, nbuf);
			if(q->dev != p->dev)
				errno = EXDEV;
			i = link(p->name, nbuf);
			if(i != -1)
				errno = 0;
			else
				debug("\tlink %d", errno);
		}
		else if(x->flags == NCREAT) {
			debug1("\tnami creat 0%o %s\n", x->mode, nbuf);
			if(noaccess(x, &p->statb, S_IWRITE)) {
				debug1("\tnoaccess\n");
				respond(EACCES);
				return;
			}
			switch(x->mode & S_IFMT) {
			case 0:
			case S_IFREG:
				fd = creat(nbuf, x->mode);
				if(fd != -1) {
					q = newnetf(nbuf, fd, 1);
					y.ino = q->ino;
					y.dev = q->dev;
					errno = 0;
					chown(nbuf, myuid(x->uid, x->gid),
						mygid(x->uid, x->gid));
					debug1("\tchown %d %d\n",
						myuid(x->uid, x->gid),
						mygid(x->uid, x->gid));
					(void) fstat(fd, &q->statb);
				}
				break;
			case S_IFDIR:
				if(x->uid != 0) {
					debug1("\tsuser %d\n", x->uid);
					respond(EPERM);
					return;
				}
				i = mknod(nbuf, x->mode, 0);
				if(i != -1) {
					q = newnetf(nbuf, -1, 0);
					y.ino = q->ino;
					y.dev = q->dev;
					errno = 0;
					chown(nbuf, myuid(x->uid, x->gid),
						mygid(x->uid, x->gid));
					(void) fstat(q->fd, &q->statb);
					debug1("\tmknod 0%o %d %d\n",
						q->statb.st_mode, q->statb.st_uid, q->statb.st_gid);
				}
				else
					debug1("\tmknod\n");
				break;
			case S_IFLNK:
				errno = 0;
				fd = creat(nbuf, 0777);
				if(fd < 0)
					break;
				chown(nbuf, myuid(x->uid, x->gid),
					mygid(x->uid, x->gid));
				i = fchmod(fd, x->mode | S_IFLNK);
				debug1("\tfchmod(%s) %d errno %d\n", nbuf, i, errno);
				if(errno == 0) {
					debug2("\tfd = %d\n", fd);
					q = newnetf(nbuf, fd, 1);
					y.ino = q->ino;
					y.dev = q->dev;
				}
				break;
			default:
				errno = EPERM;
				break;
			}
		}
	}
bad:
	y.tag = q->tag;
	y.nlink = q->statb.st_nlink;
	y.size = q->statb.st_size;
	y.uid = hostuid(&q->statb);
	y.gid = hostuid(&q->statb);
	respond(errno);
}
//GO.SYSIN DD work.c
echo profit.c 1>&2
sed 's/^-//' >profit.c <<'//GO.SYSIN DD profit.c'
#include "stdio.h"
#include "signal.h"
struct rec {
	long len;
	struct rec *next;
	char *fname;
	long cnt[1];
} *proFptr = (struct rec *)-1;	/* end of list marker */
profit()
{	int i;
	FILE *fd;
	struct rec *x = proFptr;
	fd = fopen("/etc/net/prof.out", "w");
	if(fd == NULL)
		fd = fopen("/usr/net/prof.out", "w");
	while(x != (struct rec *)-1) {
		fprintf(fd, "%s\n", x->fname);
		for(i = 3; i < x->len; i++)
			fprintf(fd, "%d\n", x->cnt[i-3]);
		x = x->next;
	}
	fflush(fd);
	fclose(fd);
	signal(SIGTERM, profit);
}
//GO.SYSIN DD profit.c
exit


From mcvax!ukc!mmdf  Mon Oct 21 17:14:44 1985
>From ukc!mmdf  Mon Oct 21 17:14:44 1985 remote from mcvax
Received: by mcvax.UUCP; Mon, 21 Oct 85 17:14:44 +0100 (MET)
Message-Id: <8510211614.AA24367@mcvax.UUCP>
Received: from [nedaftp] by ukc.AC.UK id a007863; 21 Oct 85 17:01 BST
From: Andy Linton <mcvax!cheviot!andy>, mcvax!ndy@cheviot.newcastle.ac.uk
Mmdf-Warning:  Parse error in original version of preceding line at Ukc.AC.UK
Date: Mon, 21 Oct 85 14:46:12 bst
To: research!v8news
Subject: Deuna driver


We'll  take one - bugs and all!
Thanks
andy

From dutoit!dmr Thu Oct 24 00:56 EDT 1985
>From dmr Thu Oct 24 00:56 EDT 1985 remote from dutoit
Subject: v8 tapes

I called Judy Macor after coming back from some vacation and it
turns out that tapes were not mailed until today!  She had them
the day I first sent my triumphant announcement but there was
some sort of nonsense that prevented the mailing.   The ones
actually sent were to Newcastle and to Toronto.  I asked how
the Newc. one was sent, and she said she specified (to shipping)
"the fastest way" and had them decide.

The Princeton one is supposed to be mailed when Judy finds Pat P's
address.

There is some remaining hangup on Purdue.  McIlroy is
be working on it.  I will poke him tomorrow.  It is not supposed to
be serious, but the last one was supposed to be nonexistent.

I think she still wants paper from Sydney.

If you want to communicate directly with her, the address is

	Judy Macor
	AT&T Bell Laboratories, 2F128
	Murray Hill, NJ 07974

	phone 201-582-7710


	Dennis

PS. to Andy-- the only v8source has been Honeyman's file
server stuff, which was mailed about the same instant as
your inquiry.  I trust it's arrived?

From mcvax!ukc!eagle.ukc.ac.uk!cheviot.newcastle.ac.uk!ncx  Thu Oct 24 14:21:10 1985
>From ukc!eagle.ukc.ac.uk!cheviot.newcastle.ac.uk!ncx  Thu Oct 24 14:21:10 1985 remote from mcvax
Received: by mcvax.UUCP; Thu, 24 Oct 85 14:21:10 +0100 (MET)
Message-Id: <8510241321.AA05783@mcvax.UUCP>
Received: from [nedaftp] by ukc.AC.UK id a028985; 24 Oct 85 13:10 BST
From: "Lindsay F. Marshall" <mcvax!ncx@cheviot.newcastle.ac.uk>
Date: Thu, 24 Oct 85 13:10:23 bst
To: research!v8news
Subject: The fastest way.....................

I shall expect the ATT ICBM to land at any instant.

	Lindsay

P.S.  I hope you left the plaster at home when you were on holiday, Dennis

------------------------------------------------------------------------------
Lindsay F. Marshall, Computing Lab., U of Newcastle upon Tyne, Tyne & Wear, UK
  ARPA  : lindsay%cheviot.newcastle.ac.uk@ucl-cs.arpa
  JANET : lindsay@uk.ac.newcastle.cheviot
  UUCP  : <UK>!ukc!cheviot!lindsay
-------------------------------------------------------------------------------

From mcvax!ukc!eagle.ukc.ac.uk!cheviot.newcastle.ac.uk!ncx  Thu Oct 24 16:18:49 1985
>From ukc!eagle.ukc.ac.uk!cheviot.newcastle.ac.uk!ncx  Thu Oct 24 16:18:49 1985 remote from mcvax
Received: by mcvax.UUCP; Thu, 24 Oct 85 16:18:49 +0100 (MET)
Message-Id: <8510241518.AA13345@mcvax.UUCP>
Received: from [nedaftp] by ukc.AC.UK id a004634; 24 Oct 85 15:21 BST
From: "Lindsay F. Marshall" <mcvax!ncx@cheviot.newcastle.ac.uk>
Date: Thu, 24 Oct 85 15:20:35 bst
To: research!v8news
Subject: 4.2 file systems.....

I know this sounds like heresy but has anyone a file system type that
supports the 4.2 disc structures ..............

Lindsay
------------------------------------------------------------------------------
Lindsay F. Marshall, Computing Lab., U of Newcastle upon Tyne, Tyne & Wear, UK
  ARPA  : lindsay%cheviot.newcastle.ac.uk@ucl-cs.arpa
  JANET : lindsay@uk.ac.newcastle.cheviot
  UUCP  : <UK>!ukc!cheviot!lindsay
-------------------------------------------------------------------------------


From mcvax!ukc!eagle.ukc.ac.uk!cheviot.newcastle.ac.uk!ncx  Tue Oct 29 11:18:05 1985
>From ukc!eagle.ukc.ac.uk!cheviot.newcastle.ac.uk!ncx  Tue Oct 29 11:18:05 1985 remote from mcvax
Received: by mcvax.UUCP; Tue, 29 Oct 85 11:18:05 +0100 (MET)
Message-Id: <8510291018.AA15250@mcvax.UUCP>
Received: from [nedaftp] by ukc.AC.UK id a010683; 29 Oct 85 10:10 GMT
From: "Lindsay F. Marshall" <mcvax!ncx@cheviot.newcastle.ac.uk>
Date: Mon, 28 Oct 85 14:58:28 gmt
To: research!v8news
Subject: 4.2 file systems

Soembody mailed me this weekend asking why I wanted this. Unfortunately,
whilst skimming through my mail my BLIT threw a wobbler and sent all
kinds of garbage up the line, resulting in the complete loss of all my
mail *SIGH*. So I dont know who it was who asked, but here's
why....................

Basically, we have no useful demountable discs, and it would be nice to
keep our options open as regards which system we run (some people have
been using features of 4.2 in their work). Now, 4.2 .just isnt flexible
enough to allow this, but perhaps we coud do it with V8??????

Lindsay

From princeton!down!honey  Sat Nov  2 19:18:11 1985
>From down!honey  Sat Nov  2 19:18:11 1985 remote from princeton
Date: 2 Nov 1985 19:16-EST
To: research!v8news
Subject: rwhod, rwho, ruptime

in my bid for the dubious achievement award for 1985, i am following this
note by a posting of the 4.2 udp/who server, modified for eighth edition.

	peter


From princeton!down!honey  Sat Nov  2 19:20:27 1985
>From down!honey  Sat Nov  2 19:20:27 1985 remote from princeton
Date: 2 Nov 1985 19:18-EST
To: research!v8source

# To unbundle, sh this file
echo makefile 1>&2
sed 's/^-//' >makefile <<'//GO.SYSIN DD makefile'
CC=cc -g
CFLAGS=-I/usr/src/cmd/inet/h
DESTDIR=/usr/inet

all: rwhod ruptime rwho

rwhod:	rwhod.o
	${CC} -o rwhod rwhod.o -lin

ruptime: ruptime.o
	${CC} -o ruptime ruptime.o

rwho: rwho.o
	${CC} -o rwho rwho.o

install: rwhod ruptime rwho
	cp rwhod ${DESTDIR}/etc/rwhod
	-mkdir ${DESTDIR}/usr/spool/rwho
	cp ruptime rwho ${DESTDIR}/bin

clean:
	rm -f rwhod rwhod.o ruptime ruptime.o rwho rwho.o a.out core errs
//GO.SYSIN DD makefile
echo rwhod.h 1>&2
sed 's/^-//' >rwhod.h <<'//GO.SYSIN DD rwhod.h'
#include <sys/param.h>
#include <stdio.h>
#include <utmp.h>
#include <sys/inet/udp_user.h>
#include "config.h"

struct	whod {
	struct udpaddr udpaddr;		/* datagram header */
	char	wd_vers;		/* protocol version # */
	char	wd_type;		/* packet type, see below */
	char	wd_pad[2];
	long	wd_sendtime;		/* time stamp by sender */
	long	wd_recvtime;		/* time stamp applied by receiver */
	char	wd_hostname[32];	/* hosts's name */
	int	wd_loadav[3];		/* load average as in uptime */
	long	wd_boottime;		/* time system booted */
	struct	whoent {
		struct	utmp we_utmp;	/* active tty info */
		int	we_idle;	/* tty idle time */
	} wd_we[1024 / sizeof (struct whoent)];
};

#define	WHODVERSION	1
#define	WHODTYPE_STATUS	1		/* host status */
//GO.SYSIN DD rwhod.h
echo rwhod.c 1>&2
sed 's/^-//' >rwhod.c <<'//GO.SYSIN DD rwhod.c'
#include "rwhod.h"

#include <sys/stat.h>
#include <sys/utsname.h>
#include <sys/ioctl.h>

#include <ctype.h>
#include <errno.h>
#include <nlist.h>
#include <signal.h>

extern int errno;
extern long lseek(), time();
extern int sprintf();

int configure();

struct	nlist nl[] = {
#define	NL_AVENRUN	0
	{ "_avenrun" },
#define NL_NINET	1
	{"_Ninet"},
	0
};

/*
 * We communicate with each neighbor in
 * a list constructed at the time we're
 * started up.  Neighbors are currently
 * directly connected via a hardware interface.
 */
in_addr *neighbors;
int ninet;

struct	whod mywd;
int	s, utmpf, kmemf = -1;

#define LASTBOOT	"/usr/adm/lastboot"
#define	WHDRSIZE	(sizeof (mywd) - sizeof (mywd.wd_we))
#define	RWHODIR		"/usr/spool/rwho"
#define IPDEVICE	"/dev/ip0"

#ifndef DEBUG
#define xwrite write
#endif

main()
{	int i, n, cc, whod;
	struct whoent *we;
	struct in_service *sp;
	char path[64];
	struct utsname ubuf;
	struct whod wd;
	int onalrm();
	extern char *strcpy();
	extern struct in_service *in_service();

	if (getuid()) {
		fprintf(stderr, "rwhod: not super user\n");
		exit(1);
	}
	if (uname(&ubuf) < 0) {
		perror("uname");
		exit(1);
	}
	utmpf = open(UTMP, 0);
	if (utmpf < 0) {
		fputs("rwhod: ", stderr);
		perror(UTMP);
		exit(1);
	}

	sp = in_service("who", "udp", 0);
	if (sp == 0) {
		fprintf(stderr, "rwhod: udp/who: unknown service\n");
		exit(1);
	}
	mywd.udpaddr.port = sp->port;
	(void) signal(SIGHUP, configure);
	strcpy(mywd.wd_hostname, ubuf.sysname);
	getkmem();

	if ((s = udp_datagram(sp->port)) < 0) {
		perror("rwhod: socket");
		exit(1);
	}
	configure();
	onalrm();
	for (;;) {
		cc = read(s, (char *)&wd, sizeof (struct whod));
		if (cc <= 0) {
			if (cc < 0 && errno != EINTR)
				perror("rwhod: read");
			continue;
		}
		if (wd.udpaddr.port != sp->port) {
			fprintf(stderr, "rwhod: %d: bad from port\n",
				ntohs(wd.udpaddr.port));
			continue;
		}
		if (wd.wd_vers != WHODVERSION)
			continue;
		if (wd.wd_type != WHODTYPE_STATUS)
			continue;
		if (!verify(wd.wd_hostname)) {
			fprintf(stderr, "rwhod: malformed host name from %x\n",
				wd.udpaddr.host);
			continue;
		}
		(void) sprintf(path, "%s/whod.%s", RWHODIR, wd.wd_hostname);
		whod = creat(path, 0666);
		if (whod < 0) {
			fprintf(stderr, "rwhod: ");
			perror(path);
			continue;
		}

		/* undo header byte swapping before writing to file */
		wd.wd_sendtime = ntohl((u_long) wd.wd_sendtime);
		for (i = 0; i < 3; i++)
			wd.wd_loadav[i] = ntohl((u_long) wd.wd_loadav[i]);
		wd.wd_boottime = ntohl((u_long) wd.wd_boottime);
		we = wd.wd_we;
		n = (cc - WHDRSIZE)/sizeof(struct whoent);
		for (i = 0; i < n; i++) {
			we->we_idle = ntohl((u_long) we->we_idle);
			we->we_utmp.ut_time =
				    ntohl((u_long) we->we_utmp.ut_time);
				we++;
		}
		(void) time(&wd.wd_recvtime);
		(void) write(whod, (char *)&wd, cc);
		(void) close(whod);
	}
}

/*
 * Check out host name for unprintables
 * and other funnies before allowing a file
 * to be created.  Sorry, but blanks aren't allowed.
 */
verify(name)
	register char *name;
{
	register int size = 0;

	while (*name) {
		if (!isascii(*name) || !isalnum(*name))
			return (0);
		name++, size++;
	}
	return (size > 0);
}

int	utmptime;
int	utmpent;
struct	utmp utmp[100];

onalrm()
{
	register int i;
	struct stat stb;
	struct whoent *we = mywd.wd_we, *wlast;
	int cc;
	double avenrun[3];
	long now = time((long *) 0);

	(void) fstat(utmpf, &stb);
	if (stb.st_mtime != utmptime) {
		(void) lseek(utmpf, 0L, 0);
		cc = read(utmpf, (char *)utmp, sizeof (utmp));
		if (cc < 0) {
			perror("/etc/utmp");
			goto done;
		}
		wlast = &mywd.wd_we[1024 / sizeof (struct whoent) - 1];
		utmpent = cc / sizeof (struct utmp);
		for (i = 0; i < utmpent; i++)
			if (utmp[i].ut_name[0]) {
				bcopy(utmp[i].ut_line, we->we_utmp.ut_line,
				   sizeof (utmp[i].ut_line));
				bcopy(utmp[i].ut_name, we->we_utmp.ut_name,
				   sizeof (utmp[i].ut_name));
				we->we_utmp.ut_time = htonl((u_long) utmp[i].ut_time);
				if (we >= wlast)
					break;
				we++;
			}
		utmpent = we - mywd.wd_we;
	}
	we = mywd.wd_we;
	for (i = 0; i < utmpent; i++) {
		if (stat(we->we_utmp.ut_line, &stb) >= 0)
			we->we_idle = htonl((u_long) now - stb.st_atime);
		we++;
	}
	(void) lseek(kmemf, (long) nl[NL_AVENRUN].n_value, 0);
	(void) read(kmemf, (char *)avenrun, sizeof (avenrun));
	for (i = 0; i < 3; i++)
		mywd.wd_loadav[i] = htonl((u_long)(avenrun[i] * 100));
	mywd.wd_sendtime = htonl((u_long) time((long *) 0));
	mywd.wd_vers = WHODVERSION;
	mywd.wd_type = WHODTYPE_STATUS;
	cc = (char *)we - (char *)&mywd;
	for (i = 0; i < ninet && neighbors[i]; i += 2) {
		mywd.udpaddr.host = neighbors[i];
		errno = 0;
		(void) xwrite(s, (char *)&mywd, cc);
	}
done:
	signal(SIGALRM, onalrm);
	(void) alarm(60);
}

getkmem()
{	struct stat statbuf;
	struct nlist *nlp;

	for (nlp = &nl[sizeof (nl) / sizeof (nl[0])]; --nlp >= nl; ) {
		nlp->n_value = 0;
		nlp->n_type = 0;
	}
	nlist("/unix", nl);
	if (nl[0].n_value == 0) {
		fprintf(stderr, "rwhod: /unix namelist botch\n");
		exit(1);
	}
	kmemf = open("/dev/kmem", 0);
	if (kmemf < 0) {
		perror("/dev/kmem");
		exit(1);
	}
	if (stat(LASTBOOT, &statbuf) < 0) {
		perror(LASTBOOT);
		exit(1);
	}
	mywd.wd_boottime = htonl((u_long) statbuf.st_mtime);
}

/*
 * Figure out device configuration and select
 * networks which deserve status information.
 */
configure()
{	int ipfd;
	extern char *malloc();

	(void) signal(SIGHUP, configure);
	if (neighbors)
		(void) free((char *) neighbors);
	(void) lseek(kmemf, (long) nl[NL_NINET].n_value, 0);
	if (read(kmemf, (char *) &ninet, sizeof(ninet)) != sizeof(ninet)) {
		perror("rwhod: read kmem");
		exit(1);
	}
	ninet *= 2;	/* configure stuff comes in pairs */
	if ((neighbors = (in_addr *) malloc((unsigned) ninet)) == 0) {
		perror("rwhod: malloc");
		exit(1);
	}
	if ((ipfd = open(IPDEVICE, 0)) < 0) {
		perror(IPDEVICE);
		exit(1);
	}
	if (ioctl(ipfd, IPIOGETIFS, neighbors) < 0) {
		perror("rwhod: IPIOGETIFS");
		exit(1);
	}
	(void) close(ipfd);
}

#ifdef DEBUG
xwrite(s, buf, cc)
	int s;
	char *buf;
	int cc;
{	register struct whod *w = (struct whod *)buf;
	register struct whoent *we;
	char *interval();
	extern char *in_ntoa();

	printf("sendto %s.%d\n", in_ntoa(w->udpaddr.host), w->udpaddr.port);
	printf("hostname %s %s\n", w->wd_hostname,
	   interval(ntohl(w->wd_sendtime) - ntohl(w->wd_boottime), "  up"));
	printf("load %4.2f, %4.2f, %4.2f\n",
	    ntohl(w->wd_loadav[0]) / 100.0, ntohl(w->wd_loadav[1]) / 100.0,
	    ntohl(w->wd_loadav[2]) / 100.0);
	cc -= WHDRSIZE;
	for (we = w->wd_we, cc /= sizeof (struct whoent); cc > 0; cc--, we++) {
		time_t t = ntohl(we->we_utmp.ut_time);
		printf("%-8.8s %s:%s %.12s",
			we->we_utmp.ut_name,
			w->wd_hostname, we->we_utmp.ut_line,
			ctime(&t)+4);
		we->we_idle = ntohl(we->we_idle) / 60;
		if (we->we_idle) {
			if (we->we_idle >= 100*60)
				we->we_idle = 100*60 - 1;
			if (we->we_idle >= 60)
				printf(" %2d", we->we_idle / 60);
			else
				printf("   ");
			printf(":%02d", we->we_idle % 60);
		}
		printf("\n");
	}
}

char *
interval(time, updown)
	int time;
	char *updown;
{
	static char resbuf[32];
	int days, hours, minutes;

	if (time < 0 || time > 3*30*24*60*60) {
		(void) sprintf(resbuf, "   %s ??:??", updown);
		return (resbuf);
	}
	minutes = (time + 59) / 60;		/* round to minutes */
	hours = minutes / 60; minutes %= 60;
	days = hours / 24; hours %= 24;
	if (days)
		(void) sprintf(resbuf, "%s %2d+%02d:%02d",
		    updown, days, hours, minutes);
	else
		(void) sprintf(resbuf, "%s    %2d:%02d",
		    updown, hours, minutes);
	return (resbuf);
}
#endif
//GO.SYSIN DD rwhod.c
echo rwho.c 1>&2
sed 's/^-//' >rwho.c <<'//GO.SYSIN DD rwho.c'
#include "rwhod.h"

#include <ndir.h>

DIR	*etc;

struct	whod wd;
int	utmpcmp();
#define	NUSERS	1000
struct	myutmp {
	char	myhost[32];
	int	myidle;
	struct	utmp myutmp;
} myutmp[NUSERS];
int	nusers;

#define	WHDRSIZE	(sizeof (wd) - sizeof (wd.wd_we))
#define	RWHODIR		"/usr/spool/rwho"

char	*ctime(), *strcpy();
int	now;
int	aflg;

main(argc, argv)
	int argc;
	char **argv;
{
	struct direct *dp;
	int cc, width;
	register struct whod *w = &wd;
	register struct whoent *we;
	register struct myutmp *mp;
	int f, n, i;

	argc--, argv++;
again:
	if (argc > 0 && !strcmp(argv[0], "-a")) {
		argc--, argv++;
		aflg++;
		goto again;
	}
	(void) time(&now);
	if (chdir(RWHODIR) < 0) {
		perror(RWHODIR);
		exit(1);
	}
	etc = opendir(".");
	if (etc == NULL) {
		perror("/etc");
		exit(1);
	}
	mp = myutmp;
	while (dp = readdir(etc)) {
		if (dp->d_ino == 0)
			continue;
		if (strncmp(dp->d_name, "whod.", 5))
			continue;
		f = open(dp->d_name, 0);
		if (f < 0)
			continue;
		cc = read(f, (char *)&wd, sizeof (struct whod));
		if (cc < WHDRSIZE) {
			(void) close(f);
			continue;
		}
		if (now - w->wd_recvtime > 5 * 60) {
			(void) close(f);
			continue;
		}
		cc -= WHDRSIZE;
		we = w->wd_we;
		for (n = cc / sizeof (struct whoent); n > 0; n--) {
			if (aflg == 0 && we->we_idle >= 60*60) {
				we++;
				continue;
			}
			if (nusers >= NUSERS) {
				printf("too many users\n");
				exit(1);
			}
			mp->myutmp = we->we_utmp; mp->myidle = we->we_idle;
			(void) strcpy(mp->myhost, w->wd_hostname);
			nusers++; we++; mp++;
		}
		(void) close(f);
	}
	qsort((char *)myutmp, nusers, sizeof (struct myutmp), utmpcmp);
	mp = myutmp;
	width = 0;
	for (i = 0; i < nusers; i++) {
		int j = strlen(mp->myhost) + 1 + strlen(mp->myutmp.ut_line);
		if (j > width)
			width = j;
		mp++;
	}
	mp = myutmp;
	for (i = 0; i < nusers; i++) {
		char buf[22];
		sprintf(buf, "%s:%s", mp->myhost, mp->myutmp.ut_line);
		printf("%-8.8s %-*s %.12s",
		   mp->myutmp.ut_name,
		   width,
		   buf,
		   ctime((time_t *)&mp->myutmp.ut_time)+4);
		mp->myidle /= 60;
		if (mp->myidle) {
			if (aflg) {
				if (mp->myidle >= 100*60)
					mp->myidle = 100*60 - 1;
				if (mp->myidle >= 60)
					printf(" %2d", mp->myidle / 60);
				else
					printf("   ");
			} else
				printf(" ");
			printf(":%02d", mp->myidle % 60);
		}
		printf("\n");
		mp++;
	}
	exit(0);
}

utmpcmp(u1, u2)
	struct myutmp *u1, *u2;
{
	int rc;

	rc = strncmp(u1->myutmp.ut_name, u2->myutmp.ut_name, 8);
	if (rc)
		return (rc);
	rc = strncmp(u1->myhost, u2->myhost, 8);
	if (rc)
		return (rc);
	return (strncmp(u1->myutmp.ut_line, u2->myutmp.ut_line, 8));
}
//GO.SYSIN DD rwho.c
echo ruptime.c 1>&2
sed 's/^-//' >ruptime.c <<'//GO.SYSIN DD ruptime.c'
#include "rwhod.h"

#include <ndir.h>

DIR	*etc;

#define	NHOSTS	100
int	nhosts;
struct	hs {
	struct	whod *hs_wd;
	int	hs_nusers;
} hs[NHOSTS];
struct	whod awhod;
int	hscmp(), ucmp(), lcmp(), tcmp();

#define	WHDRSIZE	(sizeof (awhod) - sizeof (awhod.wd_we))
#define	RWHODIR		"/usr/spool/rwho"

char	*interval();
int	now;
char	*malloc(), *sprintf();
int	aflg;

#define down(h)		(now - (h)->hs_wd->wd_recvtime > 5 * 60)

main(argc, argv)
	int argc;
	char **argv;
{
	struct direct *dp;
	int f, i, t;
	char buf[BUFSIZ]; int cc;
	register struct hs *hsp = hs;
	register struct whod *wd;
	register struct whoent *we;
	int maxloadav = 0;
	int (*cmp)() = hscmp;

	time(&t);
	argc--, argv++;
again:
	if (argc && !strcmp(*argv, "-a")) {
		aflg++;
		argc--, argv++;
		goto again;
	}
	if (argc && !strcmp(*argv, "-l")) {
		cmp = lcmp;
		argc--, argv++;
		goto again;
	}
	if (argc && !strcmp(*argv, "-u")) {
		cmp = ucmp;
		argc--, argv++;
		goto again;
	}
	if (argc && !strcmp(*argv, "-t")) {
		cmp = tcmp;
		argc--, argv++;
		goto again;
	}
	if (chdir(RWHODIR) < 0) {
		perror(RWHODIR);
		exit(1);
	}
	etc = opendir(".");
	if (etc == NULL) {
		perror("/etc");
		exit(1);
	}
	while (dp = readdir(etc)) {
		if (dp->d_ino == 0)
			continue;
		if (strncmp(dp->d_name, "whod.", 5))
			continue;
		if (nhosts == NHOSTS) {
			fprintf(stderr, "too many hosts\n");
			exit(1);
		}
		f = open(dp->d_name, 0);
		if (f > 0) {
			cc = read(f, buf, BUFSIZ);
			if (cc >= WHDRSIZE) {
				hsp->hs_wd = (struct whod *)malloc(WHDRSIZE);
				wd = (struct whod *)buf;
				bcopy(buf, hsp->hs_wd, WHDRSIZE);
				hsp->hs_nusers = 0;
				for (i = 0; i < 2; i++)
					if (wd->wd_loadav[i] > maxloadav)
						maxloadav = wd->wd_loadav[i];
				we = (struct whoent *)(buf+cc);
				while (--we >= wd->wd_we)
					if (aflg || we->we_idle < 3600)
						hsp->hs_nusers++;
				nhosts++; hsp++;
			}
		}
		(void) close(f);
	}
	(void) time(&now);
	qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
	if (nhosts == 0) {
		printf("no hosts!?!\n");
		exit(1);
	}
	for (i = 0; i < nhosts; i++) {
		hsp = &hs[i];
		if (down(hsp)) {
			printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
			    interval(now - hsp->hs_wd->wd_recvtime, "down"));
			continue;
		}
		printf("%-12.12s%s,  %4d user%s  load %*.2f, %*.2f, %*.2f\n",
		    hsp->hs_wd->wd_hostname,
		    interval(hsp->hs_wd->wd_sendtime -
			hsp->hs_wd->wd_boottime, "  up"),
		    hsp->hs_nusers,
		    hsp->hs_nusers == 1 ? ", " : "s,",
		    maxloadav >= 1000 ? 5 : 4,
			hsp->hs_wd->wd_loadav[0] / 100.0,
		    maxloadav >= 1000 ? 5 : 4,
		        hsp->hs_wd->wd_loadav[1] / 100.0,
		    maxloadav >= 1000 ? 5 : 4,
		        hsp->hs_wd->wd_loadav[2] / 100.0);
		cfree(hsp->hs_wd);
	}
	exit(0);
}

char *
interval(time, updown)
	int time;
	char *updown;
{
	static char resbuf[32];
	int days, hours, minutes;

	if (time < 0 || time > 3*30*24*60*60) {
		(void) sprintf(resbuf, "   %s ??:??", updown);
		return (resbuf);
	}
	minutes = (time + 59) / 60;		/* round to minutes */
	hours = minutes / 60; minutes %= 60;
	days = hours / 24; hours %= 24;
	if (days)
		(void) sprintf(resbuf, "%s %2d+%02d:%02d",
		    updown, days, hours, minutes);
	else
		(void) sprintf(resbuf, "%s    %2d:%02d",
		    updown, hours, minutes);
	return (resbuf);
}

hscmp(h1, h2)
	struct hs *h1, *h2;
{

	return (strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
}

/*
 * Compare according to load average.
 */
lcmp(h1, h2)
	struct hs *h1, *h2;
{

	if (down(h1))
		if (down(h2))
			return (tcmp(h1, h2));
		else
			return (1);
	else if (down(h2))
		return (-1);
	else
		return (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]);
}

/*
 * Compare according to number of users.
 */
ucmp(h1, h2)
	struct hs *h1, *h2;
{

	if (down(h1))
		if (down(h2))
			return (tcmp(h1, h2));
		else
			return (1);
	else if (down(h2))
		return (-1);
	else
		return (h2->hs_nusers - h1->hs_nusers);
}

/*
 * Compare according to uptime.
 */
tcmp(h1, h2)
	struct hs *h1, *h2;
{
	long t1, t2;

	return (
		(down(h2) ? h2->hs_wd->wd_recvtime - now
			  : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
		-
		(down(h1) ? h1->hs_wd->wd_recvtime - now
			  : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
	);
}
//GO.SYSIN DD ruptime.c
exit


From princeton!down!honey  Sat Nov  2 19:32:10 1985
>From down!honey  Sat Nov  2 19:32:10 1985 remote from princeton
Date: 2 Nov 1985 19:29-EST
To: research!v8source
Subject: rwho makefile

uh ...
	-mkdir /usr/spool/rwho

you get the idea ...


From mcvax!ukc!eagle.ukc.ac.uk!cheviot.ncl.ac.uk!andy  Fri Nov 29 08:38:13 1985
>From ukc!eagle.ukc.ac.uk!cheviot.ncl.ac.uk!andy  Fri Nov 29 08:38:13 1985 remote from mcvax
Received: by mcvax.UUCP; Fri, 29 Nov 85 08:38:13 +0100 (MET)
Message-Id: <8511290738.AA26744@mcvax.UUCP>
Received: from [nedaftp] by eagle.Ukc.AC.UK   via Janet with NIFTP  id a003359;
          28 Nov 85 16:57 GMT
From: Andy Linton <mcvax!andy@cheviot.ncl.ac.uk>
Date: Thu, 28 Nov 85 16:58:46 gmt
To: research!v8news


We now have our v8 stuff - or at least some of it!  The file tty.h has
zero length and as it contains or did in the past the definition of the
clist structure there have been some complaints from the compiler when
I try to build a system.  Can I use the 4.2 definitions or are there
some extra bits I need.

We have made some attempts to get mpx running on our blits and it works
after a fashion. I have incorporated the 4.2 kernel mods on the tape
and although we could load and run mpx the system keeps crashing with
"KSP not valid". Are there some system parameters I need tweek - we are
set up for 16 users and currently have 2 Mbytes of memory on the
machine. I have 3 more Mbytes arriving shortly if this will help.

I also have a DHU11 interface coming to replace the 2 aging DZ's I have
- is there a driver available for this? If I have to do one is anyone
interested?

Thanks
andy


From dutoit!norman Tue Dec  3 06:31 EST 1985
>From norman Tue Dec  3 06:31 EST 1985 remote from dutoit
To: v8news
Subject: tty.h and lp drivers

tty.h on the V8 tape is correct; there aren't any clists in the system any
more.  There's an empty file for convenience, because of programs that
blithely include the file.  It should really go away, and such programs
should be mended.

Andy was told about the problem by /usr/sys/dev/lp.c, which is an alleged
lp driver.  This file is a dreg; it's an old driver that was never converted
to the new system.  dev/tri.c is a hackishly done `trilog driver' that
should work reasonably well for LP11-like devices (and is what we use).
Anyone who wants to do the right thing and make a stream driver for an
LP11 is encouraged to do so (and anyone who wants an lp driver with
output canonicalization should do that instead).

From acsnet!basser!john Wed Dec  4 16:28 AESST 1985
>From john Wed Dec  4 16:28 AESST 1985 remote from acsnet!basser
# To unbundle, sh this file
echo h/lp.h 1>&2
sed 's/.//' >h/lp.h <<'//GO.SYSIN DD h/lp.h'
-/*
-**	Ioctl commands.
-*/
-
-#define	LPGET	0
-#define	LPSET	1
-
-struct lpiocb
-{
-	char	lp_state;
-	char	lp_flag;
-};
-
-/*
-**	Internal state of driver.
-*/
-
-#define	CLOSED	0	/* device closed */
-#define	OPEN	1	/* device open for writing */
-#define	CLOSING	2	/* user has called `close' */
-
-/*
-**	Flags.
-*/
-
-#define	ASLP	0001	/* sleeping for buffers */
-#define	ERR	0002	/* error bit set in status register */
-#define	FLSH	0004	/* flush all buffers & return error */
-#define	TIMOFAIL 010	/* timeout call failed to set */
//GO.SYSIN DD h/lp.h
echo dev/lp.c 1>&2
sed 's/.//' >dev/lp.c <<'//GO.SYSIN DD dev/lp.c'
-/*
-**	%W%	(Basser) %E%
-**
-**	Data Products B900 line printer driver.
-**
-**	A stream driver for DP type printers
-**	using QBIGB to deliver 1k output chunks.
-*/
-
-#include	"lp.h"
-#if	NLP > 0
-
-#include	"../h/param.h"
-#include	"../h/systm.h"
-#include	"../h/buf.h"
-#include	"../h/conf.h"
-#include	"../h/stream.h"
-#include	"../h/ioctl.h"
-#include	"../h/ttyld.h"
-#include	"../h/ubavar.h"
-#include	"../h/lp.h"
-
-#include	<errno.h>
-
-/*
-**	Controller access
-*/
-
-struct device
-{
-	short	lpcsr;			/* Control and status word */
-	short	lpbuf;			/* Output buffer */
-};
-
-/*
-**	Status register bits.
-*/
-
-#define	IENABLE	0100			/* enable interrupts */
-#define	READY	0200			/* printer ready */
-#define	ERROR	0100000			/* error */
-
-/*
-**	Per printer structure
-*/
-
-typedef struct lpst
-{
-	unsigned char *	ba;		/* next char in buffer */
-	struct block *	oblock;		/* current output buffer */
-	struct queue *	wrq;		/* queue for this stream */
-	struct device *	addr;		/* this printer's address */
-	short		icol;		/* input column */
-	short		ocol;		/* output column */
-	short		bc;		/* byte count */
-	short		dev;		/* minor bits */
-	short		state;		/* internal state */
-	short		flag;		/* mode flags */
-}
-		Lpst;
-
-/*
-**	Miscellaneous
-*/
-
-#define	MAXWAIT	100			/* Maximum count in loop waiting for READY */
-#define	LPPRI	(PZERO+8)		/* sleep priority */
-#define	spllp	spl4			/* interrupt priority level */
-
-typedef struct device	Device;
-typedef struct block	Block;
-typedef struct queue	Queue;
-typedef union stmsg	Stmsg;
-
-#define	STP(bp)		((Stmsg *)(bp)->rptr)
-#define	IOCOM(bp)	(STP(bp)->ioc0.com)
-#define	SGP(bp)		(&(STP(bp)->ioc1.sb))
-#define	LIP(bp)		((struct lpiocb *)SGP(bp))
-
-#ifdef	EBUG
-#define	DEBUG	EBUG
-#define	DODEBUG(L,A)	{if(lp_debug>=(L)){A;}}
-#else	EBUG
-#define	DODEBUG(L,A)
-#endif	EBUG
-
-int		lp_debug;		/* set non-zero to print anything */
-
-Lpst		lp[NLP];
-
-/*
-**	Stream interface.
-*/
-
-long		lpopen();
-int		lpclose(), lpwput();
-extern int	nodev();
-
-static struct qinit	lprinit = {  nodev, NULL, lpopen, lpclose,    0,    0 };
-static struct qinit	lpwinit = { lpwput, NULL, lpopen, lpclose, 3000, 1500 };
-struct streamtab	lpinfo = { &lprinit, &lpwinit };
-
-/*
-**	Configuration.
-*/
-
-int			lpprobe(), lpattach();
-u_short			lpstd[] = { 0177514 };
-struct uba_device *	lpuinfo[NLP];
-struct uba_driver 	lpdriver = { lpprobe, 0, lpattach, 0, lpstd, "lp", lpuinfo };
-
-lpattach(ui)
-	struct uba_device *ui;
-{
-	
-}
-
-lpprobe(reg)
-	caddr_t			reg;
-{
-	register int		br, cvec;		/* value-result */
-
-	((Device *)reg)->lpcsr = IENABLE;
-	DELAY(100000);
-	((Device *)reg)->lpcsr = 0;
-	return 1;
-}
-
-/*
-**	Enforce single open (for writing), but allow unlimited opens
-**	for reading (for mode changes using e.g. slp)
-*/
-
-long
-lpopen(rdq, dev)
-	Queue *			rdq;
-	register int		dev;
-{
-	register Lpst *		plp;
-	register Device *	lp_addr;
-	register int		x;
-	struct uba_device *	ui;
-
-	if
-	(
-		(dev = minor(dev)) >= NLP
-		||
-		(plp = &lp[dev])->state == OPEN
-		||
-		(ui = lpuinfo[dev]) == 0
-		||
-		ui->ui_alive == 0
-		||
-		((lp_addr = (Device *)ui->ui_addr)->lpcsr & ERROR)
-	)
-		return 0;
-
-	x = spllp();
-		while ( plp->state != CLOSED )
-			sleep(plp, LPPRI);
-	splx(x);
-
-	plp->dev = dev;
-	plp->addr = lp_addr;
-	plp->wrq = WR(rdq);
-
-	rdq->ptr = (caddr_t)plp;
-	plp->wrq->ptr = (caddr_t)plp;
-	plp->wrq->flag |= QBIGB;
-
-	plp->state = OPEN;
-	plp->icol = plp->ocol = 0;
-
-	return 1;
-}
-
-/*
-**	Close routine. Only called (by system) on last close,
-**	so if OPEN tidy up as though writer is closing.
-*/
-
-lpclose(rdq)
-	Queue *		rdq;
-{
-	register Lpst *	plp;
-	register int	x;
-
-	plp = (Lpst *)rdq->ptr;
-
-	x = spllp();
-		if ( plp->state == OPEN )
-		{
-			plp->state = CLOSING;
-
-			if ( plp->oblock == (Block *)0 )
-			{
-				plp->state = CLOSED;
-
-				if ( plp->ocol && (plp->addr->lpcsr & READY) )
-					plp->addr->lpbuf = '\n';
-
-				plp->wrq = (Queue *)0;
-			}
-		}
-	splx(x);
-}
-
-/*
-**	Write put routine.
-*/
-
-lpwput(wrq, bp)
-	Queue *		wrq;
-	register Block *bp;
-{
-	register Lpst *	plp;
-	register int	x;
-
-	plp = (Lpst *)wrq->ptr;
-
-	switch ( bp->type )
-	{
-	case M_IOCTL:
-		lpioctl(wrq, bp);
-		return;
-	
-	case M_DATA:
-		if ( plp->flag & FLSH )
-			break;
-
-		x = spllp();
-			DODEBUG(2, printf("lpwput %d\n", bp->wptr - bp->rptr));
-
-			if ( plp->oblock )
-				putq(wrq, bp);
-			else
-			{
-				plp->oblock = bp;
-				plp->bc = bp->wptr - bp->rptr;
-				plp->ba = bp->rptr;
-				plp->addr->lpcsr |= IENABLE;
-			}
-		splx(x);
-		return;
-
-	case M_FLUSH:
-		x = spllp();
-			if ( plp->oblock )
-			{
-				freeb(plp->oblock);
-				plp->oblock = (Block *)0;
-				plp->bc = 0;
-			}
-		splx(x);
-		flushq(wrq, 1);
-		break;
-		
-	}
-
-	freeb(bp);
-}
-
-/*
-**	Interrupt handler. Most of the work is done here.
-*/
-
-lpintr(dev)
-{
-	register Lpst *	plp;
-	register short *lpa;
-	register short *lps;
-	register	d;
-
-	plp = &lp[dev];
-	lps = &plp->addr->lpcsr;
-	lpa = &plp->addr->lpbuf;
-
-	if ( *lps & ERROR )
-	{
-		if ( plp->flag & FLSH )
-			goto flush;
-err:
-		plp->flag |= ERR;
-		*lps &= ~IENABLE;
-		if ( timeout(lpintr, dev, hz) )	/* try again in one second */
-			plp->flag &= ~TIMOFAIL;
-		else
-			plp->flag |= TIMOFAIL;
-		return;
-	}
-
-	if ( (*lps & READY) == 0 )		/* not ready? */
-		return;				/* prob. an unneeded timeout */
-
-	plp->flag &= ~(TIMOFAIL|ERR);
-flush:
-	if ( plp->oblock == (Block *)0 )	/* nowt to do ... */
-		goto fin;
-
-	if ( plp->flag & FLSH )			/* flush all output */
-	{
-		register Block *	bp;
-
-		while ( (bp = getq(plp->wrq)) != (Block *)0 )
-			freeb(bp);
-
-		if ( bp = plp->oblock )
-		{
-			freeb(bp);
-			plp->oblock = (Block *)0;
-			plp->bc = 0;
-		}
-
-		plp->flag &= ~FLSH;
-		goto fin;
-	}
-
-	*lps |= IENABLE;			/* not set if came from timeout */
-
-loop:
-	while ( (*lps & READY) && (plp->bc-- > 0) )
-	{
-		register int	c;
-
-		switch ( c = *plp->ba++ )
-		{
-		case '\t':
-			plp->icol = (plp->icol + 8) & ~07;
-			break;
-
-		case '\b':
-			if (plp->icol > 0)
-				plp->icol--;
-			break;
-
-		case '\n':
-		case '\f':
-		case '\r':
-			plp->icol = 0;
-			plp->ocol = 0;
-			*lpa = c;
-			break;
-
-		default:
-			if ( (c < 040 || c >= 0177) && lp_debug == 0 )	/* garbage char */
-				c = '?';		/* prints thusly */
-
-			if ( plp->icol < plp->ocol )	/* overstrike */
-			{
-				*lpa = '\r';
-				plp->ocol = 0;
-				plp->ba--;	/* "unget" the character */
-				plp->bc++;
-				break;
-			}
-
-			while ( plp->icol > plp->ocol )
-			{
-				*lpa = ' ';
-				plp->ocol++;
-				d = 0;
-
-				while ( *lps == IENABLE )	/* neither ERROR nor READY */
-					if ( ++d > MAXWAIT )
-					{
-						plp->ba--;
-						plp->bc++;
-						goto loop;
-					}
-			}
-
-			*lpa = c;
-			plp->icol++;
-			plp->ocol++;
-			d = 0;
-
-			while ( *lps == IENABLE )	/* neither ERROR nor READY */
-				if ( ++d > MAXWAIT )
-					goto loop;
-		}
-	}
-
-	if ( *lps & ERROR )
-		goto err;
-
-	if ( plp->bc <= 0 )	/* this buffer gone */
-	{
-		register Block *	bp;
-
-		freeb(plp->oblock);
-
-		if ( plp->oblock = bp = getq(plp->wrq) )	/* more buffers to go */
-		{
-			plp->ba = bp->rptr;
-			plp->bc = bp->wptr - bp->rptr;
-			goto loop;
-		}
-
-fin:
-		*lps &= ~IENABLE;
-
-		if ( plp->state == CLOSING )
-		{
-			plp->state = CLOSED;
-
-			if ( plp->ocol && (*lps & READY) )
-			{
-				*lpa = '\n';
-				plp->ocol = 0;
-			}
-
-			plp->wrq = (Queue *)0;
-			wakeup(plp);
-		}
-	}
-}
-
-/*
-**	Get/set info to/from user.
-*/
-
-lpioctl(qp, bp)
-	Queue *			qp;
-	register Block *	bp;
-{
-	register Lpst *		plp;
-	register int		cmd = IOCOM(bp);
-
-	plp = (Lpst *)qp->ptr;
-
-	if ( cmd == LPGET )
-	{
-		LIP(bp)->lp_state = plp->state;
-		LIP(bp)->lp_flag = plp->flag;
-		bp->wptr = bp->rptr + sizeof(IOCOM(bp)) + sizeof(struct lpiocb);
-		bp->type = M_IOCACK;
-	}
-	else
-	if ( cmd == LPSET )
-	{
-		register int	x;
-
-		if ( LIP(bp)->lp_flag & FLSH )
-		{
-			x = spllp();
-				if ( plp->oblock != (Block *)0 )
-					plp->flag |= FLSH;
-			splx(x);
-		}
-
-		if ( LIP(bp)->lp_flag & TIMOFAIL )
-		{
-			x = spllp();
-				if ( plp->flag & TIMOFAIL )
-					lpintr(plp->dev);
-			splx(x);
-		}
-
-		bp->wptr = bp->rptr;
-		bp->type = M_IOCACK;
-	}
-	else
-	{
-		bp->wptr = bp->rptr;
-		*bp->wptr++ = EINVAL;
-		bp->type = M_IOCNAK;
-	}
-
-	qreply(qp, bp);
-}
-
-#endif	NLP > 0
//GO.SYSIN DD dev/lp.c
echo /usr/man/man4/lp.4 1>&2
sed 's/.//' >/usr/man/man4/lp.4 <<'//GO.SYSIN DD /usr/man/man4/lp.4'
-.TH LP 4
-.SH NAME
-lp \- line printer driver
-.SH DESCRIPTION
-.I Lp
-provides a \fIstream\fP interface to any of the standard
-Digital Equipment Corporation line printers,
-or those capable of interfacing to the LP11 controller.
-It uses 1024 byte buffers for high throughput.
-.PP
-The driver correctly interprets
-carriage returns, backspaces, tabs, and form-feeds.
-.PP
-There are two
-.IR ioctl (2)
-commands to control the driver's behaviour.
-These pass data in a structure \fIstruct lpiocb\fP described in the header file
-.IR /usr/include/sys/lp.h .
-The commands are:-
-.RS 1
-.TP "\w'\s-1LPGETXX\s0'u"
-.SM LPSET
-Only two flags have any effect with this command.
-.SM FLSH
-flushes output (superceded by 
-.SM TIOCFLUSH\c
-),
-and
-.SM TIMOFAIL
-restarts the timeout scanner, if it has failed.
-.TP
-.SM LPGET
-The structure pointed at by the third argument
-is filled with the current driver status.
-.RE
-.SH FILES
-/dev/lp
-.br
-/usr/include/sys/lp.h
-.SH "SEE ALSO"
-lpr(1),
-stream(4).
//GO.SYSIN DD /usr/man/man4/lp.4

From acsnet!basser!john Wed Dec  4 16:28 AESST 1985
>From john Wed Dec  4 16:28 AESST 1985 remote from acsnet!basser
To: v8news,norman@research

Piers has written a stream driver for LP-11s.  We've been
using it for quite a while and haven't had any problems
at all.  I've mailed it to v8source.

From koura!bill Thu Dec 12 09:11 EST 1985
>From bill Thu Dec 12 09:11 EST 1985 remote from koura
Hi Bill Pretyka from Bellcore here. I am interested in chatting with those of
you who are running 5620 terminals (mux) over ethernet.. Specifically, I have
the latest v8 running the latest inet software from Dave Presotto and using
Bridge Communications CS/100's running tcp/ip as terminals servers. Mux loads 
up fine and then the windows just hang... Any comments mail koura!bill


From koura!bill Tue Dec 17 16:21 EST 1985
>From bill Tue Dec 17 16:21 EST 1985 remote from koura
Right again! Jerqs do work over transparent networks when flow control is turned off.
My next question is how do I get telnetd to be incorporated into streams.
The problem that I am having is that a telnetd process is created when logging on
from a Bridge terminal server using the TCP/IP protocol.  And these processes are 
killing my 750.					Thanks koura!bill


From dutoit!dmr Sat Jan  4 00:50 EST 1986
Subject: long names
To: v8news

One of the things about v8 that has turned out to be controversial is
the error you get when you try to refer to a file whose name is longer
than 14 characters.  Our earlier systems and S/V just truncate the name
silently; 4.2, of course, handles it.

This code (it's in nami.c) was put in deliberately, in the belief that
it is better to tell the user that the system is not going doing what
was asked, than to lull him into ignoring potential problems.

The behavior seems to be perceived as a problem precisely where it is
most valuable: in file-collections received from 4.2 sites (archives,
tar) and in programs that consistently derive new, longer names from
existing file names (sccs).  The point is that in either situation, you
may be unknowingly overwriting existing files because of name
squashing.   Tar has already been modified to do something useful
(thanks to Mark Liberman), and ar should be.  I would argue that a
program that creates "s.verylongname" out of both "verylongname.c" and
"verylongname.s" is also doing something the user should be told
about.

However, the issue is not a moral one.  If it turns out, on balance,
that it is better for you to follow the old rule, feel free to change
the system.  I don't believe that anything relies on the current
behavior.

	Dennis


From cbosgd!utcs!ian  Tue Jan  7 21:09:15 1986
>From utcs!ian  Tue Jan  7 21:09:15 1986 remote from cbosgd
Date: Tue, 7 Jan 86 17:46:01 est
From: ian@utcs.uucp (Ian F. Darwin)
To: research!v8source
Subject: 98% of a DH-11 driver
Cc: hacks

(Alternate title: How I spent my winter vacation.)

.SH HISTORY
I borrowed a student machine for the holidays and put up V8.
Had lots of fun. After got V8 up, wrote a DH-11 driver by smashing 
together the V8 DZ driver and the 4.2 DH driver. Found lots of hideous
botches in my smushed code. Geoff came back from holidays
and found lots more. These are all fixed.

The driver now sorta works. We have logged on through it.
(We are using ABLE DH/DM-11, not the old DEC 9-slot-system-unit variety).

We would love to finish the driver, but people here aren't sufficiently
pro-V8 to let us keep the machine running v8; they insist on
running 4.2. So it's unlikely we'll have time fully to debug
it; if we do there will be an update. We will be trying to get
at least a regular V8 timeslot on the machine.

We are posting the driver now in case anybody needs it or finds parts 
useful;  it might form a good base for a DMF stream driver
(although I note in re-reading v8news that Basser already has one).

.SH BUGS
a) flow control isn't quite right - you get some extra characters out
when you do the ^Q of ^S-^Q (at least you don't lose any :=) ).
This may be a problem with the arithmetic in dhtint().
b) We suspect there may be a problem with freeing stream blocks
at the wrong time (had a panic trap type 8 in allocb).
c) We suspect there may be a problem in computing the unit number
or offset: we haven't been able to get many lines going.
d) We have had no luck with the multiple unibus support.
In fact we have no way to test multiple unibuses. Do not
define MULTI_UBA unless you are willing to do substantial debugging.
Does anybody run V8 with multiple unibi?

Here it is. Best wishes.

Ian Darwin
Geoff Collyer
U of Toronto Computing Services


---------- cut here ----------
: To unbundle, sh this file
mkdir dev h
echo x - dev/dh.c 1>&2
cat >dev/dh.c <<'@@@End of dev/dh.c'
/*
 * DH-11/DM-11 driver for Eighth Edition UNIX
 * Synthesised by Ian Darwin and Geoff Collyer,
 * University of Toronto, January 1986.
 */

#include "dh.h"
#include "dm.h"
#if NDH > 0
#include "../h/param.h"
#include "../h/stream.h"
#include "../h/ioctl.h"
#include "../h/ttyld.h"
#include "../h/pte.h"
#include "../h/map.h"
#include "../h/buf.h"
#include "../h/systm.h"
#include "../h/ubareg.h"
#include "../h/ubavar.h"
#include "../h/conf.h"
#include "sparam.h"

#include "../h/dhreg.h"		/* half of hardware */
#include "../h/dmreg.h"		/* half of hardware */
#include "../h/mdmreg.h"	/* modem command stuff */


#define NPER	16		/* lines per board */
#define	NDHLINE	(NDH*NPER)

/* bits in dh[]->state */
#define	EXISTS	01
#define	ISOPEN	02
#define	WOPEN	04
#define	TIMEOUT	010
#define	CARR_ON	020
#define	DHSTOP	040
#define	HPCL	0100
#define	BRKING	0200
#define	DIALOUT	0400	/* used as dialout with smart modems */
#define BUSY	01000
#define FLUSH	02000

#define SSPEED	B4800	/* half reasonable default nowadays */
#define DHPRI	30

/*
 * interface to auto-configuration.
 * There is one definition for the dh and one for the dm.
 */
int	dhprobe(), dhattach(), dhrint(), dhtint();
struct	uba_device *dhboard[NDH];
u_short	dhstd[] = { 0 };
struct	uba_driver dhdriver =
	{ dhprobe, 0, dhattach, 0, dhstd, "dh", dhboard };

int	dmprobe(), dmattach(), dmintr();
struct	uba_device *dmboard[NDM];
u_short	dmstd[] = { 0 };
struct	uba_driver dmdriver =
	{ dmprobe, 0, dmattach, 0, dmstd, "dm", dmboard };

/*
 * interface with stream i/o system
 */
int	dhopen(), dhclose(), dhoput(), nodev();
static	struct qinit dhrinit = { nodev, NULL, dhopen, dhclose, 0, 0 };
static	struct qinit dhwinit = { dhoput, NULL, dhopen, dhclose, 200, 100 };
struct	streamtab dhinfo = { &dhrinit, &dhwinit };

/*
 * private data for the driver
 */

/*
 * Well, we can't map the clist space onto each Unibus,
 * since we ain't got no more clists (rah!).
 * Fortunately, we can get the same effect by mapping all stream
 * buffers onto the Unibus space  (as does qinit()).
 */
#define UBADMASK 0x3ffff		/* 18 bits of address */
#ifdef MULTI_UBA
#define UBACVT(x, uba)  (dhblkubad[uba] + ((caddr_t)(x)-(caddr_t)blkdata))
#else
#define UBACVT(x, uba)  ((blkubad&UBADMASK) + ((caddr_t)(x)-(caddr_t)blkdata))
#endif
#define	UBADDR(x, uba)  (UBACVT((x), (uba))&0xffff)	/* low order 16 bits */
#define UBXADDR(x, uba) ((UBACVT((x), (uba))>>16)&0x3)	/* high order 2 bits */

/*
 * One structure per line
 */
struct	dh {
	short	state;
	short	flags;
	struct	block	*oblock;
	struct	queue	*rdq;
	char	board;
	char	line;
	char	ispeed, ospeed;
	short	brking;
} dh[NDHLINE];

/*
 * misc private data
 */
#ifdef MULTI_UBA
long	dhblkubad[MAXNUBA];		/* uba allocation */
#else
extern long blkubad;
extern u_char blkdata[];
#endif
int	dhoverrun;

short	dhsar[NDH];		/* software copy of last bar */
int	dhmiss;			/* chars lost due to q full */

/*
 * routines for top half hardware -- the dh11
 */
int	dhstart();

/*
 * Routine for configuration to force a dh to interrupt.
 * Set to transmit at 9600 baud, and cause a transmitter interrupt.
 *
 * From 4BSD.
 */
/*ARGSUSED*/
dhprobe(reg)
caddr_t reg;
{
	register int br, cvec;		/* these are ``value-result'' */
	register struct dhdevice *dhaddr = (struct dhdevice *)reg;

#ifdef lint
	br = 0; cvec = br; br = cvec;
	dhrint(0); dhtint(0);
#endif
	dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI;
	DELAY(1000);
	dhaddr->un.dhcsr &= ~DH_RI;
	dhaddr->un.dhcsr = 0;
	return 1;
}

/*
 * Routine to attach a dh.
 * Map the stream buffers onto the unibus (qinit tries to do this,
 * but only does it for unibus zero; the dh might be on any unibus).
 */
dhattach(ui)
register struct uba_device *ui;
{
	register int i;
#ifdef MULTI_UBA
	/* this defn must match that in dev/stream.c: */
	extern u_char blkdata[1024*NBLKBIG + 64*NBLK64 + NBLK16*16 + NBLK4*4];
	extern long blkubad;		/* wanton licentiousness w/ streamld */
#endif

	for (i = 0; i < NPER; i++) {
		dh[ui->ui_unit*NPER+i].state = EXISTS;
		dh[ui->ui_unit*NPER+i].board = ui->ui_unit;
		dh[ui->ui_unit*NPER+i].line  = i;
	}
#ifdef MULTI_UBA
#if 0
	if (ui->ui_ubanum == 0)			/* uba 0 */
		/* won't work because blkubad isn't initialised yet */
		dhblkubad[ui->ui_ubanum] = blkubad;
	else
#endif
		/* adding 512 is from 4.2, allegedly a hardware kludge */
		dhblkubad[ui->ui_ubanum] = uballoc(ui->ui_ubanum,
			(caddr_t)blkdata, 512 + sizeof blkdata, 0);
	if (dhblkubad[ui->ui_ubanum] == 0) {
		printf("dh%d: can't map blkdata\n", ui->ui_unit);
		return 0;
	}
	dhblkubad[ui->ui_ubanum] &= UBADMASK;
#endif
	return 1;
}

/*
 * Open a DH11 line.
 * Do not monkey with uba mapping.
 * Turn on dh if this is its first open.
 * Call dmopen to wait for carrier.
 */
/*ARGSUSED*/
dhopen(q, d, flag)
register struct queue *q;
dev_t d;
int flag;
{
	register int dev;
	register struct dh *dhp;

	dev = minor(d);
	dhp = &dh[dev];
	if (dev >= NDHLINE || !(dhp->state & EXISTS))
		return (0);

	q->ptr = (caddr_t)dhp;
	WR(q)->ptr = (caddr_t)dhp;
	/*
	 * If this is first open, initialise tty state to default.
	 */
	if ((dhp->state&ISOPEN)==0 || (dhp->state&CARR_ON)==0) {
		register int s = spl5();

		dhp->flags = ODDP|EVENP;
		dhp->ispeed = dhp->ospeed = SSPEED;
		dhp->state |= WOPEN;
		dhparam(dhp);
		dmopen(dev);	/* wait for carrier */
		if (!(dhp->state & CARR_ON)) {
			wakeup((caddr_t)dhp);
			dhp->ispeed = dhp->ospeed = 0;
			dhparam(dhp);
			splx(s);
			return 0;
		}
		dhp->rdq = q;
		dhp->state |= ISOPEN;
		dhp->state &= ~WOPEN;
		splx(s);
	}
	return 1;
}

/*
 * Close a DH11 line, turning off the DM11.
 */
/*ARGSUSED*/
dhclose(q, d)
dev_t d;
register struct queue *q;
{
	register struct dh *dhp;
	int s = spl5();

	dhp = (struct dh *)q->ptr;
	if (dhp->oblock != NULL) {
		register struct block *bp = dhp->oblock;

		dhp->oblock = NULL;
		freeb(bp);
	}
	flushq(WR(q), 1);
	dhp->rdq = NULL;
	((struct dhdevice *)dhboard[dhp->board]->ui_addr)->dhbreak &=
		~(1<<(minor(d) & 017));
	if (dhp->state&HPCL || (dhp->state&CARR_ON)==0) {
		dhp->ispeed = dhp->ospeed = 0;
		dhparam(dhp);
	}
	dhp->state &= EXISTS;
	
	/* there is no dmclose() to call */
	splx(s);
}


/*
 * dh11 write put routine
 */
dhoput(q, bp)
register struct queue *q;
register struct block *bp;
{
	register struct dh *dhp = (struct dh *)q->ptr;
	register union stmsg *sp;
	register int s;
	int delaytime;

	switch (bp->type) {

	case M_IOCTL:
		sp = (union stmsg *)bp->rptr;
		switch (sp->ioc0.com) {

		case TIOCSETP:
		case TIOCSETN:
			delaytime = 0;
			if (dhp->ispeed != sp->ioc1.sb.sg_ispeed)
				delaytime = 20;
			dhp->ispeed = sp->ioc1.sb.sg_ispeed;
			dhp->flags = sp->ioc1.sb.sg_flags;
			bp->type = M_IOCACK;
			bp->wptr = bp->rptr;
			qreply(q, bp);
			qpctl1(q, M_DELAY, delaytime);	/* wait a bit */
			qpctl(q, M_CTL);		/* means do dhparam */
			dhstart(dhp);
			return;

		case TIOCGETP:
			sp->ioc1.sb.sg_ispeed = dhp->ispeed;
			sp->ioc1.sb.sg_ospeed = dhp->ospeed;
			bp->type = M_IOCACK;
			qreply(q, bp);
			return;

		case TIOCHPCL:
			dhp->state |= HPCL;
			bp->type = M_IOCACK;
			bp->wptr = bp->rptr;
			qreply(q, bp);
			return;

		default:
			bp->wptr = bp->rptr;
			bp->type = M_IOCNAK;
			qreply(q, bp);
			return;
		}

	case M_STOP:
		s = spl5();
		dhp->state |= DHSTOP;
		freeb(bp);
		if ((bp = dhp->oblock) != NULL) {
			dhp->oblock = NULL;
			putbq(q, bp);
		}
		dhstop(dhp);
		splx(s);
		return;

	case M_START:
		dhp->state &= ~DHSTOP;
		dhstart(dhp);
		break;

	case M_FLUSH:
		flushq(q, 1);
		freeb(bp);
		s = spl5();
		if ((bp = dhp->oblock) != NULL) {
			dhp->oblock = NULL;
			freeb(bp);
		}
		splx(s);
		return;

	case M_BREAK:
		qpctl1(q, M_DELAY, 10);
		putq(q, bp);
		qpctl1(q, M_DELAY, 10);
		dhstart(dhp);
		return;

	case M_HANGUP:
		dhp->state &= ~DHSTOP;
	case M_DELAY:
	case M_DATA:
		putq(q, bp);
		dhstart(dhp);
		return;

	default:		/* not handled; just toss */
		break;
	}
	freeb(bp);
}


/*
 * Set parameters from open or stty into the DH hardware
 * registers.
 */
dhparam(dhp)
register struct dh *dhp;
{
	register struct dhdevice *addr;
	register int lpar;
	int unit = dhp->line;

	addr = (struct dhdevice *)dhboard[dhp->board]->ui_addr;
	addr->un.dhcsr = (unit&017) | DH_IE;
	if ((dhp->ispeed)==0) {
		dhp->state |= HPCL;
		dmctl(unit, DML_OFF, DMSET);		/* hang up */
		return;
	}
	lpar = ((dhp->ospeed)<<10) | ((dhp->ispeed)<<6);
	if ((dhp->ispeed) == B134)
		lpar |= BITS6|PENABLE|HDUPLX;
	else if (dhp->flags & RAW)
		lpar |= BITS8;
	else
		lpar |= BITS7|PENABLE;
	if ((dhp->flags&EVENP) == 0)
		lpar |= OPAR;
	if ((dhp->ospeed) == B110)	/* 110 baud (ugh!): 2 stop bits */
		lpar |= TWOSB;
	addr->dhlpr = lpar;
}

/*
 * DH11 receiver interrupt.
 */
dhrint(dev)
int dev;
{
	register struct block *bp;
	register struct dhdevice *dhaddr;
	register struct dh *dhp;
	register int c;

	if (dev >= NDH) {
		printf("dh%d: bad rd intr\n", dev);
		return;
	}
	dhaddr = (struct dhdevice *)dhboard[dev]->ui_addr;
	/*
	 * get chars from the silo for this line
	 */
	while ((c = dhaddr->dhrcr) < 0) { /* char present */
		dhp = &dh[dev*NPER + ((c>>8) & 017)];
		if (c&DH_DO) {
			++dhoverrun;
			continue;
		}
		if (dhp->rdq == NULL)
			continue;
		if (dhp->rdq->next->flag & QFULL) {
			dhmiss++;	/* you lose */
			continue;
		}
		if ((bp = allocb(16)) == NULL)
			continue;	/* out of space - you lose */
		if (c&DH_FE)		/* frame error == BREAK */
			bp->type = M_BREAK;
		else
			*bp->wptr++ = c;
		(*dhp->rdq->next->qinfo->putp)(dhp->rdq->next, bp);
	}
}


/*
 * DH11 transmitter interrupt. Dev is board number.
 * Restart each line which used to be active but has
 * terminated transmission since the last interrupt.
 */
dhtint(dev)
int dev;
{
	register struct dhdevice *dhaddr = (struct dhdevice *)dhboard[dev]->ui_addr;
	register struct dh *dhp;
	register struct block *bp;
	register dev_t unit;
	short bar, *sbar, ttybit;

	if (dhaddr->un.dhcsr & DH_NXM) {	/* somebody goofed */
		dhaddr->un.dhcsr |= DH_CNI;	/* make amends */
		printf("dh%d: NXM\n", dev);
	}
	sbar = &dhsar[dev];
	bar = *sbar & ~dhaddr->dhbar;
	unit = dev * NPER;
	ttybit = 1;
	dhaddr->un.dhcsr &= (short)~DH_TI;	/* no more, please */
	for (; bar; unit++, ttybit <<= 1)
		if (bar & ttybit) {
			*sbar &= ~ttybit;
			bar &= ~ttybit;
			dhp = &dh[unit];
			dhp->state &= ~BUSY;
			if (dhp->state&FLUSH)
				dhp->state &= ~FLUSH;
			else {
				register u_short cntr;
				struct uba_device *ui = dhboard[dev];

				dhaddr->un.dhcsrl = (unit&017)|DH_IE;
				bp = dhp->oblock;
				if (bp != NULL) {
					/*
					 * Do arithmetic in a short to make up
					 * for lost 16&17 address bits.
					 * This is an awful kludge.
					 */
					cntr = dhaddr->dhcar -
						UBACVT(bp->rptr, ui->ui_ubanum);
					/* whole block done? */
					if (cntr == (bp->wptr - bp->rptr)) {
						freeb(bp);
					} else {	/* block interrupted */
						bp->rptr += cntr;
						putbq(dhp->rdq, bp);
					}
					dhp->oblock = NULL;
				}
			}
			dhstart(dhp);
		}
}

dhtimo(dhp)
register struct dh *dhp;
{
	if (dhp->state&BRKING) {
		dhp->brking &= ~(1 << dhp->line);
		((struct dhdevice *)dhboard[dhp->board]->ui_addr)->dhbreak =
		    dhp->brking;
	}
	dhp->state &= ~(TIMEOUT|BRKING);
	dhstart(dhp);
}

/*
 * Start (restart) transmission on the given DH11 line.
 */
dhstart(dhp)
register struct dh *dhp;
{
	register struct dhdevice *dhaddr =
		(struct dhdevice *)dhboard[dhp->board]->ui_addr;
	register int dh, unit;
	register int s = spl5();
	register struct block *bp;

#define	GETOUT	{ splx(s); return; }
	unit = dhp->line;
	dh = unit / NPER;
again:
	if (dhp->state&(TIMEOUT|DHSTOP|BRKING) || dhp->oblock != NULL) {
		GETOUT;
	}
	
	if (dhp->rdq == NULL)
		GETOUT;
	if ((bp = getq(WR(dhp->rdq))) == NULL) {
		GETOUT;
	}

	switch (bp->type) {
	case M_DATA:
		dhp->oblock = bp;
		if (bp->wptr > bp->rptr) {	/* positive length transfer */
			/*
			 * truly hideous, but what can you do when
			 * dealing with a VAX dh?
			 */
			dhaddr->un.dhcsrl = unit | DH_IE |
				UBXADDR(bp->rptr, dhboard[dh]->ui_ubanum) << 4;
			/*
			 * nonsense with `word' is to be sure the dhbar |= word
			 * below is done with an interlocking bisw2 instruction.
			 */
			{
			short word = 1 << unit;
	
			dhsar[dh] |= word;
			dhaddr->dhcar = UBADDR(bp->rptr, dhboard[dh]->ui_ubanum);
			dhaddr->dhbcr = -(bp->wptr - bp->rptr);
			dhaddr->dhbar |= word;
			}
			dhp->state |= BUSY;
		}
		break;

	case M_BREAK:
		dhp->brking |= 1 << dhp->line;
		dhaddr->dhbreak = dhp->brking;
		dhp->state |= BRKING|TIMEOUT;
		timeout(dhtimo, (caddr_t)dhp, 15);	/* about 250 ms */
		freeb(bp);
		break;

	case M_DELAY:
		dhp->state |= TIMEOUT;
		timeout(dhtimo, (caddr_t)dhp, (int)*bp->rptr + 6);
		freeb(bp);
		break;

	case M_HANGUP:
		dhp->ispeed = dhp->ospeed = 0;
	case M_CTL:
		freeb(bp);
		dhparam(dhp);
		goto again;

	}
	splx(s);
}


/*
 * Stop output on a line, e.g. for ^S/^Q or output flush (e.g. ^O).
 */
/*ARGSUSED*/
dhstop(dhp)
register struct dh *dhp;
{
	register struct dhdevice *addr = 
		(struct dhdevice *)dhboard[dhp->board]->ui_addr;
	register int unit, s = spl5();

	if (dhp->state & BUSY) {
		/*
		 * Device is transmitting; stop output
		 * by selecting the line and setting the byte
		 * count to -1.  We will clean up later
		 * by examining the address where the dh stopped.
		 */
		unit = dhp->line;
		addr->un.dhcsrl = (unit&017) | DH_IE;
		dhp = &dh[unit];
		if (!(dhp->state&DHSTOP))	/* not called for ^S */
			dhp->state |= FLUSH;	/* must have been for ^O */
		addr->dhbcr = -1;
	}
	splx(s);
}


/*
 * At software clock interrupt time or after a UNIBUS reset
 * empty all the dh silos.
 */
dhtimer()
{
	register int dh;
	register int s = spl5();

	for (dh = 0; dh < NDH; dh++)
		dhrint(dh);
	splx(s);
}

/*
 * reset driver after a unibus reset
 */
dhreset(uban)
int uban;
{
	register int dhn;
	register int unit;
	register struct dh *dhp;
	register struct uba_device *ui;
	int i;

	for (dhn = 0; dhn < NDH; dhn++) {
		ui = dhboard[dhn];
		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
			continue;
		printf(" dh%d", dhn);
		((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE;
		((struct dhdevice *)ui->ui_addr)->dhsilo = 16;
		unit = dhn * NPER;
		for (i = 0; i < NPER; i++) {
			dhp = &dh[unit];
			if (dhp->state & (ISOPEN|WOPEN)) {
				dhparam(dhp);
				dmctl(unit, DML_ON, DMSET);
				dhp->state &= ~BUSY;
				dhstart(dhp);
			}
			unit++;
		}
	}
	dhtimer();
}

/*
 * Routines for DM11 half of hardware
 */

/*
 * Configuration routine to cause a dm to interrupt.
 */
dmprobe(reg)
caddr_t reg;
{
	register int br, vec;			/* value-result */
	register struct dmdevice *dmaddr = (struct dmdevice *)reg;

#ifdef lint
	br = 0; vec = br; br = vec;
	dmintr(0);
#endif
	dmaddr->dmcsr = DM_DONE|DM_IE;
	DELAY(20);
	dmaddr->dmcsr = 0;
	return (1);
}

/*ARGSUSED*/
dmattach(ui)
struct uba_device *ui;
{

	/* no local state to set up */
}

/*
 * Turn on the line associated with dh dev.
 *
 * From 4BSD.
 */
dmopen(dev)
{
	register struct dh *dhp;
	register struct dmdevice *addr;
	register struct uba_device *ui;
	register dev_t unit;
	register int dm;
	int s;

	unit = minor(dev);
	dm = unit / NPER;
	dhp = &dh[unit];
	unit &= 0xf;
	if (dm >= NDM || (ui = dmboard[dm]) == 0 || ui->ui_alive == 0 ||
	    ui->ui_flags & (1<<unit)) {
		dhp->state |= CARR_ON|DIALOUT;
		return;
	}
	addr = (struct dmdevice *)ui->ui_addr;
	s = spl5();
	addr->dmcsr &= ~DM_SE;
	while (addr->dmcsr & DM_BUSY)
		/* please do not adjust yr set */ ;
	addr->dmcsr = unit;
	addr->dmlstat = DML_ON;
	if (addr->dmlstat&DML_CAR)
		dhp->state |= CARR_ON;
	addr->dmcsr = DM_IE|DM_SE;
	while ((dhp->state&CARR_ON)==0)
		if (tsleep((caddr_t)dhp, DHPRI, 0) != TS_OK)
			break;
	splx(s);
}

/*
 * Dump control bits into the DM registers.
 */
dmctl(dev, bits, how)
int dev;
int bits, how;
{
	register struct uba_device *ui;
	register struct dmdevice *addr;
	register int unit, s;
	int dm;

	unit = minor(dev);
	dm = unit / NPER;
	if ((ui = dmboard[dm]) == 0 || ui->ui_alive == 0)
		return;
	addr = (struct dmdevice *)ui->ui_addr;
	s = spl5();
	addr->dmcsr &= ~DM_SE;
	while (addr->dmcsr & DM_BUSY)
		/* be patient, I'm only a DH-11 */ ;
	addr->dmcsr = unit & 0xf;
	switch (how) {
	case DMSET:
		addr->dmlstat = bits;
		break;
	case DMBIS:
		addr->dmlstat |= bits;
		break;
	case DMBIC:
		addr->dmlstat &= ~bits;
		break;
	}
	addr->dmcsr = DM_IE|DM_SE;
	splx(s);
}

/*
 * DM11 interrupt; deal with carrier transitions.
 */
dmintr(dm)
register int dm;
{
	register struct uba_device *ui;
	register struct dh *dhp;
	register struct dmdevice *addr;

	ui = dmboard[dm];
	if (ui == 0)
		return;
	addr = (struct dmdevice *)ui->ui_addr;
	if (addr->dmcsr&DM_DONE) {
		if (addr->dmcsr&DM_CF) {
			dhp = &dh[dm * NPER +(addr->dmcsr&0xf)];
			wakeup((caddr_t)dhp);
#ifdef	NOTDEF
			if ((dhp->state&WOPEN) == 0 ) {
				if (addr->dmlstat & DML_CAR) {
					dhp->state &= ~DHSTOP;
					wakeup((caddr_t)dhp);
				} else if ((dhp->state&DHSTOP) == 0) {
					dhp->state |= DHSTOP;
					dhstop(dhp);
				}
			} else 
#endif
			if ((addr->dmlstat&DML_CAR)==0) {
				if (!(dhp->state&WOPEN) && !(dhp->state&DIALOUT)) {
					putctl(dhp->rdq->next, M_HANGUP);
					addr->dmlstat = 0;
				}
				dhp->state &= ~CARR_ON;
			} else
				dhp->state |= CARR_ON;
		}
		addr->dmcsr = DM_IE|DM_SE;
	}
}

@@@End of dev/dh.c
echo x - h/dhreg.h 1>&2
cat >h/dhreg.h <<'@@@End of h/dhreg.h'
/*	dhreg.h	6.1	83/07/29	*/

/* 
 * DH-11 device register definitions.
 */
struct dhdevice {
	union {
		short	dhcsr;		/* control-status register */
		char	dhcsrl;		/* low byte for line select */
	} un;
	short	dhrcr;			/* receive character register */
	short	dhlpr;			/* line parameter register */
	u_short dhcar;			/* current address register */
	short	dhbcr;			/* byte count register */
	u_short	dhbar;			/* buffer active register */
	short	dhbreak;		/* break control register */
	short	dhsilo;			/* silo status register */
};

/* Bits in dhcsr */
#define	DH_TI	0100000		/* transmit interrupt */
#define	DH_SI	0040000		/* storage interrupt */
#define	DH_TIE	0020000		/* transmit interrupt enable */
#define	DH_SIE	0010000		/* storage interrupt enable */
#define	DH_MC	0004000		/* master clear */
#define	DH_NXM	0002000		/* non-existant memory */
#define	DH_MM	0001000		/* maintenance mode */
#define	DH_CNI	0000400		/* clear non-existant memory interrupt */
#define	DH_RI	0000200		/* receiver interrupt */
#define	DH_RIE	0000100		/* receiver interrupt enable */

/* Bits in dhlpr */
#define	BITS6	01
#define	BITS7	02
#define	BITS8	03
#define	TWOSB	04
#define	PENABLE	020
/* DEC manuals incorrectly say this bit causes generation of even parity. */
#define	OPAR	040
#define	HDUPLX	040000

#define	DH_IE	(DH_TIE|DH_SIE|DH_RIE)

/* Bits in dhrcr */
#define	DH_PE		0010000		/* parity error */
#define	DH_FE		0020000		/* framing error */
#define	DH_DO		0040000		/* data overrun */
@@@End of h/dhreg.h
echo x - h/dmreg.h 1>&2
cat >h/dmreg.h <<'@@@End of h/dmreg.h'
/*	dmreg.h	6.1	83/07/29	*/

/*
 * DM-11 device register definitions.
 */
struct dmdevice {
	short	dmcsr;		/* control status register */
	short	dmlstat;	/* line status register */
	short	dmpad1[2];
};

/* bits in dm csr */
#define	DM_RF		0100000		/* ring flag */
#define	DM_CF		0040000		/* carrier flag */
#define	DM_CTS		0020000		/* clear to send */
#define	DM_SRF		0010000		/* secondary receive flag */
#define	DM_CS		0004000		/* clear scan */
#define	DM_CM		0002000		/* clear multiplexor */
#define	DM_MM		0001000		/* maintenance mode */
#define	DM_STP		0000400		/* step */
#define	DM_DONE		0000200		/* scanner is done */
#define	DM_IE		0000100		/* interrupt enable */
#define	DM_SE		0000040		/* scan enable */
#define	DM_BUSY		0000020		/* scan busy */

/* bits in dm lsr */
#define	DML_RNG		0000200		/* ring */
#define	DML_CAR		0000100		/* carrier detect */
#define	DML_CTS		0000040		/* clear to send */
#define	DML_SR		0000020		/* secondary receive */
#define	DML_ST		0000010		/* secondary transmit */
#define	DML_RTS		0000004		/* request to send */
#define	DML_DTR		0000002		/* data terminal ready */
#define	DML_LE		0000001		/* line enable */

#define	DML_ON		(DML_DTR|DML_RTS|DML_LE)
#define	DML_OFF		(DML_LE)
@@@End of h/dmreg.h
echo x - h/mdmreg.h 1>&2
cat >h/mdmreg.h <<'@@@End of h/mdmreg.h'
/*
 * mdmctl.h -- from ttydev.h
 */

#ifdef KERNEL
/*
 * Modem control commands.
 */
#define	DMSET		0
#define	DMBIS		1
#define	DMBIC		2
#define	DMGET		3
#endif
@@@End of h/mdmreg.h
echo These next few files recreated from memory... our v8 system is down >&2
echo x - dev/dm.c >&2
cat >dev/dm.c <<!
/*
 * dm - this file intentionally left blank
 * file exists only to satisfy config.
 */
!
echo x - devices >&2
cat>devices.dh <<!
stream-device	53	dh	dh	info
device		54	dm	dm	open
!
echo x - files >&2
cat>files.dh <<!
dev/dh.c	optional dh device driver
dev/dm.c	optional dm device driver
!
echo x - conf.dh >&2
cat>conf.dh <<!
device	 	dh0	at uba? csr 0160020 vector dhrint dhtint
device		dm0	at uba? csr 0170500 vector dmintr
!


From ihnp4!mot!mnetor!yetti!utcs!ian  Fri Jan 17 02:38:54 1986
>From mot!mnetor!yetti!utcs!ian  Fri Jan 17 02:38:54 1986 remote from ihnp4
Received: by ihnp4.ATT.UUCP id AA03699; 17 Jan 86 02:38:54 CST (Fri)
Received: by mnetor.UUCP (4.12/4.7)
	id AA06395; Thu, 16 Jan 86 16:38:39 est
Date: Thu, 16 Jan 86 16:38:39 est
Message-Id: <8601162138.AA06395@mnetor.UUCP>
From: ihnp4!mnetor!yetti!utcs!ian (Ian F. Darwin)
To: research!v8source
Subject: (trivial) makefile for man0
Cc: hacks

I wanted to print some manuals, and it took a while to figure
out what files go where in man0. I don't assert() that this
is complete, it's probably not, but it's most of what I used
to generate a complete printout of man0, and might save
you a bit of time if you decide to do some printing.


all:		title preface cont intr index

title:		title.copyr
		troff $? | dcat
preface:	pref
		troff -ms $? | dcat
cont:		contmac contents
		troff -ms contmac | dcat
intr:		intro
		troff -ms intro | dcat
index:		makind makind1 ptxmac
		sh makind
		troff -ms ptxmac | dcat
		
clean:
		rm -f toc? tocx? ptxx


From utcsri!drg  Tue Jan 21 15:08:10 1986
>From drg  Tue Jan 21 15:08:10 1986 remote from utcsri
Received: by utcsri.UUCP (4.24/5.1.UofT)
	id AA10865; Tue, 21 Jan 86 15:08:10 est
Date: Tue, 21 Jan 86 15:08:10 est
From: Dave Galloway <utcsri!drg>
Message-Id: <8601212008.AA10865@utcsri.UUCP>
To: research!v8news
Subject: Porting the Blit software to the Atari 520ST

This is a fairly long article.  In summary, we've converted an Atari
520ST personal computer into a Blit, and ported the Blit software to
it.  No hardware changes were needed.  It works, for the most part.
Our only objection to the result is that the screen is too small, and
the keyboard is a bit flakey.

HARDWARE

The Atari 520ST is Atari's latest personal computer.  It contains an 8
Mz 68000, 512 Kb of RAM, a directly mapped 400x640 black and white
display, an RS-232 line, a mouse, a keyboard and a floppy disk.  It
costs about $800 US.  If you ignore the floppy disk and squint a bit,
what you have is the original prototype Blit terminal, with twice as
much memory and a smaller screen.

There are obviously other hardware differences, which did not get in
the way very much.  The screen is not interlaced, and runs at 70 Hz.
It is much crisper than the 5620 screen.  It has 80 pixels to the inch,
rather than 100.  The mouse has only 2 buttons, instead of 3.

The Atari has a slot in one side, intended for a diagnostic
cartridge.  We built a cartridge to fit the slot, and filled it with
two 27128 EPROMS.  This gives us 32K bytes of ROM.  Into it we put the
standard 68000 Blit terminal program, and made it look like a
diagnostic cartridge.  When the Atari is powered on or re-booted, the
normal Atari ROMs inside the machine see our cartridge, and jump to it
rather than booting the normal Atari operating system.  The machine
reverts to a normal Atari by simply removing the cartridge and powering
the machine back on.

SOFTWARE

We had to make some changes to the Blit software in order to make it
work on the Atari.  We created a -lstsys library to contain all of the
machine dependent code for the Atari.  We moved all of the machine
dependent library code for the Blit into the already existing -lsys
library.  Along with a new runtime start off file, this allowed us to
compile and run the old stand alone demos on the Atari.

We then modified mpxterm so that it would work.  No changes were needed
in the mpx (host side) program itself, but the terminal side program
did have to be changed to support the different hardware.

We added the "Jrect" variable to the list of things in mpx.h that are
fetched from the mpxterm "operating system", rather than being compiled
into each user program.  Jrect contains the absolute size of the
screen, which is different on the Atari and the Blit.  Once we had done
that, we were able to run the same binary user programs on either the
Atari or the Blit without re-compilation.

PORTABILITY

We found that most of the code in the system was well written, and that
porting it to the Atari was usually a matter of recompilation, once we
had the libraries correct.  However, we did run into a few non-portable
constructs.  If you want to write portable code, avoid:

1) Using absolute device addresses:

<                       *((char *)(384*1024L+062)) = 2;
---
>                       ringbell();

and:

<         srand(*XMOUSE);
---
>         srand(mouse.xy.x);

2) Using absolute ROM addresses:

< #define bitblt(s, r, d, p, c) (*((void(*)())0x430d6))(s, r, d, p, c)
< #define texture(s, r, d, c)   (*((void(*)())0x4372c))(s, r, d, c)

3) Assuming things about the font:

< #define       CW      9       /* width of a character */
---
> #define       CW      defont.info[' '].width  /* width of a character */

4) Assuming that YMAX is a power of 2:

<                               y = (x ^ j) & (YMAX - 1);

5) Assuming that YMAX is a manifest literal:

< long	bitarray[(YMAX/BINWIDTH)*(YMAX/BINWIDTH)];
---
> #define MAXSCREENSIZE	1024
> long	bitarray[(MAXSCREENSIZE/BINWIDTH)*(MAXSCREENSIZE/BINWIDTH)];


CONCLUSIONS

1) The 400x640 screen is small when used as a Blit.  Even after
making the Blit font narrower, the screen is only 80 characters wide.  Much
of the UNIX software (esp. 4.2BSD) is assumes an 80 column terminal,
which means you want your windows to be at least 80 columns wide.  If
you do this on a screen that is only 80 columns wide, you can't overlap
the windows in any useful way (ie so that you can get at the corners to
bring them to the top).  If you were re-designing the Blit from
scratch, you would want to use a screen like the SUN's 950x1150 or
so.

2) The Blit software is quite portable.  Most of it does not depend on
the screen resolution, and a simple change to mpx.h can take care of
that for programs that run under mpx or mux.

3) mpxterm and muxterm can successfully hide machine dependencies from
the user programs that run under them.  We are using the same binaries on
both the Blit and the Atari.

4) We were lucky.  There are some machine dependencies in the code that
we would not like to have faced.  For instance, both machines agree
that the upper left corner of the screen is the origin.  Both also
agree that the MSB of a word is the left most pixel on the screen.

FUTURE WORK

We are going to try squeezing the font size down one more time, to make
it 7 or even 6 bits wide.  This will allow us to put more than one 80
column window on the screen, and still leave the corners of the windows
visible.  Of course, we could go blind staring at it.

We just got mux to work, and are still playing with it.  We have not
done anything with pi.  We would also like to back port some of the 5620
stuff, including jim.

			-- Dave Blythe (utcsri!drb)
			-- Dave Galloway (utcsri!drg)

From utcsri!drg  Tue Jan 21 15:11:22 1986
>From drg  Tue Jan 21 15:11:22 1986 remote from utcsri
Received: by utcsri.UUCP (4.24/5.1.UofT)
	id AA10919; Tue, 21 Jan 86 15:11:22 est
Date: Tue, 21 Jan 86 15:11:22 est
From: Dave Galloway <utcsri!drg>
Message-Id: <8601212011.AA10919@utcsri.UUCP>
To: research!v8news
Subject: random missing things on the V8 distribution

We've looked at some of the V8 stuff in varying amounts of detail.
This is a short list of problems we have noticed.  They are
in no particular order.

- /usr/man/man1/ksh.1 is there, but the source and binary are missing.

- /usr/doc contains only awk, grap, pic and v8directions.  This seems
a bit sparse.  What about cip and C++, for example ?

- /usr/games/lib/mars/*.obj look like pieces of someone's
RA81 driver.  Looks like file system damage at some point.

From cbosgd!utcs!geoff  Tue Feb  4 03:39:12 1986
>From utcs!geoff  Tue Feb  4 03:39:12 1986 remote from cbosgd
Date: Mon, 3 Feb 86 22:51:50 est
From: geoff@utcs.uucp (Geoff Collyer)
To: Dave Galloway <utcsri!drg>
Cc: research!v8news
Subject: Re: random missing things on the V8 distribution
In-Reply-To: Your message of 23 Jan 1986 1022-EST (Thursday).

Maybe I'm just cynical, but I thought the reason that only ksh.1 was
present was so that you could see how overgrown and un-UNIX-like ksh is,
and so you wouldn't *want* the binary or source. (Do you really want
subsets of emacs, vi, basic and nroff built into your shell? a 32-page
manual page (sic), bigger than the csh's?)  I note that in the v8 shell,
perhaps as a reaction to all this cruft in ksh, Rob Pike has ripped out
all the V.2 performance mods.

As for C++ manuals, I suspect that you have to buy the book, to avoid
copyright problems, as for the C reference manual since K&R was
published. (On V6, I recall that the C ref. man. was in /usr/doc.)

From dutoit!norman Tue Feb  4 07:58 EST 1986
>From norman Tue Feb  4 07:58 EST 1986 remote from dutoit
ksh.1 is on the tape out of mere sloppiness.  A few people here use it, hence
the man page is there, but they take care of it themselves.  I don't know
offhand who has the source, and really don't want to know.  If anyone ever
ships it to dutoit, I'll probably rm it.

Alas, there simply aren't new /usr/doc papers for much of the system.  This
is also why there's no Eighth Edition of Volume 2 of the manual.

From seismo!mcvax!cheviot.ncl.ac.uk!andy Thu Feb  6 09:21:07 1986
Received: from mcvax.UUCP by seismo.CSS.GOV with UUCP; Thu, 6 Feb 86 08:50:41 EST
Received: by mcvax.uucp; Thu, 6 Feb 86 12:15:58 +0100 (MET)
Message-Id: <8602061115.AA20733@mcvax.uucp>
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a010883; 6 Feb 86 10:36 GMT
From: Andy Linton <seismo!mcvax!cheviot.ncl.ac.uk!andy>
Date: Thu, 6 Feb 86 10:31:40 gmt
To: research!v8news
Subject: ht driver


In some of the early messages on v8 news problems were mentioned
with the ht driver. 
Has anybody done any work on it? We are using it with a DEC TU77
and the TM03 controller.
Thanks
andy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SENDER 	: Andy Linton		PHONE	: +44 632 329233
POST	: Computing Lab, University of Newcastle upon Tyne, UK, NE1 7RU
ARPA	: andy%cheviot.newcastle.ac.uk@ucl-cs.ARPA)
JANET	: andy@uk.ac.newcastle.cheviot
UUCP	: <UK>!ukc!cheviot!andy

***  Ni fui moran beagan d'aon rud, ach is fui moran beagan ceille.  ***

From seismo!mcvax!cheviot.ncl.ac.uk!andy Thu Feb  6 10:48:45 1986
Received: from mcvax.UUCP by seismo.CSS.GOV with UUCP; Thu, 6 Feb 86 08:25:20 EST
Received: by mcvax.uucp; Thu, 6 Feb 86 11:19:31 +0100 (MET)
Message-Id: <8602061019.AA17000@mcvax.uucp>
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a007887; 6 Feb 86 9:56 GMT
From: Andy Linton <seismo!mcvax!cheviot.ncl.ac.uk!andy>
Date: Thu, 6 Feb 86 09:55:20 gmt
To: research!v8news
Subject: Bringing up V8 at Newcastle


We have now had the system up for just over two weeks and are beginning
to whip it into the shape we need.
Bringing up the system on top of a 4.2 filesystem was not too bad.
Having built the system which was very straightforward apart from the
#endif's which were missing from some of the source files, we used the
proto option to mkfs (which hasn't been exercised for years - see mkfs(8))
to get a 'mini' root file system onto the root partition of the disk.
This means we had no option but to choose a 1k filesytem for the root
partition. Would the addition  of the proto code to mkbitfs be a useful
thing?  I got caught by the definition of a 4k system in swapra.c
and so the first attempt failed when the system went off to read the disc.
As we have only one RA81 we noticed the absence of a swapra1.c - we are
poor on this side of the Atlantic! I also increased the size of partitions
0 and 1 by ~ 50% and decreased 5 accordingly.
The proto file is appended - it was sufficient to get us running - it may
contain more than absolutely necessary. Permissions on the files don't
need to be so lax but it seemed easier at the time.
I hacked the 4.2 MAKEDEV to do some of the V8 special devices. Its here
if anyone wants it.

Proto file for v8 'mini' root filesystem
~~~~~~~~~~~~~~ cut here ~~~~~~~~~~~~~~~~
/v8fs/usr/boot/bb/1kboot
7680 1024
d--777 3 1
	boot ---777 0 10 /v8fs/boot
	unix ---777 0 10 /v8fs/unix
	proto ---777 0 10 /v8fs/proto
	tmp d--777 0 10
	$
	usr d--777 0 10
	$

	bin  d--777 0 10
		STTY ---777 0 10 /v8fs/bin/STTY
		cat  ---777 0 10 /v8fs/bin/cat
		cp   ---777 0 10 /v8fs/bin/cp
		echo ---777 0 10 /v8fs/bin/echo
		login -u-777 0 10 /v8fs/etc/login
		ls   ---777 0 10 /v8fs/bin/ls
		make ---777 0 10 /v8fs/bin/make
		mkdir ---777 0 10 /v8fs/bin/mkdir
		mt ---777 0 10 /v8fs/bin/mt
		mv ---777 0 10 /v8fs/bin/mv
		rm ---777 0 10 /v8fs/bin/rm
		sh ---777 0 10 /v8fs/bin/sh
		stty ---777 0 10 /v8fs/bin/stty
		sync ---777 0 10 /v8fs/bin/sync
		tar ---777 0 10 /v8fs/bin/tar
	$
	dev d--777 0 10
		MAKEDEV ---777 0 10 /v8fs/dev/MAKEDEV
		console c--777 0 10 0 0
		drum c--777 0 10 7 0
		fd d--777 0 10
			0 c--777 0 10 40 0
			1 c--777 0 10 40 1
			10 c--777 0 10 40 10
			11 c--777 0 10 40 11
			12 c--777 0 10 40 12
			13 c--777 0 10 40 13
			14 c--777 0 10 40 14
			15 c--777 0 10 40 15
			2 c--777 0 10 40 2
			3 c--777 0 10 40 3
			4 c--777 0 10 40 4
			5 c--777 0 10 40 5
			6 c--777 0 10 40 6
			7 c--777 0 10 40 7
			8 c--777 0 10 40 8
			9 c--777 0 10 40 9
		$
		kUmem c--777 0 10 3 3
		kmem c--777 0 10 3 1
		kmemr c--777 0 10 3 4
		mem c--777 0 10 3 0
		mt0 b--777 0 10 1 0
		mt12 b--777 0 10 1 12
		mt4 b--777 0 10 1 4
		mt8 b--777 0 10 1 8
		nmt0 b--777 0 10 1 4
		nmt8 b--777 0 10 1 12
		nrmt0 c--777 0 10 5 4
		nrmt8 c--777 0 10 5 12
		null c--777 0 10 3 2
		pt d--777 0 10
			pt0 c--777 0 10 18 0
			pt1 c--777 0 10 18 1
			pt10 c--777 0 10 18 10
			pt11 c--777 0 10 18 11
			pt12 c--777 0 10 18 12
			pt13 c--777 0 10 18 13
			pt14 c--777 0 10 18 14
			pt15 c--777 0 10 18 15
			pt2 c--777 0 10 18 2
			pt3 c--777 0 10 18 3
			pt4 c--777 0 10 18 4
			pt5 c--777 0 10 18 5
			pt6 c--777 0 10 18 6
			pt7 c--777 0 10 18 7
			pt8 c--777 0 10 18 8
			pt9 c--777 0 10 18 9
		$
		ra00 b--777 0 10 7 0
		ra01 b--777 0 10 7 1
		ra02 b--777 0 10 7 2
		ra03 b--777 0 10 7 3
		ra04 b--777 0 10 7 4
		ra05 b--777 0 10 7 5
		ra06 b--777 0 10 7 6
		ra07 b--777 0 10 7 7
		rmt0 c--777 0 10 5 0
		rmt12 c--777 0 10 5 12
		rmt4 c--777 0 10 5 4
		rmt8 c--777 0 10 5 8
		rra00 c--777 0 10 28 0
		rra01 c--777 0 10 28 1
		rra02 c--777 0 10 28 2
		rra03 c--777 0 10 28 3
		rra04 c--777 0 10 28 4
		rra05 c--777 0 10 28 5
		rra06 c--777 0 10 28 6
		rra07 c--777 0 10 28 7
		stderr c--777 0 10 40 2
		stdin c--777 0 10 40 0
		stdout c--777 0 10 40 1
		tty c--777 0 10 40 3
		tty00 c--777 0 10 1 0
		tty01 c--777 0 10 1 1
		tty02 c--777 0 10 1 2
		tty03 c--777 0 10 1 3
		tty04 c--777 0 10 1 4
		tty05 c--777 0 10 1 5
		tty06 c--777 0 10 1 6
		tty07 c--777 0 10 1 7
	$
	etc d--777 0 10
		fsck ---777 0 10 /v8fs/etc/fsck
		fstab ---777 0 10 /v8fs/etc/fstab
		getty ---777 0 10 /v8fs/etc/getty
		group ---777 0 10 /v8fs/etc/group
		init ---777 0 10 /v8fs/etc/init
		ldpcs ---777 0 10 /v8fs/etc/ldpcs
		login -u-777 0 10 /v8fs/etc/login
		mkfs ---777 0 10 /v8fs/etc/mkfs
		mknod ---777 0 10 /v8fs/etc/mknod
		motd ---777 0 10 /v8fs/etc/motd
		mount ---777 0 10 /v8fs/etc/mount
		passwd ---777 0 10 /v8fs/etc/passwd
		pcs750.etc ---777 0 10 /v8fs/etc/pcs750.bin
		rarct ---777 0 10 /v8fs/etc/rarct
		rarepl ---777 0 10 /v8fs/etc/rarepl
		rc ---777 0 10 /v8fs/etc/rc
		ttys ---777 0 10 /v8fs/etc/ttys
		umount ---777 0 10 /v8fs/etc/umount
	$
$
~~~~~~~~ end of proto ~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SENDER 	: Andy Linton		PHONE	: +44 632 329233
POST	: Computing Lab, University of Newcastle upon Tyne, UK, NE1 7RU
ARPA	: andy%cheviot.newcastle.ac.uk@ucl-cs.ARPA)
JANET	: andy@uk.ac.newcastle.cheviot
UUCP	: <UK>!ukc!cheviot!andy

***  Ni fui moran beagan d'aon rud, ach is fui moran beagan ceille.  ***




From seismo!mcvax!cheviot.ncl.ac.uk!ncx Thu Feb  6 12:48:57 1986
Received: from mcvax.UUCP by seismo.CSS.GOV with UUCP; Thu, 6 Feb 86 12:34:36 EST
Received: by mcvax.uucp; Thu, 6 Feb 86 15:24:22 +0100 (MET)
Message-Id: <8602061424.AA02255@mcvax.uucp>
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a018548; 6 Feb 86 13:28 GMT
From: "Lindsay F. Marshall" <seismo!mcvax!cheviot.ncl.ac.uk!ncx>
Date: Thu, 6 Feb 86 13:27:37 gmt
To: research!v8source
Subject: mux

Does anybody have a version of mux that will support the -l option
for the Blit?????? It would be very useful......

From mcvax!cheviot.ncl.ac.uk!ncx Thu Feb 13 15:37:40 1986
Received: by mcvax.uucp; Thu, 13 Feb 86 15:37:40 +0100 (MET)
Message-Id: <8602131437.AA07015@mcvax.uucp>
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a002316; 13 Feb 86 9:16 GMT
From: "Lindsay F. Marshall" <mcvax!cheviot.ncl.ac.uk!ncx>
Date: Thu, 13 Feb 86 09:08:53 gmt
To: research!v8source
Subject: Pads and other things

1) Is there any documentation available for the pads package??

2) Is there a version of paint that will work in a Blit???

3) What's eric????

Lindsay

From mcvax!cheviot.ncl.ac.uk!root Mon Feb 24 19:48:10 1986
Received: by mcvax.uucp; Mon, 24 Feb 86 19:48:10 +0100 (MET)
Message-Id: <8602241848.AA22304@mcvax.uucp>
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a008966; 24 Feb 86 16:43 GMT
From: Super User <mcvax!cheviot.ncl.ac.uk!root>
Date: Mon, 24 Feb 86 16:43:10 gmt
To: research!v8news
Subject: Diagnostic programs for the blits


Of the blits we had from Bell Labs two are non-runners.
There are some diagnostic programs in /usr/blit/diag
including stuff to make diagnostic proms? These use a routine
called 'dobits' which we don't appear to have. 
Any help with this would be appreciated
Thanks
andy

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SENDER 	: Andy Linton		PHONE	: +44 632 329233
POST	: Computing Lab, University of Newcastle upon Tyne, UK, NE1 7RU
ARPA	: andy%cheviot.newcastle.ac.uk@ucl-cs.ARPA)
JANET	: andy@uk.ac.newcastle.cheviot
UUCP	: <UK>!ukc!cheviot!andy

***  Ni fui moran beagan d'aon rud, ach is fui moran beagan ceille.  ***




From allegra!utzoo!utcs!geoff Tue Apr  1 05:25:50 1986
Date: Tue, 1 Apr 86 01:02:54 est
From: allegra!utcs!geoff (Geoff Collyer)
To: research!v8news
Subject: v8 tcp vs 4.2bsd

If anyone tries to use the distributed v8 inet code to talk tcp/ip to
a 4.2bsd system, they will need to turn trailers *off* on the 4.2
interface(s) in order to rcp (ropy) files bigger than 1023 bytes.


From allegra!pandora!bill Tue Apr  1 10:25:08 1986
To: allegra!utcs!geoff, allegra!utcs!research!v8news
Subject: Re:  v8 tcp vs 4.2bsd

Thanks I also saw this problem in talking with a Pyramid OSX.

From dutoit!dmr Wed Apr  2 00:44 EST 1986
Subject: v8 tcp vs. trailers

Presotto said (at somewhat greater length, actually) "What are trailers?"
and so I venture that the previous analysis is correct.  Trailers
may be buried in there somewhere but I don't know where.

From dutoit!dmr Wed Apr  2 00:44 EST 1986
Subject: v8 tcp vs. trailers

Presotto said (at somewhat greater length, actually) "What are trailers?"
and so I venture that the previous analysis is correct.  Trailers
may be buried in there somewhere but I don't know where.

From koura!bill Thu Apr 10 11:45 EST 1986
Does anyone know the number of 4k blocks in a ra?6 file system?
I tried /etc/mkbitfs /dev/ra?6 93693 and also 92668 but the results are always
93693(92668) 4k blocks -2 blocks of inodes, -128 inodes
free map won't fit, blk = 93693, wd = 93693
Bottom line is how does one make a very large file system 3X123 meg.
Thanks koura!bill


From mcvax!cheviot.ncl.ac.uk!ncx Fri Apr 11 14:27:15 1986
Received: by mcvax.uucp; Fri, 11 Apr 86 14:27:15 +0100 (MET)
Message-Id: <8604111327.AA08698@mcvax.uucp>
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a019709; 11 Apr 86 13:36 BST
From: "Lindsay F. Marshall" <mcvax!cheviot.ncl.ac.uk!ncx>
Date: Fri, 11 Apr 86 13:31:00 gmt
To: research!v8source
Subject: Bit maps and music

1) Does anyone have either

	a) an explanation of the format of the files created by Blitblt
	  and twid (the code is not exactly esy to understand!)

	b) A program that generates some more universal format from
	   these files (We want to go to a QMS Lasergrafix by the way)

2) What about all this music software we keep hearing about........

	Lindsay



From dutoit!dmr Fri Apr 11 17:01 EST 1986
Subject: blitblt formats
To: v8news

See man9/b*.  If they are insufficiently detailed,
try sending some mail to Tom Killian (research!tom).

	Dennis

From utcsri!drb Sun Apr 13 07:22:43 1986
Received: by utcsri.UUCP (4.24/5.1.UofT)
	id AA16667; Sun, 13 Apr 86 07:22:43 est
Date: Sun, 13 Apr 86 07:22:43 est
From: David R. Blythe <utcsri!drb>
Message-Id: <8604131222.AA16667@utcsri.UUCP>
To: research!v8source
Subject: Re: Bit maps and music

The format for these files is described in bitfile under section 9 of the
manuals. The programs bcan.c and bdump.c found in the blitblt source directory
may be of some interest (beware of the idiosyncratic format demanded by the
imagen in bcan). I hacked bcan to dump stuff to our laser-writer as a
postscript bitmap but the program is not suitable for public display.

I haven't seen any mention of music software, but would also be interested
in hearing about it. I noticed that the icon catalogues contain notes and
clefs and stuff that could be used in a score editor?

On a more general note, I would like to hear about what people have been
doing with their Blits. Have you got them working, do people use them as their
`preferred' terminal? Has anybody written any interesting programs for theirs? 

	-drb

From ihnp4!pur-ee!mckay Mon Apr 14 20:10:39 1986
From: ihnp4!pur-ee!mckay
Received: by ihnp4.ATT.COM id AA06210; 14 Apr 86 20:10:39 CST (Mon)
Received: by ee.purdue.edu (5.44/1.2)
	id AA24258; Mon, 14 Apr 86 10:31:14 EST
Message-Id: <8604141531.AA24258@ee.purdue.edu>
To: research!v8source
Cc: mckay
Subject: Re: Bit maps and music
In-Reply-To: Your message of Sun 13 Apr 1986  07:22:43.
	     <8604141444.AA21773@ee.purdue.edu>
Date: 14 Apr 86 10:31:08 EST (Mon)


drb asks:
>On a more general note, I would like to hear about what people have been
>doing with their Blits. Have you got them working, do people use them as their
>`preferred' terminal? Has anybody written any interesting programs for theirs? 

Yes, we have a few Blits (5620's are really called Jerq's right?) running on
our 4.3 BSD systems here at Purdue.  "Preferred terminal"?  Depends on who
ask around here.  Some folks can't stand them.  I think they're alright.
(I'd really like a SUN :-)  We've not written anything really outstanding for
them, a couple of status-line toys, an alarm clock, got most of the V8 Blit
games working; stuff like that.  I use the troff previewer "proof" fairly
regularly.

Has anyone come up with a better mouse-driven editor than "jim"?

--ddm

From dutoit!dmr Tue Apr 15 03:38 EST 1986
To: v8news
Subject: stuff

I know I sound like one of the netnews neatness compulsives, but
please send stuff intended to be read to v8news.  v8source is for
source and doesn't arrive in my mailbox; I have to search it out.

People seem interested in music.  We don't have anything to distribute,
but Tom Killian is doing things with MIDI interfaces and DX7s and things
like that.  He might be interested in correspondence, at least with
people working in the same area.  I don't thing he wants to handle
requests for software or braindumps yet.  He does have a passable
Brandenburg Concerto rendered by a 5620 controlling a synthesizer,
along with a musical analog of Munching Squares.  [research!tom]

Rob's new editor is called sam and is a redesigned jim.  The mouse part
is nearly the same as jim, but it has a command window instead of a
line.  The commands are in many ways like ed's, but the global things
(generalization of  g ) and the handling of regular expressions are
much more powerful.  He has a manuscript and has given a talk on the
larger subject of which this is a manifestation, so perhaps he
could be enticed somewhere, but probably he will have a refractory
period after his return from Australia.

There now is an Atari 1040ST (a megabyte lowered resolution Blit,
one might say) for $995.  Any possibly forthcoming AT&T 5620 replacement
will have tough competition (I can say no more).

From ikeya!rob Thu Apr 24 13:58 EST 1986
The following is a set of diffs for fixing a few bugs in the shell as
distributed on v8.  < is the original, > is the current research version.
Several of the fixes change output format for uniformity, but the main
fix is an important one: invoking a function no longer overwrites the
positional parameters of the invoking shell.  Thanks to Chris Maltby
for this fix, which eliminates the only BUGS line in sh(1).

--========args.c========
--11,14c11,17
--< static struct dolnod *copyargs();
--< static struct dolnod *freedolh();
--< extern struct dolnod *freeargs();
--< static struct dolnod *dolh;
-----
--> static struct dolnod	*copyargs();
--> static void		freedolh();
--> extern struct dolnod	*freeargs();
--> static struct dolnod	*dolh;
--> static int		dollev = 0;
--> static char		**savdolv;
--> static int		savdolc;
--170a174
--> 	register struct dolnod *nxtblk = 0;
--175c179
--< 	 * free old ones unless on for loop chain
-----
--> 	 * free old ones unless on 'for' loop chain
--176a181,182
--> 	if (dolh)
--> 		nxtblk = dolh->dolnxt;
--179a186
--> 	dolh->dolnxt = nxtblk;
--183c190,244
--< static struct dolnod *
-----
--> 
--> /*
-->  * pushes a set of positional parameters
-->  */
--> pushargs(argi)
--> 	char	*argi[];
--> {
--> 	register char **argp = argi;	/* count args */
--> 	register int argn = 0;
--> 	register struct dolnod *nxtblk;
--> 
--> 	while (Rcheat(*argp++) != ENDARGS)
--> 		argn++;
--> 	if (nxtblk = dolh)
--> 		++nxtblk->doluse;
--> 	else /* if (dollev == 0) */
--> 	{
--> 		savdolv = dolv;
--> 		savdolc = dolc;
--> 	}
--> 	dolh = copyargs(argi, argn);	/* sets dolv also */
--> 	dolc = argn - 1;
--> 	++dollev;
--> 	dolh->dolnxt = nxtblk;
--> }
--> 
--> 
--> /*
-->  * pop a set of positional parameters
-->  */
--> popargs()
--> {
--> 	register char **argp;	/* count args */
--> 	register int argn;
--> 	register struct dolnod *nxtblk = 0;
--> 	
--> 	if (dolh && (nxtblk = dolh->dolnxt))
--> 		--nxtblk->doluse;
--> 	--dollev;
--> 	freedolh();
--> 	if (dolh = nxtblk)
--> 	{
--> 		dolv = dolh->dolarg;
--> 		for (argp = dolv, argn = 0; Rcheat(*argp++) != ENDARGS; argn++);
--> 		dolc = argn - 1;
--> 	}
--> 	else /* if (dollev == 0) */
--> 	{
--> 		dolv = savdolv;
--> 		dolc = savdolc;
--> 	}
--> }
--> 
--> 
--> static void
--211c272
--< 		argr = argblk->dolnxt;
-----
--> 		argr = argblk->dolfor;
--238c299
--< 	register struct dolnod *np = (struct dolnod *)alloc(sizeof(char**) * n + 3 * BYTESPERWORD);
-----
--> 	register struct dolnod *np = (struct dolnod *)alloc(sizeof(struct dolnod) + sizeof(char**) * n);
--242a304,305
--> 	np->dolnxt = 0;
--> 	np->dolfor = 0;
--263c326
--< 		argr = argblk->dolnxt;
-----
--> 		argr = argblk->dolfor;
--265,267c328
--< 		if (argblk == dolh)
--< 			argblk->doluse = 1;
--< 		else
-----
--> 		if ((--argblk->doluse) == 0)
--284a346,350
--> 	 * now throw away pushed on arglists for functions
--> 	 */
--> 	while (dolh && dollev > 0)
--> 		popargs();
--> 	/*
--304c370
--< 			dolh->dolnxt = argfor;
-----
--> 			dolh->dolfor = argfor;
--310d375
--< 
--========func.c========
--385c385
--< 				prfstr("<<");
-----
--> 				prfstr("<");
--========mac.h========
--25d24
--< #define MAX(a,b)	((a)>(b)?(a):(b))
--========macro.c========
--266a267
--> 	register struct ionod *saviopend;
--277a279,281
--> 
--> 	saviopend = iopend;
--> 	iopend = (struct ionod *)0;
--290a295,296
--> 	iopend = saviopend;
--> 
--342d347
--< 
--========mode.h========
--106a107
--> 	struct dolnod	*dolfor;
--========spname.c========
--45c49
--< 		if((dirf=opendir(newname,0)) == NULL)
-----
--> 		if((dirf=opendir(*newname? newname : "",0)) == NULL)
--========xec.c========
--107c107
--< 						setargs(com);
-----
--> 						pushargs(com);
--109a110
--> 						popargs();
--223a225,227
--> 										prs_buff("trap ");
--> 										prs_buff(quotedstring(trapcom[i]));
--> 										prc_buff(SP);
--225,226d228
--< 										prs_buff(colon);	
--< 										prs_buff(trapcom[i]);	


From utcsri!drb Fri Apr 25 00:39:32 1986
Received: by utcsri.UUCP (4.24/5.1.UofT)
	id AA01893; Fri, 25 Apr 86 00:39:32 est
Date: Fri, 25 Apr 86 00:39:32 est
From: David R. Blythe <utcsri!drb>
Message-Id: <8604250539.AA01893@utcsri.UUCP>
To: research!v8news
Subject: Blit vs 5620

	I wonder if someone might be able to tell me how the mux software
for the 5620 differs from the Blit. I know we have the source, but a diff
of the files is not as informative as a higher-level description. I know
that the 5620 has some EEPROM and such for storing terminal configuration
and function key strings, ..., but what I really am interested in finding 
out is how the window management has evolved. For instance I know that dark
borders are used to indicate the current window rather than the stipple
patterns used for `background' windows in the Blit mux. I wonder if the
mechanisms for cutting and pasting text have changed at all? The Blit mux
seems to have a problem with deciding whether or not the trailing newline
should be included in a selected line. Has anything been done to rectify this?
I noticed also that the contents of the `snarf' buffer are now more generally
available to other layer programs for manipulation.

	I also wouldn't mind hearing some more about Sam and the evolution of
Jim.

	Any comments would be appreciated.

From utcsri!drb Fri May  2 20:21:59 1986
Received: by utcsri.UUCP (4.24/5.1.UofT)
	id AA26035; Fri, 2 May 86 20:21:59 edt
Date: Fri, 2 May 86 20:21:59 edt
From: David R. Blythe <utcsri!drb>
Message-Id: <8605030021.AA26035@utcsri.UUCP>
To: research!v8source
Subject: minor bug in pic

	There is a small bug to do with computing sizes of pictures involving
arrows. The picture
.PS
line -> from 1,1 to 2,2 to 4,3 to 3,-7
.PE
has a dimension of 10x3 and is correctly computed by pic; however, the picture
.PS
arrow from 1,1 to 2,2 to 4,3 to 3,-7
.PE
is exactly the same size, but pic computes its size as 8x2. The problem is
that the vertices of arrows are not always included in picture extrema
calculations. There is a simple fix which can be applied to linegen.c which
seems to correct the problem.

diff  -r1.1 linegen.c
184c184
< 		if (type == LINE)
---
> 		if (type == LINE || type == ARROW)
	
	-drb

From pandora!bill Wed May 14 15:46 EDT 1986
I'm looking for a version of kermit which will compile on V8. Has anyone
done this port? bellcore!koura!bill


From utzoo!henry Thu May 15 16:18:11 1986
To: research!v8news
Subject: V8 awk documentation problem

One of the first things in the V8 awk manual is ".so /usr/bwk/src/cprog.mac".
Naturally, /usr/bwk isn't in the distribution.  Foo.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From dutoit!dmr Fri May 16 02:47 EDT 1986
Subject: no sooner said than done

OK, here is /usr/bwk/src/cprog.mac, suitable for interpolating
into the awk manual.
The editorial comment on the second line is in the file itself, I promise.
-----------------
.ig
	Brian's crummy macros for including programs.
	.P1
	program text, with tabs...
	.P2
	This will keep it all on one page; insert
	.P3 at will for optional page breaks.

The following are settable number registers:
..
.nr dP 1	\" delta point size for program
		\" 1 makes it 1 smaller than text
.nr dV 1	\" delta vertical for programs; ditto
.nr dT 8	\" tab stops this far apart in .P1/.P2
.nr NH .5v	\" adds extra space before NH or SH heading
.nr ds .5i	\" default indent for programs
.nr P1 .5i
.hy 14		\" set hyphenation: 2=not last lines; 4= no -xx; 8=no xx-
.\"
.\"
.de UC		\" print 1st arg in smaller size (upper case)
.		\" .UC smaller after before
.		\" e.g., .UC UNIX .)
\&\\$3\s-1\\$1\\s0\&\\$2
..
.de IT		\" italicize first argument; same convention for 2nd, 3rd args
.nr ff \\n(.f
\&\\$3\f2\\$1\f\\n(ff\^\&\\$2
..
.de UL		\" print 1st arg in CW font.  don't ask why the name
.nr ff \\n(.f
\%\&\\$3\f(CW\\$1\f\\n(ff\&\\$2
..
.de CW
.UL \\$1 \\$2 \\$3
..
.de UI		\" print first arg in CW, second in italic
.nr ff \\n(.f
\%\&\\$3\f(CW\\$1\f2\\$2\f\\n(ff
..
.de BI		\" makes bold italic
.nr ff \\n(.f
\&\\$3\f4\\$1\f\\n(ff\^\&\\$2
..
.de P1		\" start a program display
.ie \\n(.$ .DS I \\$1
.el .DS I \\n(dsu
.nf
.lg 0
.ps -\\n(dP
.vs -\\n(dV
.ft CW
.nr t \\n(dT*\\w'x'u
.ta 1u*\\ntu 2u*\\ntu 3u*\\ntu 4u*\\ntu 5u*\\ntu 6u*\\ntu 7u*\\ntu 8u*\\ntu 9u*\\ntu 10u*\\ntu 11u*\\ntu 12u*\\ntu 13u*\\ntu 14u*\\ntu
.lg 0
..
.de P2		\" end a program display
.ps \\n(PS
.vs \\n(VSp
.ft 1
.fi
.DE
.lg
..
.de P3		\" provides optional break in P1/P2
.nr x \\n(DV
.nr DV 0
.P2
.P1 \\n(P1u
.nr DV \\nx
..
....	This is the .ix macro:
...
.de ix
.tm ix: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7	\\n%
..

From utzoo!henry Fri May 23 15:52:49 1986
To: research!v8news
Subject: serious typo in awk manual

In section 2.2, the output given from program P.21 is wrong.  There
should be a USSR line as well.  Spotted by our eagle-eyed proofreader,
Karen Whillans-Browning.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From mcvax!cheviot.ncl.ac.uk!lindsay Tue May 27 14:21:56 1986
Received: by mcvax.uucp; Tue, 27 May 86 14:21:56 +0200 (MET)
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a010210; 27 May 86 12:42 BST
From: "Lindsay F. Marshall" <mcvax!cheviot.ncl.ac.uk!lindsay>
Date: Tue, 27 May 86 12:41:37 gmt
Message-Id: <11926.8605271241@cheviot.newcastle.ac.uk>
To: research!v8news
Subject: Ether problems

Has anyone else observed the phenomenon of invalid packets being
emitted by the ether driver?? This appears to happen about once
every 90 seconds and the contents of the packets seem to be fragments
of old data buffers (the headers and addresses are garbage of course).

Also does anyone else suffer from the process table appearing to fill
up, even though a ps ax does not indicate an unusual number of processes??
This often seems to happen to an individual user on a blit, for whom the
problem appears as commands seeming to hang and then the error message
fork failed - too many processes. The only solution is to reboot.

	Lindsay

From dutoit!norman Tue May 27 15:13 EDT 1986
# To unbundle, sh this file
echo ip_subr.c 1>&2
sed 's/.//' >ip_subr.c <<'//GO.SYSIN DD ip_subr.c'
-#include "inet.h"
-#if NINET > 0
-
-#include "../h/param.h"
-#include "../h/stream.h"
-#include "../h/conf.h"
-#include "../h/inet/in.h"
-#include "../h/inet/ip.h"
-#include "../h/inet/ip_var.h"
-#include "../h/inet/mbuf.h"
-#include "sparam.h"
-
-struct block *
-bp_get()
-{
-	register struct block *bp;
-
-	bp = allocb(64);
-	if(bp)
-		bp->next = 0;
-	return(bp);
-}
-
-bp_check(bp)
-register struct block *bp;
-{
-	while(bp){
-		BLOCKCHK(bp);
-		bp = bp->next;
-	}
-}
-
-/* given a char *, come up with the block that holds it. yuk. */
-int dtom_hits, dtom_misses;
-u_char *xfirst16, *xfirst64, *xfirst1024, *xp;
-struct block *xbp;
-
-struct block *
-bp_dtom(p)
-u_char *p;
-{
-	extern struct block cblock[];
-	extern u_char blkdata[];
-	register u_char *first16, *first64, *first1024;
-	register struct block *bp;
-
-	/* guess. the order of things in blkdata is NBLK4, NBLK16, ... */
-	first16 = &blkdata[4 * NBLK4];
-	first64 = &first16[16 * NBLK16];
-	first1024 = &first64[64 * NBLK64];
-	if(p < first16){
-		bp = &cblock[(p - blkdata) / 4];
-	} else if(p < first64){
-		bp = &cblock[NBLK4 + (p - first16) / 16];
-	} else if(p < first1024){
-		bp = &cblock[NBLK4 + NBLK16 + (p - first64) / 64];
-	} else {
-		bp = &cblock[NBLK4 + NBLK16 + NBLK64 + (p - first1024) / 1024];
-	}
-	if(bp->base && bp->lim && bp->rptr && bp->wptr
-	   && (p >= bp->base) && (p < bp->lim)){
-		BLOCKCHK(bp);
-		dtom_hits++;
-		return(bp);
-	}
-	xfirst16 = first16;
-	xfirst64 = first64;
-	xfirst1024 = first1024;
-	xp = p;
-	xbp = bp;
-	dtom_misses++;
-	for(bp = &cblock[NBLOCK-1]; bp >= &cblock[0]; --bp){
-		if(bp->base == 0 || bp->lim == 0 || bp->rptr == 0 || bp->wptr == 0)
-			continue;
-		if((p >= bp->base) && (p < bp->lim)){
-			return(bp);
-		}
-	}
-	panic("bp_dtom");
-	/* NOTREACHED */
-}
-
-/* bp_pullup: make the first block have at least len bytes */
-struct block *
-bp_pullup(bp, len)
-register struct block *bp;
-{
-	register struct block *m, *n, *nn;
-	int count;
-
-	n = bp;
-	if(len > MAXBLEN)
-		goto bad;
-	m = allocb(MAXBLEN);
-	if(m == 0)
-		goto bad;
-	do{
-		count = len;
-		if (m->lim - m->wptr < count)
-			count = m->lim - m->wptr;
-		if (BLEN(n) < count)
-			count = BLEN(n);
-		bcopy(n->rptr, m->wptr, (unsigned)count);
-		len -= count;
-		m->wptr += count;
-		n->rptr += count;
-		if(BLEN(n))
-			break;
-		nn = n->next;
-		freeb(n);
-		n = nn;
-	} while(n);
-	if(len){
-		freeb(m);
-		goto bad;
-	}
-	m->next = n;
-	MCHECK(m);
-	return(m);
-bad:
-	printf("m_pullup bad\n");
-	bp_free(n);
-	return(0);
-}
-
-bp_free(bp)
-register struct block *bp;
-{
-	register struct block *p;
-
-	while(bp){
-		p = bp->next;
-		BLOCKCHK(bp);
-		freeb(bp);
-		bp = p;
-	}
-}
-
-struct block *
-bp_copy(m, off, len)
-register struct block *m;
-int off;
-register int len;
-{
-	register struct block *n, **np;
-	struct block *top;
-	register int clen;
-
-	MCHECK(m);
-	if(len == 0)
-		return(0);
-	if(off < 0 || len < 0)
-		panic("m_copy");
-	while(off > 0){
-		if(m == 0)
-			panic("m_copy 1");
-		if(off < BLEN(m))
-			break;
-		off -= BLEN(m);
-		m = m->next;
-	}
-	np = &top;
-	top = 0;
-	while(len > 0){
-		if(m == 0)
-			panic("m_copy 2");
-		n = allocb(len);
-		*np = n;
-		if(n == 0)
-			goto nospace;
-		n->next = 0;
-		np = &n->next;
-		do {
-			clen = len;
-			if (BLEN(m) - off < clen)
-				clen = BLEN(m) - off;
-			if (n->lim - n->wptr < clen)
-				clen = n->lim - n->wptr;
-			bcopy((caddr_t)m->rptr+off, (caddr_t)n->wptr, clen);
-			n->wptr += clen;
-			len -= clen;
-			if (len <= 0) {
-				MCHECK(top);
-				return (top);
-			}
-			if (m->rptr + off + clen < m->wptr)
-				off += clen;
-			else {
-				off = 0;
-				m = m->next;
-			}
-		} while (n->wptr < n->lim);
-	}
-	MCHECK(top);
-	return(top);
-nospace:
-	bp_free(top);
-	return(0);
-}
-
-bp_adj(m, len)
-register struct block *m;
-register int len;
-{
-
-	if (m == NULL)
-		return;
-	MCHECK(m);
-	if (len > 0) {
-		while(m && len > 0){
-			if(BLEN(m) <= len){
-				len -= BLEN(m);
-				m->wptr = m->rptr;
-				m = m->next;
-			} else {
-				m->rptr += len;
-				break;
-			}
-		}
-	}
-	else if (len < 0) {
-		len = bp_len(m) + len;
-		if (len <= 0) {
-			if (m->next)
-				bp_free(m->next);
-			m->next = 0;
-			m->wptr = m->rptr;
-			return;
-		}
-		while ((len -= BLEN(m)) > 0) {
-			if ((m = m->next) == NULL)
-				return;
-		}
-		m->wptr += len;		/* len is <= 0 */
-		bp_free(m->next);
-		m->next = 0;
-	}
-	MCHECK(m);
-}
-
-m_cat(m, n)
-register struct block *m, *n;
-{
-	struct mbuf *xn;
-
-	MCHECK(m); MCHECK(n);
-	while(m->next)
-		m = m->next;
-	while(n){
-		if((m->wptr + BLEN(n)) >= m->lim){
-			/* just join the two chains */
-			m->next = n;
-			break;
-		}
-		/* splat the data from one into the other */
-		bcopy(n->rptr, m->wptr, BLEN(n));
-		m->wptr += BLEN(n);
-		xn = n->next;
-		freeb(n);
-		n = xn;
-	}
-	MCHECK(m);
-}
-
-/* C version of 4.2bsd's Internet checksum routine */
-/* This version assumes that no message exceeds 2^16 words */
-in_cksum(m, len)
-	register struct mbuf *m;
-	register int len;
-{
-	register u_short *w;
-	register u_long sum = 0;
-	register int mlen = 0;
-
-	MCHECK(m);
-	for (; len!=0; m=m->m_next) {
-		if (m == NULL) {
-			printf("cksum: out of data\n");
-			break;
-		}
-		w = mtod(m, u_short *);
-		if (mlen == -1) {
-			/* last block ended on an odd numbered byte */
-			sum += *(u_char *)w << 8;
-			w = (u_short *)((char *)w + 1);
-			mlen = BLEN(m) - 1;
-			len--;
-		} else
-			mlen = BLEN(m);
-		if (len < mlen)
-			mlen = len;
-		len -= mlen;
-		/* vecadd returns a 16-bit checksum of the block + sum */
-		sum = vecadd(w, mlen, sum);
-	}
-	/* return complement of sum */
-	return sum^0xffff;
-}
-
-in_addr
-in_netof(x)
-in_addr x;
-{
-	if(IN_CLASSC(x))
-		return(x&IN_CLASSC_NET);
-	else if(IN_CLASSB(x))
-		return(x&IN_CLASSB_NET);
-	else
-		return(x&IN_CLASSA_NET);
-}
-
-in_addr
-in_hostof(x)
-in_addr x;
-{
-	if(IN_CLASSC(x))
-		return(x&IN_CLASSC_HOST);
-	else if(IN_CLASSB(x))
-		return(x&IN_CLASSB_HOST);
-	else
-		return(x&IN_CLASSA_HOST);
-}
-
-/*
- *  Routes are kept in a circular list.  Ip_default_route points to the
- *  "first" position in the list.  On each acess, the accessed element is
- *  moved to this first position.
- */
-#define NROUTES 50
-struct ip_route ip_routes[NROUTES];
-int Nip_route = NROUTES;		/* let netstat know number of routes */
-struct ip_route ip_default_route = { 0, 0, &ip_default_route };
-
-ip_doroute(dst, gate)
-in_addr dst, gate;
-{
-	register struct ip_route *rp, *save;
-	register struct ipif *ifp;
-
-	if(gate){
-		/* no-ops are ignored */
-		if (dst == gate)
-			return(0);
-
-		/* don't accept an indirect route, if we have a direct one */
-		for(ifp = ipif; ifp < &ipif[NINET]; ifp++){
-			if((ifp->flags&IFF_UP)
-			   && ifp->that == dst)
-				return(0);
-		}
-	}
-	/* look through existing routes (looks at ip_default_route first)*/
-	rp = &ip_default_route;
-	do {
-		if (dst == rp->next->dst) {
-			if (gate) {
-				rp->next->gate = gate;
-			} else {
-				rp->next->dst = rp->next->gate = 0;
-				rp->next = rp->next->next;
-			}
-			return(0);
-		}
-		rp = rp->next;
-	} while (rp != &ip_default_route);
-	if (gate == 0)
-		return(0);
-	/* add a new route */
-	for(rp = &ip_routes[0]; rp < &ip_routes[NROUTES]; rp++)
-		if(rp->dst == 0) {
-			rp->dst = dst;
-			rp->gate = gate;
-			rp->next = ip_default_route.next;
-			ip_default_route.next = rp;
-			return(0);
-		}
-	return(1);
-}
-
-/* Look for a route on the circular list.  If the route is found, move
- * it to the beginning of the list.
- */
-struct ip_route_info
-ip_route(dst)
-in_addr dst;
-{
-	extern unsigned long in_netof();
-	unsigned long netof_dst;
-	register struct ip_route *rp, *trp;
-	struct ip_route_info info;
-
-	/* look for host routes (start after ip_default_route) */
-	for(rp = &ip_default_route; rp->next != &ip_default_route; rp=rp->next)
-		if (dst == rp->next->dst) {
-			/* make sure the interface exists */
-			info.addr = rp->next->gate;
-			info.ifp = ip_ifonnetof(info.addr);
-			if(info.ifp == 0)
-				break;
-			/* move to first */
-			trp = rp->next;
-			rp->next = rp->next->next;
-			trp->next = ip_default_route.next;
-			ip_default_route.next = trp;
-			return(info);
-		}
-	/* now try nets (start after ip_default_route) */
-	netof_dst = in_netof(dst);
-	for (rp = &ip_default_route; rp->next != &ip_default_route; rp=rp->next)
-		if(netof_dst == rp->next->dst){
-			/* make sure the interface exists */
-			info.addr = rp->next->gate;
-			info.ifp = ip_ifonnetof(info.addr);
-			if(info.ifp == 0)
-				break;
-			/* move to first */
-			trp = rp->next;
-			rp->next = rp->next->next;
-			trp->next = ip_default_route.next;
-			ip_default_route.next = trp;
-			return(info);
-		}
-	/* try a network to which we are directly connected */
-	info.addr = dst;
-	info.ifp = ip_ifonnetof(dst);
-	if (info.ifp)
-		return info;
-	/* if all else fails, use default route */
-	info.addr = ip_default_route.gate;
-	info.ifp = ip_ifonnetof(info.addr);
-	return(info);
-}
-
-bp_len(bp)
-register struct block *bp;
-{
-	register int n;
-
-	n = 0;
-	while(bp){
-		n += BLEN(bp);
-		bp = bp->next;
-	}
-	return(n);
-}
-
-bp_putback(q, list)
-struct queue *q;
-struct block *list;
-{
-	register struct block *bp;
-	register struct block *prev, *next;
-
-	/*
-	 * reverse the list, to keep data in order
-	 */
-	prev = next = NULL;
-	for (bp = list; bp; bp = next) {
-		next = bp->next;
-		bp->next = prev;
-		prev = bp;
-	}
-	for (bp = prev; bp; bp = next) {
-		next = bp->next;
-		putbq(q, bp);
-	}
-}
-
-in_addr
-ip_hoston(dst)
-in_addr dst;
-{
-	struct ip_route_info info;
-
-	info = ip_route(dst);
-	if(info.ifp == 0)
-		return(0);
-	return(info.ifp->thishost);
-}
-
-in_lnaof(i)
-register u_long i;
-{
-
-	if(IN_CLASSA(i))
-		return((i)&IN_CLASSA_HOST);
-	else if(IN_CLASSB(i))
-		return((i)&IN_CLASSB_HOST);
-	else
-		return((i)&IN_CLASSC_HOST);
-}
-#endif NINET
//GO.SYSIN DD ip_subr.c

From dutoit!norman Tue May 27 15:15 EDT 1986
A new version of sys/inet/ip_subr.c has just gone out in v8source.
It fixes a number of bugs wherein the inet code corrupts stream blocks
(its own and others).  It probably doesn't fix them all.

From utcsri!kato Tue May 27 18:59:46 1986
Received: by utcsri.uucp id AA17694; Tue, 27 May 86 18:59:46 edt
Date: Tue, 27 May 86 18:59:46 edt
From: John Kitamura <utcsri!kato>
Message-Id: <8605272259.AA17694@utcsri.uucp>
To: research!v8news
Subject: Re: process table overflow

	A fork may fail for a number of reasons, the most likely being that the
user has exceeded the limit on the maximum number of processes per user. This
limit is controlled by the constant MAXUPRC in param.h.
	-drb

From ikeya!rob Wed Jun  4 17:45 EDT 1986
a couple of security bugs can be fixed in the shell by making the following
changes.  change setup_env() in name.c to read:

setup_env()
{
	register char **e = environ;
	int onoexec = flags&noexec;

	flags |= noexec;
	while (*e)
		setname(*e++, N_ENVNAM);
	if(!onoexec)
		flags &= ~noexec;
}

then change the line in main.c/main() that checks whether to read the profile:
new:
		if (*(simple(cmdadr)) == '-')
old:
		if (*(simple(cmdadr)) == '-')

the first change closes the hole opened by appending commands to the
end of function definitions in the environment. the second prevents
a .profile from being executed if argv[0][0]=='-'.  with these changes,
a shell script that begins
	#!/bin/sh -p
	PATH=bin:/usr/bin
	export PATH
is as safe as we know how to make.

-rob pike

From ikeya!rob Wed Jun  4 17:50 EDT 1986
darn that mux anyway.  last item should have read:
new:
		if ((flags&protflg)==0 && *(simple(cmdadr)) == '-')
old:
		if (*(simple(cmdadr)) == '-')

From acsnet!basser!rex Wed Jun 25 00:57:47 1986
To: v8news@research
Subject: pengo

Pengo is a game for Blits and 5620. The sources have been mailed to v8sources.

				Rex Di Bona.

From rob Tue Jun 24 12:22 EDT 1986
rex@basser sent to v8sources instead of v8source. so i forwarded it for him,
from the file left sitting here on research waiting for return mail.

>From rex@basser Wed Jun 25 01:00:07 1986
# To unbundle, sh this file
echo mkdir icons
mkdir icons
echo icons/0diamond 1>&2
sed 's/.//' >icons/0diamond <<'//GO.SYSIN DD icons/0diamond'
-	0x0000, 0x0000, 0x7FFF, 0xFFFE, 0x400F, 0xF002, 0x400F, 0xF002,
-	0x400F, 0xF002, 0x400F, 0xF002, 0x400F, 0xF002, 0x400F, 0xF002,    
-	0x400F, 0xF002, 0x400F, 0xF002, 0x400F, 0xF002, 0x400F, 0xF002,    
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0x400F, 0xF002, 0x400F, 0xF002, 0x400F, 0xF002, 0x400F, 0xF002,    
-	0x400F, 0xF002, 0x400F, 0xF002, 0x400F, 0xF002, 0x400F, 0xF002,    
-	0x400F, 0xF002, 0x400F, 0xF002, 0x7FFF, 0xFFFE, 0x0000, 0x0000,
//GO.SYSIN DD icons/0diamond
echo icons/100 1>&2
sed 's/.//' >icons/100 <<'//GO.SYSIN DD icons/100'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0307,0x0700,
-0x030F,0x8F80,
-0x0718,0xD8C0,
-0x0F18,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0318,0xD8C0,
-0x0FCF,0x8F80,
-0x0FC7,0x0700,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/100
echo icons/1600 1>&2
sed 's/.//' >icons/1600 <<'//GO.SYSIN DD icons/1600'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0C1C,0x1C1C,
-0x0C3E,0x3E3E,
-0x1C63,0x6363,
-0x3C63,0x6363,
-0x0C60,0x6363,
-0x0C60,0x6363,
-0x0C60,0x6363,
-0x0C7C,0x6363,
-0x0C7F,0x6363,
-0x0C63,0x6363,
-0x0C63,0x6363,
-0x0C63,0x6363,
-0x0C63,0x6363,
-0x0C63,0x6363,
-0x0C63,0x6363,
-0x0C63,0x6363,
-0x0C63,0x6363,
-0x0C63,0x6363,
-0x3F3E,0x3E3E,
-0x3F1C,0x1C1C,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/1600
echo icons/3200 1>&2
sed 's/.//' >icons/3200 <<'//GO.SYSIN DD icons/3200'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x1C1C,0x1C1C,
-0x3E3E,0x3E3E,
-0x6363,0x6363,
-0x6363,0x6363,
-0x0303,0x6363,
-0x0303,0x6363,
-0x0303,0x6363,
-0x0303,0x6363,
-0x0606,0x6363,
-0x3E06,0x6363,
-0x3E0C,0x6363,
-0x060C,0x6363,
-0x0318,0x6363,
-0x0318,0x6363,
-0x0330,0x6363,
-0x0330,0x6363,
-0x6360,0x6363,
-0x6360,0x6363,
-0x3E7F,0x3E3E,
-0x1C7F,0x1C1C,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/3200
echo icons/400 1>&2
sed 's/.//' >icons/400 <<'//GO.SYSIN DD icons/400'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0061,0xC1C0,
-0x0063,0xE3E0,
-0x00E6,0x3630,
-0x00E6,0x3630,
-0x0166,0x3630,
-0x0166,0x3630,
-0x0166,0x3630,
-0x0266,0x3630,
-0x0266,0x3630,
-0x0266,0x3630,
-0x0466,0x3630,
-0x0466,0x3630,
-0x07F6,0x3630,
-0x07F6,0x3630,
-0x0066,0x3630,
-0x0066,0x3630,
-0x0066,0x3630,
-0x0066,0x3630,
-0x0063,0xE3E0,
-0x0061,0xC1C0,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/400
echo icons/500 1>&2
sed 's/.//' >icons/500 <<'//GO.SYSIN DD icons/500'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x07F1,0xC1C0,
-0x07F3,0xE3E0,
-0x0606,0x3630,
-0x0606,0x3630,
-0x0606,0x3630,
-0x0606,0x3630,
-0x0606,0x3630,
-0x07E6,0x3630,
-0x07F6,0x3630,
-0x0036,0x3630,
-0x0036,0x3630,
-0x0036,0x3630,
-0x0036,0x3630,
-0x0036,0x3630,
-0x0036,0x3630,
-0x0036,0x3630,
-0x0636,0x3630,
-0x0636,0x3630,
-0x03E3,0xE3E0,
-0x01C1,0xC1C0,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/500
echo icons/6400 1>&2
sed 's/.//' >icons/6400 <<'//GO.SYSIN DD icons/6400'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x1C06,0x1C1C,
-0x3E06,0x3E3E,
-0x630E,0x6363,
-0x630E,0x6363,
-0x6016,0x6363,
-0x6016,0x6363,
-0x6016,0x6363,
-0x7C26,0x6363,
-0x7F26,0x6363,
-0x6326,0x6363,
-0x6346,0x6363,
-0x6346,0x6363,
-0x637F,0x6363,
-0x637F,0x6363,
-0x6306,0x6363,
-0x6306,0x6363,
-0x6306,0x6363,
-0x6306,0x6363,
-0x3E06,0x3E3E,
-0x1C06,0x1C1C,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/6400
echo icons/bee0 1>&2
sed 's/.//' >icons/bee0 <<'//GO.SYSIN DD icons/bee0'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0007,0x8000,
-0x003C,0xF000,
-0x01C0,0x0E00,
-0x0300,0x0300,
-0x0600,0x0180,
-0x0C00,0x00C0,
-0x0800,0x0040,
-0x1800,0x0060,
-0x1000,0x0020,
-0x3000,0x0030,
-0x2000,0x0010,
-0x6000,0x0018,
-0x4000,0x0008,
-0x4000,0x0008,
-0x4000,0x0008,
-0x4000,0x0008,
-0x4000,0x0008,
-0x4000,0x0008,
-0x4000,0x0008,
-0x4000,0x0008,
-0x6000,0x0018,
-0x2000,0x0010,
-0x2000,0x0010,
-0x2000,0x0010,
-0x3000,0x0030,
-0x1800,0x0060,
-0x0C00,0x00C0,
-0x0F00,0x03C0,
-0x03FF,0xFF00,
-0x0000,0x0000,
//GO.SYSIN DD icons/bee0
echo icons/bee1 1>&2
sed 's/.//' >icons/bee1 <<'//GO.SYSIN DD icons/bee1'
-0x0003,0xC000,
-0x001E,0x7800,
-0x00E0,0x0700,
-0x0180,0x0180,
-0x0300,0x00C0,
-0x0600,0x0060,
-0x0400,0x0020,
-0x0C00,0x0030,
-0x0800,0x0010,
-0x1800,0x0018,
-0x1000,0x0008,
-0x1000,0x0008,
-0x3000,0x000C,
-0x2000,0x0004,
-0x2000,0x0004,
-0x2000,0x0004,
-0x2000,0x0004,
-0x2000,0x0004,
-0x2000,0x0004,
-0x2000,0x0004,
-0x2000,0x0004,
-0x3000,0x000C,
-0x1000,0x0008,
-0x1800,0x0018,
-0x0C00,0x0030,
-0x0600,0x0060,
-0x0780,0x01E0,
-0x01FF,0xFF80,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/bee1
echo icons/beede 1>&2
sed 's/.//' >icons/beede <<'//GO.SYSIN DD icons/beede'
-0x0003,0xC000,
-0x001E,0x7800,
-0x00E0,0x0700,
-0x0180,0x0180,
-0x0300,0x00C0,
-0x0600,0x0060,
-0x0470,0x0E20,
-0x0C90,0x0930,
-0x0890,0x0910,
-0x1890,0x0918,
-0x10F1,0x8F08,
-0x1000,0x0008,
-0x3001,0x800C,
-0x2006,0x6004,
-0x2000,0x0004,
-0x2000,0x0004,
-0x21C0,0x0384,
-0x2078,0x1E04,
-0x202F,0xF404,
-0x2020,0x0404,
-0x2020,0x0404,
-0x3000,0x000C,
-0x1000,0x0008,
-0x1800,0x0018,
-0x0C00,0x0030,
-0x0600,0x0060,
-0x0780,0x01E0,
-0x01FF,0xFF80,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/beede
echo icons/blank 1>&2
sed 's/.//' >icons/blank <<'//GO.SYSIN DD icons/blank'
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
//GO.SYSIN DD icons/blank
echo icons/block 1>&2
sed 's/.//' >icons/block <<'//GO.SYSIN DD icons/block'
-	0x0000, 0x0000, 0x7FFF, 0xFFFE, 0x4000, 0x0002, 0x4000, 0x0002,
-	0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002,    
-	0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002,    
-	0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002,    
-	0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002,    
-	0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002,    
-	0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002, 0x4000, 0x0002,    
-	0x4000, 0x0002, 0x4000, 0x0002, 0x7FFF, 0xFFFE, 0x0000, 0x0000,
//GO.SYSIN DD icons/block
echo icons/chairl 1>&2
sed 's/.//' >icons/chairl <<'//GO.SYSIN DD icons/chairl'
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000C,0x0000,
-0x000E,0x0000,
-0x000F,0x0000,
-0x0007,0xFFFF,
-0x0003,0xFFFF,
-0x0003,0x090C,
-0x0003,0x108C,
-0x0003,0x204C,
-0x0003,0x5FAC,
-0x0003,0x801C,
-0x0003,0x000C,
-0x0000,0x0000,
//GO.SYSIN DD icons/chairl
echo icons/chairr 1>&2
sed 's/.//' >icons/chairr <<'//GO.SYSIN DD icons/chairr'
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x3000,
-0x0000,0x7000,
-0x0000,0xF000,
-0xFFFF,0xE000,
-0xFFFF,0xC000,
-0x3090,0xC000,
-0x3108,0xC000,
-0x3204,0xC000,
-0x35FA,0xC000,
-0x3801,0xC000,
-0x3000,0xC000,
-0x0000,0x0000,
//GO.SYSIN DD icons/chairr
echo icons/conf1 1>&2
sed 's/.//' >icons/conf1 <<'//GO.SYSIN DD icons/conf1'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x000F,0xFFE0,
-0x0030,0x0038,
-0x00C0,0x000C,
-0x0180,0x0004,
-0x030F,0xC0E2,
-0x0218,0x6133,
-0x1C10,0x2209,
-0x1000,0x0001,
-0x2000,0x0801,
-0x6000,0x0F41,
-0x41F8,0x00C1,
-0x4000,0x0001,
-0xC000,0x0001,
//GO.SYSIN DD icons/conf1
echo icons/conf12 1>&2
sed 's/.//' >icons/conf12 <<'//GO.SYSIN DD icons/conf12'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x07FF,0xFFE0,
-0x1C30,0x0C38,
-0x30C0,0x030C,
-0x2180,0x0184,
-0x470F,0xF0E2,
-0xCE9E,0x7973,
-0x9C54,0x2A39,
-0x9000,0x0009,
-0xA010,0x0805,
-0xE2F0,0x0F47,
-0xC3F8,0x1FC3,
-0xC000,0x0003,
-0xC000,0x0003,
//GO.SYSIN DD icons/conf12
echo icons/conf2 1>&2
sed 's/.//' >icons/conf2 <<'//GO.SYSIN DD icons/conf2'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x07FF,0xF000,
-0x1C00,0x0C00,
-0x3000,0x0300,
-0x2000,0x0180,
-0x4703,0xF0C0,
-0xCC86,0x1840,
-0x9044,0x0838,
-0x8000,0x0008,
-0x8010,0x0004,
-0x82F0,0x0006,
-0x8300,0x1F82,
-0x8000,0x0002,
-0x8000,0x0003,
//GO.SYSIN DD icons/conf2
echo icons/dead0 1>&2
sed 's/.//' >icons/dead0 <<'//GO.SYSIN DD icons/dead0'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0100,
-0x0000,0x0280,
-0x0000,0x0100,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0010,
-0x0000,0x0028,
-0x0000,0x0010,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0040,
-0x007C,0x00A0,
-0x03C7,0xC040,
-0x3600,0x7800,
-0x6400,0x0E20,
-0xCC00,0x0320,
-0xC800,0x3D30,
-0xF801,0xE13C,
-0x381F,0x01E7,
-0x8870,0x0389,
-0x4840,0x0F09,
-0xCC40,0x3101,
-0x8C60,0x6101,
-0xFE3F,0x8183,
-0xF300,0x03CE,
-0x81FF,0xFE78,
//GO.SYSIN DD icons/dead0
echo icons/dead1 1>&2
sed 's/.//' >icons/dead1 <<'//GO.SYSIN DD icons/dead1'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0080,
-0x0000,0x0140,
-0x0000,0x0080,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0040,
-0x0000,0x00A0,
-0x0000,0x0040,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0020,
-0x0000,0x0050,
-0x0000,0x0020,
-0x0000,0x0000,
-0x007C,0x0000,
-0x03C7,0xC000,
-0x3600,0x7800,
-0x6400,0x0E20,
-0xCC3F,0x8320,
-0xC860,0x6130,
-0xF840,0x313C,
-0x3840,0x0DE7,
-0x8870,0x0389,
-0x481F,0x0309,
-0xCC01,0xE101,
-0x8C00,0x3F01,
-0xFE00,0x0183,
-0xF300,0x03CE,
-0x81FF,0xFE78,
//GO.SYSIN DD icons/dead1
echo icons/egg 1>&2
sed 's/.//' >icons/egg <<'//GO.SYSIN DD icons/egg'
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
-	0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F,
-	0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F,
-	0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F,
-	0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F,
-	0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F,
-	0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F, 0xF000, 0x000F,
-	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
//GO.SYSIN DD icons/egg
echo icons/fblock 1>&2
sed 's/.//' >icons/fblock <<'//GO.SYSIN DD icons/fblock'
-	0xFFFF, 0xFFFF, 0x8000, 0x0001, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD,
-	0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD,
-	0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD,
-	0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD,
-	0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD,
-	0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD,
-	0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD,
-	0xBFFF, 0xFFFD, 0xBFFF, 0xFFFD, 0x8000, 0x0001, 0xFFFF, 0xFFFF,
//GO.SYSIN DD icons/fblock
echo icons/hula0 1>&2
sed 's/.//' >icons/hula0 <<'//GO.SYSIN DD icons/hula0'
-0x0007,0xE000,
-0x0018,0x1800,
-0x0010,0x0800,
-0x0036,0x6C00,
-0x0020,0x0400,
-0x0021,0x8400,
-0x0031,0x8C00,
-0x001C,0x3800,
-0x0037,0xEC00,
-0x0060,0x0600,
-0x01C0,0x0380,
-0x0780,0x01E0,
-0x0C80,0x0130,
-0x0980,0x0190,
-0x1900,0x0098,
-0x1100,0x0088,
-0x3300,0x00CC,
-0x2600,0x0064,
-0x2E00,0x0074,
-0x2A00,0x0054,
-0x2A00,0x0054,
-0x3A00,0x005C,
-0x3200,0x004C,
-0x3200,0x004C,
-0x2200,0x0044,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0100,0x0080,
-0x0100,0x0080,
-0x019E,0x7980,
-0x00F2,0x4F00,
-0x003F,0xFC00,
//GO.SYSIN DD icons/hula0
echo icons/hula1 1>&2
sed 's/.//' >icons/hula1 <<'//GO.SYSIN DD icons/hula1'
-0x0007,0xE000,
-0x0018,0x1800,
-0x0010,0x0800,
-0x0036,0x6C00,
-0x0020,0x0400,
-0x0021,0x8400,
-0x0031,0x8C00,
-0x001C,0x3800,
-0x003F,0xFC00,
-0x0060,0x0600,
-0x01C0,0x0600,
-0x0780,0x0B00,
-0x0C80,0x1900,
-0x3180,0x6180,
-0x6100,0xC380,
-0x8F01,0x1E80,
-0xF301,0xE0C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0100,0x0080,
-0x0100,0x0080,
-0x019E,0x7980,
-0x00F2,0x4F00,
-0x003F,0xFC00,
//GO.SYSIN DD icons/hula1
echo icons/hula2 1>&2
sed 's/.//' >icons/hula2 <<'//GO.SYSIN DD icons/hula2'
-0x0007,0xE000,
-0x0018,0x1800,
-0x0010,0x0800,
-0x0036,0x6C00,
-0x0020,0x0400,
-0x0021,0x8400,
-0x0031,0x8C00,
-0x001C,0x3800,
-0x003F,0xFC00,
-0x0060,0x0600,
-0x01C0,0x0200,
-0x0780,0x1F00,
-0x0C80,0x3100,
-0x0980,0x2380,
-0x1900,0x6680,
-0x1100,0x4480,
-0x3300,0xC4C0,
-0x2600,0x9840,
-0x2E00,0xB040,
-0x2A00,0xA040,
-0x2A00,0xA040,
-0x3A00,0xE040,
-0x3200,0xC040,
-0x3200,0xC040,
-0x2200,0x8040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0100,0x0080,
-0x0100,0x0080,
-0x019E,0x7980,
-0x00F2,0x4F00,
-0x003F,0xFC00,
//GO.SYSIN DD icons/hula2
echo icons/hula3 1>&2
sed 's/.//' >icons/hula3 <<'//GO.SYSIN DD icons/hula3'
-0x0007,0xE000,
-0x0018,0x1800,
-0x0010,0x0800,
-0x0036,0x6C00,
-0x0020,0x0400,
-0x0021,0x8400,
-0x0031,0x8C00,
-0x001C,0x3800,
-0x003F,0xFC00,
-0x0060,0x0600,
-0x0060,0x0380,
-0x00D0,0x01E0,
-0x0098,0x0130,
-0x0186,0x018C,
-0x01C3,0x0086,
-0x0178,0x80F1,
-0x0307,0x80CF,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0100,0x0080,
-0x0100,0x0080,
-0x019E,0x7980,
-0x00F2,0x4F00,
-0x003F,0xFC00,
//GO.SYSIN DD icons/hula3
echo icons/hula4 1>&2
sed 's/.//' >icons/hula4 <<'//GO.SYSIN DD icons/hula4'
-0x0007,0xE000,
-0x0018,0x1800,
-0x0010,0x0800,
-0x0036,0x6C00,
-0x0020,0x0400,
-0x0021,0x8400,
-0x0031,0x8C00,
-0x001C,0x3800,
-0x003F,0xFC00,
-0x0060,0x0600,
-0x0040,0x0380,
-0x00F8,0x01E0,
-0x008C,0x0130,
-0x01C4,0x0190,
-0x0166,0x0098,
-0x0122,0x0088,
-0x0323,0x00CC,
-0x0219,0x0064,
-0x020D,0x0074,
-0x0205,0x0054,
-0x0205,0x0054,
-0x0207,0x005C,
-0x0203,0x004C,
-0x0203,0x004C,
-0x0201,0x0044,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0100,0x0080,
-0x0100,0x0080,
-0x019E,0x7980,
-0x00F2,0x4F00,
-0x003F,0xFC00,
//GO.SYSIN DD icons/hula4
echo icons/null 1>&2
sed 's/.//' >icons/null <<'//GO.SYSIN DD icons/null'
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
//GO.SYSIN DD icons/null
echo icons/pback 1>&2
sed 's/.//' >icons/pback <<'//GO.SYSIN DD icons/pback'
-0x000F,0xF000,
-0x001A,0xA800,
-0x0035,0x5400,
-0x002A,0xAC00,
-0x0035,0x5400,
-0x002A,0xAC00,
-0x0035,0x5400,
-0x001A,0xA800,
-0x003F,0xFC00,
-0x0060,0x0600,
-0x00C0,0x0300,
-0x0080,0x0100,
-0x0080,0x0100,
-0x0180,0x0180,
-0x0100,0x0080,
-0x0100,0x0080,
-0x0300,0x00C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0203,0xC040,
-0x0106,0x6080,
-0x0104,0x2080,
-0x0180,0x0180,
-0x00E0,0x0700,
-0x003F,0xFC00,
//GO.SYSIN DD icons/pback
echo icons/pengo1 1>&2
sed 's/.//' >icons/pengo1 <<'//GO.SYSIN DD icons/pengo1'
-0x0007,0xE000,
-0x0004,0x3000,
-0x000C,0x1000,
-0x0008,0x1800,
-0x0018,0x0800,
-0x007C,0x0800,
-0x0004,0x1800,
-0x0006,0x3000,
-0x0003,0xFC00,
-0x001E,0x1E00,
-0x0012,0x1300,
-0x0032,0x1100,
-0x0022,0x1100,
-0x0022,0x1980,
-0x0062,0x0880,
-0x0043,0x0880,
-0x0041,0x0CC0,
-0x0041,0x0440,
-0x00C1,0x0440,
-0x0081,0x8440,
-0x0080,0x8440,
-0x0080,0xFC40,
-0x00C0,0xC040,
-0x0040,0x0040,
-0x0040,0x00C0,
-0x0060,0x0180,
-0x0038,0x0700,
-0x000F,0xFC00,
-0x0047,0x8000,
-0x00ED,0x8000,
-0x007A,0xC000,
-0x0037,0x7000,
//GO.SYSIN DD icons/pengo1
echo icons/pengo2 1>&2
sed 's/.//' >icons/pengo2 <<'//GO.SYSIN DD icons/pengo2'
-0x0007,0xE000,
-0x0004,0x3000,
-0x000C,0x1000,
-0x0008,0x1800,
-0x0018,0x0800,
-0x007C,0x0800,
-0x0004,0x1800,
-0x0006,0x3000,
-0x0003,0xFC00,
-0x001E,0x1E00,
-0x0012,0x1300,
-0x0032,0x1100,
-0x0022,0x1100,
-0x0026,0x1180,
-0x0064,0x1080,
-0x0044,0x3080,
-0x004C,0x20C0,
-0x0048,0x2040,
-0x00C8,0x2040,
-0x0088,0x6040,
-0x0088,0x4040,
-0x008F,0xC040,
-0x00C0,0xC040,
-0x0040,0x0040,
-0x0040,0x00C0,
-0x0060,0x0180,
-0x0038,0x0700,
-0x000F,0xFC00,
-0x0003,0x3800,
-0x0003,0x1E00,
-0x000B,0x0C00,
-0x0015,0x3C00,
//GO.SYSIN DD icons/pengo2
echo icons/pengo3 1>&2
sed 's/.//' >icons/pengo3 <<'//GO.SYSIN DD icons/pengo3'
-0x0007,0xE000,
-0x000C,0x2000,
-0x0008,0x3000,
-0x0018,0x1000,
-0x0010,0x1800,
-0x0010,0x3E00,
-0x0018,0x2000,
-0x000C,0x6000,
-0x003F,0xC000,
-0x0078,0x7800,
-0x00C8,0x4800,
-0x0088,0x4C00,
-0x0088,0x4400,
-0x0198,0x4400,
-0x0110,0x4600,
-0x0110,0xC200,
-0x0330,0x8200,
-0x0220,0x8200,
-0x0220,0x8300,
-0x0221,0x8100,
-0x0221,0x0100,
-0x023F,0x0100,
-0x0203,0x0300,
-0x0200,0x0200,
-0x0300,0x0200,
-0x0180,0x0600,
-0x00E0,0x1C00,
-0x003F,0xF000,
-0x0001,0xE200,
-0x0001,0xB700,
-0x0003,0x5E00,
-0x000E,0xEC00,
//GO.SYSIN DD icons/pengo3
echo icons/pengo4 1>&2
sed 's/.//' >icons/pengo4 <<'//GO.SYSIN DD icons/pengo4'
-0x0007,0xE000,
-0x000C,0x2000,
-0x0008,0x3000,
-0x0018,0x1000,
-0x0010,0x1800,
-0x0010,0x3E00,
-0x0018,0x2000,
-0x000C,0x6000,
-0x003F,0xC000,
-0x0078,0x7800,
-0x00C8,0x4800,
-0x0088,0x4C00,
-0x0088,0x4400,
-0x0188,0x6400,
-0x0108,0x2600,
-0x010C,0x2200,
-0x0304,0x3200,
-0x0204,0x1200,
-0x0204,0x1300,
-0x0206,0x1100,
-0x0202,0x1100,
-0x0203,0xF100,
-0x0203,0x0300,
-0x0200,0x0200,
-0x0300,0x0200,
-0x0180,0x0600,
-0x00E0,0x1C00,
-0x003F,0xF000,
-0x001C,0xC000,
-0x0078,0xC000,
-0x0030,0xD000,
-0x003C,0xA800,
//GO.SYSIN DD icons/pengo4
echo icons/pengo5 1>&2
sed 's/.//' >icons/pengo5 <<'//GO.SYSIN DD icons/pengo5'
-0x000F,0xF000,
-0x001A,0xA800,
-0x0035,0x5400,
-0x002A,0xAC00,
-0x0035,0x5400,
-0x002A,0xAC00,
-0x0035,0x5400,
-0x001A,0xA800,
-0x003F,0xFC00,
-0x0060,0x0600,
-0x00C0,0x0300,
-0x0080,0x0100,
-0x0080,0x0100,
-0x0180,0x0180,
-0x0100,0x0080,
-0x0100,0x0080,
-0x0300,0x00C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0207,0x0040,
-0x010D,0x8080,
-0x0108,0x8080,
-0x0180,0x0180,
-0x00E0,0x0700,
-0x003F,0xFC00,
//GO.SYSIN DD icons/pengo5
echo icons/pengo6 1>&2
sed 's/.//' >icons/pengo6 <<'//GO.SYSIN DD icons/pengo6'
-0x000F,0xF000,
-0x0015,0x5800,
-0x002A,0xAC00,
-0x0035,0x5400,
-0x002A,0xAC00,
-0x0035,0x5400,
-0x002A,0xAC00,
-0x0015,0x5800,
-0x003F,0xFC00,
-0x0060,0x0600,
-0x00C0,0x0300,
-0x0080,0x0100,
-0x0080,0x0100,
-0x0180,0x0180,
-0x0100,0x0080,
-0x0100,0x0080,
-0x0300,0x00C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0xE040,
-0x0101,0xB080,
-0x0101,0x1080,
-0x0180,0x0180,
-0x00E0,0x0700,
-0x003F,0xFC00,
//GO.SYSIN DD icons/pengo6
echo icons/pengo7 1>&2
sed 's/.//' >icons/pengo7 <<'//GO.SYSIN DD icons/pengo7'
-0x0007,0xE000,
-0x0018,0x1800,
-0x0010,0x0800,
-0x0036,0x6C00,
-0x0020,0x0400,
-0x0021,0x8400,
-0x0031,0x8C00,
-0x001C,0x3800,
-0x0037,0xEC00,
-0x0060,0x0600,
-0x00C0,0x0300,
-0x0080,0x0100,
-0x0080,0x0100,
-0x0180,0x0180,
-0x0100,0x0080,
-0x0100,0x0080,
-0x0300,0x00C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x021C,0x0040,
-0x0232,0x0040,
-0x0222,0x0040,
-0x0122,0x0080,
-0x0122,0x0080,
-0x01A2,0x7980,
-0x00E2,0x4F00,
-0x003F,0xFC00,
//GO.SYSIN DD icons/pengo7
echo icons/pengo8 1>&2
sed 's/.//' >icons/pengo8 <<'//GO.SYSIN DD icons/pengo8'
-0x0007,0xE000,
-0x0018,0x1800,
-0x0010,0x0800,
-0x0036,0x6C00,
-0x0020,0x0400,
-0x0021,0x8400,
-0x0031,0x8C00,
-0x001C,0x3800,
-0x0037,0xEC00,
-0x0060,0x0600,
-0x00C0,0x0300,
-0x0080,0x0100,
-0x0080,0x0100,
-0x0180,0x0180,
-0x0100,0x0080,
-0x0100,0x0080,
-0x0300,0x00C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x3840,
-0x0200,0x4C40,
-0x0200,0x4440,
-0x0100,0x4480,
-0x0100,0x4480,
-0x019E,0x4580,
-0x00F2,0x4700,
-0x003F,0xFC00,
//GO.SYSIN DD icons/pengo8
echo icons/playerl0 1>&2
sed 's/.//' >icons/playerl0 <<'//GO.SYSIN DD icons/playerl0'
-0x0000,0x0FC0,
-0x0000,0x1840,
-0x0000,0x1060,
-0x0000,0x31A0,
-0x0000,0x20B0,
-0x0000,0x207C,
-0x0000,0x3040,
-0x0000,0x18C0,
-0x0000,0x7F80,
-0x0000,0xF0F0,
-0x0001,0x9010,
-0x0001,0x1018,
-0x0001,0x1008,
-0x0003,0x1808,
-0x0002,0x0C0C,
-0x0002,0x0606,
-0x0006,0x0381,
-0x0004,0x0061,
-0x0004,0x0039,
-0x0004,0x000D,
-0x0004,0x0002,
-0x0004,0x0002,
-0x0004,0x0006,
-0x0004,0x0004,
-0x0006,0x0004,
-0x0003,0x000C,
-0x0001,0xC038,
-0x0000,0x7FE0,
-0x0000,0x03C4,
-0x0000,0x036E,
-0x0000,0x06BC,
-0x0000,0x1DD8,
//GO.SYSIN DD icons/playerl0
echo icons/playerl1 1>&2
sed 's/.//' >icons/playerl1 <<'//GO.SYSIN DD icons/playerl1'
-0x0000,0x03F0,
-0x0000,0x0610,
-0x0000,0x0418,
-0x0000,0x0C68,
-0x0000,0x082C,
-0x0000,0x081F,
-0x0000,0x0C10,
-0x0000,0x0630,
-0x0000,0x0EB0,
-0x0000,0x12F0,
-0x0000,0x321C,
-0x0000,0x6116,
-0x0000,0xC306,
-0x0000,0x8102,
-0x0000,0x80E2,
-0x0000,0x8062,
-0x0001,0x8039,
-0x0001,0x0031,
-0x0001,0x0019,
-0x0001,0x000D,
-0x0001,0x0002,
-0x0001,0x0002,
-0x0001,0x8006,
-0x0000,0xC01C,
-0x0000,0xFC70,
-0x0000,0x0FC0,
-0x0000,0x0360,
-0x0000,0x07C0,
-0x0000,0x0680,
-0x0000,0x0780,
-0x0000,0x0380,
-0x0000,0x01C0,
//GO.SYSIN DD icons/playerl1
echo icons/playerr0 1>&2
sed 's/.//' >icons/playerr0 <<'//GO.SYSIN DD icons/playerr0'
-0x03F0,0x0000,
-0x0218,0x0000,
-0x0608,0x0000,
-0x058C,0x0000,
-0x0D04,0x0000,
-0x3E04,0x0000,
-0x020C,0x0000,
-0x0318,0x0000,
-0x01FE,0x0000,
-0x0F0F,0x0000,
-0x0809,0x8000,
-0x1808,0x8000,
-0x1008,0x8000,
-0x1018,0xC000,
-0x3030,0x4000,
-0x6060,0x4000,
-0x81C0,0x6000,
-0x8600,0x2000,
-0x9C00,0x2000,
-0xB000,0x2000,
-0x4000,0x2000,
-0x4000,0x2000,
-0x6000,0x2000,
-0x2000,0x2000,
-0x2000,0x6000,
-0x3000,0xC000,
-0x1C03,0x8000,
-0x07FE,0x0000,
-0x23C0,0x0000,
-0x76C0,0x0000,
-0x3D60,0x0000,
-0x1BB8,0x0000,
//GO.SYSIN DD icons/playerr0
echo icons/playerr1 1>&2
sed 's/.//' >icons/playerr1 <<'//GO.SYSIN DD icons/playerr1'
-0x07E0,0x0000,
-0x1818,0x0000,
-0x1008,0x0000,
-0x366C,0x0000,
-0x2004,0x0000,
-0x2184,0x0000,
-0x318C,0x0000,
-0x1C38,0x0000,
-0x0FF0,0x0000,
-0x0F58,0x0000,
-0x384C,0x0000,
-0x6886,0x0000,
-0x60C3,0x0000,
-0x4081,0x0000,
-0x4701,0x0000,
-0x4601,0x0000,
-0x9C01,0x8000,
-0x8C00,0x8000,
-0x9800,0x8000,
-0xB000,0x8000,
-0x4000,0x8000,
-0x4000,0x8000,
-0x6001,0x8000,
-0x3803,0x0000,
-0x0E3F,0x0000,
-0x03F0,0x0000,
-0x06C0,0x0000,
-0x03E0,0x0000,
-0x0160,0x0000,
-0x01E0,0x0000,
-0x01C0,0x0000,
-0x0380,0x0000,
//GO.SYSIN DD icons/playerr1
echo icons/salute 1>&2
sed 's/.//' >icons/salute <<'//GO.SYSIN DD icons/salute'
-0x001F,0xE000,
-0x0028,0x1800,
-0x0060,0x0800,
-0x00D6,0x6C00,
-0x00A0,0x0400,
-0x01A1,0x8400,
-0x0131,0x8C00,
-0x031C,0x3800,
-0x0237,0xEC00,
-0x0260,0x0600,
-0x02C0,0x0300,
-0x0280,0x0100,
-0x0280,0x0100,
-0x0380,0x0180,
-0x0300,0x0080,
-0x0100,0x0080,
-0x0300,0x00C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0100,0x0080,
-0x0100,0x0080,
-0x019E,0x7980,
-0x00F2,0x4F00,
-0x003F,0xFC00,
//GO.SYSIN DD icons/salute
echo icons/sq_0down 1>&2
sed 's/.//' >icons/sq_0down <<'//GO.SYSIN DD icons/sq_0down'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x71F8,0x1E38,
-0x6F07,0xF1EC,
-0xC082,0x0004,
-0x405C,0x000C,
-0x2068,0x0038,
-0x1C00,0xFCE0,
-0x03FF,0x8700,
-0x0000,0x0000,
//GO.SYSIN DD icons/sq_0down
echo icons/sq_0left 1>&2
sed 's/.//' >icons/sq_0left <<'//GO.SYSIN DD icons/sq_0left'
-0x0400,0x0000,
-0x0F00,0x0000,
-0x1300,0x0000,
-0x2100,0x0000,
-0x2200,0x0000,
-0x2200,0x0000,
-0x4200,0x0000,
-0x4300,0x0000,
-0x4500,0x0000,
-0x5900,0x0000,
-0x5100,0x0000,
-0x4900,0x0000,
-0x5900,0x0000,
-0x4A00,0x0000,
-0x4600,0x0000,
-0x4200,0x0000,
-0x6200,0x0000,
-0x2200,0x0000,
-0x2200,0x0000,
-0x2300,0x0000,
-0x2100,0x0000,
-0x6100,0x0000,
-0x4100,0x0000,
-0x4200,0x0000,
-0x2200,0x0000,
-0x2200,0x0000,
-0x3300,0x0000,
-0x1100,0x0000,
-0x1B00,0x0000,
-0x0E00,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/sq_0left
echo icons/sq_0right 1>&2
sed 's/.//' >icons/sq_0right <<'//GO.SYSIN DD icons/sq_0right'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0070,
-0x0000,0x00D8,
-0x0000,0x0088,
-0x0000,0x00CC,
-0x0000,0x0044,
-0x0000,0x0044,
-0x0000,0x0042,
-0x0000,0x0082,
-0x0000,0x0086,
-0x0000,0x0084,
-0x0000,0x00C4,
-0x0000,0x0044,
-0x0000,0x0044,
-0x0000,0x0046,
-0x0000,0x0042,
-0x0000,0x0062,
-0x0000,0x0052,
-0x0000,0x009A,
-0x0000,0x0092,
-0x0000,0x008A,
-0x0000,0x009A,
-0x0000,0x00A2,
-0x0000,0x00C2,
-0x0000,0x0042,
-0x0000,0x0044,
-0x0000,0x0044,
-0x0000,0x0084,
-0x0000,0x00C8,
-0x0000,0x00F0,
-0x0000,0x0020,
//GO.SYSIN DD icons/sq_0right
echo icons/sq_0up 1>&2
sed 's/.//' >icons/sq_0up <<'//GO.SYSIN DD icons/sq_0up'
-0x0000,0x0000,
-0x00E1,0xFFC0,
-0x073F,0x0038,
-0x1C00,0x1604,
-0x3000,0x3A02,
-0x2000,0x4103,
-0x378F,0xE0F6,
-0x1C78,0x1F8E,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/sq_0up
echo icons/sq_1down 1>&2
sed 's/.//' >icons/sq_1down <<'//GO.SYSIN DD icons/sq_1down'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x71F8,0x7F38,
-0x6F07,0xC1EC,
-0xC0A2,0x0004,
-0x405C,0x000C,
-0x2001,0x0018,
-0x1834,0xFC30,
-0x07DB,0xA7E0,
-0x0000,0x0000,
//GO.SYSIN DD icons/sq_1down
echo icons/sq_1left 1>&2
sed 's/.//' >icons/sq_1left <<'//GO.SYSIN DD icons/sq_1left'
-0x0400,0x0000,
-0x0F00,0x0000,
-0x1300,0x0000,
-0x2100,0x0000,
-0x2200,0x0000,
-0x4200,0x0000,
-0x4200,0x0000,
-0x4300,0x0000,
-0x4500,0x0000,
-0x4900,0x0000,
-0x2500,0x0000,
-0x6900,0x0000,
-0x4900,0x0000,
-0x2A00,0x0000,
-0x4600,0x0000,
-0x5200,0x0000,
-0x6200,0x0000,
-0x2300,0x0000,
-0x6100,0x0000,
-0x2100,0x0000,
-0x2100,0x0000,
-0x6100,0x0000,
-0x4100,0x0000,
-0x4300,0x0000,
-0x4200,0x0000,
-0x4200,0x0000,
-0x6300,0x0000,
-0x3100,0x0000,
-0x1B00,0x0000,
-0x0E00,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/sq_1left
echo icons/sq_1right 1>&2
sed 's/.//' >icons/sq_1right <<'//GO.SYSIN DD icons/sq_1right'
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0070,
-0x0000,0x00D8,
-0x0000,0x008C,
-0x0000,0x00C6,
-0x0000,0x0042,
-0x0000,0x0042,
-0x0000,0x00C2,
-0x0000,0x0082,
-0x0000,0x0086,
-0x0000,0x0084,
-0x0000,0x0084,
-0x0000,0x0086,
-0x0000,0x00C4,
-0x0000,0x0046,
-0x0000,0x004A,
-0x0000,0x0062,
-0x0000,0x0054,
-0x0000,0x0092,
-0x0000,0x0096,
-0x0000,0x00A4,
-0x0000,0x0092,
-0x0000,0x00A2,
-0x0000,0x00C2,
-0x0000,0x0042,
-0x0000,0x0042,
-0x0000,0x0044,
-0x0000,0x0084,
-0x0000,0x00C8,
-0x0000,0x00F0,
-0x0000,0x0020,
//GO.SYSIN DD icons/sq_1right
echo icons/sq_1up 1>&2
sed 's/.//' >icons/sq_1up <<'//GO.SYSIN DD icons/sq_1up'
-0x0000,0x0000,
-0x07E5,0xDBE0,
-0x0C3F,0x2C18,
-0x1800,0x8004,
-0x3000,0x3A02,
-0x2000,0x4503,
-0x3783,0xE0F6,
-0x1CFE,0x1F8E,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
-0x0000,0x0000,
//GO.SYSIN DD icons/sq_1up
echo icons/still 1>&2
sed 's/.//' >icons/still <<'//GO.SYSIN DD icons/still'
-0x0007,0xE000,
-0x0018,0x1800,
-0x0010,0x0800,
-0x0036,0x6C00,
-0x0020,0x0400,
-0x0021,0x8400,
-0x0031,0x8C00,
-0x001C,0x3800,
-0x0037,0xEC00,
-0x0060,0x0600,
-0x00C0,0x0300,
-0x0080,0x0100,
-0x0080,0x0100,
-0x0180,0x0180,
-0x0100,0x0080,
-0x0100,0x0080,
-0x0300,0x00C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0100,0x0080,
-0x0100,0x0080,
-0x019E,0x7980,
-0x00F2,0x4F00,
-0x003F,0xFC00,
//GO.SYSIN DD icons/still
echo icons/video0 1>&2
sed 's/.//' >icons/video0 <<'//GO.SYSIN DD icons/video0'
-0xFFFF,0xFFFE,
-0xFFFF,0xFFFE,
-0xFFFF,0xFFFE,
-0xFFFF,0xFFFE,
-0x7555,0x555C,
-0x6AAA,0xAAAC,
-0x7555,0x555C,
-0x3AAA,0xAAA8,
-0x3555,0x5558,
-0x1AAA,0xAAB0,
-0x0D55,0x5560,
-0x4EAA,0xAAE4,
-0x2F55,0x55E8,
-0x1FEA,0xAFF0,
-0x3F35,0x59F8,
-0x001A,0xB000,
-0x000D,0x6000,
-0x000A,0xA000,
-0x000D,0x6000,
-0x000A,0xA000,
-0x000D,0x6000,
-0x000A,0xA000,
-0x000D,0x6000,
-0x000A,0xA000,
-0x000D,0x6000,
-0x000A,0xA000,
-0x000D,0x6000,
-0x001A,0xB000,
-0x003F,0xF800,
-0xFFFF,0xFFFE,
-0xFFFF,0xFFFE,
-0x0000,0x0000,
//GO.SYSIN DD icons/video0
echo icons/wiggle0 1>&2
sed 's/.//' >icons/wiggle0 <<'//GO.SYSIN DD icons/wiggle0'
-0x000F,0xF000,
-0x001A,0xA800,
-0x0035,0x5400,
-0x002A,0xAC00,
-0x0035,0x5400,
-0x002A,0xAC00,
-0x0035,0x5400,
-0x001A,0xA800,
-0x003F,0xFC00,
-0x0060,0x0600,
-0x01C0,0x0380,
-0x0780,0x01E0,
-0x0C80,0x0130,
-0x0980,0x0190,
-0x1900,0x0098,
-0x1100,0x0088,
-0x3300,0x00CC,
-0x2600,0x0064,
-0x2E00,0x0074,
-0x2A00,0x0054,
-0x2A00,0x0054,
-0x3A00,0x005C,
-0x3200,0x004C,
-0x3200,0x004C,
-0x2200,0x0044,
-0x0200,0x0040,
-0x0203,0xC040,
-0x0106,0x6080,
-0x0104,0x2080,
-0x0180,0x0180,
-0x00E0,0x0700,
-0x003F,0xFC00,
//GO.SYSIN DD icons/wiggle0
echo icons/wiggle1 1>&2
sed 's/.//' >icons/wiggle1 <<'//GO.SYSIN DD icons/wiggle1'
-0x100F,0xF008,
-0x101A,0xA808,
-0x1835,0x5418,
-0x1C2A,0xAC38,
-0x1435,0x5428,
-0x142A,0xAC28,
-0x1635,0x5468,
-0x121A,0xA848,
-0x133F,0xFCC8,
-0x19E0,0x0798,
-0x08C0,0x0310,
-0x0880,0x0110,
-0x0C80,0x0130,
-0x0580,0x01A0,
-0x0500,0x00A0,
-0x0700,0x00E0,
-0x0300,0x00C0,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0200,0x0040,
-0x0203,0xC040,
-0x0106,0x6080,
-0x0104,0x2080,
-0x0180,0x0180,
-0x00E0,0x0700,
-0x003F,0xFC00,
-0x000A,0x5000,
-0x000C,0x3000,
-0x000C,0x3000,
-0x0014,0x2800,
-0x003E,0x7C00,
//GO.SYSIN DD icons/wiggle1

From rob Tue Jun 24 12:22 EDT 1986
rex@basser sent to v8sources instead of v8source. so i forwarded pengo for him,
from the file left sitting here on research waiting for return mail.

From acsnet!basser!rex Wed Jun 25 00:57:47 1986
To: v8news@research
Subject: pengo

Pengo is a game for Blits and 5620. The sources have been mailed to v8sources.

				Rex Di Bona.

From mcvax!cheviot.ncl.ac.uk!larry Wed Jun 25 15:40:50 1986
Received: by mcvax.uucp; Wed, 25 Jun 86 15:40:50 +0200 (MET)
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a005828; 25 Jun 86 14:16 BST
From: Larry Hughes - STUDENT <mcvax!cheviot.ncl.ac.uk!larry>
Date: Wed, 25 Jun 86 14:16:34 gmt
Message-Id: <5957.8606251416@cheviot.newcastle.ac.uk>
To: research!v8news
Subject: Version 8 UDP Sockets

I have recently ported some 4.2 software that uses UDP sockets to our v8
machine.  After making the required changes to the original software, the
v8 UDP implementation works quite well.  However, I have discovered that should
a process on the v8 host send a message to another process which also happens to
reside on the (same) v8 host, the message is put onto the Ethernet -- causing 
unnecessary traffic and delay (something the 4.2 socket software manages to 
avoid).  
 
I have attempted to send all local socket messages to 'localhost', but this
does not seem to work.  I am reluctant to use v8 pseudo terminals since the
number of processes that could be accessed would be limited to the number of
file descriptors allowed to a single process.

Has anyone else experienced this problem and, if so, what are the recommended
fixes?
 
Thanks,
larry.

From snb!presotto Wed Jun 25 21:52 EDT 1986
re: v8 UDP sockets
to: v8news

The v8 internet software is less than robust.  However, it is fairly 
extensible due to its stream based implementation.  The idea of sending
local packets out to the net was to avoid special casing local sends.
If you want udp packets to stay off of the ether (or whatever) you
can accomplish this by writing a program that performs the following:

	create a pipe
	push the ip line discipline on each end
	loop forever

The ip address associated with each end can be pretty much anything you
want.
	cheers,	
	dave

From acsnet!basser!rex Thu Jun 26 20:45:13 1986
# To unbundle, sh this file
echo bitmap.c 1>&2
sed 's/.//' >bitmap.c <<'//GO.SYSIN DD bitmap.c'
-/*
-	This file holds all the Bitmap controlling information.
-
-	Bitmaps for the moving shapes are generated on demand.
-
-*/
-
-#include "pengo.h"
-
-Bitmap	bit32 = {
-	(Word *) 0,
-	shorts(2),
-	{ { 0, 0 } , { 32, 32} }
-};
-
-Bitmap	bit16 = {
-	(Word *) 0,
-#ifdef	JERQ
-	shorts(2),
-#define	MUL	32
-#else	JERQ
-	shorts(1),
-#define	MUL	16
-#endif	JERQ
-	{ { 0, 0 } , { 16, 16 } }
-};
-
-Bitmap *
-bchar(ch)	/* returns 16x16 Bitmap of char 'ch' */
-char ch;
-{
-
-/* all that has to be done is assign bit16.base */
-
-	if ((ch >= '0') && (ch <= '9'))
-		bit16.base = (Word *)&char_0_9[((ch - '0') * MUL)];
-	else if ((ch >= 'A') && (ch <= 'Z'))
-		bit16.base = (Word *)&char_A_Z[((ch - 'A') * MUL)];
-	else if ((ch >= 'a') && (ch <= 'z'))
-		bit16.base = (Word *)&char_A_Z[((ch - 'a') * MUL)];
-	else switch(ch)
-	{
-	case '.':
-		bit16.base = (Word *)char_dot;
-		break;
-
-	case ':':
-		bit16.base = (Word *)char_colon;
-		break;
-
-	case '?':
-		bit16.base = (Word *)char_question;
-		break;
-
-	case ')':
-		bit16.base = (Word *)char_rbrkt;
-		break;
-
-	case '(':
-		bit16.base = (Word *)char_lbrkt;
-		break;
-
-	case '_':
-		bit16.base = (Word *)char_uscore;
-		break;
-
-	case '/':
-		bit16.base = (Word *)char_slash;
-		break;
-	
-	default:
-		bit16.base = (Word *)char_space;
-		break;
-	}
-	return (&bit16);
-}
-
//GO.SYSIN DD bitmap.c
echo digits.c 1>&2
sed 's/.//' >digits.c <<'//GO.SYSIN DD digits.c'
-#include "pengo.h"
-
-/* These are bitmaps for the big numerals that are used to display
- *	the score.
- */
-short	N[] = {
-/* 0 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 1 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x001F, 0x8000,
-	0x003F, 0xC000,
-	0x007F, 0xC000,
-	0x007F, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x00FF, 0xFF00,
-	0x00FF, 0xFF00,
-	0x00FF, 0xFF00,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 2 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x07C0,
-	0x0000, 0x0FC0,
-	0x0000, 0x3F80,
-	0x0000, 0xFF00,
-	0x0003, 0xFE00,
-	0x0007, 0xF800,
-	0x000F, 0xE000,
-	0x001F, 0xC000,
-	0x003F, 0x0000,
-	0x007E, 0x0000,
-	0x00FC, 0x0000,
-	0x01F8, 0x0000,
-	0x03F0, 0x0000,
-	0x03E0, 0x0000,
-	0x03E0, 0x0000,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFFC0,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 3 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x07C0,
-	0x000F, 0xFF80,
-	0x000F, 0xFF00,
-	0x000F, 0xFF00,
-	0x000F, 0xFF80,
-	0x0000, 0x07C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 4 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 5 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03FF, 0xFC00,
-	0x03FF, 0xFF00,
-	0x03FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x0000, 0x0FC0,
-	0x0000, 0x07C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x07C0,
-	0x03C0, 0x0FC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFF80,
-	0x03FF, 0xFF00,
-	0x01FF, 0xFC00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 6 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03FF, 0xFC00,
-	0x03FF, 0xFF00,
-	0x03FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x0FC0,
-	0x03C0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03F0, 0x0FC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x003F, 0xFC00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 7 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFFC0,
-	0x01FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x07C0,
-	0x03C0, 0x0780,
-	0x0000, 0x0F80,
-	0x0000, 0x0F00,
-	0x0000, 0x1F00,
-	0x0000, 0x3E00,
-	0x0000, 0x3E00,
-	0x0000, 0x7C00,
-	0x0000, 0x7800,
-	0x0000, 0xF000,
-	0x0001, 0xF000,
-	0x0001, 0xE000,
-	0x0003, 0xE000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 8 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 9 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x003F, 0xFC00,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03F0, 0x0FC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x03C0,
-	0x03F0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFFC0,
-	0x00FF, 0xFFC0,
-	0x003F, 0xFFC0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-};
//GO.SYSIN DD digits.c
echo endgame.c 1>&2
sed 's/.//' >endgame.c <<'//GO.SYSIN DD endgame.c'
-#include "pengo.h"
-
-Bitmap	disp_head = {
-	(Word *) char_header,
-	shorts(14),
-	{ { 0, 0 }, { HEAD_X, HEAD_Y } }
-};
-
-newgame()
-{
-	int	ch;
-	int	x;
-	int	y;
-
-	y = FALSE;
-	rectf(&display, counter, F_CLR);
-	addstr("Another", counter.origin, F_STORE);
-	addstr("Game?", add(counter.origin, Pt(16, 16)), F_STORE);
-	addstr("(Y/N)?_", add(counter.origin, Pt(0, 32)), F_STORE);
-	for (;;)
-	{
-		for(x = 0; x < HEAD_COUNT; x++)
-			if ((ch = kbdchar()) != -1)
-				break;
-			else
-				sleep(2);
-		if (ch == -1)
-		{
-			/* do static display */
-			
-			if (
-				((board.corner.x - board.origin.x) > HEAD_X) &&
-				((board.corner.y - board.origin.y) > HEAD_Y)
-			)
-			{
-				if (y == FALSE)
-				{
-					rectf(&display, board, F_CLR);
-					bitblt(&disp_head, disp_head.rect,
-						&display,
-						add(
-						    div(
-							sub(
-							    sub(
-								board.corner,
-								board.origin
-							    ),
-							    Pt(HEAD_X, HEAD_Y)
-							),
-							2
-						    ),
-						    board.origin
-						), F_STORE);
-#ifdef	JERQ
-#ifdef	MPX
-					if (!VALSCREENCOLOR)
-						rectf(&display, board, F_XOR);
-#endif	MPX
-#endif	JERQ
-					y = TRUE;
-				}
-			}
-			while(((ch = kbdchar()) == -1) && (!button123()))
-				wait(CPU);
-		}
-		if (button123() && (ch == -1))
-			return(TRUE);
-		switch(ch)
-		{
-		case 'Y':
-		case 'y':
-			return(TRUE);
-	
-		case 'N':
-		case 'n':
-		case 'Q':
-		case 'q':
-			exit();
-		}
-	}
-}
//GO.SYSIN DD endgame.c
echo event.c 1>&2
sed 's/.//' >event.c <<'//GO.SYSIN DD event.c'
-/*
-	This file contains the code that handles the scheduling of the
-	processes in the system. All moving objects set up a 'next run
-	time' using add_event.
-
-*/
-#include "pengo.h"
-#define	MAX_ARRAY	100		/* number of schedule slots */
-#define	MAX_TIME	10000L
-
-int	ebase	= 0;	/* pointer to first event */
-
-struct	event {
-	long	event_time;
-	int	(*event_fn)();
-	int	event_arg;
-	int	next_event;
-} event_array[MAX_ARRAY];	/* space for scheduled events */
-
-add_event(etime, efn, earg)	/* VERY simple event scheduler */
-long	etime;
-int	(*efn)();
-int	earg;
-{
-	int	count;
-	int	last;
-	Word	*water();
-
-	for (count = 0; event_array[count].next_event != -1; count++)
-			;	/* do nothing, the condition says it all */
-	event_array[count].event_time = (etime += my_time);
-	event_array[count].event_fn   = efn;
-	event_array[count].event_arg  = earg;
-	if (event_array[(last = ebase)].event_time > etime)
-	{
-		event_array[count].next_event = ebase;
-		ebase = count;
-	}
-	else
-	{
-		while (
-			event_array[event_array[last].next_event].event_time
-			<
-			etime
-		)
-			last = event_array[last].next_event;
-		event_array[count].next_event = event_array[last].next_event;
-		event_array[last].next_event = count;
-	}
-}
-
-next_event()	/* execute the next event on the list. FALSE if none left */
-{
-	int	tmp;
-	long	tmp0;
-	int	ebase0;
-
-	wait_mouse();
-	if ((tmp = event_array[(ebase0 = ebase)].next_event) == -2)
-		return FALSE;	/* all is done. All is finished */
-	if ((tmp0 = (event_array[ebase0].event_time - my_time)) > 0)
-		sleep ((int)tmp0);
-	event_array[ebase0].next_event = -1;	/* clear this entry */
-	ebase = tmp;				/* and reset pointer */
-	my_time = event_array[ebase0].event_time;
-	(*event_array[ebase0].event_fn)(event_array[ebase0].event_arg);
-	if (score != old_score)
-	{
-		add_men(score, old_score);
-		put_score(old_score = score);
-	}
-	return (TRUE);
-}
-
-cancel_events()
-{
-	extern	int	allover();
-
-	for (ebase = MAX_ARRAY - 1; ebase > 0; ebase--)
-		event_array[ebase].next_event = -1;
-	event_array[ebase = 0].next_event = -2;
-	event_array[ebase].event_time = MAX_TIME;
-	event_array[ebase].event_fn  = allover;
-}
-
-allover()
-{
-	int	ptr;
-
-	for (ptr = MAX_ARRAY - 1; ptr > 0; ptr--)
-		event_array[ptr].event_time -= MAX_TIME;
-	add_event(MAX_TIME, allover, NULL);
-	my_time -= MAX_TIME;
-}
//GO.SYSIN DD event.c
echo globals.c 1>&2
sed 's/.//' >globals.c <<'//GO.SYSIN DD globals.c'
-/*
- *	storage  file for pengo.	BLIT version
- */
-
-#include "pengo.h"
-/* externs for files */
-int	pengo_left;	/* number of pengos left */
-int	sno_bee_left;	/* number of sno_bees left */
-int	egg_count_flag;	/* number of eggs still to hatch */
-int	manptr;		/* index into new_man */
-int	hit;		/* state of button 2 */
-int	seggs;		/* eggs on display ? */
-char	move_water;	/* side water movement */
-char	sdiamond;	/* 10000 points flag */
-char	s[MAXX][MAXY];	/* storage for which blocks are on */
-long	score;		/* current score */
-long	old_score;	/* previous score */
-long	high_score;	/* current high score */
-long	my_time;	/* 60th of a second counter for play time */
-element	pengo;		/* pengo definition */
-element	sno_bee[4];	/* which blocks are really sno_bees */
-element	eggs[MAX_BEES];	/* which blocks are eggs */
-element	diamond[3];	/* which blocks are really diamonds */
-element	moving;		/* block which is moving or breaking */
-element	breaking;	/* block which is breaking */
-element	bee_block[4];	/* blocks being broken by bees */
-Point	old_mouse;	/* initial mouse position */
-Point	new_mouse;	/* current mouse position */
-Point	move_mouse;	/* difference of old & new */
-Point	home_mouse;	/* home position of mouse */
-Rectangle	board;
-Rectangle	board0;
-Rectangle	board1;
-Rectangle	header;
-Rectangle	bwater;
-Rectangle	lwater;
-Rectangle	rwater;
-Rectangle	twater;
-Rectangle	counter;
-int	sbd;
-int	npd;
-int	bee_run;
-
-long	new_man[] = {
-	10000L, 20000L, 50000L, 100000L, 200000L, 400000L, 800000L,
-};
-
-Word	bstore[8 * 48];	/* storage, requires an even number as x, for jerq */
-		/* 10000 point bonus bitmap */
-Bitmap	bonus	= { (Word *)bstore, shorts(8), { { 0, 0 }, { 16 * 7, 48 } } };
-#ifndef	MPX
-int	reshaped;
-#endif
-int	sb_change;
-int	sb_random;
-int	sb_break;
//GO.SYSIN DD globals.c
echo score.c 1>&2
sed 's/.//' >score.c <<'//GO.SYSIN DD score.c'
-/*
-	score.c:	put score onto the screen.
-*/
-
-#include "pengo.h"
-
-add_men(score, old_score)
-long	score;
-long	old_score;
-{
-	if ((manptr >= NUM_ADD_MAN) && ((score % 800000L) < (old_score % 800000L)))
-		add_man();
-	else
-		while ((manptr < NUM_ADD_MAN) && (score > new_man[manptr]))
-		{
-			add_man();
-			manptr++;
-		}
-}
-
-put_score(score)
-long	score;
-{
-	int	count;
-
-	rectf(&display, header, F_CLR);
-	for (count = NUM_DIGITS - 1; ((count >= 0) && (score > 0)); count--)
-	{
-		bit32.base = (Word *)&N[(score % 10) * 64];
-		bitblt(&bit32, R3, &display,
-			Pt(header.origin.x + count * CHAR_WIDTH, header.origin.y),
-			F_STORE);
-		score /= 10;
-	}
-}
//GO.SYSIN DD score.c
echo screen.c 1>&2
sed 's/.//' >screen.c <<'//GO.SYSIN DD screen.c'
-/*
-	this file handles contradictions between the screen appearance
-	and what is stored in the block array
-*/
-#include "pengo.h"
-
-screen_blank(x, y)
-int	x;
-int	y;
-{
-	Point	sp;
-	int	count;
-
-	sp.x = x << 5;
-	sp.y = y << 5;
-	if (
-		PX(sp, pengo)  ||
-		(moving.exists && PX(sp, moving)) ||
-		(breaking.exists && PX(sp, breaking))
-	)
-		return FALSE;	/* something is there */
-	for (count = 0; count < MAX_BEES; count++)
-		if (
-			eggs[count].exists &&
-			(eggs[count].other == SNO_BEE) &&
-			PX(sp, eggs[count])
-		)
-			return FALSE;
-	if (screen(x, y) != BLANK)
-		return FALSE;
-	return TRUE;	/* oh well it appears to be blank */
-}
//GO.SYSIN DD screen.c
echo sno_bee.c 1>&2
sed 's/.//' >sno_bee.c <<'//GO.SYSIN DD sno_bee.c'
-/*
-	This file contains the code required to move the sno_bees about
-*/
-
-#include "pengo.h"
-#define	SB	sno_bee[bee_num]
-#define	MW(x)	(((x < 0) || (x >= sizeof(move_weights)/sizeof(move_weights[0]))) ? 0 : move_weights[x])
-
-int	move_weights[] = {
-	10,	/* BLANK */
-	5,	/* BLOCK */
-	10,	/* SNO_BEE */
-	100,	/* PENGO */
-	0,	/* DIAMOND */
-	0,	/* EGG */
-	0,	/* HATCH */
-	5,	/* BREAK ... same as BLOCK */
-	10,	/* CONF ... same as SNO_BEE */
-};
-
-move_sno_bee(bee_num)
-int	bee_num;
-{
-	if (SB.exists != TRUE)	/* let somebody else handle it!! */
-		return;
-	if (SB.other != SNO_BEE)
-		return;
-	if (((SB.x & 31) == 0) && ((SB.y & 31) == 0))
-	{
-		if ((rand() % 100) < sb_change)	/* how often to change */
-		{
-			if ((rand() % 100) < sb_random)
-			{
-				SB.movex = SB.movey = 0;
-				switch(rand() % 5)
-				{
-				case UP:
-					SB.movey = -8;
-					break;
-				case DOWN:
-					SB.movey = 8;
-					break;
-				case RIGHT:
-					SB.movex = 8;
-					break;
-				case LEFT:
-					SB.movex = -8;
-					break;
-				}
-			}
-			else
-			{
-				int	dx;
-				int	dy;
-
-				SB.movex = SB.movey = 0;
-				dx = (pengo.x - SB.x) / 32;
-				dy = (pengo.y - SB.y) / 32;
-				dx *= MW(screen((SB.x+((dx>0)?32:-32))>>5,SB.y>>5));
-				dy *= MW(screen(SB.x>>5,(SB.y+((dy>0)?32:-32))>>5));
-				if (abs(dx) > abs(dy))
-					SB.movex = ((dx > 0) ? 8 : -8);
-				else
-					SB.movey = ((dy > 0) ? 8 : -8);
-			}
-		}
-		switch (
-			screen(
-				(SB.x + 4 * SB.movex) >> 5,
-				(SB.y + 4 * SB.movey) >> 5
-			)
-		)
-		{
-		case BREAK:	/* can move through breaking blocks */
-		case BLANK:
-		case PENGO:
-		case SNO_BEE:
-			put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-			SB.x += SB.movex;
-			SB.y += SB.movey;
-			put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-			break;
-
-		case BLOCK:
-			if (
-				(bee_block[bee_num].exists == FALSE) &&
-				((rand() % 100) < sb_break)
-			)
-			{
-				bee_block[bee_num].count = NUM_BREAK;
-				bee_block[bee_num].exists = TRUE;
-				bee_block[bee_num].x = SB.x + 4 * SB.movex;
-				bee_block[bee_num].y = SB.y + 4 * SB.movey;
-				screen(bee_block[bee_num].x >> 5,
-					bee_block[bee_num].y >> 5) = BREAK;
-				add_event(DIE_BLOCK, bee_break, bee_num);
-			}
-			break;
-
-		default:
-			SB.movex = SB.movey = 0;
-			break;
-		}
-	}
-	else
-	{
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-		SB.x += SB.movex;
-		SB.y += SB.movey;
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-	}
-	if (
-		(pengo.exists) &&
-		PX(pengo, SB)
-	)
-	{
-		pengo.other = DYING;	/* he, he the sno_bee got him */
-		add_event(P_DYING, die_pengo, NULL);
-	}
-	if (bee_run)
-		add_event(MOVE_BEE0, run_sno_bee, bee_num);
-	else
-		add_event(MOVE_BEE0, move_sno_bee, bee_num);
-}
-
-run_sno_bee(bee_num)
-int	bee_num;
-{
-	if (SB.exists != TRUE)
-		return;
-	if (SB.other != SNO_BEE)
-		return;
-	if (((SB.x & 31) == 0) && ((SB.y & 31) == 0))
-	{
-		/* run towards a corner */
-		int	posx;
-		int	posy;
-		int	dirn;
-
-		posx = SB.x >> 5;
-		posy = SB.y >> 5;
-
-		if (
-			(((blockx - 1) == posx) || (posx == 0))
-			&&
-			(((blocky - 1) == posy) || (posy == 0))
-		)
-		{
-			SB.other = VANISH;
-			SB.count = DYING_TIME;
-			add_event(DIE_BEE, vanish_bee, bee_num);
-			return;
-		}
-		if (((blockx - 1) - posx) < posx)	/* to the right */
-		{
-			if (((blocky - 1) - posy) < posy)	/* down */
-			{
-				if (
-					(
-						(blockx - 1) != posx
-					) &&
-					(
-						((blocky - 1) == posy) ||
-						(
-							((blockx - 1) - posx)
-							<
-							((blocky - 1) - posy)
-						)
-					)
-				)
-					dirn = RIGHT;
-				else
-					dirn = DOWN;
-			}
-			else				/* up */
-			{
-				if (
-					(
-						(blockx - 1) != posx
-					) &&
-					(
-						(posy == 0 ) ||
-						(
-							((blockx - 1) - posx)
-							<
-							posy
-						)
-					)
-				)
-					dirn = RIGHT;
-				else
-					dirn = UP;
-			}
-		}
-		else				/* to the left */
-		{
-			if (((blocky - 1) - posy) < posy)	/* down */
-			{
-				if (
-					(
-						posx != 0
-					) &&
-					(
-						((blocky - 1) == posy) ||
-						(posx < ((blocky - 1) - posy))
-					)
-				)
-					dirn = LEFT;
-				else
-					dirn = DOWN;
-			}
-			else				/* up */
-			{
-				if (
-					(
-						posx != 0
-					) &&
-					(
-						(posy == 0) ||
-						(posx < posy)
-					)
-				)
-					dirn = LEFT;
-				else
-					dirn = UP;
-			}
-		}
-		switch(dirn)
-		{
-		case UP:
-			SB.movex = 0;
-			SB.movey = -8;
-			break;
-
-		case DOWN:
-			SB.movex = 0;
-			SB.movey = 8;
-			break;
-
-		case RIGHT:
-			SB.movex = 8;
-			SB.movey = 0;
-			break;
-
-		case LEFT:
-			SB.movex = -8;
-			SB.movey = 0;
-			break;
-		}
-		switch (
-			screen(
-				(SB.x + 4 * SB.movex) >> 5,
-				(SB.y + 4 * SB.movey) >> 5
-			)
-		)
-		{
-		case BREAK:
-		case BLANK:
-		case PENGO:
-		case SNO_BEE:
-			put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-			SB.x += SB.movex;
-			SB.y += SB.movey;
-			put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-			break;
-
-		case BLOCK:
-			if (bee_block[bee_num].exists == FALSE)
-			{
-				bee_block[bee_num].count = NUM_BREAK;
-				bee_block[bee_num].exists = TRUE;
-				bee_block[bee_num].x = SB.x + 4 * SB.movex;
-				bee_block[bee_num].y = SB.y + 4 * SB.movey;
-				screen(bee_block[bee_num].x >> 5,
-					bee_block[bee_num].y >> 5) = BREAK;
-				add_event(DIE_BLOCK, bee_break, bee_num);
-			}
-			break;
-
-		default:
-			SB.other = VANISH;
-			SB.count = DYING_TIME;
-			add_event(DIE_BEE, vanish_bee, bee_num);
-			return;
-		}
-	}	
-	else
-	{
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-		SB.x += SB.movex;
-		SB.y += SB.movey;
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-	}
-	add_event(MOVE_BEE0, run_sno_bee, bee_num);
-}
-
-vanish_bee(bee_num)
-int	bee_num;
-{
-	put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-	if (SB.count--)
-		add_event(DIE_BEE, vanish_bee, bee_num);
-	else
-	{
-		disp_sno_bee(0);	/* no sno_bees */
-		cancel_events();	/* all gone ... */
-	}
-}
-
-confused_bee(bee_num)
-int	bee_num;
-{
-	if (SB.other != CONFUSED)
-		return;
-	put_char(SB.x, SB.y, CONF, F_XOR, (SB.count-- & 1) | (bee_num << 1));
-	put_char(SB.x, SB.y, CONF, F_XOR, (SB.count & 1) | (bee_num << 1));
-	if (SB.count == 0)
-	{
-		put_char(SB.x, SB.y, CONF, F_XOR, (bee_num << 1));
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-		SB.other = SNO_BEE;
-		if (bee_run)
-			add_event(MOVE_BEE0, run_sno_bee, bee_num);
-		else
-			add_event(MOVE_BEE0, move_sno_bee, bee_num);
-	}
-	else
-		add_event(TIME_CONFUSED, confused_bee, bee_num);
-}
//GO.SYSIN DD sno_bee.c
echo water.c 1>&2
sed 's/.//' >water.c <<'//GO.SYSIN DD water.c'
-/*
-	character arrays for water shapes
-*/
-#include "pengo.h"
-
-short nw[] = {
-	0x5555, 0xAAAA, 0x5555, 0xAAAA,
-	0x5555, 0xAAAA, 0x5555, 0xAAAA,
-	0x5555, 0xAAAA, 0x5555, 0xAAAA,
-	0x5555, 0xAAAA, 0x5555, 0xAAAA,
-};
-
-short tw[] = {
-	0x5555, 0xAAAA, 0x4141, 0x0808,
-	0x5555, 0xAAAA, 0x4141, 0x0808,
-	0x5555, 0xAAAA, 0x4141, 0x0808,
-	0x5555, 0xAAAA, 0x4141, 0x0808,
-};
-
-short bw[] = {
-	0x5555, 0x0808, 0x4141, 0xAAAA,
-	0x5555, 0x0808, 0x4141, 0xAAAA,
-	0x5555, 0x0808, 0x4141, 0xAAAA,
-	0x5555, 0x0808, 0x4141, 0xAAAA,
-};
-
-short lw[] = {
-	0x1111, 0xAAAA, 0x1111, 0x8888,
-	0x5555, 0x8888, 0x1111, 0xAAAA,
-	0x1111, 0xAAAA, 0x1111, 0x8888,
-	0x5555, 0x8888, 0x1111, 0xAAAA,
-};
-
-short rw[] = {
-	0x5555, 0x8888, 0x1111, 0xAAAA,
-	0x1111, 0x8888, 0x5555, 0x8888,
-	0x5555, 0x8888, 0x1111, 0xAAAA,
-	0x1111, 0x8888, 0x5555, 0x8888,
-};
-
-swill_water(num)
-int	num;
-{
-	Word	*p;
-	Rectangle w;
-	int	dx;
-	int	dy;
-	int	x;
-
-	if (num == 0)
-	{
-		move_water = STILL;
-		return;
-	}
-	dx = dy = -1;
-	switch(move_water)
-	{
-	case UP:
-		p = (Word *)tw;
-		w = twater;
-		dy = 0;
-		break;
-
-	case DOWN:
-		p = (Word *)bw;
-		w = bwater;
-		dy = blocky - 1;
-		break;
-
-	case LEFT:
-		p = (Word *)lw;
-		w = lwater;
-		dx = 0;
-		break;
-
-	case RIGHT:
-		p = (Word *)rw;
-		w = rwater;
-		dx = blockx - 1;
-		break;
-
-	default:
-		return;
-	}
-	if (num & 1)
-		p = (Word *)nw;
-	texture(&display, w, p, F_STORE);
-	for (x = 0; x < 4; x++)
-		if (
-			(sno_bee[x].exists == TRUE) &&
-			(sno_bee[x].other == SNO_BEE) &&
-			(
-				(
-					(dx != -1) &&
-					(sno_bee[x].x == (dx << 5))
-				) ||
-				(
-					(dy != -1) &&
-					(sno_bee[x].y == (dy << 5))
-				)
-			)
-		)
-		{
-			sno_bee[x].count = NUM_CONFUSED;
-			sno_bee[x].other = CONFUSED;
-			add_event(TIME_CONFUSED, confused_bee, x);
-			put_char(sno_bee[x].x, sno_bee[x].y,
-				SNO_BEE, F_XOR, x);
-			put_char(sno_bee[x].x, sno_bee[x].y,
-				CONF, F_XOR, (NUM_CONFUSED & 1) | (x << 1));
-		}
-	add_event(WATER_TIME, swill_water, --num);
-}
//GO.SYSIN DD water.c
echo pengo.c 1>&2
sed 's/.//' >pengo.c <<'//GO.SYSIN DD pengo.c'
-/*
-	main routine in PENGO!!!!!
-
-*/
-#include "pengo.h"
-
-main()
-{
-	int	level = 0;
-
-#ifndef	JERQ
-	*(char *)(384*1024L+040) = 1;	/* set to Black on White */
-#endif	JERQ
-	sb_change = SNO_BEE_CHANGE;
-	sb_random = SNO_BEE_RANDOM;
-	sb_break  = SNO_BEE_BREAK;
-	pengo_left = NUM_PENGO;
-	srand((int)realtime());	/* set up random number thingy */
-	my_time = 0;
-	init();
-	{
-		/* do static display */
-		
-		if (
-			((board.corner.x - board.origin.x) > HEAD_X) &&
-			((board.corner.y - board.origin.y) > HEAD_Y)
-		)
-		{
-			rectf(&display, board, F_CLR);
-			bitblt(&disp_head, disp_head.rect,
-				&display,
-				add(
-				    div(
-					sub(
-					    sub(
-						board.corner,
-						board.origin
-					    ),
-					    Pt(HEAD_X, HEAD_Y)
-					),
-					2
-				    ),
-				    board.origin
-				), F_STORE);
-#ifdef	JERQ
-#ifdef	MPX
-			if (!VALSCREENCOLOR)	/* change the screen shade */
-				rectf(&display, board, F_XOR);
-#endif	MPX
-#endif	JERQ
-		}
-		while(!((own() & MOUSE) && button123()))
-		{
-			rand();		/* roll random number generator */
-			wait(CPU);
-		}
-		texture(&display, Drect, char_space, F_STORE);
-	}
-	sno_bee_left = (level < (MAX_BEES - 9)) ? level + 8 : MAX_BEES;
-	init_scr();
-	init_board();
-	score = 0;
-	for(;;)
-	{
-		int	screen_time;
-
-		pengo.exists = TRUE;	/* pengo is now alive */
-		add_event(MOVE_PENGO, move_player, NULL);
-		while (next_event())
-		{
-#ifdef	MPX
-			if (P->state & RESHAPED)
-			{
-				level = -1;
-				changed_screen();
-				pengo_left = NUM_PENGO;
-			}
-#else
-			if (reshaped == TRUE)
-			{
-				level = -1;
-				changed_screen();
-				pengo_left = NUM_PENGO;
-			}
-#endif
-		}
-		if ((screen_time = my_time / 60) < 0)
-			screen_time = 0;
-		if (pengo.exists == TRUE)
-		{
-			/* player was alive at the end of that one */
-			if (level >= 0)
-			{
-				extra_score(screen_time);
-				if (level++ & 1)
-				{
-					/* do dance of the levels */
-					level_dance(level);
-				}
-			}
-			else
-				level = 0;
-			sno_bee_left = (level < (MAX_BEES - 9))?level+8 : MAX_BEES;
-			my_time = 0;
-			init_scr();
-			init_board();
-		}
-		else	/* player was killed */
-			if (pengo_left == -1)
-			{
-				/* all dead now */
-				newgame();	/* new game ? */
-				my_time = 0;
-				level = 0;
-				pengo_left = NUM_PENGO;
-				sno_bee_left = (level < (MAX_BEES - 9)) ?
-					level + 8 : MAX_BEES;
-				init_scr();
-				init_board();
-				put_score(score = 0);
-			}
-			else
-			{
-				init_scr();
-				redraw_screen();
-			}
-		breaking.exists = FALSE;	/* if we were breaking a block */
-	}
-}
-
-Word *
-water(x)
-int x;
-{
-	switch(x)
-	{
-	case STILL:
-		return (Word *)nw;
-
-	case UP:
-		return (Word *)tw;
-
-	case DOWN:
-		return (Word *)bw;
-
-	case LEFT:
-		return (Word *)lw;
-
-	case RIGHT:
-		return (Word *)rw;
-	}
-	return (Word *)nw;
-}
-
-put_char(x, y, ch, format, other)
-int	x;
-int	y;
-int	ch;
-int	format;
-int	other;
-{
-	extern	Bitmap	bit32;
-	int	tmp;
-
-#ifdef	MPX
-	if (P->state & RESHAPED)
-		return;
-#else
-	if (reshaped == TRUE)
-		return;
-#endif
-	switch(ch)
-	{
-	case BLANK:
-		bit32.base = (Word *)char_blank;
-		break;
-
-	case BLOCK:
-		bit32.base = (Word *)char_block;
-		break;
-
-	case FBLOCK:
-		bit32.base = (Word *)flip_block;
-		break;
-
-	case PENGO:
-		if (pengo.movex)
-			if (pengo.movex < 0)
-				tmp = 1;
-			else
-				tmp = 3;
-		else
-			if (pengo.movey < 0)
-				tmp = 5;
-			else if (pengo.movey)
-				tmp = 7;
-			else
-				tmp = 0;
-		if ((pengo.x & 16) || (pengo.y & 16))
-			tmp++;
-		bit32.base = (Word *)pengo_moves[tmp];	
-		break;
-
-	case PENGO_D:
-		bit32.base = (Word *)(other ? char_1dead : char_0dead);
-		break;
-
-	case DIAMOND:
-		bit32.base = (Word *)(other ? char_1diamond : char_0diamond);
-		break;
-
-	case SNO_BEE:
-		bit32.base = (Word *)((
-				(sno_bee[other].x & 16) |
-				(sno_bee[other].y & 16)
-			     ) ? char_1bee : char_0bee);
-		x += (other>> 1) & 1;
-		y += other & 1;
-		break;
-
-	case EGG:
-		bit32.base = (Word *)(seggs ? char_egg : flip_block);
-		break;
-
-	case HATCH:
-		bit32.base = (Word *)char_egg;
-		break;
-
-	case CONF:
-		bit32.base = (Word *)((other & 1) ? conf1 : conf2);
-		x += (other >> 2) & 1;
-		y += (other >> 1) & 1;
-		break;
-
-	default:
-		bit32.base = (Word *)char_null;
-		break;
-
-/* others here ... */
-	}
-	bitblt(&bit32, Rect(0, 0, 32, 32), &display,
-		add(board.origin, Pt(x, y)), format);
-}
//GO.SYSIN DD pengo.c
echo player.c 1>&2
sed 's/.//' >player.c <<'//GO.SYSIN DD player.c'
-/*
-	This file contains the code to control the players movements
-*/
-
-#include "pengo.h"
-#define	MMX	(pengo.movex = (move_mouse.x > 0)?-8:8)
-#define	MMY	(pengo.movey = (move_mouse.y > 0)?-8:8)
-
-Rectangle	mouse_board;
-
-move_player()
-{
-	int	push;	/* keyboard push */
-	int	type0;
-	int	tmp;
-
-	if (pengo.other == DYING)	/* it has hit a sno_bee */
-		return;			/* this can overlap with die_pengo */
-	put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-	if (
-		((pengo.x & 31) == 0) &&
-		((pengo.y & 31) == 0)
-	)
-	{
-		push = FALSE;
-		new_mouse = mouse.xy;		/* get current location */
-		move_mouse = sub(old_mouse, new_mouse);
-		move_mouse.x /= 32;
-		move_mouse.y /= 32;
-		if (move_mouse.x | move_mouse.y)
-			cursset(new_mouse = home_mouse);
-		if (own() & KBD)
-		{
-			/* keyboard movement routine */
-
-			push = TRUE;
-			switch (kbdchar())
-			{
-			case 'H':
-				push = TRUE;
-			case 'h':
-				move_mouse.x = 8;
-				move_mouse.y = 0;
-				break;
-
-			case 'J':
-				push = TRUE;
-			case 'j':
-				move_mouse.x = 0;
-				move_mouse.y = -8;
-				break;
-
-			case 'K':
-				push = TRUE;
-			case 'k':
-				move_mouse.x = 0;
-				move_mouse.y = 8;
-				break;
-
-			case 'L':
-				push = TRUE;
-			case 'l':
-				move_mouse.x = -8;
-				move_mouse.y = 0;
-				break;
-
-			case ' ':
-				hit = TRUE;		/* stop pengo */
-				move_mouse.x = 0;
-				move_mouse.y = 0;
-				break;
-
-			default:
-				;
-				/* nothing, just throw the key away */
-			}
-		}
-		{
-			int	tmp;
-			int	tmp0;
-
-			tmp  = FALSE;
-			tmp0 = FALSE;
-			if (button1())
-			{
-				put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-				tmp = TRUE;
-			}
-			while (button1() || hit)
-			{
-				if (button1() && (!tmp))
-				{
-					put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-					tmp = TRUE;
-				}
-				tmp0 = TRUE;
-				wait(CPU);
-				hit = FALSE;
-			}
-			if (tmp)
-				put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-			if (tmp0)
-			{
-				pengo.movex = pengo.movey = 0;
-				move_mouse.x = move_mouse.y = 0;
-				old_mouse = mouse.xy;
-			}
-		}
-		if ((move_mouse.y | move_mouse.x) != 0)
-		{
-			if (!(ptinrect(mouse.xy, mouse_board)))
-				cursset(old_mouse = home_mouse);
-			else
-				old_mouse = new_mouse;
-			pengo.movex = pengo.movey = 0;
-			if (abs(move_mouse.y) == abs(move_mouse.x))
-				if (pengo.movex)
-					MMX;
-				else if (pengo.movey)
-					MMY;
-				else if (rand() & 1)	/* Random direction */
-					MMX;
-				else
-					MMY;
-			else if (abs(move_mouse.x) > abs(move_mouse.y))
-				MMX;
-			else
-				MMY;
-		}
-		if (
-			((pengo.movex) || (pengo.movey)) &&
-			screen_blank(
-				((pengo.x + 4 * pengo.movex) >> 5),
-				((pengo.y + 4 * pengo.movey) >> 5)
-			)
-		)
-		{
-			pengo.x += pengo.movex;
-			pengo.y += pengo.movey;
-		}
-		else if (!(button2() || push))	/* stop or hit? */
-		{
-			pengo.movex = pengo.movey = 0;
-		}
-		else
-			/* try to move or destroy block */
-
-			switch (type0 = screen(
-				(pengo.x + 4 * pengo.movex) >> 5,
-				(pengo.y + 4 * pengo.movey) >> 5)
-			)
-			{
-			case BLANK:
-			default:
-				/* should never occur */
-				break;
-			case WALL:
-			case BORDER:
-				if (move_water)
-					break;
-				move_water = pengo.movex ?
-					(pengo.movex < 0) ? LEFT : RIGHT :
-					(pengo.movey < 0) ? UP   : DOWN;
-				swill_water(NUM_WATER);
-				break;
-			case PENGO:
-			case HATCH:
-			case BREAK:
-				/* sorry, cannot move it .. */
-				break;
-			case SNO_BEE:
-				/* He'll get it shortly. */
-				break;
-			case DIAMOND:
-			case EGG:
-			case BLOCK:
-				/* ok, lets try to move it */
-				if (
-					screen(
-						(pengo.x + 8 * pengo.movex) >> 5,
-						(pengo.y + 8 * pengo.movey) >> 5
-					)
-					==
-					BLANK
-				)
-				{
-					int	x;
-
-					if (moving.exists)
-						break;
-					/* ok, we can move the block */
-					moving.other = type0 == BLOCK ? FBLOCK
-						: type0;
-					moving.exists = TRUE;
-					moving.movex = pengo.movex;
-					moving.movey = pengo.movey;
-					moving.x = pengo.x + 4 * pengo.movex;
-					moving.y = pengo.y + 4 * pengo.movey;
-					moving.count = 0;
-					if (type0 == DIAMOND)
-					{
-						for (x = 0; x < 3; x++)
-							if (
-							(diamond[x].x == moving.x)
-							&&
-							(diamond[x].y == moving.y)
-							)
-								break;
-					}
-					if (type0 == EGG)
-					{
-						for (x = 0; x < MAX_BEES; x++)
-							if (
-							(eggs[x].x == moving.x)
-							&&
-							(eggs[x].y == moving.y)
-							)
-							{
-								eggs[x].other =
-									MOVING;
-								break;
-							}
-					}
-					add_event(MOVE_BLOCK,
-						move_block, x);
-					screen(moving.x >> 5,
-						moving.y >> 5) = BLANK;
-				}
-				else switch(type0)
-				{
-					/* ok, lets break it, if we can! */
-				case DIAMOND:
-					/* no luck joe. */
-					break;
-				case EGG:
-					if (breaking.exists)
-						break;
-					/* delete from egg lists */
-					{
-						int	x;	/* tmp */
-
-						for (x = 0; x < MAX_BEES; x++)
-							if (
-								(eggs[x].exists ==
-									TRUE
-								) &&
-								(eggs[x].x ==
-									(pengo.x +
-									4 *
-									pengo.movex)
-								) &&
-								(eggs[x].y ==
-									(pengo.y +
-									4 *
-									pengo.movey)
-								)
-							)
-							{
-							    eggs[x].exists = FALSE;
-							    if (seggs)
-							    {
-								put_char(
-									eggs[x].x,
-									eggs[x].y,
-									EGG,
-									F_XOR, 0
-								);
-								put_char(
-									eggs[x].x,
-									eggs[x].y,
-									FBLOCK,
-									F_XOR, 0
-								);
-							    }
-							    disp_sno_bee(
-								--sno_bee_left);
-							}
-					}
-				{
-					int	new_b;
-
-					add_score(
-						new_b = (
-							(((pengo.x + 4 * pengo.movex >> 5) & 31) << 8) |
-							(((pengo.y + 4 * pengo.movey >> 5) & 31) << 3) |
-							(5)
-						)
-					);
-					add_event(SHOW_SCORE, add_score, new_b);
-				}
-				case BLOCK:
-					if (breaking.exists)
-						break;
-					breaking.other = type0;
-					breaking.exists = TRUE;
-					breaking.count = NUM_BREAK;
-					breaking.movex = pengo.movex;
-					breaking.movey = pengo.movey;
-					breaking.x = pengo.x + 4 * pengo.movex;
-					breaking.y = pengo.y + 4 * pengo.movey;
-					screen(
-						(pengo.x + 4 * pengo.movex) >> 5,
-						(pengo.y + 4 * pengo.movey) >> 5
-					) = BREAK;
-					add_event(DIE_BLOCK,
-						die_block, NULL);
-				}
-			}
-	}
-	else
-	{
-		pengo.x += pengo.movex;
-		pengo.y += pengo.movey;
-	}
-	for (tmp = 0; tmp < 4; tmp++)
-	{
-		if (
-			(sno_bee[tmp].exists) &&
-			PX(pengo, sno_bee[tmp])
-		)
-		{
-			if (sno_bee[tmp].other == CONFUSED)
-			{
-				int	new_b;
-				int	show;
-
-				put_char(sno_bee[tmp].x, sno_bee[tmp].y,
-					CONF, F_XOR, (sno_bee[tmp].count & 1) |
-					(tmp << 1));
-				sno_bee[tmp].exists = FALSE;
-				sno_bee[tmp].other = SQUASH;
-				score += 100;
-				add_score(
-					new_b = (
-						(((sno_bee[tmp].x >> 5)& 31) << 8) |
-						(((sno_bee[tmp].y >> 5)& 31) << 3) |
-						((tmp & 3) << 13) |
-						7
-					)
-				);
-				add_event(SHOW_SCORE, add_score, new_b);
-				show = FALSE;
-				disp_sno_bee(--sno_bee_left);
-				for (new_b = 0; new_b < 1; new_b++)
-				{
-					int	pos;
-
-					for (pos = 0; pos < MAX_BEES; pos++)
-					{
-						if (eggs[pos].exists == TRUE)
-							break;
-					}
-					if (pos < MAX_BEES)
-					{
-						int	a;
-
-						for (a = 0; a < 4; a++)
-						{
-							if
-							(
-								(sno_bee[a].exists
-								==
-								FALSE ) &&
-								(sno_bee[a].other
-								!=
-								HATCHING )
-							)
-							break;
-						}
-						if (a < 4)
-						{
-							eggs[pos].exists = FALSE;
-							sno_bee[a].other = HATCHING;
-							sno_bee[a].count=NUM_HATCH;
-							sno_bee[a].x = eggs[pos].x;
-							sno_bee[a].y = eggs[pos].y;
-							screen(
-								sno_bee[a].x >> 5,
-								sno_bee[a].y >> 5
-							) = HATCH;
-							if (seggs)
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								EGG,
-								F_XOR,
-								0
-							);
-							else
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								FBLOCK,
-								F_XOR,
-								0
-							);
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								HATCH,
-								F_XOR,
-								0
-							);
-							add_event(
-								EGG_HATCH,
-								egg_hatch,
-								a
-							);
-							show = TRUE;
-						}
-					}
-					else
-					{
-						/* no eggs left */
-						if (sno_bee_left <= 0)
-						{
-							/* all bees dead */
-							cancel_events();
-							return;
-						}
-						if (sno_bee_left == 1)
-						{
-							/* last one.. RUNNING */
-
-							add_event(RUN_DELAY,
-								run_bee, NULL);
-						}
-					}
-				}
-				if (show)
-					show_eggs();
-			}
-			else if (sno_bee[tmp].other == SNO_BEE)
-			{
-				pengo.other = DYING;
-				add_event(P_DYING, die_pengo, NULL);
-			}
-		}
-	}
-	put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-	add_event(MOVE_PENGO, move_player, NULL);
-}
//GO.SYSIN DD player.c
echo shapes.c 1>&2
sed 's/.//' >shapes.c <<'//GO.SYSIN DD shapes.c'
-/*
-	shapes of the moving items, pengo, sno_bees blocks, diamonds
-	etc...
-*/
-#include "pengo.h"
-
-short	char_blank[] = {
-#include "icons/blank"
-};
-
-short	flip_block[] = {
-#include "icons/fblock"
-};
-
-short	char_block[] = {
-#include "icons/block"
-};
-
-short	char_0diamond[] = {
-#include "icons/0diamond"
-};
-
-short	*char_1diamond = char_blank;
-
-short	char_null[] = {
-#include "icons/null"
-};
-
-short	char_egg[] = {
-#include "icons/egg"
-};
-
-short	sbee[] = {
-#include "icons/beede"
-};
-
-short	char_100[] = {
-#include "icons/100"
-};
-
-short	char_400[] = {
-#include "icons/400"
-};
-
-short	char_500[] = {
-#include "icons/500"
-};
-
-short	char_1600[] = {
-#include "icons/1600"
-};
-
-short	char_3200[] = {
-#include "icons/3200"
-};
-
-short	char_6400[] = {
-#include "icons/6400"
-};
-
-short	conf1[] = {
-#include "icons/conf1"
-};
-
-short	conf2[] = {
-#include "icons/conf2"
-};
-
-short	char_0bee[] = {
-#include "icons/bee0"
-};
-
-short	char_1bee[] = {
-#include "icons/bee1"
-};
-
-short	char_0pengo[] = {
-#include "icons/still"
-};
-
-short	char_1pengo[] = {
-#include "icons/pengo1"
-};
-
-short	char_2pengo[] = {
-#include "icons/pengo2"
-};
-
-short	char_3pengo[] = {
-#include "icons/pengo3"
-};
-
-short	char_4pengo[] = {
-#include "icons/pengo4"
-};
-
-short	char_5pengo[] = {
-#include "icons/pengo5"
-};
-
-short	char_6pengo[] = {
-#include "icons/pengo6"
-};
-
-short	char_7pengo[] = {
-#include "icons/pengo7"
-};
-
-short	char_8pengo[] = {
-#include "icons/pengo8"
-};
-
-short	*char_still = char_0pengo;
-
-short	*char_sorry = char_0pengo;
-
-short	*char_happy = char_0pengo;
-
-short	char_0dead[] = {
-#include "icons/dead0"
-};
-
-short	char_1dead[] = {
-#include "icons/dead1"
-};
-
-short	*pengo_moves[] = {
-	char_0pengo,
-	char_1pengo,
-	char_2pengo,
-	char_3pengo,
-	char_4pengo,
-	char_5pengo,
-	char_6pengo,
-	char_7pengo,
-	char_8pengo,
-};
-
-short	char_pback[] = {
-#include "icons/pback"
-};
-
-short	char_salute[] = {
-#include "icons/salute"
-};
-
-short	char_0wiggle[] = {
-#include "icons/wiggle0"
-};
-
-short	char_1wiggle[] = {
-#include "icons/wiggle1"
-};
-
-short	ch_sq_0down[] = {
-#include "icons/sq_0down"
-};
-
-short	ch_sq_0left[] = {
-#include "icons/sq_0left"
-};
-
-short	ch_sq_0right[] = {
-#include "icons/sq_0right"
-};
-
-short	ch_sq_0up[] = {
-#include "icons/sq_0up"
-};
-
-short	ch_sq_1down[] = {
-#include "icons/sq_1down"
-};
-
-short	ch_sq_1left[] = {
-#include "icons/sq_1left"
-};
-
-short	ch_sq_1right[] = {
-#include "icons/sq_1right"
-};
-
-short	ch_sq_1up[] = {
-#include "icons/sq_1up"
-};
-
-short	*squash_moves[] = {
-	ch_sq_0up,
-	ch_sq_0down,
-	ch_sq_0left,
-	ch_sq_0right,
-	ch_sq_1up,
-	ch_sq_1down,
-	ch_sq_1left,
-	ch_sq_1right,
-};
-
-short	char_0hula[] = {
-#include "icons/hula0"
-};
-
-short	char_1hula[] = {
-#include "icons/hula1"
-};
-
-short	char_2hula[] = {
-#include "icons/hula2"
-};
-
-short	char_3hula[] = {
-#include "icons/hula3"
-};
-
-short	char_4hula[] = {
-#include "icons/hula4"
-};
-
-short	*hula_moves[] = {
-	char_0hula,
-	char_1hula,
-	char_2hula,
-	char_3hula,
-	char_4hula,
-};
-
-short	char_lchair[] = {
-#include "icons/chairl"
-};
-
-short	char_rchair[] = {
-#include "icons/chairr"
-};
-
-short	char_0video[] = {
-#include "icons/video0"
-};
-
-short	char_0lplayer[] = {
-#include "icons/playerl0"
-};
-
-short	char_1lplayer[] = {
-#include "icons/playerl1"
-};
-
-short	char_0rplayer[] = {
-#include "icons/playerr0"
-};
-
-short	char_1rplayer[] = {
-#include "icons/playerr1"
-};
//GO.SYSIN DD shapes.c

From acsnet!basser!john Fri Jun 27 06:38:42 1986
does anyone have dumpcatch, mentioned in /usr/sys/h/dumpl.h?

From acsnet!basser!rex Thu Jun 26 20:45:13 1986
# To unbundle, sh this file
echo bitmap.c 1>&2
sed 's/.//' >bitmap.c <<'//GO.SYSIN DD bitmap.c'
-/*
-	This file holds all the Bitmap controlling information.
-
-	Bitmaps for the moving shapes are generated on demand.
-
-*/
-
-#include "pengo.h"
-
-Bitmap	bit32 = {
-	(Word *) 0,
-	shorts(2),
-	{ { 0, 0 } , { 32, 32} }
-};
-
-Bitmap	bit16 = {
-	(Word *) 0,
-#ifdef	JERQ
-	shorts(2),
-#define	MUL	32
-#else	JERQ
-	shorts(1),
-#define	MUL	16
-#endif	JERQ
-	{ { 0, 0 } , { 16, 16 } }
-};
-
-Bitmap *
-bchar(ch)	/* returns 16x16 Bitmap of char 'ch' */
-char ch;
-{
-
-/* all that has to be done is assign bit16.base */
-
-	if ((ch >= '0') && (ch <= '9'))
-		bit16.base = (Word *)&char_0_9[((ch - '0') * MUL)];
-	else if ((ch >= 'A') && (ch <= 'Z'))
-		bit16.base = (Word *)&char_A_Z[((ch - 'A') * MUL)];
-	else if ((ch >= 'a') && (ch <= 'z'))
-		bit16.base = (Word *)&char_A_Z[((ch - 'a') * MUL)];
-	else switch(ch)
-	{
-	case '.':
-		bit16.base = (Word *)char_dot;
-		break;
-
-	case ':':
-		bit16.base = (Word *)char_colon;
-		break;
-
-	case '?':
-		bit16.base = (Word *)char_question;
-		break;
-
-	case ')':
-		bit16.base = (Word *)char_rbrkt;
-		break;
-
-	case '(':
-		bit16.base = (Word *)char_lbrkt;
-		break;
-
-	case '_':
-		bit16.base = (Word *)char_uscore;
-		break;
-
-	case '/':
-		bit16.base = (Word *)char_slash;
-		break;
-	
-	default:
-		bit16.base = (Word *)char_space;
-		break;
-	}
-	return (&bit16);
-}
-
//GO.SYSIN DD bitmap.c
echo digits.c 1>&2
sed 's/.//' >digits.c <<'//GO.SYSIN DD digits.c'
-#include "pengo.h"
-
-/* These are bitmaps for the big numerals that are used to display
- *	the score.
- */
-short	N[] = {
-/* 0 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 1 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x001F, 0x8000,
-	0x003F, 0xC000,
-	0x007F, 0xC000,
-	0x007F, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x00FF, 0xFF00,
-	0x00FF, 0xFF00,
-	0x00FF, 0xFF00,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 2 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x07C0,
-	0x0000, 0x0FC0,
-	0x0000, 0x3F80,
-	0x0000, 0xFF00,
-	0x0003, 0xFE00,
-	0x0007, 0xF800,
-	0x000F, 0xE000,
-	0x001F, 0xC000,
-	0x003F, 0x0000,
-	0x007E, 0x0000,
-	0x00FC, 0x0000,
-	0x01F8, 0x0000,
-	0x03F0, 0x0000,
-	0x03E0, 0x0000,
-	0x03E0, 0x0000,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFFC0,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 3 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x07C0,
-	0x000F, 0xFF80,
-	0x000F, 0xFF00,
-	0x000F, 0xFF00,
-	0x000F, 0xFF80,
-	0x0000, 0x07C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 4 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 5 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03FF, 0xFC00,
-	0x03FF, 0xFF00,
-	0x03FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x0000, 0x0FC0,
-	0x0000, 0x07C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x07C0,
-	0x03C0, 0x0FC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFF80,
-	0x03FF, 0xFF00,
-	0x01FF, 0xFC00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 6 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03C0, 0x0000,
-	0x03FF, 0xFC00,
-	0x03FF, 0xFF00,
-	0x03FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x0FC0,
-	0x03C0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03F0, 0x0FC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x003F, 0xFC00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 7 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFFC0,
-	0x01FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x07C0,
-	0x03C0, 0x0780,
-	0x0000, 0x0F80,
-	0x0000, 0x0F00,
-	0x0000, 0x1F00,
-	0x0000, 0x3E00,
-	0x0000, 0x3E00,
-	0x0000, 0x7C00,
-	0x0000, 0x7800,
-	0x0000, 0xF000,
-	0x0001, 0xF000,
-	0x0001, 0xE000,
-	0x0003, 0xE000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0003, 0xC000,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 8 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-/* 9 */
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-	0x003F, 0xFC00,
-	0x00FF, 0xFF00,
-	0x01FF, 0xFF80,
-	0x03FF, 0xFFC0,
-	0x03F0, 0x0FC0,
-	0x03E0, 0x07C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x03C0,
-	0x03F0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFFC0,
-	0x00FF, 0xFFC0,
-	0x003F, 0xFFC0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x0000, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03C0, 0x03C0,
-	0x03E0, 0x07C0,
-	0x03FF, 0xFFC0,
-	0x03FF, 0xFFC0,
-	0x01FF, 0xFF80,
-	0x00FF, 0xFF00,
-	0x0000, 0x0000,
-	0x0000, 0x0000,
-};
//GO.SYSIN DD digits.c
echo endgame.c 1>&2
sed 's/.//' >endgame.c <<'//GO.SYSIN DD endgame.c'
-#include "pengo.h"
-
-Bitmap	disp_head = {
-	(Word *) char_header,
-	shorts(14),
-	{ { 0, 0 }, { HEAD_X, HEAD_Y } }
-};
-
-newgame()
-{
-	int	ch;
-	int	x;
-	int	y;
-
-	y = FALSE;
-	rectf(&display, counter, F_CLR);
-	addstr("Another", counter.origin, F_STORE);
-	addstr("Game?", add(counter.origin, Pt(16, 16)), F_STORE);
-	addstr("(Y/N)?_", add(counter.origin, Pt(0, 32)), F_STORE);
-	for (;;)
-	{
-		for(x = 0; x < HEAD_COUNT; x++)
-			if ((ch = kbdchar()) != -1)
-				break;
-			else
-				sleep(2);
-		if (ch == -1)
-		{
-			/* do static display */
-			
-			if (
-				((board.corner.x - board.origin.x) > HEAD_X) &&
-				((board.corner.y - board.origin.y) > HEAD_Y)
-			)
-			{
-				if (y == FALSE)
-				{
-					rectf(&display, board, F_CLR);
-					bitblt(&disp_head, disp_head.rect,
-						&display,
-						add(
-						    div(
-							sub(
-							    sub(
-								board.corner,
-								board.origin
-							    ),
-							    Pt(HEAD_X, HEAD_Y)
-							),
-							2
-						    ),
-						    board.origin
-						), F_STORE);
-#ifdef	JERQ
-#ifdef	MPX
-					if (!VALSCREENCOLOR)
-						rectf(&display, board, F_XOR);
-#endif	MPX
-#endif	JERQ
-					y = TRUE;
-				}
-			}
-			while(((ch = kbdchar()) == -1) && (!button123()))
-				wait(CPU);
-		}
-		if (button123() && (ch == -1))
-			return(TRUE);
-		switch(ch)
-		{
-		case 'Y':
-		case 'y':
-			return(TRUE);
-	
-		case 'N':
-		case 'n':
-		case 'Q':
-		case 'q':
-			exit();
-		}
-	}
-}
//GO.SYSIN DD endgame.c
echo event.c 1>&2
sed 's/.//' >event.c <<'//GO.SYSIN DD event.c'
-/*
-	This file contains the code that handles the scheduling of the
-	processes in the system. All moving objects set up a 'next run
-	time' using add_event.
-
-*/
-#include "pengo.h"
-#define	MAX_ARRAY	100		/* number of schedule slots */
-#define	MAX_TIME	10000L
-
-int	ebase	= 0;	/* pointer to first event */
-
-struct	event {
-	long	event_time;
-	int	(*event_fn)();
-	int	event_arg;
-	int	next_event;
-} event_array[MAX_ARRAY];	/* space for scheduled events */
-
-add_event(etime, efn, earg)	/* VERY simple event scheduler */
-long	etime;
-int	(*efn)();
-int	earg;
-{
-	int	count;
-	int	last;
-	Word	*water();
-
-	for (count = 0; event_array[count].next_event != -1; count++)
-			;	/* do nothing, the condition says it all */
-	event_array[count].event_time = (etime += my_time);
-	event_array[count].event_fn   = efn;
-	event_array[count].event_arg  = earg;
-	if (event_array[(last = ebase)].event_time > etime)
-	{
-		event_array[count].next_event = ebase;
-		ebase = count;
-	}
-	else
-	{
-		while (
-			event_array[event_array[last].next_event].event_time
-			<
-			etime
-		)
-			last = event_array[last].next_event;
-		event_array[count].next_event = event_array[last].next_event;
-		event_array[last].next_event = count;
-	}
-}
-
-next_event()	/* execute the next event on the list. FALSE if none left */
-{
-	int	tmp;
-	long	tmp0;
-	int	ebase0;
-
-	wait_mouse();
-	if ((tmp = event_array[(ebase0 = ebase)].next_event) == -2)
-		return FALSE;	/* all is done. All is finished */
-	if ((tmp0 = (event_array[ebase0].event_time - my_time)) > 0)
-		sleep ((int)tmp0);
-	event_array[ebase0].next_event = -1;	/* clear this entry */
-	ebase = tmp;				/* and reset pointer */
-	my_time = event_array[ebase0].event_time;
-	(*event_array[ebase0].event_fn)(event_array[ebase0].event_arg);
-	if (score != old_score)
-	{
-		add_men(score, old_score);
-		put_score(old_score = score);
-	}
-	return (TRUE);
-}
-
-cancel_events()
-{
-	extern	int	allover();
-
-	for (ebase = MAX_ARRAY - 1; ebase > 0; ebase--)
-		event_array[ebase].next_event = -1;
-	event_array[ebase = 0].next_event = -2;
-	event_array[ebase].event_time = MAX_TIME;
-	event_array[ebase].event_fn  = allover;
-}
-
-allover()
-{
-	int	ptr;
-
-	for (ptr = MAX_ARRAY - 1; ptr > 0; ptr--)
-		event_array[ptr].event_time -= MAX_TIME;
-	add_event(MAX_TIME, allover, NULL);
-	my_time -= MAX_TIME;
-}
//GO.SYSIN DD event.c
echo globals.c 1>&2
sed 's/.//' >globals.c <<'//GO.SYSIN DD globals.c'
-/*
- *	storage  file for pengo.	BLIT version
- */
-
-#include "pengo.h"
-/* externs for files */
-int	pengo_left;	/* number of pengos left */
-int	sno_bee_left;	/* number of sno_bees left */
-int	egg_count_flag;	/* number of eggs still to hatch */
-int	manptr;		/* index into new_man */
-int	hit;		/* state of button 2 */
-int	seggs;		/* eggs on display ? */
-char	move_water;	/* side water movement */
-char	sdiamond;	/* 10000 points flag */
-char	s[MAXX][MAXY];	/* storage for which blocks are on */
-long	score;		/* current score */
-long	old_score;	/* previous score */
-long	high_score;	/* current high score */
-long	my_time;	/* 60th of a second counter for play time */
-element	pengo;		/* pengo definition */
-element	sno_bee[4];	/* which blocks are really sno_bees */
-element	eggs[MAX_BEES];	/* which blocks are eggs */
-element	diamond[3];	/* which blocks are really diamonds */
-element	moving;		/* block which is moving or breaking */
-element	breaking;	/* block which is breaking */
-element	bee_block[4];	/* blocks being broken by bees */
-Point	old_mouse;	/* initial mouse position */
-Point	new_mouse;	/* current mouse position */
-Point	move_mouse;	/* difference of old & new */
-Point	home_mouse;	/* home position of mouse */
-Rectangle	board;
-Rectangle	board0;
-Rectangle	board1;
-Rectangle	header;
-Rectangle	bwater;
-Rectangle	lwater;
-Rectangle	rwater;
-Rectangle	twater;
-Rectangle	counter;
-int	sbd;
-int	npd;
-int	bee_run;
-
-long	new_man[] = {
-	10000L, 20000L, 50000L, 100000L, 200000L, 400000L, 800000L,
-};
-
-Word	bstore[8 * 48];	/* storage, requires an even number as x, for jerq */
-		/* 10000 point bonus bitmap */
-Bitmap	bonus	= { (Word *)bstore, shorts(8), { { 0, 0 }, { 16 * 7, 48 } } };
-#ifndef	MPX
-int	reshaped;
-#endif
-int	sb_change;
-int	sb_random;
-int	sb_break;
//GO.SYSIN DD globals.c
echo score.c 1>&2
sed 's/.//' >score.c <<'//GO.SYSIN DD score.c'
-/*
-	score.c:	put score onto the screen.
-*/
-
-#include "pengo.h"
-
-add_men(score, old_score)
-long	score;
-long	old_score;
-{
-	if ((manptr >= NUM_ADD_MAN) && ((score % 800000L) < (old_score % 800000L)))
-		add_man();
-	else
-		while ((manptr < NUM_ADD_MAN) && (score > new_man[manptr]))
-		{
-			add_man();
-			manptr++;
-		}
-}
-
-put_score(score)
-long	score;
-{
-	int	count;
-
-	rectf(&display, header, F_CLR);
-	for (count = NUM_DIGITS - 1; ((count >= 0) && (score > 0)); count--)
-	{
-		bit32.base = (Word *)&N[(score % 10) * 64];
-		bitblt(&bit32, R3, &display,
-			Pt(header.origin.x + count * CHAR_WIDTH, header.origin.y),
-			F_STORE);
-		score /= 10;
-	}
-}
//GO.SYSIN DD score.c
echo screen.c 1>&2
sed 's/.//' >screen.c <<'//GO.SYSIN DD screen.c'
-/*
-	this file handles contradictions between the screen appearance
-	and what is stored in the block array
-*/
-#include "pengo.h"
-
-screen_blank(x, y)
-int	x;
-int	y;
-{
-	Point	sp;
-	int	count;
-
-	sp.x = x << 5;
-	sp.y = y << 5;
-	if (
-		PX(sp, pengo)  ||
-		(moving.exists && PX(sp, moving)) ||
-		(breaking.exists && PX(sp, breaking))
-	)
-		return FALSE;	/* something is there */
-	for (count = 0; count < MAX_BEES; count++)
-		if (
-			eggs[count].exists &&
-			(eggs[count].other == SNO_BEE) &&
-			PX(sp, eggs[count])
-		)
-			return FALSE;
-	if (screen(x, y) != BLANK)
-		return FALSE;
-	return TRUE;	/* oh well it appears to be blank */
-}
//GO.SYSIN DD screen.c
echo sno_bee.c 1>&2
sed 's/.//' >sno_bee.c <<'//GO.SYSIN DD sno_bee.c'
-/*
-	This file contains the code required to move the sno_bees about
-*/
-
-#include "pengo.h"
-#define	SB	sno_bee[bee_num]
-#define	MW(x)	(((x < 0) || (x >= sizeof(move_weights)/sizeof(move_weights[0]))) ? 0 : move_weights[x])
-
-int	move_weights[] = {
-	10,	/* BLANK */
-	5,	/* BLOCK */
-	10,	/* SNO_BEE */
-	100,	/* PENGO */
-	0,	/* DIAMOND */
-	0,	/* EGG */
-	0,	/* HATCH */
-	5,	/* BREAK ... same as BLOCK */
-	10,	/* CONF ... same as SNO_BEE */
-};
-
-move_sno_bee(bee_num)
-int	bee_num;
-{
-	if (SB.exists != TRUE)	/* let somebody else handle it!! */
-		return;
-	if (SB.other != SNO_BEE)
-		return;
-	if (((SB.x & 31) == 0) && ((SB.y & 31) == 0))
-	{
-		if ((rand() % 100) < sb_change)	/* how often to change */
-		{
-			if ((rand() % 100) < sb_random)
-			{
-				SB.movex = SB.movey = 0;
-				switch(rand() % 5)
-				{
-				case UP:
-					SB.movey = -8;
-					break;
-				case DOWN:
-					SB.movey = 8;
-					break;
-				case RIGHT:
-					SB.movex = 8;
-					break;
-				case LEFT:
-					SB.movex = -8;
-					break;
-				}
-			}
-			else
-			{
-				int	dx;
-				int	dy;
-
-				SB.movex = SB.movey = 0;
-				dx = (pengo.x - SB.x) / 32;
-				dy = (pengo.y - SB.y) / 32;
-				dx *= MW(screen((SB.x+((dx>0)?32:-32))>>5,SB.y>>5));
-				dy *= MW(screen(SB.x>>5,(SB.y+((dy>0)?32:-32))>>5));
-				if (abs(dx) > abs(dy))
-					SB.movex = ((dx > 0) ? 8 : -8);
-				else
-					SB.movey = ((dy > 0) ? 8 : -8);
-			}
-		}
-		switch (
-			screen(
-				(SB.x + 4 * SB.movex) >> 5,
-				(SB.y + 4 * SB.movey) >> 5
-			)
-		)
-		{
-		case BREAK:	/* can move through breaking blocks */
-		case BLANK:
-		case PENGO:
-		case SNO_BEE:
-			put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-			SB.x += SB.movex;
-			SB.y += SB.movey;
-			put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-			break;
-
-		case BLOCK:
-			if (
-				(bee_block[bee_num].exists == FALSE) &&
-				((rand() % 100) < sb_break)
-			)
-			{
-				bee_block[bee_num].count = NUM_BREAK;
-				bee_block[bee_num].exists = TRUE;
-				bee_block[bee_num].x = SB.x + 4 * SB.movex;
-				bee_block[bee_num].y = SB.y + 4 * SB.movey;
-				screen(bee_block[bee_num].x >> 5,
-					bee_block[bee_num].y >> 5) = BREAK;
-				add_event(DIE_BLOCK, bee_break, bee_num);
-			}
-			break;
-
-		default:
-			SB.movex = SB.movey = 0;
-			break;
-		}
-	}
-	else
-	{
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-		SB.x += SB.movex;
-		SB.y += SB.movey;
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-	}
-	if (
-		(pengo.exists) &&
-		PX(pengo, SB)
-	)
-	{
-		pengo.other = DYING;	/* he, he the sno_bee got him */
-		add_event(P_DYING, die_pengo, NULL);
-	}
-	if (bee_run)
-		add_event(MOVE_BEE0, run_sno_bee, bee_num);
-	else
-		add_event(MOVE_BEE0, move_sno_bee, bee_num);
-}
-
-run_sno_bee(bee_num)
-int	bee_num;
-{
-	if (SB.exists != TRUE)
-		return;
-	if (SB.other != SNO_BEE)
-		return;
-	if (((SB.x & 31) == 0) && ((SB.y & 31) == 0))
-	{
-		/* run towards a corner */
-		int	posx;
-		int	posy;
-		int	dirn;
-
-		posx = SB.x >> 5;
-		posy = SB.y >> 5;
-
-		if (
-			(((blockx - 1) == posx) || (posx == 0))
-			&&
-			(((blocky - 1) == posy) || (posy == 0))
-		)
-		{
-			SB.other = VANISH;
-			SB.count = DYING_TIME;
-			add_event(DIE_BEE, vanish_bee, bee_num);
-			return;
-		}
-		if (((blockx - 1) - posx) < posx)	/* to the right */
-		{
-			if (((blocky - 1) - posy) < posy)	/* down */
-			{
-				if (
-					(
-						(blockx - 1) != posx
-					) &&
-					(
-						((blocky - 1) == posy) ||
-						(
-							((blockx - 1) - posx)
-							<
-							((blocky - 1) - posy)
-						)
-					)
-				)
-					dirn = RIGHT;
-				else
-					dirn = DOWN;
-			}
-			else				/* up */
-			{
-				if (
-					(
-						(blockx - 1) != posx
-					) &&
-					(
-						(posy == 0 ) ||
-						(
-							((blockx - 1) - posx)
-							<
-							posy
-						)
-					)
-				)
-					dirn = RIGHT;
-				else
-					dirn = UP;
-			}
-		}
-		else				/* to the left */
-		{
-			if (((blocky - 1) - posy) < posy)	/* down */
-			{
-				if (
-					(
-						posx != 0
-					) &&
-					(
-						((blocky - 1) == posy) ||
-						(posx < ((blocky - 1) - posy))
-					)
-				)
-					dirn = LEFT;
-				else
-					dirn = DOWN;
-			}
-			else				/* up */
-			{
-				if (
-					(
-						posx != 0
-					) &&
-					(
-						(posy == 0) ||
-						(posx < posy)
-					)
-				)
-					dirn = LEFT;
-				else
-					dirn = UP;
-			}
-		}
-		switch(dirn)
-		{
-		case UP:
-			SB.movex = 0;
-			SB.movey = -8;
-			break;
-
-		case DOWN:
-			SB.movex = 0;
-			SB.movey = 8;
-			break;
-
-		case RIGHT:
-			SB.movex = 8;
-			SB.movey = 0;
-			break;
-
-		case LEFT:
-			SB.movex = -8;
-			SB.movey = 0;
-			break;
-		}
-		switch (
-			screen(
-				(SB.x + 4 * SB.movex) >> 5,
-				(SB.y + 4 * SB.movey) >> 5
-			)
-		)
-		{
-		case BREAK:
-		case BLANK:
-		case PENGO:
-		case SNO_BEE:
-			put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-			SB.x += SB.movex;
-			SB.y += SB.movey;
-			put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-			break;
-
-		case BLOCK:
-			if (bee_block[bee_num].exists == FALSE)
-			{
-				bee_block[bee_num].count = NUM_BREAK;
-				bee_block[bee_num].exists = TRUE;
-				bee_block[bee_num].x = SB.x + 4 * SB.movex;
-				bee_block[bee_num].y = SB.y + 4 * SB.movey;
-				screen(bee_block[bee_num].x >> 5,
-					bee_block[bee_num].y >> 5) = BREAK;
-				add_event(DIE_BLOCK, bee_break, bee_num);
-			}
-			break;
-
-		default:
-			SB.other = VANISH;
-			SB.count = DYING_TIME;
-			add_event(DIE_BEE, vanish_bee, bee_num);
-			return;
-		}
-	}	
-	else
-	{
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-		SB.x += SB.movex;
-		SB.y += SB.movey;
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-	}
-	add_event(MOVE_BEE0, run_sno_bee, bee_num);
-}
-
-vanish_bee(bee_num)
-int	bee_num;
-{
-	put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-	if (SB.count--)
-		add_event(DIE_BEE, vanish_bee, bee_num);
-	else
-	{
-		disp_sno_bee(0);	/* no sno_bees */
-		cancel_events();	/* all gone ... */
-	}
-}
-
-confused_bee(bee_num)
-int	bee_num;
-{
-	if (SB.other != CONFUSED)
-		return;
-	put_char(SB.x, SB.y, CONF, F_XOR, (SB.count-- & 1) | (bee_num << 1));
-	put_char(SB.x, SB.y, CONF, F_XOR, (SB.count & 1) | (bee_num << 1));
-	if (SB.count == 0)
-	{
-		put_char(SB.x, SB.y, CONF, F_XOR, (bee_num << 1));
-		put_char(SB.x, SB.y, SNO_BEE, F_XOR, bee_num);
-		SB.other = SNO_BEE;
-		if (bee_run)
-			add_event(MOVE_BEE0, run_sno_bee, bee_num);
-		else
-			add_event(MOVE_BEE0, move_sno_bee, bee_num);
-	}
-	else
-		add_event(TIME_CONFUSED, confused_bee, bee_num);
-}
//GO.SYSIN DD sno_bee.c
echo water.c 1>&2
sed 's/.//' >water.c <<'//GO.SYSIN DD water.c'
-/*
-	character arrays for water shapes
-*/
-#include "pengo.h"
-
-short nw[] = {
-	0x5555, 0xAAAA, 0x5555, 0xAAAA,
-	0x5555, 0xAAAA, 0x5555, 0xAAAA,
-	0x5555, 0xAAAA, 0x5555, 0xAAAA,
-	0x5555, 0xAAAA, 0x5555, 0xAAAA,
-};
-
-short tw[] = {
-	0x5555, 0xAAAA, 0x4141, 0x0808,
-	0x5555, 0xAAAA, 0x4141, 0x0808,
-	0x5555, 0xAAAA, 0x4141, 0x0808,
-	0x5555, 0xAAAA, 0x4141, 0x0808,
-};
-
-short bw[] = {
-	0x5555, 0x0808, 0x4141, 0xAAAA,
-	0x5555, 0x0808, 0x4141, 0xAAAA,
-	0x5555, 0x0808, 0x4141, 0xAAAA,
-	0x5555, 0x0808, 0x4141, 0xAAAA,
-};
-
-short lw[] = {
-	0x1111, 0xAAAA, 0x1111, 0x8888,
-	0x5555, 0x8888, 0x1111, 0xAAAA,
-	0x1111, 0xAAAA, 0x1111, 0x8888,
-	0x5555, 0x8888, 0x1111, 0xAAAA,
-};
-
-short rw[] = {
-	0x5555, 0x8888, 0x1111, 0xAAAA,
-	0x1111, 0x8888, 0x5555, 0x8888,
-	0x5555, 0x8888, 0x1111, 0xAAAA,
-	0x1111, 0x8888, 0x5555, 0x8888,
-};
-
-swill_water(num)
-int	num;
-{
-	Word	*p;
-	Rectangle w;
-	int	dx;
-	int	dy;
-	int	x;
-
-	if (num == 0)
-	{
-		move_water = STILL;
-		return;
-	}
-	dx = dy = -1;
-	switch(move_water)
-	{
-	case UP:
-		p = (Word *)tw;
-		w = twater;
-		dy = 0;
-		break;
-
-	case DOWN:
-		p = (Word *)bw;
-		w = bwater;
-		dy = blocky - 1;
-		break;
-
-	case LEFT:
-		p = (Word *)lw;
-		w = lwater;
-		dx = 0;
-		break;
-
-	case RIGHT:
-		p = (Word *)rw;
-		w = rwater;
-		dx = blockx - 1;
-		break;
-
-	default:
-		return;
-	}
-	if (num & 1)
-		p = (Word *)nw;
-	texture(&display, w, p, F_STORE);
-	for (x = 0; x < 4; x++)
-		if (
-			(sno_bee[x].exists == TRUE) &&
-			(sno_bee[x].other == SNO_BEE) &&
-			(
-				(
-					(dx != -1) &&
-					(sno_bee[x].x == (dx << 5))
-				) ||
-				(
-					(dy != -1) &&
-					(sno_bee[x].y == (dy << 5))
-				)
-			)
-		)
-		{
-			sno_bee[x].count = NUM_CONFUSED;
-			sno_bee[x].other = CONFUSED;
-			add_event(TIME_CONFUSED, confused_bee, x);
-			put_char(sno_bee[x].x, sno_bee[x].y,
-				SNO_BEE, F_XOR, x);
-			put_char(sno_bee[x].x, sno_bee[x].y,
-				CONF, F_XOR, (NUM_CONFUSED & 1) | (x << 1));
-		}
-	add_event(WATER_TIME, swill_water, --num);
-}
//GO.SYSIN DD water.c
echo pengo.c 1>&2
sed 's/.//' >pengo.c <<'//GO.SYSIN DD pengo.c'
-/*
-	main routine in PENGO!!!!!
-
-*/
-#include "pengo.h"
-
-main()
-{
-	int	level = 0;
-
-#ifndef	JERQ
-	*(char *)(384*1024L+040) = 1;	/* set to Black on White */
-#endif	JERQ
-	sb_change = SNO_BEE_CHANGE;
-	sb_random = SNO_BEE_RANDOM;
-	sb_break  = SNO_BEE_BREAK;
-	pengo_left = NUM_PENGO;
-	srand((int)realtime());	/* set up random number thingy */
-	my_time = 0;
-	init();
-	{
-		/* do static display */
-		
-		if (
-			((board.corner.x - board.origin.x) > HEAD_X) &&
-			((board.corner.y - board.origin.y) > HEAD_Y)
-		)
-		{
-			rectf(&display, board, F_CLR);
-			bitblt(&disp_head, disp_head.rect,
-				&display,
-				add(
-				    div(
-					sub(
-					    sub(
-						board.corner,
-						board.origin
-					    ),
-					    Pt(HEAD_X, HEAD_Y)
-					),
-					2
-				    ),
-				    board.origin
-				), F_STORE);
-#ifdef	JERQ
-#ifdef	MPX
-			if (!VALSCREENCOLOR)	/* change the screen shade */
-				rectf(&display, board, F_XOR);
-#endif	MPX
-#endif	JERQ
-		}
-		while(!((own() & MOUSE) && button123()))
-		{
-			rand();		/* roll random number generator */
-			wait(CPU);
-		}
-		texture(&display, Drect, char_space, F_STORE);
-	}
-	sno_bee_left = (level < (MAX_BEES - 9)) ? level + 8 : MAX_BEES;
-	init_scr();
-	init_board();
-	score = 0;
-	for(;;)
-	{
-		int	screen_time;
-
-		pengo.exists = TRUE;	/* pengo is now alive */
-		add_event(MOVE_PENGO, move_player, NULL);
-		while (next_event())
-		{
-#ifdef	MPX
-			if (P->state & RESHAPED)
-			{
-				level = -1;
-				changed_screen();
-				pengo_left = NUM_PENGO;
-			}
-#else
-			if (reshaped == TRUE)
-			{
-				level = -1;
-				changed_screen();
-				pengo_left = NUM_PENGO;
-			}
-#endif
-		}
-		if ((screen_time = my_time / 60) < 0)
-			screen_time = 0;
-		if (pengo.exists == TRUE)
-		{
-			/* player was alive at the end of that one */
-			if (level >= 0)
-			{
-				extra_score(screen_time);
-				if (level++ & 1)
-				{
-					/* do dance of the levels */
-					level_dance(level);
-				}
-			}
-			else
-				level = 0;
-			sno_bee_left = (level < (MAX_BEES - 9))?level+8 : MAX_BEES;
-			my_time = 0;
-			init_scr();
-			init_board();
-		}
-		else	/* player was killed */
-			if (pengo_left == -1)
-			{
-				/* all dead now */
-				newgame();	/* new game ? */
-				my_time = 0;
-				level = 0;
-				pengo_left = NUM_PENGO;
-				sno_bee_left = (level < (MAX_BEES - 9)) ?
-					level + 8 : MAX_BEES;
-				init_scr();
-				init_board();
-				put_score(score = 0);
-			}
-			else
-			{
-				init_scr();
-				redraw_screen();
-			}
-		breaking.exists = FALSE;	/* if we were breaking a block */
-	}
-}
-
-Word *
-water(x)
-int x;
-{
-	switch(x)
-	{
-	case STILL:
-		return (Word *)nw;
-
-	case UP:
-		return (Word *)tw;
-
-	case DOWN:
-		return (Word *)bw;
-
-	case LEFT:
-		return (Word *)lw;
-
-	case RIGHT:
-		return (Word *)rw;
-	}
-	return (Word *)nw;
-}
-
-put_char(x, y, ch, format, other)
-int	x;
-int	y;
-int	ch;
-int	format;
-int	other;
-{
-	extern	Bitmap	bit32;
-	int	tmp;
-
-#ifdef	MPX
-	if (P->state & RESHAPED)
-		return;
-#else
-	if (reshaped == TRUE)
-		return;
-#endif
-	switch(ch)
-	{
-	case BLANK:
-		bit32.base = (Word *)char_blank;
-		break;
-
-	case BLOCK:
-		bit32.base = (Word *)char_block;
-		break;
-
-	case FBLOCK:
-		bit32.base = (Word *)flip_block;
-		break;
-
-	case PENGO:
-		if (pengo.movex)
-			if (pengo.movex < 0)
-				tmp = 1;
-			else
-				tmp = 3;
-		else
-			if (pengo.movey < 0)
-				tmp = 5;
-			else if (pengo.movey)
-				tmp = 7;
-			else
-				tmp = 0;
-		if ((pengo.x & 16) || (pengo.y & 16))
-			tmp++;
-		bit32.base = (Word *)pengo_moves[tmp];	
-		break;
-
-	case PENGO_D:
-		bit32.base = (Word *)(other ? char_1dead : char_0dead);
-		break;
-
-	case DIAMOND:
-		bit32.base = (Word *)(other ? char_1diamond : char_0diamond);
-		break;
-
-	case SNO_BEE:
-		bit32.base = (Word *)((
-				(sno_bee[other].x & 16) |
-				(sno_bee[other].y & 16)
-			     ) ? char_1bee : char_0bee);
-		x += (other>> 1) & 1;
-		y += other & 1;
-		break;
-
-	case EGG:
-		bit32.base = (Word *)(seggs ? char_egg : flip_block);
-		break;
-
-	case HATCH:
-		bit32.base = (Word *)char_egg;
-		break;
-
-	case CONF:
-		bit32.base = (Word *)((other & 1) ? conf1 : conf2);
-		x += (other >> 2) & 1;
-		y += (other >> 1) & 1;
-		break;
-
-	default:
-		bit32.base = (Word *)char_null;
-		break;
-
-/* others here ... */
-	}
-	bitblt(&bit32, Rect(0, 0, 32, 32), &display,
-		add(board.origin, Pt(x, y)), format);
-}
//GO.SYSIN DD pengo.c
echo player.c 1>&2
sed 's/.//' >player.c <<'//GO.SYSIN DD player.c'
-/*
-	This file contains the code to control the players movements
-*/
-
-#include "pengo.h"
-#define	MMX	(pengo.movex = (move_mouse.x > 0)?-8:8)
-#define	MMY	(pengo.movey = (move_mouse.y > 0)?-8:8)
-
-Rectangle	mouse_board;
-
-move_player()
-{
-	int	push;	/* keyboard push */
-	int	type0;
-	int	tmp;
-
-	if (pengo.other == DYING)	/* it has hit a sno_bee */
-		return;			/* this can overlap with die_pengo */
-	put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-	if (
-		((pengo.x & 31) == 0) &&
-		((pengo.y & 31) == 0)
-	)
-	{
-		push = FALSE;
-		new_mouse = mouse.xy;		/* get current location */
-		move_mouse = sub(old_mouse, new_mouse);
-		move_mouse.x /= 32;
-		move_mouse.y /= 32;
-		if (move_mouse.x | move_mouse.y)
-			cursset(new_mouse = home_mouse);
-		if (own() & KBD)
-		{
-			/* keyboard movement routine */
-
-			push = TRUE;
-			switch (kbdchar())
-			{
-			case 'H':
-				push = TRUE;
-			case 'h':
-				move_mouse.x = 8;
-				move_mouse.y = 0;
-				break;
-
-			case 'J':
-				push = TRUE;
-			case 'j':
-				move_mouse.x = 0;
-				move_mouse.y = -8;
-				break;
-
-			case 'K':
-				push = TRUE;
-			case 'k':
-				move_mouse.x = 0;
-				move_mouse.y = 8;
-				break;
-
-			case 'L':
-				push = TRUE;
-			case 'l':
-				move_mouse.x = -8;
-				move_mouse.y = 0;
-				break;
-
-			case ' ':
-				hit = TRUE;		/* stop pengo */
-				move_mouse.x = 0;
-				move_mouse.y = 0;
-				break;
-
-			default:
-				;
-				/* nothing, just throw the key away */
-			}
-		}
-		{
-			int	tmp;
-			int	tmp0;
-
-			tmp  = FALSE;
-			tmp0 = FALSE;
-			if (button1())
-			{
-				put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-				tmp = TRUE;
-			}
-			while (button1() || hit)
-			{
-				if (button1() && (!tmp))
-				{
-					put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-					tmp = TRUE;
-				}
-				tmp0 = TRUE;
-				wait(CPU);
-				hit = FALSE;
-			}
-			if (tmp)
-				put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-			if (tmp0)
-			{
-				pengo.movex = pengo.movey = 0;
-				move_mouse.x = move_mouse.y = 0;
-				old_mouse = mouse.xy;
-			}
-		}
-		if ((move_mouse.y | move_mouse.x) != 0)
-		{
-			if (!(ptinrect(mouse.xy, mouse_board)))
-				cursset(old_mouse = home_mouse);
-			else
-				old_mouse = new_mouse;
-			pengo.movex = pengo.movey = 0;
-			if (abs(move_mouse.y) == abs(move_mouse.x))
-				if (pengo.movex)
-					MMX;
-				else if (pengo.movey)
-					MMY;
-				else if (rand() & 1)	/* Random direction */
-					MMX;
-				else
-					MMY;
-			else if (abs(move_mouse.x) > abs(move_mouse.y))
-				MMX;
-			else
-				MMY;
-		}
-		if (
-			((pengo.movex) || (pengo.movey)) &&
-			screen_blank(
-				((pengo.x + 4 * pengo.movex) >> 5),
-				((pengo.y + 4 * pengo.movey) >> 5)
-			)
-		)
-		{
-			pengo.x += pengo.movex;
-			pengo.y += pengo.movey;
-		}
-		else if (!(button2() || push))	/* stop or hit? */
-		{
-			pengo.movex = pengo.movey = 0;
-		}
-		else
-			/* try to move or destroy block */
-
-			switch (type0 = screen(
-				(pengo.x + 4 * pengo.movex) >> 5,
-				(pengo.y + 4 * pengo.movey) >> 5)
-			)
-			{
-			case BLANK:
-			default:
-				/* should never occur */
-				break;
-			case WALL:
-			case BORDER:
-				if (move_water)
-					break;
-				move_water = pengo.movex ?
-					(pengo.movex < 0) ? LEFT : RIGHT :
-					(pengo.movey < 0) ? UP   : DOWN;
-				swill_water(NUM_WATER);
-				break;
-			case PENGO:
-			case HATCH:
-			case BREAK:
-				/* sorry, cannot move it .. */
-				break;
-			case SNO_BEE:
-				/* He'll get it shortly. */
-				break;
-			case DIAMOND:
-			case EGG:
-			case BLOCK:
-				/* ok, lets try to move it */
-				if (
-					screen(
-						(pengo.x + 8 * pengo.movex) >> 5,
-						(pengo.y + 8 * pengo.movey) >> 5
-					)
-					==
-					BLANK
-				)
-				{
-					int	x;
-
-					if (moving.exists)
-						break;
-					/* ok, we can move the block */
-					moving.other = type0 == BLOCK ? FBLOCK
-						: type0;
-					moving.exists = TRUE;
-					moving.movex = pengo.movex;
-					moving.movey = pengo.movey;
-					moving.x = pengo.x + 4 * pengo.movex;
-					moving.y = pengo.y + 4 * pengo.movey;
-					moving.count = 0;
-					if (type0 == DIAMOND)
-					{
-						for (x = 0; x < 3; x++)
-							if (
-							(diamond[x].x == moving.x)
-							&&
-							(diamond[x].y == moving.y)
-							)
-								break;
-					}
-					if (type0 == EGG)
-					{
-						for (x = 0; x < MAX_BEES; x++)
-							if (
-							(eggs[x].x == moving.x)
-							&&
-							(eggs[x].y == moving.y)
-							)
-							{
-								eggs[x].other =
-									MOVING;
-								break;
-							}
-					}
-					add_event(MOVE_BLOCK,
-						move_block, x);
-					screen(moving.x >> 5,
-						moving.y >> 5) = BLANK;
-				}
-				else switch(type0)
-				{
-					/* ok, lets break it, if we can! */
-				case DIAMOND:
-					/* no luck joe. */
-					break;
-				case EGG:
-					if (breaking.exists)
-						break;
-					/* delete from egg lists */
-					{
-						int	x;	/* tmp */
-
-						for (x = 0; x < MAX_BEES; x++)
-							if (
-								(eggs[x].exists ==
-									TRUE
-								) &&
-								(eggs[x].x ==
-									(pengo.x +
-									4 *
-									pengo.movex)
-								) &&
-								(eggs[x].y ==
-									(pengo.y +
-									4 *
-									pengo.movey)
-								)
-							)
-							{
-							    eggs[x].exists = FALSE;
-							    if (seggs)
-							    {
-								put_char(
-									eggs[x].x,
-									eggs[x].y,
-									EGG,
-									F_XOR, 0
-								);
-								put_char(
-									eggs[x].x,
-									eggs[x].y,
-									FBLOCK,
-									F_XOR, 0
-								);
-							    }
-							    disp_sno_bee(
-								--sno_bee_left);
-							}
-					}
-				{
-					int	new_b;
-
-					add_score(
-						new_b = (
-							(((pengo.x + 4 * pengo.movex >> 5) & 31) << 8) |
-							(((pengo.y + 4 * pengo.movey >> 5) & 31) << 3) |
-							(5)
-						)
-					);
-					add_event(SHOW_SCORE, add_score, new_b);
-				}
-				case BLOCK:
-					if (breaking.exists)
-						break;
-					breaking.other = type0;
-					breaking.exists = TRUE;
-					breaking.count = NUM_BREAK;
-					breaking.movex = pengo.movex;
-					breaking.movey = pengo.movey;
-					breaking.x = pengo.x + 4 * pengo.movex;
-					breaking.y = pengo.y + 4 * pengo.movey;
-					screen(
-						(pengo.x + 4 * pengo.movex) >> 5,
-						(pengo.y + 4 * pengo.movey) >> 5
-					) = BREAK;
-					add_event(DIE_BLOCK,
-						die_block, NULL);
-				}
-			}
-	}
-	else
-	{
-		pengo.x += pengo.movex;
-		pengo.y += pengo.movey;
-	}
-	for (tmp = 0; tmp < 4; tmp++)
-	{
-		if (
-			(sno_bee[tmp].exists) &&
-			PX(pengo, sno_bee[tmp])
-		)
-		{
-			if (sno_bee[tmp].other == CONFUSED)
-			{
-				int	new_b;
-				int	show;
-
-				put_char(sno_bee[tmp].x, sno_bee[tmp].y,
-					CONF, F_XOR, (sno_bee[tmp].count & 1) |
-					(tmp << 1));
-				sno_bee[tmp].exists = FALSE;
-				sno_bee[tmp].other = SQUASH;
-				score += 100;
-				add_score(
-					new_b = (
-						(((sno_bee[tmp].x >> 5)& 31) << 8) |
-						(((sno_bee[tmp].y >> 5)& 31) << 3) |
-						((tmp & 3) << 13) |
-						7
-					)
-				);
-				add_event(SHOW_SCORE, add_score, new_b);
-				show = FALSE;
-				disp_sno_bee(--sno_bee_left);
-				for (new_b = 0; new_b < 1; new_b++)
-				{
-					int	pos;
-
-					for (pos = 0; pos < MAX_BEES; pos++)
-					{
-						if (eggs[pos].exists == TRUE)
-							break;
-					}
-					if (pos < MAX_BEES)
-					{
-						int	a;
-
-						for (a = 0; a < 4; a++)
-						{
-							if
-							(
-								(sno_bee[a].exists
-								==
-								FALSE ) &&
-								(sno_bee[a].other
-								!=
-								HATCHING )
-							)
-							break;
-						}
-						if (a < 4)
-						{
-							eggs[pos].exists = FALSE;
-							sno_bee[a].other = HATCHING;
-							sno_bee[a].count=NUM_HATCH;
-							sno_bee[a].x = eggs[pos].x;
-							sno_bee[a].y = eggs[pos].y;
-							screen(
-								sno_bee[a].x >> 5,
-								sno_bee[a].y >> 5
-							) = HATCH;
-							if (seggs)
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								EGG,
-								F_XOR,
-								0
-							);
-							else
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								FBLOCK,
-								F_XOR,
-								0
-							);
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								HATCH,
-								F_XOR,
-								0
-							);
-							add_event(
-								EGG_HATCH,
-								egg_hatch,
-								a
-							);
-							show = TRUE;
-						}
-					}
-					else
-					{
-						/* no eggs left */
-						if (sno_bee_left <= 0)
-						{
-							/* all bees dead */
-							cancel_events();
-							return;
-						}
-						if (sno_bee_left == 1)
-						{
-							/* last one.. RUNNING */
-
-							add_event(RUN_DELAY,
-								run_bee, NULL);
-						}
-					}
-				}
-				if (show)
-					show_eggs();
-			}
-			else if (sno_bee[tmp].other == SNO_BEE)
-			{
-				pengo.other = DYING;
-				add_event(P_DYING, die_pengo, NULL);
-			}
-		}
-	}
-	put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-	add_event(MOVE_PENGO, move_player, NULL);
-}
//GO.SYSIN DD player.c
echo shapes.c 1>&2
sed 's/.//' >shapes.c <<'//GO.SYSIN DD shapes.c'
-/*
-	shapes of the moving items, pengo, sno_bees blocks, diamonds
-	etc...
-*/
-#include "pengo.h"
-
-short	char_blank[] = {
-#include "icons/blank"
-};
-
-short	flip_block[] = {
-#include "icons/fblock"
-};
-
-short	char_block[] = {
-#include "icons/block"
-};
-
-short	char_0diamond[] = {
-#include "icons/0diamond"
-};
-
-short	*char_1diamond = char_blank;
-
-short	char_null[] = {
-#include "icons/null"
-};
-
-short	char_egg[] = {
-#include "icons/egg"
-};
-
-short	sbee[] = {
-#include "icons/beede"
-};
-
-short	char_100[] = {
-#include "icons/100"
-};
-
-short	char_400[] = {
-#include "icons/400"
-};
-
-short	char_500[] = {
-#include "icons/500"
-};
-
-short	char_1600[] = {
-#include "icons/1600"
-};
-
-short	char_3200[] = {
-#include "icons/3200"
-};
-
-short	char_6400[] = {
-#include "icons/6400"
-};
-
-short	conf1[] = {
-#include "icons/conf1"
-};
-
-short	conf2[] = {
-#include "icons/conf2"
-};
-
-short	char_0bee[] = {
-#include "icons/bee0"
-};
-
-short	char_1bee[] = {
-#include "icons/bee1"
-};
-
-short	char_0pengo[] = {
-#include "icons/still"
-};
-
-short	char_1pengo[] = {
-#include "icons/pengo1"
-};
-
-short	char_2pengo[] = {
-#include "icons/pengo2"
-};
-
-short	char_3pengo[] = {
-#include "icons/pengo3"
-};
-
-short	char_4pengo[] = {
-#include "icons/pengo4"
-};
-
-short	char_5pengo[] = {
-#include "icons/pengo5"
-};
-
-short	char_6pengo[] = {
-#include "icons/pengo6"
-};
-
-short	char_7pengo[] = {
-#include "icons/pengo7"
-};
-
-short	char_8pengo[] = {
-#include "icons/pengo8"
-};
-
-short	*char_still = char_0pengo;
-
-short	*char_sorry = char_0pengo;
-
-short	*char_happy = char_0pengo;
-
-short	char_0dead[] = {
-#include "icons/dead0"
-};
-
-short	char_1dead[] = {
-#include "icons/dead1"
-};
-
-short	*pengo_moves[] = {
-	char_0pengo,
-	char_1pengo,
-	char_2pengo,
-	char_3pengo,
-	char_4pengo,
-	char_5pengo,
-	char_6pengo,
-	char_7pengo,
-	char_8pengo,
-};
-
-short	char_pback[] = {
-#include "icons/pback"
-};
-
-short	char_salute[] = {
-#include "icons/salute"
-};
-
-short	char_0wiggle[] = {
-#include "icons/wiggle0"
-};
-
-short	char_1wiggle[] = {
-#include "icons/wiggle1"
-};
-
-short	ch_sq_0down[] = {
-#include "icons/sq_0down"
-};
-
-short	ch_sq_0left[] = {
-#include "icons/sq_0left"
-};
-
-short	ch_sq_0right[] = {
-#include "icons/sq_0right"
-};
-
-short	ch_sq_0up[] = {
-#include "icons/sq_0up"
-};
-
-short	ch_sq_1down[] = {
-#include "icons/sq_1down"
-};
-
-short	ch_sq_1left[] = {
-#include "icons/sq_1left"
-};
-
-short	ch_sq_1right[] = {
-#include "icons/sq_1right"
-};
-
-short	ch_sq_1up[] = {
-#include "icons/sq_1up"
-};
-
-short	*squash_moves[] = {
-	ch_sq_0up,
-	ch_sq_0down,
-	ch_sq_0left,
-	ch_sq_0right,
-	ch_sq_1up,
-	ch_sq_1down,
-	ch_sq_1left,
-	ch_sq_1right,
-};
-
-short	char_0hula[] = {
-#include "icons/hula0"
-};
-
-short	char_1hula[] = {
-#include "icons/hula1"
-};
-
-short	char_2hula[] = {
-#include "icons/hula2"
-};
-
-short	char_3hula[] = {
-#include "icons/hula3"
-};
-
-short	char_4hula[] = {
-#include "icons/hula4"
-};
-
-short	*hula_moves[] = {
-	char_0hula,
-	char_1hula,
-	char_2hula,
-	char_3hula,
-	char_4hula,
-};
-
-short	char_lchair[] = {
-#include "icons/chairl"
-};
-
-short	char_rchair[] = {
-#include "icons/chairr"
-};
-
-short	char_0video[] = {
-#include "icons/video0"
-};
-
-short	char_0lplayer[] = {
-#include "icons/playerl0"
-};
-
-short	char_1lplayer[] = {
-#include "icons/playerl1"
-};
-
-short	char_0rplayer[] = {
-#include "icons/playerr0"
-};
-
-short	char_1rplayer[] = {
-#include "icons/playerr1"
-};
//GO.SYSIN DD shapes.c

From acsnet!basser!rex Thu Jun 26 20:44:56 1986
# To unbundle, sh this file
echo chars.c 1>&2
sed 's/.//' >chars.c <<'//GO.SYSIN DD chars.c'
-#include "pengo.h"
-
-short char_0_9[] = {
-/* 0 */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x30F0), sbits(0x31F0), sbits(0x33B0), sbits(0x3730),
-	 sbits(0x3E30), sbits(0x3C30), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* 1 */
-	 sbits(0x0300), sbits(0x0700), sbits(0x0F00), sbits(0x0F00),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0300), sbits(0x0300),
-	 sbits(0x1FE0), sbits(0x1FE0), sbits(0x0000), sbits(0x0000),
-/* 2 */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3070), sbits(0x3030),
-	 sbits(0x0030), sbits(0x0070), sbits(0x00E0), sbits(0x01C0),
-	 sbits(0x0380), sbits(0x0700), sbits(0x0E00), sbits(0x1C00),
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x0000), sbits(0x0000),
-/* 3 */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x0030), sbits(0x0030), sbits(0x0FE0), sbits(0x0FE0),
-	 sbits(0x0030), sbits(0x0030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* 4 */
-	 sbits(0x0380), sbits(0x0780), sbits(0x0780), sbits(0x0D80),
-	 sbits(0x0D80), sbits(0x1980), sbits(0x1980), sbits(0x3180),
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x0180), sbits(0x0180),
-	 sbits(0x0180), sbits(0x0180), sbits(0x0000), sbits(0x0000),
-/* 5 */
-	 sbits(0x3FE0), sbits(0x3FE0), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x1FC0), sbits(0x0FE0),
-	 sbits(0x0030), sbits(0x0030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* 6 */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3FC0), sbits(0x3FE0),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* 7 */
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x0030), sbits(0x0070),
-	 sbits(0x00E0), sbits(0x00C0), sbits(0x01C0), sbits(0x0380),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0000), sbits(0x0000),
-/* 8 */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x1FE0), sbits(0x1FE0),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* 9 */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x1FF0), sbits(0x0FF0),
-	 sbits(0x0030), sbits(0x0030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-};
-short char_A_Z[] = {
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3FF0), sbits(0x3FF0),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x0000), sbits(0x0000),
-/* B */
-	 sbits(0x3FC0), sbits(0x3FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3FF0), sbits(0x3FF0),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3FE0), sbits(0x3FC0), sbits(0x0000), sbits(0x0000),
-/* C */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* D */
-	 sbits(0x3FC0), sbits(0x3FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3FE0), sbits(0x3FC0), sbits(0x0000), sbits(0x0000),
-/* E */
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3FC0), sbits(0x3FC0),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x0000), sbits(0x0000),
-/* F */
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3FC0), sbits(0x3FC0),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x0000), sbits(0x0000),
-/* G */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x30F0), sbits(0x30F0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* H */
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3FF0), sbits(0x3FF0),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x0000), sbits(0x0000),
-/* I */
-	 sbits(0x1FE0), sbits(0x1FE0), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0300), sbits(0x0300),
-	 sbits(0x1FE0), sbits(0x1FE0), sbits(0x0000), sbits(0x0000),
-/* J */
-	 sbits(0x0FF0), sbits(0x0FF0), sbits(0x0180), sbits(0x0180),
-	 sbits(0x0180), sbits(0x0180), sbits(0x0180), sbits(0x0180),
-	 sbits(0x0180), sbits(0x0180), sbits(0x1980), sbits(0x1980),
-	 sbits(0x1F80), sbits(0x0F00), sbits(0x0000), sbits(0x0000),
-/* K */
-	 sbits(0x3030), sbits(0x3070), sbits(0x30E0), sbits(0x31C0),
-	 sbits(0x3380), sbits(0x3700), sbits(0x3E00), sbits(0x3C00),
-	 sbits(0x3E00), sbits(0x3700), sbits(0x3380), sbits(0x31C0),
-	 sbits(0x30E0), sbits(0x3060), sbits(0x0000), sbits(0x0000),
-/* L */
-	 sbits(0x3000), sbits(0x3000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3FE0), sbits(0x3FE0), sbits(0x0000), sbits(0x0000),
-/* M */
-	 sbits(0x3030), sbits(0x3030), sbits(0x3CF0), sbits(0x3CF0),
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x3330), sbits(0x3330),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x0000), sbits(0x0000),
-/* N */
-	 sbits(0x3830), sbits(0x3830), sbits(0x3C30), sbits(0x3C30),
-	 sbits(0x3630), sbits(0x3630), sbits(0x3330), sbits(0x3330),
-	 sbits(0x31B0), sbits(0x31B0), sbits(0x30F0), sbits(0x30F0),
-	 sbits(0x3070), sbits(0x3070), sbits(0x0000), sbits(0x0000),
-/* O */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* P */
-	 sbits(0x3FC0), sbits(0x3FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3FE0), sbits(0x3FC0),
-	 sbits(0x3000), sbits(0x3000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x0000), sbits(0x0000),
-/* Q */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x30F0), sbits(0x30F0),
-	 sbits(0x1FF0), sbits(0x0FF0), sbits(0x0000), sbits(0x0000),
-/* R */
-	 sbits(0x3FC0), sbits(0x3FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3FE0), sbits(0x3FC0),
-	 sbits(0x3700), sbits(0x3380), sbits(0x31C0), sbits(0x30E0),
-	 sbits(0x3070), sbits(0x3030), sbits(0x0000), sbits(0x0000),
-/* S */
-	 sbits(0x0FC0), sbits(0x1FE0), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3000), sbits(0x3000), sbits(0x1FC0), sbits(0x0FE0),
-	 sbits(0x0030), sbits(0x0030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* T */
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0000), sbits(0x0000),
-/* U */
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x1FE0), sbits(0x0FC0), sbits(0x0000), sbits(0x0000),
-/* V */
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3870), sbits(0x1CE0), sbits(0x0FC0),
-	 sbits(0x0780), sbits(0x0300), sbits(0x0000), sbits(0x0000),
-/* W */
-	 sbits(0x3030), sbits(0x3030), sbits(0x3030), sbits(0x3030),
-	 sbits(0x3030), sbits(0x3030), sbits(0x3330), sbits(0x3330),
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x3CF0), sbits(0x3CF0),
-	 sbits(0x3030), sbits(0x3030), sbits(0x0000), sbits(0x0000),
-/* X */
-	 sbits(0x3030), sbits(0x3030), sbits(0x3870), sbits(0x1CF0),
-	 sbits(0x0CC0), sbits(0x0FC0), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0FC0), sbits(0x0CC0), sbits(0x1CE0), sbits(0x3870),
-	 sbits(0x3030), sbits(0x3030), sbits(0x0000), sbits(0x0000),
-/* Y */
-	 sbits(0x3030), sbits(0x3030), sbits(0x3870), sbits(0x1CF0),
-	 sbits(0x0CC0), sbits(0x0FC0), sbits(0x0780), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0300), sbits(0x0300),
-	 sbits(0x0300), sbits(0x0300), sbits(0x0000), sbits(0x0000),
-/* Z */
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x0030), sbits(0x0070),
-	 sbits(0x00E0), sbits(0x01C0), sbits(0x0380), sbits(0x0700),
-	 sbits(0x0E00), sbits(0x1C00), sbits(0x3800), sbits(0x3000),
-	 sbits(0x3FF0), sbits(0x3FF0), sbits(0x0000), sbits(0x0000),
-};
-short char_colon[] = {
-	 sbits(0x0000), sbits(0x0000), sbits(0xF000), sbits(0xF000),
-	 sbits(0xF000), sbits(0xF000), sbits(0x0000), sbits(0x0000),
-	 sbits(0x0000), sbits(0x0000), sbits(0xF000), sbits(0xF000),
-	 sbits(0xF000), sbits(0xF000), sbits(0x0000), sbits(0x0000),
-};
-short char_dot[] = {
-	 sbits(0x0000), sbits(0x0000), sbits(0x0000), sbits(0x0000),
-	 sbits(0x0000), sbits(0x0000), sbits(0x0000), sbits(0x0000),
-	 sbits(0x0000), sbits(0x0000), sbits(0x3000), sbits(0x3000),
-	 sbits(0x3000), sbits(0x3000), sbits(0x0000), sbits(0x0000),
-};
-short char_space[] = {
-	 sbits(0x0000), sbits(0x0000), sbits(0x0000), sbits(0x0000),
-	 sbits(0x0000), sbits(0x0000), sbits(0x0000), sbits(0x0000),
-	 sbits(0x0000), sbits(0x0000), sbits(0x0000), sbits(0x0000),
-	 sbits(0x0000), sbits(0x0000), sbits(0x0000), sbits(0x0000),
-};
-
-short char_question[] = {
-sbits(0x0FC0),
-sbits(0x1FE0),
-sbits(0x3030),
-sbits(0x3030),
-sbits(0x31E0),
-sbits(0x03C0),
-sbits(0x0300),
-sbits(0x0300),
-sbits(0x0300),
-sbits(0x0300),
-sbits(0x0300),
-sbits(0x0000),
-sbits(0x0300),
-sbits(0x0300),
-sbits(0x0000),
-sbits(0x0000),
-};
-
-short char_rbrkt[] = {
-sbits(0x0300),
-sbits(0x0380),
-sbits(0x0180),
-sbits(0x00C0),
-sbits(0x00C0),
-sbits(0x0060),
-sbits(0x0060),
-sbits(0x0060),
-sbits(0x0060),
-sbits(0x0060),
-sbits(0x0060),
-sbits(0x00C0),
-sbits(0x00C0),
-sbits(0x0180),
-sbits(0x0380),
-sbits(0x0300),
-};
-
-short char_lbrkt[] = {
-sbits(0x00C0),
-sbits(0x01C0),
-sbits(0x0180),
-sbits(0x0300),
-sbits(0x0300),
-sbits(0x0600),
-sbits(0x0600),
-sbits(0x0600),
-sbits(0x0600),
-sbits(0x0600),
-sbits(0x0600),
-sbits(0x0300),
-sbits(0x0300),
-sbits(0x0180),
-sbits(0x01C0),
-sbits(0x00C0),
-};
-
-short char_uscore[] = {
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x0000),
-sbits(0x3FF0),
-sbits(0x3FF0),
-sbits(0x0000),
-};
-
-short char_slash[] = {
-sbits(0x0000),
-sbits(0x0030),
-sbits(0x0030),
-sbits(0x0070),
-sbits(0x00E0),
-sbits(0x00C0),
-sbits(0x01C0),
-sbits(0x0380),
-sbits(0x0700),
-sbits(0x0E00),
-sbits(0x0C00),
-sbits(0x1C00),
-sbits(0x3800),
-sbits(0x3000),
-sbits(0x3000),
-sbits(0x0000),
-};
//GO.SYSIN DD chars.c
echo events.c 1>&2
sed 's/.//' >events.c <<'//GO.SYSIN DD events.c'
-/*
-	This file contains the code to handle the actual events that occur
-	such as pengo's dying, the score system, the bee system.
-
-*/
-#include "pengo.h"
-
-int	bee_score[] = { 0, 400, 1600, 3200, 6400 };
-
-die_pengo()
-{
-	int	x;
-
-	pengo.exists = FALSE;	/* tis now dead */
-	put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-	disp_pengo(--pengo_left);
-	for (x = 0; x < PENGO_THROES; x++)
-	{
-		put_char(pengo.x, pengo.y, PENGO_D, F_XOR, x & 1);
-		sleep((int)PENGO_D_TIME);
-		dead_pengo(pengo_left, x & 1);
-		put_char(pengo.x, pengo.y, PENGO_D, F_XOR, x & 1);
-	}
-	disp_pengo(pengo_left);
-	cancel_events();
-}
-
-add_man()
-{
-	disp_pengo(++pengo_left);
-}
-
-disp_sno_bee(num)
-int	num;
-{
-	int	x;
-
-	bit32.base = (Word *)sbee;
-	rectf(&display, sno_bm, F_CLR);
-	for (x = 0; (x < num) && (x < sbd); x++)
-		bitblt(&bit32, R3, &display,
-			Pt(sno_bm.origin.x + (x + 1) * CHAR_WIDTH, sno_bm.origin.y),
-			F_STORE);
-}
-
-dead_pengo(num, other)
-int	num;
-int	other;
-{
-	int	x;
-
-	bit32.base = (Word *)(other ? char_1dead : char_0dead);
-	rectf(&display, pengom, F_CLR);
-	for (x = 0; (x < num) && (x < npd); x++)
-		bitblt(&bit32, R3, &display,
-			Pt(pengom.origin.x + x * CHAR_WIDTH, pengom.origin.y),
-			F_STORE);
-}
-
-disp_pengo(num)
-int	num;
-{
-	int	x;
-
-	bit32.base = (Word *)char_still;
-	rectf(&display, pengom, F_CLR);
-	for (x = 0; (x < num) && (x < npd); x++)
-		bitblt(&bit32, R3, &display,
-			Pt(pengom.origin.x + x * CHAR_WIDTH, pengom.origin.y),
-			F_STORE);
-}
-
-add_score(num)
-int	num;
-{
-
-	/*
-		add_score's argument is composed of the following sixteen bits:
-
-		Bits -	Function
-		0 - 2	value to be added
-		3 - 7	y posn of the block (in blocks)
-		8 -12	x posn (in blocks)
-		13-14	movement in case of score '100'
-		15	unused
-
-	*/
-
-	int	x;
-	int	y;
-
-	x = ((num >> 8) & 31) << 5;
-	y = ((num >> 3) & 31) << 5;
-	switch(num & 7)
-	{
-	case 1:
-		bit32.base = (Word *)char_400;
-		break;
-
-	case 2:
-		bit32.base = (Word *)char_1600;
-		break;
-
-	case 3:
-		bit32.base = (Word *)char_3200;
-		break;
-
-	case 4:
-		bit32.base = (Word *)char_6400;
-		break;
-
-	case 5:
-		bit32.base = (Word *)char_500;
-		break;
-
-	case 7:
-		bit32.base = (Word *)char_100;
-		x += (num >> 14) & 1;
-		y += (num >> 13) & 1;
-		break;
-
-	default:
-		bit32.base = (Word *)char_null;
-		break;
-	}
-	bitblt(&bit32, R3, &display, add(board.origin, Pt(x, y)), F_XOR);
-}
-
-move_block(num)
-int	num;
-{
-	int	tmp;
-	int	x4 = ((moving.x + 4 * moving.movex) >> 5);
-	int	y4 = ((moving.y + 4 * moving.movey) >> 5);
-
-	if (((moving.x & 31) == 0) && ((moving.y & 31) == 0))
-	{
-		if (screen(x4, y4) == BLANK)
-		{
-			put_squash();
-			put_char(moving.x, moving.y, moving.other, F_XOR, NULL);
-			moving.x += moving.movex;
-			moving.y += moving.movey;
-			put_squash();
-			put_char(moving.x, moving.y, moving.other, F_XOR, NULL);
-		}
-		else
-		{
-			int	new_b;
-			int	show;
-
-			show = FALSE;
-			switch(screen(x4, y4))
-			{
-			case BLOCK:
-			case WALL:
-			case BORDER:
-			case PENGO:
-			case HATCH:
-			case BREAK:
-			case EGG:
-			case DIAMOND:
-			default:
-				/* sorry, end of the line */
-				put_squash();	/* turn off */
-				moving.movex = moving.movey = 0;
-				screen(
-					moving.x >> 5,
-					moving.y >> 5
-				) =
-				moving.other == FBLOCK ? BLOCK : moving.other;
-				if (moving.other == EGG)
-				{
-					eggs[num].x = moving.x;
-					eggs[num].y = moving.y;
-					eggs[num].other = ALIVE;
-				}
-				score += bee_score[moving.count];
-				add_score(
-					new_b = (
-						(((moving.x >> 5) & 31) << 8) |
-						(((moving.y >> 5) & 31) << 3) |
-						(moving.count & 7)
-					)
-				);
-				add_event(SHOW_SCORE, add_score, new_b);
-				for (new_b = 0; new_b < moving.count; new_b++)
-				{
-					int	pos;
-
-					for (pos = 0; pos < MAX_BEES; pos++)
-					{
-						if (eggs[pos].exists == TRUE)
-							break;
-					}
-					if (pos < MAX_BEES)
-					{
-						int	a;
-
-						for (a = 0; a < 4; a++)
-						{
-							if
-							(
-								(sno_bee[a].exists
-								==
-								FALSE ) &&
-								(sno_bee[a].other
-								!=
-								HATCHING )
-							)
-								break;
-						}
-						if (a < 4)
-						{
-							eggs[pos].exists = FALSE;
-							sno_bee[a].other = HATCHING;
-							sno_bee[a].count=NUM_HATCH;
-							sno_bee[a].x = eggs[pos].x;
-							sno_bee[a].y = eggs[pos].y;
-							screen(
-								sno_bee[a].x >> 5,
-								sno_bee[a].y >> 5
-							) = HATCH;
-							if (seggs)
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								EGG,
-								F_XOR,
-								NULL
-							);
-							else
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								FBLOCK,
-								F_XOR,
-								NULL
-							);
-							put_char(
-								sno_bee[a].x,
-								sno_bee[a].y,
-								HATCH,
-								F_XOR,
-								NULL
-							);
-							add_event(
-								EGG_HATCH,
-								egg_hatch,
-								a
-							);
-							show = TRUE;
-						}
-					}
-					else
-					{
-						/* no eggs left */
-						if (sno_bee_left == 0)
-						{
-							/* all bees dead */
-							cancel_events();
-						}
-						if (sno_bee_left == 1)
-						{
-							/* last one.. RUNNING */
-
-							add_event(RUN_DELAY,
-								run_bee, NULL);
-						}
-					}
-				}
-				moving.count = 0;
-				moving.exists = FALSE;
-				if (show)
-					show_eggs();
-				if (moving.other == DIAMOND)
-				{
-					diamond[num].x = moving.x;
-					diamond[num].y = moving.y;
-					if (sdiamond == FALSE)
-				{
-					if((
-						diamond[0].x == diamond[1].x &&
-						diamond[1].x == diamond[2].x &&
-						inline (
-							diamond[0].y,
-							diamond[1].y,
-							diamond[2].y
-						)
-					) ||
-					(
-						diamond[0].y == diamond[1].y &&
-						diamond[1].y == diamond[2].y &&
-						inline (
-							diamond[0].x,
-							diamond[1].x,
-							diamond[2].x
-						)
-					))
-				{
-					int	x;
-					int	dir;
-
-					if (
-						inline (
-							diamond[0].x,
-							diamond[1].x,
-							diamond[2].x
-						)
-					)
-						dir = HORIZ;
-					else
-						dir = VERT;
-					old_mouse = mouse.xy;
-					sdiamond = TRUE;
-					for (x = 0; x < NUM_FLASH; x++)
-					{
-						put_char(diamond[0].x,
-							diamond[0].y,
-							DIAMOND,
-							F_XOR,
-							1);
-						put_char(diamond[1].x,
-							diamond[1].y,
-							DIAMOND,
-							F_XOR,
-							1);
-						put_char(diamond[2].x,
-							diamond[2].y,
-							DIAMOND,
-							F_XOR,
-							1);
-						sleep((int)FLASH_DIAMOND);
-					}
-					bitblt(&display,
-						counter,
-						&bonus,
-						Pt(0, 0),
-						F_STORE);
-					rectf(&display, counter, F_CLR);
-					addstr("BONUS", counter.origin, F_STORE);
-					addstr("Pts.", add(counter.origin,
-						Pt(48, 32)), F_STORE);
-					if ((dir == VERT) ?
-						((diamond[0].x == 0) ||
-						(diamond[0].x == (blockx - 1) << 5))
-						:
-						((diamond[0].y == 0) ||
-						(diamond[0].y == (blocky - 1) << 5))
-					)
-					{
-						addstr(" 5000", add(counter.origin,
-							Pt(16, 16)), F_STORE);
-						x = 49;
-					}
-					else
-					{
-						addstr("10000", add(counter.origin,
-							Pt(16, 16)), F_STORE);
-						x = 99;
-					}
-					sleep(40);
-					addchar(' ', add(counter.origin,
-						Pt(16, 16)),
-						F_STORE);
-					for (; x >= 0; x--)
-					{
-						addchar((x/10)? '0' + (x/10) : ' ',
-						 add(counter.origin, Pt(32, 16)),
-						 F_STORE);
-						addchar(x % 10 + '0',
-						 add(counter.origin, Pt(48, 16)),
-						 F_STORE);
-						score += 100;
-						put_score(score);
-						sleep(2);
-					}
-					addstr("  ",add(counter.origin,
-						Pt(48,16)), F_STORE);
-					sleep(50);
-					bitblt(&bonus,
-						bonus.rect,
-						&display,
-						counter.origin,
-						F_STORE);
-					for (x = 0; x < 4; x++)
-					{
-					    if (sno_bee[x].exists == TRUE)
-					    {
-						switch(sno_bee[x].other)
-						{
-						case SNO_BEE:
-							sno_bee[x].other = CONFUSED;
-							put_char(sno_bee[x].x,
-								sno_bee[x].y,
-								SNO_BEE, F_XOR, x);
-							put_char(sno_bee[x].x,
-								sno_bee[x].y,
-								CONF, F_XOR,
-								(NUM_CONFUSED & 1) |
-								(x << 1));
-							sno_bee[x].count =
-								NUM_CONFUSED;
-							add_event(TIME_CONFUSED,
-								confused_bee, x);
-							break;
-
-						case CONFUSED:
-							sno_bee[x].other = SNO_BEE;
-							put_char(sno_bee[x].x,
-								sno_bee[x].y,
-								CONF, F_XOR,
-								(NUM_CONFUSED & 1) |
-								(x << 1));
-							put_char(sno_bee[x].x,
-								sno_bee[x].y,
-								SNO_BEE, F_XOR, x);
-							if (bee_run)
-								add_event(MOVE_BEE0,
-									run_sno_bee,
-									x);
-							else
-								add_event(MOVE_BEE0,
-								       move_sno_bee,
-									x);
-							break;
-
-						default:
-							break;
-						}
-					    }
-					}
-				}
-				else
-					add_event(FLASH_DIAMOND,
-						flash_diamond, NUM_FLASH);
-				}
-				}
-				break;
-			case BLANK:
-				/* means a sno_bee is there, I'll get it shortly */
-				break;
-			case SNO_BEE:
-				/* shouldn't happen but what the heck */
-				break;
-			}
-		}
-	}
-	else
-	{
-		put_char(moving.x, moving.y, moving.other, F_XOR, 0);
-		put_squash();
-		moving.x += moving.movex;
-		moving.y += moving.movey;
-		put_char(moving.x, moving.y, moving.other, F_XOR, 0);
-		put_squash();
-	}
-	for (tmp = 0; tmp < 4; tmp++)
-		if (
-			moving.exists &&
-			(sno_bee[tmp].exists) &&
-			RX(moving, sno_bee[tmp])
-		)
-		{
-			if (sno_bee[tmp].other != CONFUSED)
-				put_char(sno_bee[tmp].x, sno_bee[tmp].y,
-					SNO_BEE, F_XOR, tmp);
-			else
-				put_char(sno_bee[tmp].x, sno_bee[tmp].y,
-					CONF, F_XOR,
-					(sno_bee[tmp].count & 1) | (tmp << 1));
-			sno_bee[tmp].exists = FALSE;	/* it has gone */
-			sno_bee[tmp].other = SQUASH;
-			disp_sno_bee(--sno_bee_left);
-			if (!moving.count++)
-				put_squash();	/* only on first sno_bee */
-		}
-	if (moving.exists == TRUE)
-		add_event(MOVE_BLOCK, move_block, num);
-}
-
-put_squash()
-{
-	/* squashed sno_bee on moving block */
-	int	tmp;
-
-	if (!moving.count)
-		return;
-	if (moving.movex)
-		if (moving.movex < 0)
-			tmp = 2;
-		else
-			tmp = 3;
-	else
-		if (moving.movey < 0)
-			tmp = 0;
-		else
-			tmp = 1;
-	if ((moving.x & 16) || (moving.y & 16))
-		tmp += 4;
-	bit32.base = (Word *)squash_moves[tmp];
-	bitblt(&bit32, R3, &display,add(board.origin,Pt(moving.x,moving.y)),F_XOR);
-}	
-
-die_block()
-{
-	put_char(breaking.x, breaking.y, FBLOCK, F_XOR, NULL);
-	if (--breaking.count)
-	{
-		add_event(DIE_BLOCK, die_block, NULL);
-	}
-	else
-	{
-		breaking.exists = FALSE;
-		screen(breaking.x >> 5, breaking.y >> 5) = BLANK;
-		if (breaking.other == EGG)
-			score += 500;	/* egg score */
-		else
-			score += 30;	/* for breaking one */
-	}
-}
-
-bee_break(x)
-int	x;
-{
-	put_char(bee_block[x].x, bee_block[x].y, FBLOCK, F_XOR, NULL);
-	if (--bee_block[x].count)
-	{
-		add_event(DIE_BLOCK, bee_break, x);
-	}
-	else
-	{
-		bee_block[x].exists = FALSE;
-		screen(bee_block[x].x >> 5, bee_block[x].y >> 5) = BLANK;
-	}
-}
-
-addstr(str, ptr, fmt)
-char	*str;
-Point	ptr;
-int	fmt;
-{
-	while (*str)
-	{
-		addchar(*str++, ptr, fmt);
-		ptr.x += 16;
-	}
-}
-
-inline(a, b, c)
-int	a;
-int	b;
-int	c;
-{
-	int	x;	/* lowest */
-	int	y;
-	int	z;	/* highest */
-
-	if (a < b)
-		if (a < c)
-			if (c < b)
-			{
-				x = a;
-				y = c;
-				z = b;
-			}
-			else
-			{
-				x = a;
-				y = b;
-				z = c;
-			}
-		else
-		{
-			x = c;
-			y = a;
-			z = b;
-		}
-	else
-		if (a < c)
-		{
-			x = b;
-			y = a;
-			z = c;
-		}
-		else
-			if (c < b)
-			{
-				x = c;
-				y = b;
-				z = a;
-			}
-			else
-			{
-				x = b;
-				y = c;
-				z = a;
-			}
-	return (((x + 32) == y) && ((y + 32) == z));
-}
-
-egg_hatch(num)
-int	num;
-{
-	if (--sno_bee[num].count)
-	{
-		put_char(sno_bee[num].x, sno_bee[num].y, HATCH, F_XOR, 1);
-		add_event(EGG_HATCH, egg_hatch, num);
-	}
-	else
-	{
-		sno_bee[num].exists = TRUE;
-		sno_bee[num].other = SNO_BEE;
-		screen(sno_bee[num].x >> 5, sno_bee[num].y >> 5) = BLANK;
-		put_char(sno_bee[num].x, sno_bee[num].y, SNO_BEE, F_XOR, num);
-		add_event(MOVE_BEE0, move_sno_bee, num);
-	}
-}
-
-clear_eggs()
-{
-	int	x;
-
-	if (--egg_count_flag > 0)
-		return;
-	for (x = 0; x < MAX_BEES; x++)
-	{
-		if (eggs[x].exists)
-			switch(eggs[x].other)
-			{
-			case ALIVE:
-				put_char(eggs[x].x, eggs[x].y, EGG, F_XOR, 0);
-				put_char(eggs[x].x, eggs[x].y, FBLOCK, F_XOR, 0);
-				break;
-
-			case MOVING:
-				put_char(moving.x, moving.y, EGG, F_XOR, 0);
-				put_char(moving.x, moving.y, FBLOCK, F_XOR, 0);
-				break;
-
-			default:
-				/* no action */
-				break;
-			}
-	}
-	egg_count_flag = 0;
-	seggs = FALSE;
-}
-
-show_eggs()
-{
-	int	x;
-
-	if (egg_count_flag++ <= 0)
-	{
-		seggs = TRUE;
-		for (x = 0; x < MAX_BEES; x++)
-		{
-			if (eggs[x].exists)
-				switch(eggs[x].other)
-				{
-				case ALIVE:
-					put_char(eggs[x].x, eggs[x].y, FBLOCK,
-						F_XOR, 0);
-					put_char(eggs[x].x, eggs[x].y, EGG,
-						F_XOR, 0);
-					break;
-
-				case MOVING:
-					put_char(moving.x, moving.y, FBLOCK,
-						F_XOR, 0);
-					put_char(moving.x, moving.y, EGG,
-						F_XOR, 0);
-					break;
-
-				default:
-				/* no action */
-					break;
-				}
-		}
-	}
-	add_event(SHOW_EGGS, clear_eggs, NULL);
-}
-
-run_bee()
-{
-	bee_run = TRUE;
-}
-
-flash_diamond(num)
-int	num;
-{
-	if (num--)
-	{
-		put_char(diamond[0].x, diamond[0].y, DIAMOND, F_XOR, 1);
-		put_char(diamond[1].x, diamond[1].y, DIAMOND, F_XOR, 1);
-		put_char(diamond[2].x, diamond[2].y, DIAMOND, F_XOR, 1);
-		add_event(FLASH_DIAMOND, flash_diamond, num);
-	}
-}
//GO.SYSIN DD events.c
echo header.c 1>&2
sed 's/.//' >header.c <<'//GO.SYSIN DD header.c'
-
-#include "pengo.h"
-
-short	char_header[] = {
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0190, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03f7, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07ff, 0xf7c0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x57ff, 0xffc1, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xfff3, 0xf000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x001f, 0xffff, 0xffff, 0xff40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x007f, 0xffff, 0xffff, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x007f, 0xffff, 0xffff, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffff, 0xffff, 0xfffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x01ff, 0xffff, 0xffff, 0xfffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x01ff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x07ff, 0xffff, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x1fff, 0xffff, 0xffff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x1fff, 0xffff, 0xffff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x1fff, 0xffff, 0xffff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x3fff, 0xffff, 0xffff, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0xffff, 0xffff, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0003, 0xffff, 0xffff, 0xffff, 0xffff, 0xf800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0003, 0xffff, 0xffff, 0xffff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0007, 0xffff, 0xffff, 0xffff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0007, 0xffff, 0xffff, 0xcfff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x000e, 0xbfff, 0xffff, 0xcfff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x000a, 0x0fff, 0xffff, 0xdfff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0fff, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0004, 0x07ff, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0050, 0x0fff, 0xffff, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0201, 0x0bff, 0xffff, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0820, 0x07ff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0080, 0x03ff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x8000, 0x03ff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0004, 0x0000, 0x01ff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0010, 0x0440, 0x01ff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0041, 0x1044, 0x01ff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0157, 0x7ddd, 0xd1ff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x17ff, 0xffff, 0xfdff, 0xffff, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0003, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0003, 0xffff, 0xfebf, 0xffff, 0xffff, 0xffff, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0003, 0xfffe, 0xa4a2, 0xbfff, 0xffff, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0003, 0xed52, 0x9bea, 0x4bff, 0xffff, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0003, 0x9d57, 0xdaad, 0x44ff, 0xffff, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0003, 0xf77d, 0x6000, 0xbdff, 0xffff, 0xffff, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0xfff4, 0x0000, 0x12ff, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0xffd1, 0x9464, 0x00ff, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x3f76, 0xa904, 0x447f, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0fae, 0xea11, 0x007f, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x00bf, 0x5555, 0x59ff, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x000b, 0xb565, 0x557f, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0003, 0xbaa8, 0x447f, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x7b95, 0x19ff, 0xffff, 0xffff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x2e75, 0xd5ff, 0xffff, 0xffff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0fef, 0x76ff, 0xffff, 0xffff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0bef, 0x6bff, 0xffff, 0xffff, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x02bd, 0xddff, 0xffff, 0xfffa, 0x8fff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x003f, 0xfdff, 0xffff, 0xfea0, 0x1fff, 0xfe00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x003f, 0xffff, 0xffff, 0xfe00, 0x0bff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x001f, 0xffff, 0xffff, 0xf800, 0x02ff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x001f, 0xffff, 0xfffe, 0xe000, 0x00ff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x000f, 0xffff, 0xfff8, 0x0000, 0x003f, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x000f, 0xffff, 0xffe0, 0x0000, 0x003f, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0007, 0xffff, 0xff00, 0x0000, 0x003f, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0003, 0xffff, 0xfe00, 0x0000, 0x007f, 0xffc0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0804, 0x0000, 0xffff, 0xf800, 0x0000, 0x007f, 0xffc0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x8020, 0x5000, 0xafff, 0xe000, 0x0000, 0x007f, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x1289, 0x0000, 0x0fff, 0x8000, 0x0000, 0x00ff, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0022, 0x4208, 0x0a80, 0x53fe, 0x0000, 0x0000, 0x01ff, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0008, 0x2922, 0x4020, 0x42fe, 0x0000, 0x0000, 0x03ff, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0009, 0x0149, 0x2900, 0x2028, 0x0000, 0x0000, 0x07ff, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x02a1, 0x5424, 0x8240, 0x2100, 0x0000, 0x0000, 0x07ff, 0xfffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0804, 0x2a92, 0x2854, 0x2000, 0x0000, 0x0000, 0x0fff, 0xfffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x2152, 0x8252, 0xa500, 0x0000, 0x0000, 0x0000, 0x1fff, 0xfffc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x8449, 0x554a, 0x9295, 0x1100, 0x0000, 0x0000, 0x1fff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x1525, 0x4929, 0x4a44, 0x4800, 0x0000, 0x0000, 0x1fff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0005, 0x1094, 0x2aa5, 0x2920, 0x0880, 0x0000, 0x0000, 0x7fff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0001, 0x4a89, 0xa494, 0xaa95, 0x0140, 0x0000, 0x0000, 0x7fff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0028, 0x092a, 0x5552, 0xa450, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0xa555, 0x4a2a, 0x5548, 0x4000, 0x0000, 0x0003, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0095, 0x12a5, 0x28a9, 0x4aa4, 0xa000, 0x0000, 0x0007, 0xffff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x4894, 0xa544, 0xa914, 0x2000, 0x0000, 0x000f, 0xffff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x012a, 0xa552, 0x9552, 0x9550, 0x2000, 0x0000, 0x000f, 0xffff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0008, 0x152a, 0x52aa, 0x52a0, 0x0000, 0x0000, 0x000f, 0xffff, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0485, 0x50a5, 0x4a29, 0x4a50, 0x0000, 0x0000, 0x000f, 0xffff, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0024, 0xa694, 0xa955, 0x2950, 0x0000, 0x0000, 0x000f, 0xffff, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x1221, 0x2952, 0x9494, 0xa520, 0x0000, 0x0000, 0x0007, 0xffff, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0095, 0x494a, 0x52aa, 0x94a0, 0x0000, 0x0000, 0x0007, 0xfbff, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0894, 0x56a9, 0x4a49, 0x5280, 0x0000, 0x0000, 0x0002, 0x28bf, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x4201, 0x4095, 0x2955, 0x2a50, 0x0000, 0x0000, 0x0000, 0x003f, 0xffff, 0xf800, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0055, 0x2b54, 0xa524, 0xa540, 0x0000, 0x0000, 0x0000, 0x003f, 0xffff, 0xf800, 0x0000, 0x0000, 0x0000, 0x0000,
-0x9554, 0x9452, 0x94aa, 0x94a0, 0x0000, 0x0000, 0x0000, 0x000f, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0002, 0x528a, 0x5295, 0x52a1, 0x0000, 0x0000, 0x0000, 0x0008, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0aa5, 0x4aa9, 0x4a94, 0x4a41, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000,
-0x4015, 0x2955, 0x2a52, 0xaa44, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000,
-0x054a, 0x9522, 0x914a, 0x9102, 0x8000, 0x0000, 0x0000, 0x0001, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000,
-0x28a2, 0x54aa, 0x5529, 0x1510, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xff00, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0011, 0x4aa9, 0x4aa5, 0x5424, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xff80, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0549, 0x2115, 0x2254, 0x4a55, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0xffc0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x20a4, 0x9552, 0xa555, 0x2059, 0x0000, 0x0000, 0x0000, 0x0000, 0x3fff, 0xffc0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0092, 0x4a2a, 0x54a5, 0x54b4, 0x0000, 0x0000, 0x0000, 0x0000, 0x3fff, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0a09, 0x28a5, 0x4a91, 0x50b4, 0x0000, 0x0000, 0x0000, 0x0000, 0x3fff, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0024, 0x9528, 0xa115, 0x4150, 0x4000, 0x0000, 0x0000, 0x0000, 0x3fff, 0xffe0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x04a2, 0x44aa, 0x9564, 0x215f, 0x0000, 0x0000, 0x0000, 0x0000, 0x1fff, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0009, 0x1292, 0x2895, 0xa169, 0x0000, 0x0000, 0x0000, 0x0000, 0x07ff, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0841, 0x4a52, 0xa610, 0x02ac, 0x1000, 0x0000, 0x0004, 0x0000, 0x03ff, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0014, 0x2949, 0x516a, 0x8156, 0x8000, 0x0000, 0x0002, 0x0000, 0x03ff, 0xfff0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x8125, 0x0aa5, 0x015a, 0xa000, 0x0000, 0x0002, 0x0000, 0x03ff, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0081, 0x1494, 0xa914, 0x80bb, 0x0000, 0x0000, 0x0001, 0x0000, 0x07ff, 0xfff8, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0015, 0x224a, 0x5550, 0x00af, 0x4800, 0x0000, 0x0001, 0x0000, 0x07ff, 0xfffc, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x4a21, 0x2248, 0x005a, 0xa000, 0x0000, 0x0001, 0x0000, 0x07ff, 0xfffc, 0x0000, 0x0000, 0x0000, 0x0000,
-0x008a, 0x0894, 0xa928, 0x00aa, 0xa000, 0x0000, 0x0000, 0x8000, 0x03ff, 0xfffc, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x2152, 0x9528, 0x00ad, 0x4000, 0x0000, 0x0000, 0x8000, 0x00bf, 0xfffe, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x4512, 0x92a0, 0x0015, 0x8000, 0x0000, 0x0000, 0x0000, 0x003f, 0xfffe, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0009, 0x1450, 0x4290, 0x0056, 0xd000, 0x0000, 0x0000, 0x0000, 0x007f, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x004b, 0x5850, 0x004b, 0x4000, 0x0000, 0x0000, 0x2000, 0x01ff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0002, 0x4508, 0x4a80, 0x002d, 0x4000, 0x0000, 0x0000, 0x0000, 0x03ff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x1525, 0x22a0, 0x0015, 0xa000, 0x0000, 0x0000, 0x1000, 0x03ff, 0xffff, 0x8000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x8024, 0xa940, 0x0056, 0xa000, 0x0000, 0x0000, 0x0000, 0x03ff, 0xffff, 0x8000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0a92, 0x8940, 0x002a, 0xc000, 0x0000, 0x0000, 0x0400, 0x03ff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000,
-0x0001, 0x0012, 0x2500, 0x002b, 0x5000, 0x0000, 0x0000, 0x0000, 0x03ff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x2544, 0xa480, 0x0055, 0x6000, 0x0000, 0x0000, 0x0000, 0x01ff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0415, 0x5280, 0x004d, 0xa000, 0x0000, 0x0000, 0x0200, 0x00ff, 0xffff, 0xc000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x1092, 0x0a20, 0x002a, 0x9000, 0x0000, 0x0000, 0x0200, 0x003f, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0242, 0xa880, 0x0017, 0x5400, 0x0000, 0x0000, 0x0100, 0x000f, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x2828, 0x9540, 0x0055, 0x2000, 0x0000, 0x0000, 0x0080, 0x000f, 0xffff, 0xe000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x02aa, 0x5240, 0x004a, 0x4800, 0x0000, 0x0000, 0x02c0, 0x0007, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0002, 0x4200, 0x002b, 0x4000, 0x0000, 0x0000, 0x0140, 0x0003, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0551, 0x2900, 0x002d, 0x1000, 0x0000, 0x0000, 0x00a0, 0x0003, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x1009, 0x2a00, 0x0096, 0x9000, 0x0000, 0x0000, 0x0060, 0x0041, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x02a4, 0x8400, 0x0057, 0x4000, 0x0000, 0x0000, 0x0160, 0x0017, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x08aa, 0x5500, 0x002d, 0x2000, 0x0000, 0x0000, 0x00a0, 0x003f, 0xffff, 0xf000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0009, 0x5100, 0x00aa, 0xa000, 0x0000, 0x0000, 0x00b0, 0x003f, 0xffff, 0xf800, 0x0000, 0x0000, 0x0000,
-0x0000, 0x12a4, 0x4400, 0x002f, 0x4000, 0x0000, 0x0000, 0x00b0, 0x003f, 0xffff, 0xf800, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0415, 0x1400, 0x0095, 0x2000, 0x0000, 0x0000, 0x0050, 0x003f, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0151, 0x5200, 0x0056, 0xa000, 0x0000, 0x0000, 0x00a0, 0x002f, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x1144, 0x4a00, 0x015a, 0x0000, 0x0000, 0x0000, 0x00a8, 0x000b, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0415, 0x4900, 0x002d, 0x4000, 0x0000, 0x0000, 0x0038, 0x0003, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x2091, 0x2500, 0x00b5, 0x0000, 0x0000, 0x0000, 0x0028, 0x0002, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0a44, 0x9400, 0x00d6, 0xa000, 0x0000, 0x0000, 0x00a8, 0x0000, 0xffff, 0xfc00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0254, 0x9200, 0x005a, 0x0000, 0x0000, 0x0000, 0x0010, 0x0000, 0x3fff, 0xfc00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x4912, 0x4a00, 0x012a, 0x0000, 0x0000, 0x0000, 0x0028, 0x0001, 0x3fff, 0xfc00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0145, 0x5500, 0x00aa, 0x8000, 0x0000, 0x0000, 0x0028, 0x0000, 0xbfff, 0xfe00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x1455, 0x1200, 0x0056, 0x8000, 0x0000, 0x0000, 0x0004, 0x0000, 0x3fff, 0xfe00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x4114, 0x4a00, 0x012a, 0x8000, 0x0000, 0x0000, 0x0010, 0x0000, 0x6fff, 0xfe00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0940, 0xa400, 0x02aa, 0x8000, 0x0000, 0x0000, 0x0008, 0x0000, 0x5fff, 0xfe00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x8455, 0x1400, 0x0055, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, 0x5fff, 0xfe00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x2252, 0x4a00, 0x0155, 0x4000, 0x0000, 0x0000, 0x0004, 0x0000, 0x3fff, 0xff00, 0x0000, 0x0000, 0x0000,
-0x0001, 0x290a, 0xaa00, 0x012a, 0x4000, 0x0000, 0x0000, 0x0004, 0x0000, 0x3fff, 0xff00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x08a8, 0x8280, 0x0425, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0xff00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x8244, 0x2800, 0x02d5, 0x6000, 0x0000, 0x0000, 0x0004, 0x0000, 0x7fff, 0xff80, 0x0000, 0x0000, 0x0000,
-0x0000, 0x2912, 0xab00, 0x020a, 0xa000, 0x0000, 0x0000, 0x0005, 0x0000, 0x7fff, 0xff80, 0x0000, 0x0000, 0x0000,
-0x0002, 0x44aa, 0x8100, 0x08a5, 0xa000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0xff80, 0x0000, 0x0000, 0x0000,
-0x0000, 0x5288, 0x54a0, 0x0494, 0x5000, 0x0000, 0x0000, 0x0002, 0x0000, 0x7fff, 0xff80, 0x0000, 0x0000, 0x0000,
-0x0001, 0x0825, 0x2280, 0x0452, 0x9000, 0x0000, 0x0000, 0x0001, 0x8000, 0x3fff, 0xff80, 0x0000, 0x0000, 0x0000,
-0x0004, 0x2a92, 0x2954, 0x5205, 0x6800, 0x0000, 0x0000, 0x0000, 0x8000, 0x0fff, 0xffc0, 0x0000, 0x0000, 0x0000,
-0x0000, 0xa248, 0x8954, 0x4294, 0x2800, 0x0000, 0x0000, 0x0000, 0x8000, 0x0fff, 0xffc0, 0x0000, 0x0000, 0x0000,
-0x0001, 0x092a, 0xa449, 0x0852, 0x9000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07ff, 0xffe0, 0x0000, 0x0000, 0x0000,
-0x0005, 0x4922, 0x254a, 0x9100, 0x2800, 0x0000, 0x0000, 0x0000, 0xc000, 0x03ff, 0xffe0, 0x0000, 0x0000, 0x0000,
-0x0000, 0x2488, 0x9125, 0x54a1, 0x1000, 0x0000, 0x0000, 0x0000, 0x2000, 0x03ff, 0xffe0, 0x0000, 0x0000, 0x0000,
-0x000a, 0x2252, 0x9429, 0x2408, 0x1400, 0x0000, 0x0000, 0x0000, 0x2000, 0x01ff, 0xffe0, 0x0000, 0x0000, 0x0000,
-0x0000, 0x8914, 0x45aa, 0xa544, 0xa800, 0x0000, 0x0000, 0x0000, 0x1000, 0x00ff, 0xffe0, 0x0000, 0x0000, 0x0000,
-0x0001, 0x5545, 0x2824, 0x5214, 0xa800, 0x0000, 0x0000, 0x0000, 0x0800, 0x00ff, 0xffe0, 0x0000, 0x0000, 0x0000,
-0x000a, 0x4452, 0x9291, 0x0aaa, 0x5000, 0x0000, 0x0000, 0x0000, 0x0a00, 0x00ff, 0xffe0, 0x0000, 0x0000, 0x0000,
-0x0000, 0x1288, 0x524a, 0xaa91, 0x5400, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xffe1, 0x0000, 0x0000, 0x0000,
-0x0005, 0x52a5, 0x4929, 0x5155, 0x1400, 0x0000, 0x0000, 0x0000, 0x0400, 0x00ff, 0xffe3, 0x0000, 0x0000, 0x0000,
-0x0000, 0x8812, 0x84a5, 0x1555, 0x4800, 0x0000, 0x0000, 0x0000, 0x0280, 0x01ff, 0xfff7, 0xc000, 0x0000, 0x0000,
-0x0002, 0xa54a, 0xb244, 0xa244, 0xaa00, 0x0000, 0x0000, 0x0000, 0x0080, 0x0dff, 0xffff, 0xc000, 0x0000, 0x0000,
-0x0008, 0x1524, 0x0954, 0xa952, 0xa800, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000,
-0x0001, 0x5095, 0x4912, 0x552a, 0x5000, 0x0000, 0x0000, 0x0000, 0x0002, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000,
-0x0005, 0x4450, 0xa529, 0x52a9, 0x4800, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000,
-0x0000, 0x154a, 0x94a5, 0x0a55, 0x2a00, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xd000, 0x0000, 0x0000,
-0x0000, 0x528a, 0x5294, 0x6954, 0xa000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xc000, 0x0000, 0x0000,
-0x0005, 0x4a34, 0x4a91, 0xa58a, 0x9000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000,
-0x0000, 0x2945, 0x2956, 0x94a9, 0x5000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0xffff, 0x8000, 0x0000, 0x0000,
-0x0000, 0xa492, 0x9148, 0x5255, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7fff, 0xffff, 0x8000, 0x0000, 0x0000,
-0x0002, 0x8452, 0x5525, 0x6a95, 0xa000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000,
-0x0000, 0x112a, 0x4435, 0x256a, 0xb000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000,
-0x0001, 0x12a9, 0x1294, 0xb54a, 0xd400, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000,
-0x0000, 0x4445, 0x5552, 0x9535, 0x5800, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0x8000, 0x0000, 0x0000,
-0x0000, 0x4554, 0x554a, 0xd5ad, 0x6a00, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xc000, 0x0000, 0x0000,
-0x0000, 0x152b, 0x54a9, 0x56d5, 0xb410, 0x0010, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xf400, 0x0000, 0x0000,
-0x0001, 0x10a9, 0x52b5, 0xb6b7, 0x5420, 0x0000, 0x0000, 0x0000, 0x0001, 0xffff, 0xffff, 0xfc00, 0x0000, 0x0000,
-0x0000, 0x4a95, 0x5b56, 0xd9da, 0xf850, 0x0020, 0x0000, 0x0000, 0x0007, 0xffff, 0xffff, 0xfa00, 0x0000, 0x0000,
-0x0002, 0x2555, 0xaeef, 0x6f5d, 0xbdda, 0x0020, 0x0000, 0x0000, 0x0007, 0xffff, 0xfffb, 0xf800, 0x0000, 0x0000,
-0x0000, 0x9576, 0xfabb, 0x7dff, 0xffa8, 0x4010, 0x0000, 0x0000, 0x001f, 0xffff, 0xffe3, 0xf800, 0x0000, 0x0000,
-0x0001, 0x555e, 0xdfff, 0xffff, 0xeff5, 0x0050, 0x0000, 0x0000, 0x001f, 0xffff, 0xfbb3, 0xe800, 0x0000, 0x0000,
-0x0000, 0x094a, 0xaaaa, 0xaaaa, 0xaaff, 0x5028, 0x0040, 0x0000, 0x003f, 0xffff, 0xe010, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0028, 0xa888, 0x8000, 0x003f, 0xd53d, 0x0150, 0x0000, 0x007f, 0xffff, 0xc070, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0104, 0x25ef, 0xfdfd, 0x3555, 0x0000, 0x017f, 0xffff, 0xc160, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaffd, 0x57f1, 0x0440, 0x5fff, 0xffff, 0xd540, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0012, 0xa800, 0x1fff, 0xffe8, 0x5155, 0x7fff, 0xffff, 0xd480, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0011, 0x0000, 0x5ffc, 0xaee0, 0x102a, 0x3fff, 0xffff, 0xfe00, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0045, 0x4015, 0xfffc, 0x2925, 0x0000, 0x1fff, 0xffff, 0xa000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x002d, 0xe376, 0xbffe, 0x017d, 0x4d54, 0x5fff, 0xfea0, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x8040, 0x22be, 0xd6ff, 0xfffd, 0x3aaa, 0x8000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x808a, 0xa888, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x115f, 0xffd0, 0x0000, 0x0500, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x055d, 0x7fff, 0xfff7, 0x5001, 0x6800, 0x0000,
-0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x155d, 0xffff, 0xffff, 0xffff, 0xffff, 0x4000, 0x0000,
-};
//GO.SYSIN DD header.c

From acsnet!basser!rex Thu Jun 26 20:44:37 1986
# To unbundle, sh this file
echo README 1>&2
sed 's/.//' >README <<'//GO.SYSIN DD README'
-INSTALLATION:
-
-Provided is a series of source files, and a makefile.
-The makefile is for a stand-alone Blit version, and both a stand-alone
-and mux version suitable for the 5620. The Blit version is too large to
-run under mux.
-
-To make the version desired
-just remove the comment '#'s from the makefile lines of the version required.
-do a 'make clean' if another version's .o files are present and do 'make'
-or 'make pengo'. No 'make install' is present as different machines would
-most probable have the loadable in different place.
-
-The code of pengo itself is awful. It was written in little pieces over
-a period of several months. Requests for bug fixes will be accepted, but
-general flames as to style and the such can be sent to /dev/null. Constructive
-comments as to problems with the code will be read as long as they have
-examples of what should be done. So don't just say 'the code at line 30 of
-file X is stupid', say rather 'the code at line 30 of file X could be written
-as .....' which would remove problem YYYYY.
-
-I would prefer that no local hacking of the code is performed. I will
-(occasionally) be working on it when not doing what I should be doing, so
-new versions, better end of game stuff and the such will be coming out.
-
-
-				Rex Di Bona.
-
-				rex@basser.oz
-				seismo!munnari!basser.oz!rex
//GO.SYSIN DD README
echo pengo.9 1>&2
sed 's/.//' >pengo.9 <<'//GO.SYSIN DD pengo.9'
-.TH PENGO 9.6
-.SH NAME
-pengo \- squash the sno-bees
-.SH SYNOPSIS
-.B pengo
-.PP
-.SH DESCRIPTION
-.I Pengo
-plays the video game, pengo, on either a 5620 or Blit.
-.PP
-.SH PLAYING
-This game is based upon the popular arcade game
-`pengo'. Pengo uses the mouse to control the game. Moving the mouse around
-controls the movement of the penguin character. Pressing the mouse buttons
-do different things. The usual keys, 'hjkl' also move the penguin, with the
-space bar stopping movement.
-.PP
-Button 1:	Stop the penguin at the next block boundary.
-.PP
-Button 2:	Push (or break) a block, or splash the water boundary.
-.PP
-Button 3:	Display a menu to control aspects of the game.
-.PP
-When moving in a given direction the penguin will continue to move in the
-same direction (at the same speed) unless acted upon by an outside force.
-An outside force is defined as moving the mouse, or a wall or border.
-If button 2 is pressed when the block is encountered then the block is
-pushed. If another block (or a wall) is behind the first then the block
-will shatter.
-.PP
-Breaking a block in this manner will score 30 points. If this breaking is
-done to an egg then 500 points are scored. When started moving a block will
-also move in the same direction. Hitting a sno-bee whilst moving causes the
-sno-bee to slide in front of the block and eventually be crushed against
-either another block or the wall. The score for this depends upon the number
-of sno-bees crushed per block :-
-.nf
-.ta 1i 2.5i 3i 4i 5i
-	1 sno-bee	400 points
-	2 sno-bees	1600 points
-	3 sno-bees	3200 points
-	4 sno-bees	6400 points
-.DT
-.fi
-There are three blocks with a cross on them. Lining these three blocks
-up is worth 10000 points if they are not lined against a wall, 5000 points
-if they are. Bonus penguins are given out every so often.
-.PP
-The border around the playing board is a liquid substance. Pushing on this
-will cause ripples to move outwards (at a VERY high rate). If a sno-bee is
-against the border it becomes `stunned'. When stunned the penguin may crush a
-sno-bee underfoot for 100 points.
-.PP
-Pressing button 3 displays the following menu:
-.PP
-.nf
-	Pause
-	Stats
-	New Game
-	Quit
-.fi
-.TP
-Pause
-Turns the cursor int a 'zzz' symbol and pengo halts till button 3 is
-pressed again. Pengo also halts when it is not the current window.
-.TP
-Stats
-Presents the user with three slider graphs. These have the following
-meanings (use button 1 to slide the graph):
-.in +5m
-.TP
-\&'C'	Change
-(% of time that the sno-bees change direction)
-.TP
-\&'R'	Random
-(% of time that a random direction is chosen
-when changing)
-.TP
-\&'B'	Break
-% of time that a sno-bee will break a block
-that is blocking its way)
-.sp
-.in -5m
-Click button 3 when the settings have been adjusted.
-.TP
-New Game
-Scraps the current game and starts a new game (confirm on button 3).
-.TP
-Quit
-Exit from PENGO (confirm on button 3).
-.PP
-When first run, and at certain times a display of a digitised penguin may
-appear on the screen. Pressing any of the mouse buttons will start a new game
-running.
-.PP
-.SH FILES
-pengo \(em Blit or 5620 executable, use 32ld or 68ld to execute.
//GO.SYSIN DD pengo.9
echo Makefile 1>&2
sed 's/.//' >Makefile <<'//GO.SYSIN DD Makefile'
-#
-#	Blit Version (stand alone only)
-#
-#
-#CFLAGS=-O -j
-#CC=/usr/blit/bin/mcc
-#I=/usr/blit/include
-#CYFLAGS=
-#
-#*********************************************
-#
-#	5620 Version (mux)
-#
-#
-#CFLAGS=-DJERQ
-#CC=/usr/jerq/bin/3cc
-#I=/usr/jerq/include
-#CYFLAGS=-DJERQ
-#
-#*********************************************
-#
-#	5620 Version (stand alone)
-#
-#
-#CFLAGS=-J -DJERQ
-#CC=/usr/jerq/bin/3cc
-#I=/usr/jerq/include
-#CYFLAGS=-DJERQ
-#
-CFILES	= bitmap.c chars.c digits.c endgame.c event.c \
-		events.c globals.c header.c init.c level.c \
-		mouse.c pengo.c player.c \
-		score.c screen.c shapes.c \
-		sno_bee.c water.c
-CYFILES	= bitmap.O chars.O digits.O endgame.O event.O \
-		events.O globals.O header.O init.O level.O \
-		mouse.O pengo.O player.O \
-		score.O screen.O shapes.O \
-		sno_bee.O water.O
-OFILES	= bitmap.o chars.o digits.o endgame.o event.o \
-		events.o globals.o header.o init.o level.o \
-		mouse.o pengo.o player.o \
-		score.o screen.o shapes.o \
-		sno_bee.o water.o
-
-ICONS	= \
-	icons/0diamond	icons/conf1	icons/pengo1	icons/sq_0left \
-	icons/100	icons/conf12	icons/pengo2	icons/sq_0right \
-	icons/1600	icons/conf2	icons/pengo3	icons/sq_0up \
-	icons/3200	icons/dead0	icons/pengo4	icons/sq_1down \
-	icons/400	icons/dead1	icons/pengo5	icons/sq_1left \
-	icons/500	icons/egg	icons/pengo6	icons/sq_1right \
-	icons/6400	icons/fblock	icons/pengo7	icons/sq_1up \
-	icons/bee0	icons/hula0	icons/pengo8	icons/still \
-	icons/bee1	icons/hula1	icons/playerl0	icons/video0 \
-	icons/beede	icons/hula2	icons/playerl1	icons/wiggle0 \
-	icons/blank	icons/hula3	icons/playerr0	icons/wiggle1 \
-	icons/block	icons/hula4	icons/playerr1 \
-	icons/chairl	icons/null	icons/salute \
-	icons/chairr	icons/pback	icons/sq_0down
-
-pengo: pengo.h $(OFILES)
-	$(CC) $(CFLAGS) $(LDFLAGS) $(OFILES) -o pengo
-	chmod 644 pengo
-
-shapes.o:	screen.c $(ICONS)
-		$(CC) $(CFLAGS) -c shapes.c
-
-%.O:	%.c
-	cyntax -c -I$(I) $(CYFLAGS) $%.c
-
-cyntax:	pengo.h $(CYFILES)
-	cyntax $(CYFILES)
-
-clean:
-	rm -f $(OFILES) $(CYFILES) core jim.recover
-
-print:
-	@pr -n Makefile pengo.h $(CFILES) $(ICONS) 
//GO.SYSIN DD Makefile
echo pengo.h 1>&2
sed 's/.//' >pengo.h <<'//GO.SYSIN DD pengo.h'
-/*
- *	header file for pengo.	BLIT (and jerq) version
- */
-
-#ifdef	JERQ
-#include "jerq.h"
-#define	 sbits(x)	x, 0x0000
-#ifdef	MUX
-#define	MPX	MPX		/* blit uses MPX */
-#endif	MUX
-#else
-#include "blit.h"
-#define	 sbits(x)	x
-#endif
-#include "font.h"
-
-#undef	NULL			/* define NULL for those who need it */
-#define	NULL	0
-
-#define	HEAD_X	(13 * 16)	/* number of bits wide */
-#define	HEAD_Y	203		/* number of rows deep */
-#define	HEAD_COUNT	300	/* 10 seconds till static display */
-
-#define	TRUE	1
-#define	FALSE	0
-
-#define	ALIVE	0		/* states that a character can be in */
-#define	DYING	1
-#define	DEAD	2		/* must be the same as SNO_BEE (defined later) */
-#define	CONFUSED	3
-#define	HATCHING	4
-#define	SQUASH	5
-#define	MOVING	6
-#define	VANISH	7
-
-#define	STILL	0		/* direction movements */
-#define	DOWN	1
-#define	RIGHT	2
-#define	LEFT	3
-#define	UP	4
-
-#define	VERT	0	/* vertical */
-#define	HORIZ	1	/* horizontal */
-
-/* defines for the game */
-#define	shorts(x)	((x)/(sizeof(Word)/sizeof(short)))
-#define	MAX_X	23		/* maximum X blocks */
-#define	MAX_Y	29		/* maximum Y blocks */
-#define	MAXX	(MAX_X + 4)	/* used for screen co-ordinates */
-#define	MAXY	(MAX_Y + 4)	/* used for screen co-ordinates */
-
-#define	SHAPE_WIDTH	32	/* sorry, this really can't be changed */
-#define	SHAPE_HEIGHT	32
-#define	CHAR_HEIGHT	32
-#define	CHAR_WIDTH	32
-#define	NUM_DIGITS	6
-#define	NUM_ADD_MAN	7
-#define MINX	((NUM_DIGITS + 2) * SHAPE_WIDTH)     /* min size of screen (x) */
-#define MINY	(NUM_DIGITS * SHAPE_HEIGHT + CHAR_HEIGHT)   /* min size (y) */
-
-/* different states that a spot on the screen can be in. */
-#define	BLANK	0
-#define	BLOCK	1
-#define	SNO_BEE	2	/* not really, but just in case */
-#define	PENGO	3	/* not really, but just in case */
-#define	DIAMOND	4
-#define	EGG	5
-#define	HATCH	6
-#define	BREAK	7
-#define	CONF	8	/* when sno_bee is confused */
-/* used for put_char only */
-#define	PENGO_D	9
-#define	SALUTE	10
-#define	WIGGLE	11
-#define	BACK	12
-/*
-	13 to 15 used for top states
-*/
-#define	FBLOCK	13	/* special for put_char and move_block only */
-#define	WALL	14
-#define	BORDER	15
-
-#define	HULA	16
-#define	CHAIR	17
-#define	VIDEO	18
-#define	PLAYERR	19
-#define	PLAYERL	20
-
-/* movement rates. Number of clock ticks allowed between moves */
-#define	MOVE_PENGO	3L	/* pengo movement ~1 sec */
-#define	MOVE_BEE2	2L	/* angry or running bee */
-#define	MOVE_BEE1	3L	/* annoyed/fast bee */
-#define	MOVE_BEE0	4L	/* normal/slow bee state */
-#define	MOVE_BLOCK	2L	/* block movement */
-#define	DIE_BLOCK	2L	/* block destruction time */
-#define	EGG_HATCH	4L	/* egg hatching time */
-
-#define	BEE_MOVE	8	/* movement rate of sno_bee */
-#define	PENGO_MOVE	8	/* movement rate of pengo */
-#define	BLOCK_MOVE	4	/* movement rate of a block */
-
-#define	NUM_HATCH	8	/* number of states in a hatching */
-#define	NUM_BREAK	7	/* number of states in a breaking */
-
-#define	MAX_BEES	12	/* Maximum number of bees displayable */
-#define	MAX_PENGO	8	/* Maximum number of Pengo's displayable */
-#define	NUM_PENGO	4	/* initial number of Pengo's */
-#define	NUM_WATER	6	/* number of cycles in the mater movement */
-#define	NUM_SCORES	5	/* number of scores possible on screen */
-
-#define	DYING_TIME	10L	/* time for dying loop */
-#define	P_DYING		10L	/* pengo dying time */
-#define	PENGO_D_TIME	4L	/* time while pengo is dying */
-#define	PENGO_W_TIME	6L	/* time while pengo is wiggling */
-#define	CLR_SCORE	120L	/* score on the screen time */
-#define	FLASH_DIAMOND	3L	/* diamond flashing time */
-#define	WATER_TIME	5L	/* water movement delay */
-#define	SHOW_EGGS	150L	/* time that eggs are on screen for */
-#define	RUN_DELAY	600L	/* 10 seconds till it runs */
-#define	NUM_FLASH	10	/* number of flashes in the diamonds */
-#define	DIE_BEE		10L	/* a sno_bee dying */
-#define	TIME_CONFUSED	18L	/* six seconds of confusion */
-#define	NUM_CONFUSED	20	/* 20 * 18 = 360 ticks */
-#define	NUM_WIGGLE	20	/* number of wiggles done */
-#define	NUM_HULA	3	/* number of hula loops */
-#define	NUM_HULA0	5	/* number each side */
-#define	SHOW_SCORE	150L	/* time score shown on screen */
-#define	PENGO_SALUTE	180L	/* time that pengo's salute for */
-#define	DANCE_PENGO	4L	/* while pengo's are moving during levels */
-#define	PENGO_THROES	10	/* dying throes */
-#define	PENGO_HULA	4L	/* hula dance of pengo's */
-#define	SHOW_VIDEO	8L	/* time video player is hown for */
-#define	NUM_BOUNCE	8	/* number of bounces at video table (must be even) */
-
-#define	SNO_BEE_CHANGE	30	/* 30 % chance of changing direction */
-#define	SNO_BEE_RANDOM	40	/* 40 % chance of moving in a random direction */
-#define	SNO_BEE_BREAK	10	/* 10 % chance of breaking block */
-
-/* type definitions */
-
-typedef	struct	element	{
-	int	x;		/* x position */
-	int	y;		/* y position */
-#ifdef	JERQ
-	int	movex;		/* x-movement */
-	int	movey;		/* y movement */
-	int	exists;		/* is it on the screen? */
-	int	count;		/* what stage it is up to */
-	int	other;
-#else	JERQ
-	char	movex;		/* x-movement */
-	char	movey;		/* y movement */
-	char	exists;		/* is it on the screen? */
-	char	count;		/* what stage it is up to */
-	char	other;
-#endif	JERQ
-} element;
-/* externs for files */
-
-extern	int	pengo_left;	/* number of pengos left */
-extern	int	sno_bee_left;	/* number of sno_bees left */
-extern	int	egg_count_flag;	/* # eggs left */
-extern	int	manptr;		/* index into new_man array */
-extern	int	hit;		/* button 2 state */
-extern	int	seggs;		/* are eggs on display ? */
-extern	char	move_water;	/* side wall movement */
-extern	char	sdiamond;	/* has the diamond's score been added ? */
-extern	char	s[MAXX][MAXY];	/* storage for which blocks are on */
-extern	long	score;		/* current score */
-extern	long	high_score;	/* current high score */
-extern	long	my_time;	/* 60th of a second counter for play time */
-extern	long	old_score;	/* Previous score.. Temp variable */
-extern	long	new_man[];	/* scores at which a new man is awarded */
-extern	Menu	menu3;		/* menu for button 3 */
-extern	element	pengo;		/* pengo definition */
-extern	element	sno_bee[4];	/* which blocks are really sno_bees */
-extern	element	eggs[MAX_BEES];	/* which blocks are eggs */
-extern	element	diamond[3];	/* which blocks are really diamonds */
-extern	element	moving;		/* block which is moving or breaking */
-extern	element	breaking;	/* block which is being broken */
-extern	element	bee_block[4];	/* blocks being broken by bees */
-
-extern	Point	old_mouse;	/* initial mouse position */
-extern	Point	new_mouse;	/* current mouse position */
-extern	Point	move_mouse;	/* difference of old & new */
-extern	Point	home_mouse;	/* mouse home position */
-
-extern	Bitmap	bit16;		/* 16 * 16 generic Bitmap */
-extern	Bitmap	bit32;		/* 32 * 32 generic Bitmap */
-extern	Bitmap	bonus;		/* 10000 point bonus bitmap */
-extern	Bitmap	disp_head;	/* startup and waiting display */
-
-extern	Rectangle	board;
-extern	Rectangle	board0;
-extern	Rectangle	board1;
-extern	Rectangle	header;
-extern	Rectangle	bwater;
-extern	Rectangle	lwater;
-extern	Rectangle	rwater;
-extern	Rectangle	twater;
-extern	Rectangle	counter;
-
-extern	short	N[];		/* storage for digits */
-extern	short	char_0_9[];	/* 16 * 16 digits */
-extern	short	char_A_Z[];	/* 16 * 16 A->Z */
-extern	short	char_colon[];	/* 16 * 16 ':' */
-extern	short	char_space[];	/* 16 * 16 space */
-extern	short	char_dot[];	/* 16 * 16 '.' */
-extern	short	char_blank[];	/* 32 * 32 space */
-extern	short	char_block[];	/* 32 * 32 block */
-extern	short	flip_block[];	/* 32 * 32 block */
-extern	short	char_pengo[];	/* 32 * 32 pengo */
-extern	short	char_sno_bee[];	/* 32 * 32 sno_bee */
-extern	short	char_0diamond[];/* 32 * 32 diamond 0 */
-extern	short	*char_1diamond;	/* 32 * 32 diamond 1 */
-extern	short	char_null[];	/* 32 * 32 NULL pattern */
-extern	short	char_egg[];	/* 32 * 32 egg shape */
-extern	short	nw[];		/* still water */
-extern	short	tw[];		/* top water barrier */
-extern	short	bw[];		/* bottom water barrier */
-extern	short	lw[];		/* left barrier */
-extern	short	rw[];		/* right barrier */
-extern	Texture	skull;		/* skull and X bones for quit */
-
-/* access routines for the RAM screen map */
-
-#define	screen(x, y)	s[((x) + 2)][((y) + 2)]
-
-#define	max(a, b)	((a > b) ? (a) : (b))
-#define	min(a, b)	((a < b) ? (a) : (b))
-#define abs(a)		((a < 0) ? (-a) : (a))
-#define	R3		Rect(0, 0, 32, 32)
-#define	RX(a, b)	rectXrect(raddp(R3,Pt(a.x,a.y)),raddp(R3,Pt(b.x,b.y)))
-#define	P3		Rect(8, 8, 24, 24)	/* pengo shape (smaller) */
-#define	PX(a, b)	rectXrect(raddp(P3,Pt(a.x,a.y)),raddp(R3,Pt(b.x,b.y)))
-#define	addchar(c,p,f)	bitblt(bchar(c), Rect(0, 0, 16, 16), &display, p, f)
-/* functions called for add_event */
-extern	int	clr_bee();
-extern	int	die_pengo();
-extern	int	add_score();
-extern	int	move_player();
-extern	int	move_sno_bee();
-extern	int	move_block();
-extern	int	die_block();
-extern	int	add_man();
-extern	Bitmap	*bchar();	/* return bitmap of character */
-extern	int	swill_water();
-extern	int	egg_hatch();
-extern	int	clear_egg();
-extern	int	show_eggs();
-extern	int	sbd;
-extern	int	npd;
-extern	Rectangle	pengom;
-extern	Rectangle	sno_bm;
-extern	Rectangle	dboard;
-extern	Rectangle	dsp0;
-extern	Rectangle	dsp1;
-extern	Rectangle	dsp2;
-extern	short	spengo[];
-extern	short	sbee[];
-extern	int	run_bee();
-extern	int	flash_diamond();
-extern	int	run_sno_bee();
-extern	int	bee_run;
-extern	int	bee_break();
-extern	char	blockx;
-extern	char	blocky;
-extern	int	vanish_bee();
-extern	int	confused_bee();
-extern	short	conf1[];
-extern	short	conf2[];
-extern	short	char_100[];
-extern	short	char_400[];
-extern	short	char_500[];
-extern	short	char_1600[];
-extern	short	char_3200[];
-extern	short	char_6400[];
-extern	short	char_0bee[];
-extern	short	char_1bee[];
-extern	short	char_0pengo[];
-extern	short	char_1pengo[];
-extern	short	char_2pengo[];
-extern	short	char_3pengo[];
-extern	short	char_4pengo[];
-extern	short	char_5pengo[];
-extern	short	char_6pengo[];
-extern	short	char_7pengo[];
-extern	short	char_8pengo[];
-extern	short	*char_still;
-extern	short	*char_sorry;
-extern	short	*char_happy;
-extern	short	char_0dead[];
-extern	short	char_1dead[];
-extern	short	*pengo_moves[];
-extern	short	char_question[];
-extern	short	char_lbrkt[];
-extern	short	char_rbrkt[];
-extern	short	char_uscore[];
-extern	short	char_slash[];
-extern	short	char_pback[];
-extern	short	char_salute[];
-extern	short	char_0wiggle[];
-extern	short	char_1wiggle[];
-extern	int	reshaped;	/* for use in the stand alone world.. */
-extern	int	sb_change;
-extern	int	sb_random;
-extern	int	sb_break;
-extern	short	ch_sq_0down[];
-extern	short	ch_sq_0left[];
-extern	short	ch_sq_0right[];
-extern	short	ch_sq_0up[];
-extern	short	ch_sq_1down[];
-extern	short	ch_sq_1left[];
-extern	short	ch_sq_1right[];
-extern	short	ch_sq_1up[];
-extern	short	*squash_moves[];
-extern	short	char_header[];
-extern	short	char_0hula[];
-extern	short	char_1hula[];
-extern	short	char_2hula[];
-extern	short	char_3hula[];
-extern	short	char_4hula[];
-extern	short	*hula_moves[];
-extern	short	char_lchair[];
-extern	short	char_rchair[];
-extern	short	char_0video[];
-extern	short	char_0lplayer[];
-extern	short	char_1lplayer[];
-extern	short	char_0rplayer[];
-extern	short	char_1rplayer[];
//GO.SYSIN DD pengo.h
echo init.c 1>&2
sed 's/.//' >init.c <<'//GO.SYSIN DD init.c'
-/*
-	Initialisation routines for various stages...
-
-*/
-#include "pengo.h"
-
-int	sizex;	/* number of pixels across */
-int	sizey;	/* number of pixels down */
-char	blockx;	/* number of blocks across */
-char	blocky;	/* number of blocks down */
-char	count;
-char	pos;
-char	tmp;
-char	store[4];
-char	store1[MAX_X * MAX_Y][2];
-int	point1;
-int	block_count;
-extern	Rectangle	mouse_board;
-
-Rectangle	board	= { { 0, 0 }, { 0, 0 } };	/* inside water boundary */
-Rectangle	board0	= { { 0, 0 }, { 0, 0 } };	/* whole board */
-Rectangle	board1	= { { 0, 0 }, { 0, 0 } };	/* board excluding score */
-Rectangle	header	= { { 0, 0 }, { 0, 0 } };
-Rectangle	bwater	= { { 0, 0 }, { 0, 0 } };
-Rectangle	lwater	= { { 0, 0 }, { 0, 0 } };
-Rectangle	rwater	= { { 0, 0 }, { 0, 0 } };
-Rectangle	twater	= { { 0, 0 }, { 0, 0 } };
-Rectangle	pengom	= { { 0, 0 }, { 0, 0 } };
-Rectangle	sno_bm	= { { 0, 0 }, { 0, 0 } };
-Rectangle	dboard	= { { 0, 0 }, { 0, 0 } };
-
-changed_screen()
-{
-#ifdef	MPX
-	if (P->state & RESHAPED)
-	{
-		init();
-		init_scr();
-		P->state &= ~RESHAPED;
-	}
-#else
-	init();
-	init_scr();
-	reshaped = FALSE;
-#endif
-}
-
-init()
-{
-	cursswitch(char_space);
-	cancel_events();
-	while(TRUE)
-	{
-		score = 0;	/* reset score */
-		my_time = 0;	/* reset pseudo clock */
-		cancel_events();
-		request(KBD | MOUSE);
-#ifdef	MPX
-		P->state &= ~RESHAPED;
-#else
-		reshaped = FALSE;
-#endif
-		sizex = Drect.corner.x - Drect.origin.x;
-		sizey = Drect.corner.y - Drect.origin.y;
-		if ((sizex < MINX) || (sizey < MINY))
-		{
-			string(&defont, "Pengo:", &display,
-				Drect.origin, F_XOR);
-			string(&defont, "Reshape", &display,
-				add(Drect.origin, Pt(0, 12)), F_XOR);
-		}
-		else
-			break;	/* screen is of an adequate size */
-		request(KBD);
-#ifdef	MPX
-		P->state &= ~RESHAPED;
-		while(!(P->state & RESHAPED))
-		{
-			int c;
-
-			if (((c = kbdchar()) == 'q') || (c == 'Q'))
-				exit(0);
-			wait(CPU);	/* let others have a go */
-		}
-#endif
-	}
-	texture(&display, Drect, char_space, F_STORE);
-	sizex &= ~31;	/* clear off lower bits */
-	sizey &= ~31;	/* same thing... */
-	if (!(sizey & 32))	/* if sizey is even take off 32 */
-		sizey -= 32;
-	if (sizex & 32)		/* if sizex is odd take off 32 */
-		sizex -= 32;
-	board.corner.x  = Drect.origin.x + sizex - 16;
-	board.corner.y  = Drect.origin.y + sizey - 16;
-	board.origin.x  = Drect.origin.x + 16;
-	board.origin.y  = Drect.origin.y + CHAR_HEIGHT + 16;
-	board0.corner.x = Drect.origin.x + sizex;
-	board0.corner.y = Drect.origin.y + sizey;
-	board0.origin.x = Drect.origin.x;
-	board0.origin.y = Drect.origin.y;
-	board1.corner.x = Drect.origin.x + sizex;
-	board1.corner.y = Drect.origin.y + sizey;
-	board1.origin.x = Drect.origin.x;
-	board1.origin.y = Drect.origin.y + CHAR_HEIGHT;
-	bwater.corner.x = Drect.origin.x + sizex - 16;
-	bwater.corner.y = Drect.origin.y + sizey;
-	bwater.origin.x = Drect.origin.x + 16;
-	bwater.origin.y = Drect.origin.y + sizey - 16;
-	lwater.corner.x = Drect.origin.x + 16;
-	lwater.corner.y = Drect.origin.y + sizey - 16;
-	lwater.origin.x = Drect.origin.x;
-	lwater.origin.y = Drect.origin.y + CHAR_HEIGHT + 16;
-	rwater.corner.x = Drect.origin.x + sizex;
-	rwater.corner.y = Drect.origin.y + sizey - 16;
-	rwater.origin.x = Drect.origin.x + sizex - 16;
-	rwater.origin.y = Drect.origin.y + CHAR_HEIGHT + 16;
-	twater.corner.x = Drect.origin.x + sizex - 16;
-	twater.corner.y = Drect.origin.y + CHAR_HEIGHT + 16;
-	twater.origin.x = Drect.origin.x + 16;
-	twater.origin.y = Drect.origin.y + CHAR_HEIGHT;
-	texture(&display, board0, char_space, F_STORE);
-	home_mouse = div(add(board.origin, board.corner), 2);
-	mouse_board = inset(board0, 16 * 7);
-	counter.origin = div(
-		sub(
-			add(board.origin, board.corner),
-			Pt(16 * 7, 0)
-		),
-		2
-	);
-	counter.corner = add(counter.origin, Pt(16 * 7, 48));
-	{
-		/* fix up the screen header */
-
-		int	hx;	/* # chars */
-
-		hx = ((Drect.corner.x - Drect.origin.x) >> 5) - NUM_DIGITS;
-		header.origin.x = Drect.origin.x + (hx / 2) * CHAR_WIDTH;
-		header.origin.y = Drect.origin.y;
-		header.corner.x = header.origin.x + NUM_DIGITS * CHAR_WIDTH;
-		header.corner.y = Drect.origin.y + CHAR_HEIGHT;
-		pengom.origin.x = Drect.origin.x;
-		pengom.origin.y = Drect.origin.y;
-		pengom.corner.x = header.origin.x;
-		pengom.corner.y = Drect.origin.y + CHAR_HEIGHT;
-		sno_bm.origin.x = header.corner.x;
-		sno_bm.origin.y = Drect.origin.y;
-		sno_bm.corner.x = Drect.origin.x + sizex;
-		sno_bm.corner.y = Drect.origin.y + CHAR_HEIGHT;
-		npd = hx / 2;
-		sbd = ((sno_bm.corner.x - sno_bm.origin.x) >> 5) - 1;
-	}
-	dboard.origin = board.origin;
-	dboard.corner = sub(board.corner, Pt(32, 32));
-}
-
-extern	Bitmap	bit16;
-
-init_scr()	/* set up the screen, colour in the bits that need it! */
-{
-	Word	*water();
-
-	bit16.base = water(STILL);
-	texture(&display, raddp(bit16.rect, board1.origin), bit16.base, F_STORE);
-	texture(&display,
-		raddp(
-			bit16.rect,
-			add(Drect.origin, Pt(0, sizey - 16))
-		),
-		bit16.base,
-		F_STORE
-	);
-	texture(&display,
-		raddp(
-			bit16.rect,
-			add(Drect.origin, Pt(sizex - 16, 32))
-		),
-		bit16.base,
-		F_STORE
-	);
-	texture(&display, raddp(bit16.rect, board.corner), bit16.base, F_STORE);
-	texture(&display, twater, bit16.base, F_STORE);
-	texture(&display, bwater, bit16.base, F_STORE);
-	texture(&display, rwater, bit16.base, F_STORE);
-	texture(&display, lwater, bit16.base, F_STORE);
-	texture(&display, board,  char_space, F_STORE);
-	move_water = FALSE;
-}
-
-init_board()
-{
-	int	x;
-	int	y;
-
-	disp_pengo(pengo_left);
-	disp_sno_bee(sno_bee_left);
-	sdiamond = FALSE;		/* all diamonds are active */
-	blockx = ((sizex - 32) >> 5);
-	blocky = ((sizey - 64) >> 5);
-	for (x = -2; x < blockx + 2; x++)
-	{
-		screen(x, -2) = WALL;
-		screen(x, -1) = BORDER;
-		screen(x, blocky) = BORDER;
-		screen(x, blocky + 1) = WALL;
-	}
-	for (y = -1; y < blocky + 1; y++)
-	{
-		screen(-2, y) = WALL;
-		screen(-1, y) = BORDER;
-		screen(blockx, y) = BORDER;
-		screen(blockx + 1, y) = WALL;
-	}
-	for (x = 0; x < blockx; x++)
-	{
-		for (y = 0; y < blocky; y++)
-		{
-			screen(x, y) = BLOCK;
-			put_char(x << 5, y << 5, BLOCK, F_STORE, NULL);
-		}
-	}
-	screen(0, blocky - 1) = BLANK;
-	put_char(0, (blocky - 1) << 5, BLANK, F_STORE, NULL);
-	store[0] = LEFT;
-	store[1] = RIGHT;
-	store[2] = UP;
-	store[3] = DOWN;
-	for (count = 3; count > 0; count--)
-	{
-		pos = rand() % (count + 1);
-		tmp = store[pos];
-		store[pos] = store[count];
-		store[count] = tmp;
-	}
-	point1 = 0;
-	maze(0, blocky - 1);
-	add_a_pengo();
-	set_up_diamonds();
-	set_up_eggs();
-	moving.exists = FALSE;
-	bee_run = FALSE;
-	cursswitch(char_space);
-}
-
-add_a_pengo()
-{
-	pengo.other = ALIVE;	/* he hasn't died yet, just born */
-	pengo.x = blockx / 2;	/* lets put the pengo on the screen */
-	pengo.y = blocky / 2;
-	pengo.movex = pengo.movey = 0;	/* not moving yet */
-	if (screen(pengo.x, pengo.y) != BLANK)
-	{
-		for (tmp = 0; tmp < 4; tmp++)
-		{
-			switch(store[tmp])
-			{
-			case UP:
-				if (screen(pengo.x - 1, pengo.y) == BLANK)
-				{
-					pengo.x--;
-					tmp = 4;
-				}
-				break;
-			case DOWN:
-				if (screen(pengo.x + 1, pengo.y) == BLANK)
-				{
-					pengo.x++;
-					tmp = 4;
-				}
-				break;
-			case RIGHT:
-				if (screen(pengo.x, pengo.y + 1) == BLANK)
-				{
-					pengo.y++;
-					tmp = 4;
-				}
-				break;
-			case LEFT:
-				if (screen(pengo.x, pengo.y - 1) == BLANK)
-				{
-					pengo.y--;
-					tmp = 4;
-				}
-				break;
-			}
-		}
-	}
-	if (screen(pengo.x, pengo.y) != BLANK)
-	{
-		for (tmp = 0; tmp < 4; tmp++)
-		{
-			switch(store[tmp])
-			{
-			case UP:
-				if (screen(pengo.x - 1, pengo.y - 1) == BLANK)
-				{
-					pengo.x--;
-					pengo.y--;
-					tmp = 4;
-				}
-				break;
-			case DOWN:
-				if (screen(pengo.x - 1, pengo.y + 1) == BLANK)
-				{
-					pengo.x--;
-					pengo.y++;
-					tmp = 4;
-				}
-				break;
-			case RIGHT:
-				if (screen(pengo.x + 1, pengo.y - 1) == BLANK)
-				{
-					pengo.x++;
-					pengo.y--;
-					tmp = 4;
-				}
-				break;
-			case LEFT:
-				if (screen(pengo.x + 1, pengo.y + 1) == BLANK)
-				{
-					pengo.x++;
-					pengo.y++;
-					tmp = 4;
-				}
-				break;
-			}
-		}
-	}
-	if (screen(pengo.x, pengo.y) != BLANK)
-	{
-		for (tmp = 0; tmp < 4; tmp++)
-		{
-			switch(store[tmp])
-			{
-			case UP:
-				if (screen(pengo.x - 1, pengo.y) == BLOCK)
-				{
-					pengo.x--;
-					tmp = 4;
-				}
-				break;
-			case DOWN:
-				if (screen(pengo.x + 1, pengo.y) == BLOCK)
-				{
-					pengo.x++;
-					tmp = 4;
-				}
-				break;
-			case RIGHT:
-				if (screen(pengo.x, pengo.y + 1) == BLOCK)
-				{
-					pengo.y++;
-					tmp = 4;
-				}
-				break;
-			case LEFT:
-				if (screen(pengo.x, pengo.y - 1) == BLOCK)
-				{
-					pengo.y--;
-					tmp = 4;
-				}
-				break;
-			}
-		}
-		if (screen(pengo.x, pengo.y) == BLOCK)
-		{
-			put_char(pengo.x<<5, pengo.y<<5, FBLOCK, F_XOR, NULL);
-			screen(pengo.x, pengo.y) = BLANK;
-		}
-	}
-	if (screen(pengo.x, pengo.y) != BLANK)
-	{
-		for (tmp = 0; tmp < 4; tmp++)
-		{
-			switch(store[tmp])
-			{
-			case UP:
-				if (screen(pengo.x - 1, pengo.y - 1) == BLOCK)
-				{
-					pengo.x--;
-					pengo.y--;
-					tmp = 4;
-				}
-				break;
-			case DOWN:
-				if (screen(pengo.x - 1, pengo.y + 1) == BLOCK)
-				{
-					pengo.x--;
-					pengo.y++;
-					tmp = 4;
-				}
-				break;
-			case RIGHT:
-				if (screen(pengo.x + 1, pengo.y - 1) == BLOCK)
-				{
-					pengo.x++;
-					pengo.y--;
-					tmp = 4;
-				}
-				break;
-			case LEFT:
-				if (screen(pengo.x + 1, pengo.y + 1) == BLOCK)
-				{
-					pengo.x++;
-					pengo.y++;
-					tmp = 4;
-				}
-				break;
-			}
-		}
-		if (screen(pengo.x, pengo.y) == BLOCK)
-		{
-			put_char(pengo.x<<5, pengo.y<<5, FBLOCK, F_XOR, NULL);
-			screen(pengo.x, pengo.y) = BLANK;
-		}
-	}
-	if (screen(pengo.x, pengo.y) != BLANK)
-	{
-		/* blast it all, in those 9 spots not one was free
-			so I'll just take it anyway!!!	*/
-		screen(pengo.x, pengo.y) = BLANK;
-		put_char(pengo.x<<5, pengo.y<<5, BLANK, F_STORE, NULL);
-	}
-	pengo.x <<= 5;
-	pengo.y <<= 5;
-	put_char(pengo.x, pengo.y, PENGO, F_XOR, NULL);
-	old_mouse = mouse.xy;
-}
-
-maze(x, y)
-int x;
-int y;
-{
-	char	x1;
-	char	y1;
-	char	count;
-
-nasty1:
-	sleep(2);
-	for (count = 3; count > 0; count--)
-	{
-		pos = rand() % (count + 1);
-		tmp = store[pos];
-		store[pos] = store[count];
-		store[count] = tmp;
-	}
-	for (count = 0; count < 4; count++)
-	{
-nasty2:
-		pos = 0;
-	 	x1 = x;
-		y1 = y;
-		switch (store[count])
-		{
-		case RIGHT:
-			if (screen(x + 2, y) == BLOCK)
-			{
-				screen(++x1, y) = BLANK;
-				put_char(x1 << 5, y1 << 5, BLANK, F_STORE, NULL);
-				screen(++x1, y) = BLANK;
-				put_char(x1 << 5, y1 << 5, BLANK, F_STORE, NULL);
-				pos++;
-			}
-			break;
-		case LEFT:
-			if (screen(x - 2, y) == BLOCK)
-			{
-				screen(--x1, y) = BLANK;
-				put_char(x1 << 5, y1 << 5, BLANK, F_STORE, NULL);
-				screen(--x1, y) = BLANK;
-				put_char(x1 << 5, y1 << 5, BLANK, F_STORE, NULL);
-				pos++;
-			}
-			break;
-		case UP:
-			if (screen(x, y - 2) == BLOCK)
-			{
-				screen(x, --y1) = BLANK;
-				put_char(x1 << 5, y1 << 5, BLANK, F_STORE, NULL);
-				screen(x, --y1) = BLANK;
-				put_char(x1 << 5, y1 << 5, BLANK, F_STORE, NULL);
-				pos++;
-			}
-			break;
-		case DOWN:
-			if (screen(x, y + 2) == BLOCK)
-			{
-				screen(x, ++y1) = BLANK;
-				put_char(x1 << 5, y1 << 5, BLANK, F_STORE, NULL);
-				screen(x, ++y1) = BLANK;
-				put_char(x1 << 5, y1 << 5, BLANK, F_STORE, NULL);
-				pos++;
-			}
-			break;
-		}
-		if (pos)
-		{
-			store1[point1][0] = x;
-			store1[point1][1] = y;
-			x = x1;
-			y = y1;
-			point1++;
-			goto nasty1;
-		}
-#ifdef	MPX
-		if (P->state & RESHAPED)
-			return;
-#endif
-	}
-	if (point1--)
-	{
-		x = store1[point1][0];
-		y = store1[point1][1];
-		count  = 0;
-		goto nasty2;
-	}
-}
-
-set_up_diamonds()
-{
-	int	pos, x, y, z;
-
-	block_count = 0;
-	for (x = 1; x < blockx - 1; x++)
-		for (y = 1; y < blocky - 1; y++)
-			if (screen(x, y) == BLOCK)
-				block_count++;
-	for (z = 0; z < 3; z++)
-	{
-		pos = rand() % block_count--;
-		for (x = 1; (x < blockx - 1) && (pos >= 0); x++)
-			for (y = 1; (y < blocky - 1) && (pos >= 0); y++)
-				if (screen(x, y) == BLOCK)
-					pos--;
-		x--;
-		y--;
-		diamond[z].x = x << 5;
-		diamond[z].y = y << 5;
-		diamond[z].exists = TRUE;
-		diamond[z].other = 0;	/* diamond state */
-		screen(x, y) = DIAMOND;
-		put_char(diamond[z].x, diamond[z].y, FBLOCK, F_XOR, 0);
-		put_char(diamond[z].x, diamond[z].y, DIAMOND, F_XOR, 0);
-	}
-}
-
-set_up_eggs()
-{
-	int	pos, x, y, z;
-	extern	int	egg_count_flag;
-
-	egg_count_flag = 0;
-	seggs = TRUE;	/* yes, show eggs */
-	for (z = 0; z < MAX_BEES; z++)
-	{
-		eggs[z].exists = FALSE;	/* clear all eggs */
-		eggs[z].other  = ALIVE;
-	}
-	for (z = 0; z < sno_bee_left; z++)
-	{
-		pos = rand() % block_count--;
-		for (x = 1; (x < blockx - 1) && (pos >= 0); x++)
-			for (y = 1; (y < blocky - 1) && (pos >= 0); y++)
-				if (screen(x, y) == BLOCK)
-					pos--;
-		x--;
-		y--;
-		eggs[z].x = x << 5;
-		eggs[z].y = y << 5;
-		eggs[z].exists = TRUE;
-		if (z > 3)
-		{
-			eggs[z].other = 0;	/* diamond state */
-			screen(x, y) = EGG;
-		}
-		else
-		{
-			bee_block[z].exists = FALSE;
-			eggs[z].exists = FALSE;
-			sno_bee[z].exists = FALSE;
-			sno_bee[z].other = HATCHING;
-			sno_bee[z].count = NUM_HATCH + 1;
-			sno_bee[z].x = eggs[z].x;
-			sno_bee[z].y = eggs[z].y;
-			screen(x, y) = HATCH;
-			add_event(EGG_HATCH, egg_hatch, z);
-			put_char(eggs[z].x, eggs[z].y, FBLOCK, F_XOR, 0);
-		}
-	}
-	show_eggs();
-}
-
-redraw_screen()
-{
-	int	x;
-	int	y;
-	int	dx;
-	int	dy;
-	int	tmp;
-
-	disp_pengo(pengo_left);
-	for (tmp = 0; tmp < 3; tmp++)
-	{
-		diamond[tmp].x &= ~31;
-		diamond[tmp].y &= ~31;
-		screen(diamond[tmp].x>>5, diamond[tmp].y>>5) = DIAMOND;
-	}
-	for (tmp = 0; tmp < moving.count; tmp++)
-	{
-		int	pos;
-
-		for (pos = 0; pos < MAX_BEES; pos++)
-		{
-			if (eggs[pos].exists == TRUE)
-				break;
-		}
-		if (pos < MAX_BEES)
-		{
-			int	a;
-
-			for (a = 0; a < 4; a++)
-			{
-				if (
-					(sno_bee[a].exists == FALSE) &&
-					(sno_bee[a].other != HATCHING)
-				)
-					break;
-			}
-			if (a < 4)
-			{
-				eggs[pos].exists = FALSE;
-				sno_bee[a].other = HATCHING;
-				sno_bee[a].count = NUM_HATCH;
-				sno_bee[a].x = eggs[pos].x;
-				sno_bee[a].y = eggs[pos].y;
-				screen(sno_bee[a].x >> 5, sno_bee[a].y >> 5) =
-					HATCH;
-			}
-		}
-	}
-	for (tmp = 0; tmp < MAX_BEES; tmp++)
-		if (eggs[tmp].exists == TRUE)
-		{
-			eggs[tmp].x &= ~31;
-			eggs[tmp].y &= ~31;
-			eggs[tmp].other = ALIVE;
-			screen(eggs[tmp].x>>5, eggs[tmp].y>>5) = EGG;
-		}
-	for (tmp = 0; tmp < 4; tmp++)
-		if (
-			(sno_bee[tmp].exists == FALSE) &&
-			(sno_bee[tmp].other == HATCHING)
-		)
-		{
-			sno_bee[tmp].exists = TRUE;
-			sno_bee[tmp].other = SNO_BEE;
-			screen(sno_bee[tmp].x >> 5, sno_bee[tmp].y >> 5) = BLANK;
-		}
-	for (x = 0; x < blockx; x++)
-		for(y = 0; y < blocky; y++)
-			switch(screen(x, y))
-			{
-			case EGG:
-			case BLOCK:
-				put_char(x<<5, y<<5, BLOCK, F_STORE, NULL);
-				break;
-
-			case DIAMOND:
-				put_char(x<<5, y<<5, DIAMOND, F_XOR, NULL);
-				put_char(x<<5, y<<5, BLANK, F_XOR, NULL);
-				break;
-
-			case BREAK:
-				screen(x, y) = BLANK;
-			case BLANK:
-				put_char(x<<5, y<<5, BLANK, F_STORE, NULL);
-				break;
-
-			default:	/* catch for bad things */
-				put_char(x<<5, y<<5, WALL, F_STORE, NULL);
-				break;
-			}
-	breaking.exists = FALSE;
-	moving.exists = FALSE;
-	egg_count_flag = 0;
-	show_eggs();
-	add_a_pengo();
-	x = -1;
-	for (tmp = 0; tmp < 4; tmp++)
-		if (sno_bee[tmp].exists == TRUE)
-		{
-			switch(++x)
-			{
-			case 0:
-				dx = 0;
-				dy = 0;
-				break;
-
-			case 2:
-				dx = blockx - 1;
-				dy = 0;
-				break;
-
-			case 1:
-				dx = 0;
-				dy = blocky - 1;
-				break;
-
-			case 3:
-				dx = blockx - 1;
-				dy = blocky - 1;
-				break;
-			}
-			add_sno_bee(dx, dy, x, tmp);
-		}
-	if (x == 0)
-		add_event(RUN_DELAY, run_bee, NULL);
-}
-
-int	sdir[4][2] = {
-	{1, -1},
-	{1, 1},
-	{-1, -1},
-	{-1, 1},
-};
-
-add_sno_bee(dx, dy, x, num)
-int	dx;
-int	dy;
-int	x;
-int	num;
-{
-	int	mx = sdir[x][0];
-	int	my = sdir[x][1];
-	int	mn = min(blockx, blocky);
-	int	tmp;
-	for (tmp = 0; tmp < mn; tmp++)
-	{
-		int	tmp1;
-
-		for(tmp1 = 0; tmp1 <= tmp; tmp1++)
-		{
-			if (screen (dx + mx * tmp1, dy + my * tmp) == BLANK)
-			{
-				sno_bee[num].x = (dx + mx * tmp1) << 5;
-				sno_bee[num].y = (dy + my * tmp) << 5;
-				sno_bee[num].other = SNO_BEE;
-				add_event(MOVE_BEE0, move_sno_bee, num);
-				put_char(
-					sno_bee[num].x,
-					sno_bee[num].y,
-					SNO_BEE,
-					F_XOR, num);
-				return;
-			}
-			if (screen (dx + mx * tmp, dy + my * tmp1) == BLANK)
-			{
-				sno_bee[num].x = (dx + mx * tmp) << 5;
-				sno_bee[num].y = (dy + my * tmp1) << 5;
-				sno_bee[num].other = SNO_BEE;
-				add_event(MOVE_BEE0, move_sno_bee, num);
-				put_char(
-					sno_bee[num].x,
-					sno_bee[num].y,
-					SNO_BEE,
-					F_XOR, num);
-				return;
-			}
-		}
-	}
-}
//GO.SYSIN DD init.c
echo level.c 1>&2
sed 's/.//' >level.c <<'//GO.SYSIN DD level.c'
-#include "pengo.h"
-
-#define	MAX_LEVEL	8	/* maximum level reached in display routines */
-
-Rectangle	dsp0	= { { 0, 0 }, { 0, 0 } }; /* 5 * 1 rectangle */
-Rectangle	dsp1	= { { 0, 0 }, { 0, 0 } }; /* 5 * 2 rectangle */
-Rectangle	dsp2	= { { 0, 0 }, { 0, 0 } }; /* 3 * 2 rectangle */
-
-level_dance(level)
-int	level;
-{
-	Point	tmp;
-
-	int	blkx;
-	int	blky;
-	int	x;
-
-	blkx = (board.corner.x - board.origin.x) >> 5;
-	blky = (board.corner.y - (board.origin.y + 128)) >> 5;
-
-	dsp0.origin.x = board.origin.x + (((blkx - 5) >> 1) << 5);
-	dsp0.origin.y = board.origin.y + 128 + (((blky - 1) >> 1 ) << 5);
-	dsp0.corner = add(dsp0.origin, Pt(5 * 32, 32));
-	dsp1.origin = dsp0.origin;
-	dsp1.corner = add(dsp1.origin, Pt(5 * 32, 2 * 32));
-	dsp2.origin = add(dsp0.origin, Pt(0, 32));
-	dsp2.corner = add(dsp2.origin, Pt(3 * 32, 2 * 32));
-	pengo.movex = 8;
-	pengo.movey = 0;
-	switch(level % (MAX_LEVEL + 2))
-	{
-	case 2:
-	case 4:
-	case 6:		/* to save space */
-		tmp.x = board.origin.x - (32 + 8) * 2;
-		tmp.y = dsp0.origin.y;
-		dance_4(tmp, PENGO, NULL);
-		while(tmp.x < dsp0.origin.x)
-		{
-			sleep((int)DANCE_PENGO);
-			dance_4(tmp, PENGO, NULL);
-			tmp.x += 8;
-			dance_4(tmp, PENGO, NULL);
-		}
-		sleep((int)DANCE_PENGO);
-		dance_4(tmp, PENGO, NULL);
-		switch(level % (MAX_LEVEL + 2))
-		{
-		case 6:
-			dance_4(tmp, SALUTE, NULL);
-			sleep((int)PENGO_SALUTE);
-			dance_4(tmp, SALUTE, NULL);
-			break;
-
-		case 4:
-			dance_4(tmp, BACK, NULL);
-			sleep((int)DANCE_PENGO);
-			dance_4(tmp, BACK, NULL);
-			dance_4(tmp, WIGGLE, 0);
-			for (x = 0; x < NUM_WIGGLE; x++)
-			{
-				sleep((int)PENGO_W_TIME);
-				dance_4(tmp, WIGGLE, x & 1);
-				dance_4(tmp, WIGGLE, (x + 1) & 1);
-			}
-			sleep((int)DANCE_PENGO);
-			dance_4(tmp, WIGGLE, x & 1);
-			break;
-
-		case 2:
-			dance_4(tmp, HULA, 0);
-			sleep((int)PENGO_HULA);
-			dance_4(tmp, HULA, 0);
-			for (x = 0; x < NUM_HULA; x++)
-			{
-				int	i;
-
-				for (i = 0; i < NUM_HULA0; i++)
-				{
-					dance_4(tmp, HULA, 2);
-					sleep((int)PENGO_HULA);
-					dance_4(tmp, HULA, 2);
-					dance_4(tmp, HULA, 1);
-					sleep((int)PENGO_HULA);
-					dance_4(tmp, HULA, 1);
-				}
-				dance_4(tmp, HULA, 2);
-				sleep((int)PENGO_HULA);
-				dance_4(tmp, HULA, 2);
-				dance_4(tmp, HULA, 4);
-				sleep((int)PENGO_HULA);
-				dance_4(tmp, HULA, 4);
-				for (i = 0; i < NUM_HULA0; i++)
-				{
-					dance_4(tmp, HULA, 3);
-					sleep((int)PENGO_HULA);
-					dance_4(tmp, HULA, 3);
-					dance_4(tmp, HULA, 4);
-					sleep((int)PENGO_HULA);
-					dance_4(tmp, HULA, 4);
-				}
-			}
-			dance_4(tmp, HULA, 0);
-			sleep((int)PENGO_HULA);
-			dance_4(tmp, HULA, 0);
-		}
-		dance_4(tmp, PENGO, NULL);
-		while(ptinrect(tmp, board))
-		{
-			sleep((int)DANCE_PENGO);
-			dance_4(tmp, PENGO, NULL);
-			tmp.x += 8;
-			dance_4(tmp, PENGO, NULL);
-		}
-		sleep((int)DANCE_PENGO);
-		dance_4(tmp, PENGO, NULL);
-		break;
-
-	case 8:
-		tmp = add(dsp0.origin, Pt(32, 32));
-		level_put_char(add(tmp, Pt(00, 00)), CHAIR, F_XOR, 0);
-		level_put_char(add(tmp, Pt(32, 00)), VIDEO, F_XOR, 0);
-		level_put_char(add(tmp, Pt(63, 00)), CHAIR, F_XOR, 1);
-		level_put_char(add(tmp, Pt(62, -9)), PLAYERR, F_XOR, 0);
-		level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 0);
-		for (x = 0; x < NUM_BOUNCE; x++)
-		{
-			sleep((int)SHOW_VIDEO);	/* each bounce */
-			level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 0);
-			level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 1);
-		}
-		sleep((int)SHOW_VIDEO);	/* still beginning */
-		level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 0);
-		level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 1);
-		for (x = 0; x < NUM_BOUNCE; x++)
-		{
-			sleep((int)SHOW_VIDEO);	/* each bounce */
-			level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 0);
-			level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 1);
-		}
-		sleep((int)SHOW_VIDEO);	/* last bounce, right turns head */
-		level_put_char(add(tmp, Pt(62, -9)), PLAYERR, F_XOR, 0);
-		level_put_char(add(tmp, Pt(62, -9)), PLAYERR, F_XOR, 1);
-		sleep((int)SHOW_VIDEO);	/* delay whils right turns head */
-		for (x = 0; x < NUM_BOUNCE; x++)
-		{
-			sleep((int)SHOW_VIDEO);	/* each bounce */
-			level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 0);
-			level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 1);
-		}
-		sleep((int)SHOW_VIDEO);
-		level_put_char(add(tmp, Pt(01, -9)), PLAYERL, F_XOR, 1);
-		level_put_char(add(tmp, Pt(62, -9)), PLAYERR, F_XOR, 1);
-		level_put_char(add(tmp, Pt(00, 00)), CHAIR, F_XOR, 0);
-		level_put_char(add(tmp, Pt(32, 00)), VIDEO, F_XOR, 0);
-		level_put_char(add(tmp, Pt(63, 00)), CHAIR, F_XOR, 1);
-
-	default:
-		break;
-	}
-}
-
-dance_4(tmp, ch, other)
-Point	tmp;
-int	ch;
-int	other;
-{
-	int	x;
-
-	for (x = 0; x < 4; x++)
-		level_put_char(add(tmp, Pt((32 + 8) * x, 0)), ch, F_XOR, other);
-}
-
-level_put_char(tmp, ch, format, other)
-Point	tmp;
-int	ch;
-int	format;
-int	other;
-{
-	int	tmp0;
-
-	if (!ptinrect(tmp, dboard))
-		return;
-	switch(ch)
-	{
-	case PENGO:
-		if (pengo.movex)
-			if (pengo.movex < 0)
-				tmp0 = 1;
-			else
-				tmp0 = 3;
-		else
-			if (pengo.movey < 0)
-				tmp0 = 5;
-			else if (pengo.movey)
-				tmp0 = 7;
-			else
-				tmp0 = 0;
-		if (tmp.x & 16)
-			tmp0++;
-		bit32.base = (Word *)pengo_moves[tmp0];	
-		break;
-
-	case BACK:
-		bit32.base = (Word *)char_pback;
-		break;
-
-	case WIGGLE:
-		bit32.base = (Word *)(other ? char_1wiggle : char_0wiggle);
-		break;
-
-	case SALUTE:
-		bit32.base = (Word *)char_salute;
-		break;
-
-	case HULA:
-		bit32.base = (Word *)hula_moves[other];
-		break;
-
-	case CHAIR:
-		bit32.base = (Word *)(other ? char_rchair : char_lchair);
-		break;
-
-	case VIDEO:
-		bit32.base = (Word *)(other ? char_null : char_0video);
-		break;
-
-	case PLAYERR:
-		bit32.base = (Word *)(other ? char_0rplayer : char_1rplayer);
-		break;
-
-	case PLAYERL:
-		bit32.base = (Word *)(other ? char_0lplayer : char_1lplayer);
-		break;
-
-	default:
-		bit32.base = (Word *)char_null;
-		break;
-
-/* others here ... */
-	}
-	bitblt(&bit32, Rect(0, 0, 32, 32), &display,
-		add(board.origin, Pt(tmp.x, tmp.y)), format);
-}
-
-int	padd_score[] = { 5000, 1000, 500, 100, 10, 1, 0, };
-
-extra_score(seconds)
-int	seconds;
-{
-	Point	tmp;
-	int	count;
-
-	if (seconds < 0)
-		seconds = 0;
-	tmp.x = board.origin.x + (board.corner.x - board.origin.x - 16 * 16) / 2;
-	tmp.y = board.origin.y + 16;
-	rectf(&display, board, F_STORE);
-	addstr("Time Taken ....", tmp, F_CLR);
-	add_time(seconds, add(tmp, Pt(16 * 15, 0)));
-	tmp.y += 16;
-	addstr(" 0 ...  9  5000", tmp, F_CLR);
-	tmp.y += 16;
-	addstr("10 ... 19  1000", tmp, F_CLR);
-	tmp.y += 16;
-	addstr("20 ... 29   500", tmp, F_CLR);
-	tmp.y += 16;
-	addstr("30 ... 39   100", tmp, F_CLR);
-	tmp.y += 16;
-	addstr("40 ... 49    10", tmp, F_CLR);
-	tmp.y += 16;
-	addstr("50 ... 59     1", tmp, F_CLR);
-	tmp.y += 16;
-	addstr("Over 59 NO BONUS", tmp, F_CLR);
-	if (seconds >= 60)
-		seconds = 60;
-	rectf(&display, Rect(
-		board.origin.x,
-		board.origin.y + ((seconds/10) * 16) + 32,
-		board.corner.x,
-		board.origin.y + ((seconds/10) * 16) + 48), F_XOR);
-	put_score(score += padd_score[(seconds / 10) % 7]);
-	count = 0;
-	if (button123())
-		for (;count < 60; count++)
-			if (!button123())
-				break;
-			else
-				sleep(2);
-	for (;count < 60; count++)
-		if (button123())
-			break;
-		else
-			sleep(2);
-	while(button123())
-		wait(CPU);
-}
-
-add_time(seconds, pos)
-int	seconds;
-Point	pos;
-{
-	if (!seconds)
-	{
-		addstr("0 seconds", pos, F_CLR);
-		return;
-	}
-	if (seconds > 3600)	/* 1 hour */
-	{
-		addstr("Over 1 Hour", pos, F_CLR);
-		return;
-	}
-	if (seconds > 60)
-	{
-		int	minutes;
-
-		minutes = seconds / 60;
-		if (minutes > 10)
-		{
-			addchar((minutes / 10) + '0', pos, F_CLR);
-			pos.x += 16;
-		}
-		addchar((minutes % 10) + '0', pos, F_CLR);
-		seconds = seconds % 60;
-		pos.x += 16;
-		addstr(" Min:", pos, F_CLR);
-		pos.x += 5 * 16;
-	}
-	if (seconds > 10)
-	{
-		addchar((seconds / 10) + '0', pos, F_CLR);
-		pos.x += 16;
-	}
-	addchar((seconds % 10) + '0', pos, F_CLR);
-	pos.x += 16;
-	addstr(" Sec", pos, F_CLR);
-}
//GO.SYSIN DD level.c
echo mouse.c 1>&2
sed 's/.//' >mouse.c <<'//GO.SYSIN DD mouse.c'
-/*
-	mouse looker after...
-
-	Self contained mouse handler
-*/
-
-#include "pengo.h"
-
-char	*menu3text[] = { "Pause", "Stats", "New Game", "Quit", NULL };
-
-#define M_PAUSE	0
-#define	M_STATS	1
-#define	M_NEW	2
-#define	M_QUIT	3
-
-Menu	menu3 = { menu3text };
-Texture skull = {
-	 0x03C0, 0x0660, 0x0810, 0x0A50,
-	 0x1248, 0x1008, 0x1998, 0x0C30,
-	 0x0000, 0x0180, 0x0660, 0x0420,
-	 0x0020, 0x00C0, 0x0100, 0x0100,
-};
-
-Texture sunset = {
-	0x5006, 0xA819, 0x00A0, 0x04A0,
-	0x049F, 0x12A4, 0x0808, 0x03E0,
-	0x2412, 0x0808, 0x0808, 0x3FFF,
-	0x3C1F, 0x7E7E, 0x783E, 0xFCFC,
-};
-
-Texture sleepz = {
-	0xF800, 0xF800, 0x1800, 0x3000,
-	0x67C0, 0xC7C0, 0xF8C0, 0xF980,
-	0x033E, 0x063E, 0x07C6, 0x07CC,
-	0x0018, 0x0030, 0x003E, 0x003E,
-};
-
-Texture	grey = {
-	0xAAAA, 0x5555, 0xAAAA, 0x5555,
-	0xAAAA, 0x5555, 0xAAAA, 0x5555,
-	0xAAAA, 0x5555, 0xAAAA, 0x5555,
-	0xAAAA, 0x5555, 0xAAAA, 0x5555,
-};
-
-Texture	*old;
-
-Rectangle	graph;
-Rectangle	graphc;
-Rectangle	graphr;
-Rectangle	graphb;
-
-short	gstore[6 * 120];	/* storage for tmp store */
-
-Bitmap	graphs	= { (Word *) gstore, shorts(6), { { 0, 0 }, { 16 * 5, 120 } } };
-
-wait_mouse()
-{
-	while (!(own() & MOUSE))
-	{
-		wait(CPU);
-		old_mouse = mouse.xy;
-	}
-	hit = button1() ? TRUE : hit;
-	if (button3())
-	{
-		old = cursswitch((Word *)0);
-		switch (menuhit(&menu3, 3))
-		{
-		case M_QUIT:
-			cursswitch(&sunset);
-			while (!button12())
-				if (button3())
-					exit();
-				else
-					wait(CPU);
-			break;
-		case M_NEW:
-			cursswitch(&skull);	/* pause cursor */
-			while (!button12())
-				if (button3())
-				{
-					extern	int	reshaped;
-
-					cursswitch(old);
-#ifdef	JERQ
-#ifndef	MPX
-/*
- *	Don't know why these lines have to be here, but only on
- *	stand alone jerq the 'cursswitch(old)' leaves the old
- *	cursor in place... very strange.
- */
-					cursswitch(char_space);
-#endif	MPX
-#endif	JERQ
-#ifdef	MPX
-					P->state |= RESHAPED;  /* force a restart */
-#else
-					reshaped = TRUE;
-#endif
-					return(TRUE);
-				}
-				else
-					wait(CPU);
-			break;
-		case M_PAUSE:
-			cursswitch(&sleepz);
-			while(!button3())
-				wait(CPU);
-			while(button3())
-				wait(CPU);
-			break;
-
-		case M_STATS:	/* change movement stats */
-			graph.origin =
-				add(
-					board.origin,
-					div(
-						sub(
-							sub(
-								board.corner,
-								board.origin
-							),
-							Pt(80, 120)
-						),
-						2
-					)
-				);
-			graph.corner = add(graph.origin, Pt(80, 120));
-			cursswitch(old);
-#ifdef	JERQ
-#ifndef	MPX
-			cursswitch(char_space);
-#endif	MPX
-#endif	JERQ
-			bitblt(&display, raddp(graphs.rect, graph.origin),
-				&graphs, Pt(0,0), F_STORE);	/* save display */
-			graphc = raddp(Rect(0, 16, 20, 120), graph.origin);
-			graphr = raddp(graphc, Pt(30, 0));
-			graphb = raddp(graphr, Pt(30, 0));
-			rectf(&display, graph, F_CLR);
-			bitblt(bchar('C'), Rect(0,0,16,16), &display,
-				graph.origin, F_STORE);
-			bitblt(bchar('R'), Rect(0,0,16,16), &display,
-				add(graph.origin, Pt(30, 0)), F_STORE);
-			bitblt(bchar('B'), Rect(0,0,16,16), &display,
-				add(graph.origin, Pt(60, 0)), F_STORE);
-			rectf(&display, graphc, F_STORE);
-			rectf(&display, inset(graphc, 1), F_CLR);
-			rectf(&display, graphr, F_STORE);
-			rectf(&display, inset(graphr, 1), F_CLR);
-			rectf(&display, graphb, F_STORE);
-			rectf(&display, inset(graphb, 1), F_CLR);
-			gdisp(inset(graphc, 2), sb_change);
-			gdisp(inset(graphr, 2), sb_random);
-			gdisp(inset(graphb, 2), sb_break);
-			cursswitch((Word *)0);
-			sleep(2);	/* sync */
-			while(!button3())
-			{
-				/* here we adjust the graphs */
-				if (ptinrect(mouse.xy, inset(graphc,2))&& button1())
-					mgdisp(graphc, &sb_change);
-				if (ptinrect(mouse.xy, inset(graphr,2))&& button1())
-					mgdisp(graphr, &sb_random);
-				if (ptinrect(mouse.xy, inset(graphb,2))&& button1())
-					mgdisp(graphb, &sb_break);
-			}
-			while(button3())
-				wait(CPU);
-			cursswitch(old);
-#ifdef	JERQ
-#ifndef	MPX
-			cursswitch(char_space);
-#endif	MPX
-#endif	JERQ
-			bitblt(&graphs,graphs.rect,&display,graph.origin, F_STORE);
-			break;
-
-		default:
-			/* shouldn't happen */
-			exit(2);
-		}
-		cursswitch(old);
-#ifdef	JERQ
-#ifndef	MPX
-		cursswitch(char_space);
-#endif	MPX
-#endif	JERQ
-	}
-	return(FALSE);
-}
-
-gdisp(box, value)
-Rectangle	box;
-int		value;
-{
-	texture(&display,
-		Rect(
-			box.origin.x,
-			box.corner.y - value,
-			box.corner.x,
-			box.corner.y
-		),
-		&grey,
-		F_STORE);
-	rectf(&display,
-		Rect(
-			box.origin.x,
-			box.origin.y,
-			box.corner.x,
-			box.corner.y - value
-		),
-		F_CLR);
-}
-
-mgdisp(box, vp)
-Rectangle	box;
-int		*vp;
-{
-	Point	tmp;
-
-	cursswitch(old);
-#ifdef	JERQ
-#ifndef	MPX
-	cursswitch(char_space);
-#endif	MPX
-#endif	JERQ
-	while (button1() && ptinrect((tmp = mouse.xy), inset(box, 2)))
-	{
-		cursswitch((Word *)NULL);
-		*vp = box.corner.y - tmp.y - 2;
-		sleep(2);			/* sync with display */
-		cursswitch(old);
-#ifdef	JERQ
-#ifndef	MPX
-		cursswitch(char_space);
-#endif	MPX
-#endif	JERQ
-		rectf(&display, box, F_STORE);
-		gdisp(inset(box, 2), *vp);	/* put it on the screen */
-	}
-	rectf(&display, box, F_STORE);
-	rectf(&display, inset(box, 1), F_CLR);
-	gdisp(inset(box, 2), *vp);
-	cursswitch((Word *)NULL);
-}
//GO.SYSIN DD mouse.c

From utcsri!drb Tue Jul  1 01:37:38 1986
Received: by utcsri.uucp id AA05898; Tue, 1 Jul 86 01:37:38 edt
Date: Tue, 1 Jul 86 01:37:38 edt
From: David R. Blythe <utcsri!drb>
Message-Id: <8607010537.AA05898@utcsri.uucp>
To: research!v8news
Subject: troff bug (minor)

There is a minor bug in troff when it tries to load an extra font description.
It reads in the font description in to font position 0. It only reads in as
much of the width table as it has storage for, and saves the size of the old
width table. After reading in the font description, it checks to see whether
it had room for the whole table.  If it did not have room it returns an error;
however, it does not restore the old width table size, so it may corrupt some
memory the next time it attempts to read in a font description with a width
table larger than the storage space. (This probably only happens when you try
to print out a short catalog of all your fonts). A suggested bug fix follows.
	A second minor problem occurs when you try to increase the amount of
space for width table in font position 0. Presumably one does this by 
increasing the size of the constant EXTRAFONT in tdefs.h, but one must use
caution as this number less some amount for the font header and sundries
is assigned to a char variable. Thus if you brashly increase EXTRAFONT to
some large number it may have little impact as only the lower 8 bits of the 
remaining sum is recorded. Not so much a bug as an annoyance.

	-drb

diff -c -r1.1 t6.c
*** /tmp/,RCSt1005535	Tue Jul  1 01:08:53 1986
--- t6.c	Mon Jun 30 23:52:05 1986
***************
*** 637,643
  	/* have to reset the fitab pointer because the width may be different */
  	fitab[pos] = (char *) fontab[pos] + 3 * (fontbase[pos]->nwfont & BYTEMASK);
  	if ((fontbase[pos]->nwfont & BYTEMASK) > n) {
 		errprint("Font %s too big for position %d", shortname, pos);
  		return(-1);
  	}
  	fontbase[pos]->nwfont = n;	/* so can load a larger one again later */

--- 637,644 -----
  	/* have to reset the fitab pointer because the width may be different */
  	fitab[pos] = (char *) fontab[pos] + 3 * (fontbase[pos]->nwfont & BYTEMASK);
  	if ((fontbase[pos]->nwfont & BYTEMASK) > n) {
 		errprint("Font %s too big for position %d", shortname, pos);
! 		fontbase[pos]->nwfont = n;	/* for next time */
  		return(-1);
  	}
  	fontbase[pos]->nwfont = n;	/* so can load a larger one again later */

From acsnet!basser!rex Thu Jul 17 18:22:21 1986
To: v8source@research 
Subject: pengo bug fix

These are the context diffs to correct a problem with Pengo exiting when
no selection is done on a button 3 menu.

*** mouse.old	Tue Jul 15 14:19:54 1986
--- mouse.c	Thu Jul 17 18:20:41 1986
***************
*** 8,14
  
  char	*menu3text[] = { "Pause", "Stats", "New Game", "Quit", NULL };
  
! #define M_PAUSE	0
  #define	M_STATS	1
  #define	M_NEW	2
  #define	M_QUIT	3

--- 8,15 -----
  
  char	*menu3text[] = { "Pause", "Stats", "New Game", "Quit", NULL };
  
! #define	M_NONE	-1
! #define	M_PAUSE	0
  #define	M_STATS	1
  #define	M_NEW	2
  #define	M_QUIT	3
***************
*** 66,71
  		old = cursswitch((Word *)0);
  		switch (menuhit(&menu3, 3))
  		{
  		case M_QUIT:
  			cursswitch(&sunset);
  			while (!button12())

--- 67,75 -----
  		old = cursswitch((Word *)0);
  		switch (menuhit(&menu3, 3))
  		{
+ 		case M_NONE:	/* no selection */
+ 			break;
+ 
  		case M_QUIT:
  			cursswitch(&sunset);
  			while (!button12())
***************
*** 177,184
  			break;
  
  		default:
! 			/* shouldn't happen */
! 			exit(2);
  		}
  		cursswitch(old);
  #ifdef	JERQ

--- 181,190 -----
  			break;
  
  		default:
! 			/* shouldn't happen, this means that menu has
! 			   stuffed up	*/
! 
! 			break;	/* don't exit */
  		}
  		cursswitch(old);
  #ifdef	JERQ

From utzoo!henry Wed Aug  6 18:40:29 1986
To: research!v8news
Subject: error in user.h comment

Trivia Dept:  The comment on u_limit in user.h refers to <sys/limit.h>,
which does not exist.  Should be <sys/vlimit.h>.


From yquem!jim Fri Aug  8 01:20 EDT 1986
Subject: awk on foreign systems

has anyone tried running the v8 distributed awk on a 4.[23]
system? it compiles, but the following is a stripped test
program which fails with the message

	unexpected break, continue or next
	 source line number 6

(the real program with actual data in the array 'servers'
fails in the same way).

--jim	(bellcore!jim)

------------------
BEGIN {
	for (i in servers) {
		printf "server %s in file %s\n", i, servers[i]
	}
}

From yquem!jim Fri Aug  8 01:36 EDT 1986
Subject: a real awk bug

the routines openfile and closefile in run.c
should check that files[i].fname isn't NULL before
using it in a strcmp. otherwise, statements like

	close(file)

where 'file' is uninitialised, can cause a core-dump.

--jim

From yquem!jim Tue Aug 12 00:59 EDT 1986
Subject: bug in awk

there is a missing
	return (true);
at the end of instat() in run.c. depending on your
compiler, this may cause random weirdness.

--jim

From utzoo!henry Wed Aug 13 19:05:40 1986
To: research!v8news
Subject: rmdir(2) bug

Unless I have missed something subtle -- I haven't had a chance to try
this out on a running V8 yet -- there is an unpleasant bug in the rmdir
code in nami.c.  The code rejects attempts to remove a directory with
a link count greater than 2, but this check occurs *after* the parent's
link count is decremented.  So a side effect of having a rmdir rejected
for this reason is that the next directory up will have its link count
damaged.  Inspection of the code suggests that the following:

			if(dp->i_nlink > 0)
				dp->i_nlink--;
			if(dip->i_nlink <= 2)
				dip->i_nlink = 0;
			else {
				u.u_error = EBUSY;
				iput(dip);
				goto out;
			}

should really be

			if(dip->i_nlink <= 2)
				dip->i_nlink = 0;
			else {
				u.u_error = EBUSY;
				iput(dip);
				goto out;
			}
			if(dp->i_nlink > 0)
				dp->i_nlink--;

at around line 325 in nami.c.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From utzoo!henry Thu Aug 14 16:25:02 1986
To: research!v8news
Subject: signal(2) omits trivia

Documentation speak with (slightly) forked tongue...  Signal(2) lists a
modest variety of signals and then claims that the rest "have no
conventional meaning in this system".  Not quite so; the kernel is
willing to generate SIGXCPU and SIGXFSZ.  Admittedly, one would first
have to use the officially-deprecated vlimit() call to set non-infinite
values for the limits, which relegates this to the trivia department.
But the conventional meanings of those signals aren't quite gone yet.


From yquem!jim Sat Aug 16 00:25 EDT 1986
Subject: Re: porting awk
another thing to beware of when moving programs
to bsd systems is popen. it doesn't close all
unnecessary open file descriptors after forking,
with the result that if a process (such as v8 awk)
does more than one popen, the children of the
subsequent popen's get a copy of the previous popen
fd's, causing pclose to hang as the parent's pclose
doesn't cause the child to get an eof.

--jim

From utzoo!henry Sun Aug 17 01:23:58 1986
To: research!v8news
Subject: alarm(2) manpage lies

Alarm(2) claims the longest delay is 2147483647 seconds.  Nope, it's 65535.


From utzoo!henry Tue Aug 19 12:15:21 1986
To: research!v8news
Subject: probably-undesired behavior in dup2()

It would appear that dup2(), when replacing an existing descriptor, does
not clear the close-on-exec flag, so the new duplicate descriptor inherits
it from the former occupant of that slot (rather than from the duplicated
descriptor, which would seem more reasonable).


From utzoo!henry Tue Aug 19 12:17:16 1986
To: research!v8news
Subject: the ghost of the pdp11

Amusingly, the sbreak() code checks the old u_sep flag to find out
whether you're running your VAX split-I/D!  Nothing else ever touches
or sets the flag, so of course it's always zero...


From utzoo!henry Tue Aug 19 12:21:41 1986
To: research!v8news
Subject: unportable assumptions in exec

I note with displeasure that the exec stuff assumes that a negative return
from fuword is a fault.  Just as well that legitimate user addresses must
appear positive on the VAX.


From utzoo!henry Thu Aug 21 14:47:13 1986
To: research!v8news
Subject: cv.c calls physio improperly

cv.c invokes physio() with six parameters.  It only takes five.


From utzoo!henry Tue Sep  9 13:29:56 1986
To: research!v8news
Subject: docgen(1)

The V8 distribution includes a manual page docgen(1), but not the program,
its library, or the longer document referred to in the manual page.  It
would appear that the fix is to delete the manual page.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From wild!andrew Fri Oct  3 16:06 EDT 1986
To: v8news
Subject: dhv driver

there is now a dhv driver for V9. while the dhv is a Qbus device,
it is a good base for a dhu driver.

warning: the dhv is unrelated in every meaningful way to a dh

From utzoo!henry Fri Oct 17 15:32:22 1986
To: research!v8news
Subject: possible bugs in streamio.c

A thorough reading of sys/streamio.c, done because I didn't understand its
detailed workings, has disclosed several anomalies that may in fact be bugs.

stopen() calls flushq() with only one argument.  This is clearly wrong.
I suspect the second argument should be 1 here.

stread()'s M_PASS-punting code does not stexit().  This flaw is carried over
into istread().  Unless I have missed something subtle, it's a bug.

The loop conditions in stwrite() and istwrite()'s wait-for-room loops are
different, with stwrite() testing for HUNGUP first and istwrite() looking
at QFULL before checking for HUNGUP.  Looks to me like testing for HUNGUP
first is the right thing to do, on the grounds that assuming the validity
of the "next" pointer on a hung-up stream is a bad idea.  I speculate that
istwrite() was cloned from stwrite() and a later fix to stwrite() did not
get propagated.

In stioctl(), the ack-analysis code that copes with unknown ack types
prints a complaint but then does not do a freeb() on the peculiar block.
This will result in the loss of that block from the pool.  This may be
deliberate, on the grounds that the safest thing to do with a possibly-
corrupt block is to lose it.  On the other hand, no attempt is made to
note the address of the block for analysis, so I think it's an accidental
omission.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From utzoo!henry Fri Oct 17 15:58:07 1986
To: research!v8news
Subject: wrong comment in stream.h

In h/stream.h, it is claimed that queue.count is "number of blocks on Q".
This is both wrong and misleading; it's actually a measure of the volume
of data on the queue.  (It's not quite a byte count because of the
difference between rbsize[] and bsize[] in dev/stream.c.  I assume the
distinction for big blocks is for one of three reasons:  (a) give big
blocks preferential treatment since they are nice; (b) avoid having a
single big block hit high-water limits; or (c) avoid overflow problems
since queue.count is only a short.)

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From dutoit!dmr Sat Oct 18 00:33 EDT 1986
Subject: Henry's remarks
To: v8news

stopen calling flushq with one arg: yes, a bug; it is fixed here,
and the 2nd arg is indeed 1.

stread and M_PASS: looks like a bug to me; still present here.
I'm surprised it doesn't cause more trouble.

The HUNGUP test in istwrite should be the same as stwrite's to
minimize confusion if for no other reason.  I think the difference
is harmless in that I believe there should be no loose next pointers,
but safety first.

I might count the lack of a freeb() on a wrong value in in the ioctl
ack cell as deliberate, though I doubt it was.  If the diagnostic
occurs, something is wrong and should be fixed.  But adding a freeb()
won't hurt.

The comment about the comment about number of blocks on Q (stream.h)
is to the point; as Henry observed, the count is neither number of
bytes nor number of data blocks but an oddly weighted byte count.
(The lack of an accurate data byte count is annoying to some protocols, BTW).
All of this nonsense owes to the simple-minded allocator, and a not
very carefully worked out theory about how to do the flow control.

The reason for the weighting (with rbsize) is that to make things
like pipes and networks fast, one needs large limits and large blocks
for those streams; but if one writes to a stream with a large limit
and no big blocks happen to be available, it is too easy to gobble
huge numbers of small blocks.  It would be worth while to rethink
the allocation strategy in general.  I suppose a case could be made
that it is better to count blocks than bytes (this could
be achieved by adjusting rbsize, but care would then have to be given
to all the magic high/low water mark numbers).  As I recall, the SVr3
streams rethink this to some extent, but I don't have the details at hand.

Two thoughts that have been for around for a while (but remain untried)
are to grab system buffers to store the data in big blocks (this just
avoids the static allocation for big buffers) and to have a more
general allocator instead of stratifying stream blocks statically
into sizes 4,16,64,(1024).

Thanks for reading the code!  Further comments are welcome.

	Dennis


From utzoo!henry Sun Oct 19 01:47:04 1986
To: research!v8news
Subject: minor oddity in streamio.c

One slight peculiarity that I can't see any reason for:  in the already-
streaming case in stopen(), we have "qp = ip->i_sptr->wrq", although we
already have ip->i_sptr in the register variable sp.  Uses of sp abound
in the vicinity, so unless I have missed some *very* subtle race condition,
the code should be "qp = sp->wrq".  Not at all important, just cleanliness
and consistency.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From wild!piers Wed Oct 22 12:43 EDT 1986
To: v8news
Subject: stream counts

Dennis' note about stream counts not being representative of
byte counts reminded me of similar problems we had in Sydney.
I was writing a line discipline for a simple packet protocol
that needed to know the up-stream byte count in order to allocate
flow-control properly. I ``fixed'' the problem by changing
getq() and putq() to maintain the byte count in ``count''.
However, as Dennis points out, this allowed large numbers of
small blocks to flood the queue if there were a lot of M_DELIMs
being generated. So the solution was a partial re-instatement
of the previous method, in that non-M_DATA blocks were made
to count as 64 bytes. This seemed to solve the problem for all
but pipes. Pipes were now not being allocated enough queue space,
and this was solved by introducing separate "pip[rw]data" qinit
structures to be used for pipes in place of the default
"st[rw]data" structures in streamio.c.

One further change was made, to introduce blocks of size 256 for
use by the packet protocol line-discipline, whose packet sizes
were around 132 bytes. This was considered more efficient than
allocating more 1024 byte blocks and only partially filling them.

From mcvax!kelpie.ncl.ac.uk!andy Wed Oct 29 12:41:50 1986
Received: by mcvax.uucp; Wed, 29 Oct 86 12:41:50 +0100 (MET)
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a004043; 29 Oct 86 9:58 GMT
Via: kelpie.newcastle.ac.uk ; Wed, 29 Oct 86 09:59:13 gmt
From: Andy Linton <mcvax!kelpie.ncl.ac.uk!andy>
Date: Wed, 29 Oct 86 09:59:55 gmt
Message-Id: <22824.8610290959@kelpie.newcastle.ac.uk>
To: research!v8news
Subject: DHV driver


A few weeks back someone offered a DHV driver.
Is it possible to get a copy?
Thanks
andy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SENDER 	: Andy Linton		PHONE	: +44 91 232 9233
POST	: Computing Lab, University of Newcastle upon Tyne, UK, NE1 7RU
ARPA	: andy%cheviot.newcastle.ac.uk@cs.ucl.ac.uk
JANET	: andy@uk.ac.newcastle.cheviot
UUCP	: andy@cheviot.UUCP

***  Ni fui moran beagan d'aon rud, ach is fui moran beagan ceille.  ***

From utzoo!henry Wed Oct 29 11:48:13 1986
To: research!v8news
Subject: minor goof in ttyld.c

Ttyld.c/ttysig() calls putctl1() twice, the first time with the wrong
number of arguments.  From context it is fairly clear that the call
"putctl1(q->next, M_FLUSH)" should be "putctl(q->next, M_FLUSH)".


From utzoo!henry Tue Jan 27 17:23:06 1987
To: research!v8news
Subject: XDR stream module

Pure curiosity, no immediate application:  has anyone considered doing an
XDR (Sun NFS's eXternal Data Representation) stream module?  This would,
in principle, permit connecting a stream on one system to a stream on
another, with the type of messages being conveyed through and with data
representations adjusted to match.  M_DATA would presumably have to go
out as unstructured bytes, but things like ioctls could in principle be
translated.  The XDR module would presumably have to know about ioctls and
reject unknown ones, but it could still be useful.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From dmr Sun Feb  8 02:05 EST 1987
Subject: running v8 on big-memory machines
To: v8news

Ted Kowalski (research!frodo) says that the following changes suffice
to use more than 8MB of memory, if you have it.  He also points
out that if you do crash dumps to your swap area, you should make
sure it is big enough.

First, line 507 of lowmem.c, which was

	acbl	$8*1024*1024-1,$64*1024,r7,1b

needs to have the '8' fixed--it is the maximum number of megabytes
looked for.  [Talk about magic numbers!  Let's trust this
came directly from UCB.]  Second, fields in the cmap structure need
to be readusted.  Ted affirms that this one works.  It is a shell
archive, with only 1 file in it.

# sh me please
sed 's/.//' <<'Sooterkin' > "cmap.h"
X/*
X * core map entry
X *
X * Limits imposed by this structure
X *
X *		limit		cur.size	fields
X *	physical memory		128 Mb		c_next, c_prev, c_hlink
X *	mounted file systems	255		c_mdev
X *	size of proc segment	1 Gb		c_page
X *	filesystem size		8 Gb		c_blkno
X *	proc, text table size	4096		c_ndx
X */
Xstruct cmap
X{
Xunsigned int 	c_next:17,	/* index of next free list entry */
X		:8,
X		c_free:1,	/* on the free list */
X		c_intrans:1,	/* intransit bit */
X		c_gone:1,	/* associated page has been released */
X		c_want:1,	/* wanted */
X		c_lock:1,	/* locked for raw i/o or pagein */
X		c_type:2,	/* type CSYS or CTEXT or CSTACK or CDATA */
X
X		c_prev:17,	/* index of previous free list entry */
X		:7,
X		c_mdev:8,	/* which mounted dev this is from */
X
X		c_hlink:17,	/* hash link for <blkno,mdev> */
X		:3,
X		c_ndx:12,	/* index of owner proc or text */
X
X		c_blkno:24,	/* disk block this is a copy of */
X		:8,
X
X		c_page:21,	/* virtual page number in segment */
X		:3,
X		:8;
X};
X
X#define	CMHEAD	0
X
X/*
X * Shared text pages are not totally abandoned when a process
X * exits, but are remembered while in the free list hashed by <mdev,blkno>
X * off the cmhash structure so that they can be reattached
X * if another instance of the program runs again soon.
X */
X#define	CMHSIZ	512		/* SHOULD BE DYNAMIC */
X#define	CMHASH(bn)	((bn)&(CMHSIZ-1))
X
X#ifdef	KERNEL
Xstruct	cmap *cmap;
Xstruct	cmap *ecmap;
Xint	ncmap;
Xstruct	cmap *mfind();
Xint	firstfree, maxfree;
Xint	ecmx;			/* cmap index of ecmap */
Xshort	cmhash[CMHSIZ];
X#endif
X
X/* bits defined in c_type */
X
X#define	CSYS		0		/* none of below */
X#define	CTEXT		1		/* belongs to shared text segment */
X#define	CDATA		2		/* belongs to data segment */
X#define	CSTACK		3		/* belongs to stack segment */
X
X#define	pgtocm(x)	((((x)-firstfree) / CLSIZE) + 1)
X#define	cmtopg(x)	((((x)-1) * CLSIZE) + firstfree)
Sooterkin


From mcvax!cheviot.ncl.ac.uk!andy Wed Feb 11 23:08:46 1987
Received: by mcvax.cwi.nl; Wed, 11 Feb 87 23:08:46 +0100 (MET)
Received: from cheviot.ncl.ac.uk by eagle.Ukc.AC.UK   via Janet with NIFTP
           id a003239; 11 Feb 87 17:50 GMT
From: Andy Linton <mcvax!cheviot.ncl.ac.uk!andy>
Date: Wed, 11 Feb 87 17:52:17 GMT
Message-Id: <5915.8702111752@cheviot.newcastle.ac.uk>
To: research!v8news
Subject: Increased memory sizes

The line with the offending '8' in locore.s (lowmem.c) in 4.3
has been changed to:

        acbl    $MAXMEM*1024-1,$64*1024,r7,1b
	
This section of code is otherwise the same as the 8th Edition stuff.
Looks a bit like a UCBism crept in!

cmap.h has the following definition:

#define MAXMEM          64*1024         /* maximum memory, in Kbytes */

A change to this method would make sense - with MAXMEM redefined to
128*1024, of course!

From norman Sun Feb 15 18:33 EST 1987
Before anyone takes any more unwarranted snipes at Berkeley, the
literal 8096 in the startup code is present in VAX SVR2 as well.
I'm pretty sure it was in the original 32V (unless the number there
was a literal 4096), but I don't have a copy handy to check.

From rob Mon Apr 20 17:21 EDT 1987
Subject: sam

the text editor sam is now available for release to v8 licenses.
it is considered part of the eighth edition, so if you'd like it
just drop me a note and i'll wing it over the wire.

for those unfamiliar with it, sam is approximately the union of
jim and ed, although both the jim part and the ed part have been
modified creatively.  the implementation is independent of both
editors.  the original version runs on a 5620 running mux, and
howard trickey has ported it to suns running release 3 of their
window software or version 10.something of x.  in your note, please
tell me which version[s] you would like.

-rob pike
.,

From presotto Mon May 11 11:59 EDT 1987
re: penultimate hack (i.e. probably more to follow)
Here's the relevant changes to tcp_input.c to keep the new 4.3 timeout
stupidity from not working with V8:

diff /n/bowell/v8/usr/sys/inet/tcp_input.c /n/bowell/usr/sys/inet/tcp_input.c
340,341c363,364
< 			    todrop == ti->ti_len && (tiflags&TH_FIN) == 0)
< 				goto dropafterack;
---
> 			    (todrop == ti->ti_len && (tiflags&TH_FIN) == 0))
> 				goto dropafterack2;
707a700
> dropafterack2:

Berkeley's old timeout code was outside the TCP specs, so much so that it
was illegal.  The new timeout code is better but could cause acknowledge
loops.  However, we should be protected against it.

From utzoo!henry Tue May 26 13:24:10 1987
To: research!v8news
Subject: bug in V8 troff, and fix

In t6.c/setch(), we have the following code:

		c = getach();
		while ((*s = getach()) != c && *s != '\n')
			s++;

This is attempting to gather up the character name in a \C'...' construct.
Unfortunately, it is doing it wrong:  getach() never returns '\n'.  If the
user has forgotten his closing quote, or if "\C" has gotten into his file
by accident (which is what happened here), all hell will break loose and
troff may dump core.  The fix is to change '\n' to '\0'.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry


From rob Sun Sep 27 05:23 EDT 1987
new improved sam source is available to those who would like it.
some (woe, not all) bugs fixed.
this is probably the last distribution i will make,
since little is likely to happen to it henceforth.
if you'd like it, let me know, and let me know which of the following
versions are valuable to you:
	v8/5620
	sun/sunwindows
	sun/xwindows.10
other versions exist but are not yet distributed:
	v8/630
	?/microvax
let me know if these would be useful to you.

-rob pike, research!rob

From utzoo!henry Wed Nov  4 15:42:43 1987
To: research!v8news
Subject: troff graphics primitives corrupt memory

A straight recompile of the V8 troff on a Sun dumps core when you use the
graphics primitives.  The problem, by the looks of it, is that the graphics
primitives were dropped into ptout0() rather hastily and later changes have
not considered them carefully.  In particular, just before the width
calculations start, all control (< 040) characters are trapped out *except*
DRAWFCN... and the code that follows all assumes that it never sees *any*
control characters.  This results in, among other things, random memory
corruption due to out-of-bounds accesses to the width cache.  On the Sun
this stomps a vital pointer right away, bang crash thud.  Dunno what it does
on the VAX.  The following appears to solve the problem (by moving width
calculations inside a not-DRAWFCN check -- the "width" of DRAWFCN is never
used anyway -- and putting an analogous check in at one other potential
trouble spot):

--------------------------------------------------------
*** /tmp/oldt10.c	Wed Nov  4 15:27:06 1987
--- t10.c	Wed Nov  4 15:10:24 1987
***************
*** 290,301
  	}
  	if (k < 040 && k != DRAWFCN)
  		return(outsize);
- 	if (widcache[k-32].fontpts == (xfont<<8) + xpts  && !setwdf) {
- 		w = widcache[k-32].width;
- 		bd = 0;
- 		cs = 0;
- 	} else
- 		w = getcw(k-32);
  	j = z = 0;
  	if (k != DRAWFCN) {
  		if (cs) {

--- 290,295 -----
  	}
  	if (k < 040 && k != DRAWFCN)
  		return(outsize);
  	j = z = 0;
  	if (k != DRAWFCN) {
  		if (widcache[k-32].fontpts == (xfont<<8) + xpts  && !setwdf) {
***************
*** 298,303
  		w = getcw(k-32);
  	j = z = 0;
  	if (k != DRAWFCN) {
  		if (cs) {
  			if (bd)
  				w += (bd - 1) * HOR;

--- 292,303 -----
  		return(outsize);
  	j = z = 0;
  	if (k != DRAWFCN) {
+ 		if (widcache[k-32].fontpts == (xfont<<8) + xpts  && !setwdf) {
+ 			w = widcache[k-32].width;
+ 			bd = 0;
+ 			cs = 0;
+ 		} else
+ 			w = getcw(k-32);
  		if (cs) {
  			if (bd)
  				w += (bd - 1) * HOR;
***************
*** 419,425
  		else
  			fdprintf(ptid, "C%s\n", &chname[chtab[k - 128]]);
  	}
! 	if (bd) {
  		bd -= HOR;
  		if (esc += bd)
  			ptesc();

--- 419,425 -----
  		else
  			fdprintf(ptid, "C%s\n", &chname[chtab[k - 128]]);
  	}
! 	if (bd && k != DRAWFCN) {
  		bd -= HOR;
  		if (esc += bd)
  			ptesc();
--------------------------------------------------------


From research!acsnet!oz!su!cs!basser!john Thu Apr  7 20:20:17 1988
>From john@basser Fri Apr  8 11:19:56 1988
To: v8news@research.usa peter@bernina
Subject: V8/9 and DZ/KMC's

If anyone has a working DZ/KMC driver for Eighth or Ninth Edition, I
would really appreciate hearing from them.  (Believe me, I've _tried_...)

John Mackin, Basser Department of Computer Science,
	     University of Sydney, Sydney, Australia

john@basser.oz.AU (john%basser.oz.AU@UUNET.UU.NET)
{uunet,hplabs,mcvax,ukc,nttlab}!munnari!basser.oz!john

From research!utzoo!utstat!utstat.toronto.edu!geoff Tue Apr 26 00:34:29 1988
Date: Tue 26 Apr EDT 1988 00:33
Subject: changes to the shell, upas, and blit software are available

I think I have finished work on a delinted V9 shell which uses malloc
instead of catching SIGSEGV and calling sbrk; uses directory(3) instead
of private versions of some of those routines; processes here documents
more quickly; executes fewer "access" system calls; and fixes several
latent bugs, including one that causes the shell to read "in" if you
execute "bltin <in >out", where "bltin" may be any shell builtin.  So
far it is running on Sun 3s here under Sunix 3.[035] and on utzoo (a V7
PDP-11/44).  (We have plenty of Suns but almost no Vaxen left on
campus.)  I have given it back to research.

Ian Darwin, Peter Honeyman and I took an old public-domain in-kernel
SMTP implementation and turned it into a standalone user-mode SMTP
service, and added interfacing to upas based on Dave Presotto's rfc822
code.  I believe Dave has bought back our code, so it will probably be
included in future upas releases.

The people here at CSRI got the shipment of Blits when we got V8, and
they had plenty of Vaxen, so they (notably Dave Blythe) did some work on
the Blit software, then I got hold of it when I got a Blit and tried to
make the software work on a Sun.  The old 68000 Blit code assumes it
is running on a VAX-byte-order machine which tolerates dereferencing
zero pointers and is downloading into a 68000-byte-order Blit.  I have
got some of the software working, but not the most interesting (to me)
programs: cip, which is too big, and jim or sam, which dump core.

The first steps were to fix 68ld and mld to remove machine-dependencies
(or at least #ifdef them), then to avoid using either of the two
optimisers (m2 and mopt) because they both dereference zero pointers,
and I haven't taken the time to track down the causes.  Many Blit
programs were eventually made to work, at least partially, but joff
dumps core (on the host and in the Blit) too often to be helpful
debugging other Blit programs.  The failure of jim and sam may be due to
the odd history of the CSRI mux, which started out as mpx and mutated.
I now have the original V8 code on disk and may try to get the original
mux running, to see if that cures the jim and sam problems.  We are due
to get the Teletype 630 (68010) cross-compiler kit "soon" and I may try
back-porting it to the 68000 Blits.

I have been using the pty driver mods for 4.2bsd from Steve Bellovin
that came with the Blit code on the V8 distribution, and have not yet
tried using the TIOCUCNTL now available in later Sunix 3.x releases and
4.3bsd.  If TIOCUCNTL can be made to work, then recompiling all the Blit
code would permit it to run on a stock Sun kernel.

(Incidentally, have any of you tried buying 630's outside the US?  AT&T
Canada is remarkably slow and unknowledgeable for a for-profit
corporation; we have never had to fight so hard to buy a product
before.  We've been trying to buy 630s since June 1987 and so far have
0.6 of one.  I'd love to find a Canadian AT&T VAR.)

If any of you are interested in any of the above code, I'd be happy to
distribute what I have (actually the Blit code is in a bit of mess,
but I am using it successfully).  The shell and blit diffs are immense;
the smtp code is relatively small.  I don't know how to best distribute
this much code to such a widely-scattered group; perhaps tapes or mail
to v8source?  Suggestions are welcome.  Please mail a copy of any
replies to v8news, as others are interested.

Geoff Collyer	utzoo!utstat!geoff, utstat.toronto.{edu,cdn}!geoff
Dept. of Statistics, U. of Toronto


From utzoo!henry Fri Jul 15 17:57:30 1988
To: utstat!geoff research!v8news
Subject: small but very useful change to V8 cron

214,216c214,222
< 	/* skip leading white space on the line */
< 	do	c = getchar();
< 	while (c == ' ' || c == '\t');
---
> 	/* skip leading white space, comments, empty lines */
> 	for (;;) {
> 		do	c = getchar();
> 		while (c == ' ' || c == '\t');
> 		if (c != '#' && c != '\n')
> 			break;
> 		while (c != '\n')
> 			c = getchar();
> 	}


From utzoo!henry Wed Sep 21 17:35:59 1988
To: research!v8news
Subject: nroff terminal-table checker

Here's something I came up with a little while ago to help with our
conversion to the V8 nroff/troff combination:  a syntax checker for V8
nroff terminal tables.  This is actually fussier than it really needs
to be -- it enforces some things which nroff doesn't really insist on.

It found errors in tables that we thought were working fine in production,
by the way!

echo 'tabcheck':
sed 's/^X//' >'tabcheck' <<'!'
X# nroff terminal-table checker
Xawk 'BEGIN {
X	name[2] = "bset" ; type[2] = "o"
X	name[3] = "breset" ; type[3] = "o"
X	name[4] = "Hor" ; type[4] = "d"
X	name[5] = "Vert" ; type[5] = "d"
X	name[6] = "Newline" ; type[6] = "d"
X	name[7] = "Char" ; type[7] = "d"
X	name[8] = "Em" ; type[8] = "d"
X	name[9] = "Halfline" ; type[9] = "d"
X	name[10] = "Adj" ; type[10] = "d"
X	name[11] = "twinit" ; type[11] = "s"
X	name[12] = "twrest" ; type[12] = "s"
X	name[13] = "twnl" ; type[13] = "s"
X	name[14] = "hlr" ; type[14] = "s"
X	name[15] = "hlf" ; type[15] = "s"
X	name[16] = "flr" ; type[16] = "s"
X	name[17] = "bdon" ; type[17] = "s"
X	name[18] = "bdoff" ; type[18] = "s"
X	name[19] = "iton" ; type[19] = "s"
X	name[20] = "itoff" ; type[20] = "s"
X	name[21] = "ploton" ; type[21] = "s"
X	name[22] = "plotoff" ; type[22] = "s"
X	name[23] = "up" ; type[23] = "s"
X	name[24] = "down" ; type[24] = "s"
X	name[25] = "right" ; type[25] = "s"
X	name[26] = "left" ; type[26] = "s"
X	name[27] = ""; type[27] = ""
X	name[28] = "charset" ; type[28] = ""
X	charset = 0
X}
XNR == 1 {
X	fname = "tab." $0
X	if (substr(FILENAME, length(FILENAME)-length(fname)+1) != fname)
X		print "table name wrong in line 1: " $0
X	FS = "\t"
X}
XNR > 1 && charset == 0 {
X	if ($1 != name[NR])
X		print "bad field name in line " NR ": " $0
X	if ((type[NR] == "s" && $2 !~ /^".*"$/) ||			\
X			(type[NR] == "d" && $2 !~ /^[0-9]+$/) ||	\
X			(type[NR] == "o" && $2 !~ /^[0-7]+$/) ||	\
X			(type[NR] == "" && NF > 1))
X		print "bad value in line " NR ": " $0
X	if ($1 == "charset") {
X		charset = 1
X		FS = " "
X		next
X	}
X}
Xcharset != 0 {
X	if ($0 !~ /^[^ ]+ [^ ]+ (".*"|[^ ]+)$/)
X		print "bad format in line " NR ": " $0
X	if (length($1) > 2)
X		print "wrong length of name in line " NR ": " $0
X	if ($2 !~ /^[0-9]+$/)
X		print "bad width in line " NR ": " $0
X	if (length($2) > 1)
X		print "width too long in line " NR ": " $0
X}' $*
!
echo done


From utzoo!henry Wed Nov  2 13:44:19 1988
To: research!v8news
Subject: diffs to 11nm to make it portable

Herewith a set of diffs to 11nm(1) to make it byte-order-independent.

*** ../11nm.c	Tue Feb  9 03:32:02 1982
--- 11nm.c	Tue Nov  1 15:29:12 1988
***************
*** 14,20 ****
  #ifndef A_DOT_OUT		/*god*/
  #define A_DOT_OUT "a.out"
  #endif
! #define	BADMAG(x) x!=A_MAGIC1 && x!=A_MAGIC2 && x!=A_MAGIC3 && x!=A_MAGIC4
  #define	SELECT	arch_flg ? arp.ar_name : *argv
  int	numsort_flg;
  int	undef_flg;
--- 14,20 ----
  #ifndef A_DOT_OUT		/*god*/
  #define A_DOT_OUT "a.out"
  #endif
! #define	BADMAG(x) (x!=A_MAGIC1 && x!=A_MAGIC2 && x!=A_MAGIC3 && x!=A_MAGIC4)
  #define	SELECT	arch_flg ? arp.ar_name : *argv
  int	numsort_flg;
  int	undef_flg;
***************
*** 22,27 ****
--- 22,28 ----
  int	globl_flg;
  int	nosort_flg;
  int	arch_flg;
+ int	swab_flg;
  int	prep_flg;
  struct	ar_hdr	arp;
  long	arsize;
***************
*** 35,40 ****
--- 36,43 ----
  
  char	*progname;	/*god: for error messages, hold name here*/
  
+ short	swab();
+ 
  main(argc, argv)
  char **argv;
  {
***************
*** 100,105 ****
--- 103,110 ----
  		fread((char *)&magbuf, 1, sizeof(magbuf), fi);	/* get magic no. */
  		if (strncmp(magbuf.a, ARMAG, SARMAG)==0)
  			arch_flg++;
+ 		else if (BADMAG(magbuf.i) && !BADMAG(swab(magbuf.i)))
+ 			swab_flg++;
  		else if (BADMAG(magbuf.i)) {
  			fprintf(stderr, "%s: %s-- bad format\n",
  					progname, *argv);
***************
*** 118,123 ****
--- 123,138 ----
  			struct nlist sym;
  
  			fread((char *)&exp, 1, sizeof(struct exec), fi);
+ 			if (swab_flg) {
+ 				exp.a_magic = swab(exp.a_magic);
+ 				exp.a_text = swab(exp.a_text);
+ 				exp.a_data = swab(exp.a_data);
+ 				exp.a_bss  = swab(exp.a_bss );
+ 				exp.a_syms = swab(exp.a_syms);
+ 				exp.a_entry = swab(exp.a_entry);
+ 				exp.a_unused = swab(exp.a_unused);
+ 				exp.a_flag = swab(exp.a_flag);
+ 			}
  			if (BADMAG(exp.a_magic)) {		/* archive element not in  */
  				continue;	/* proper format - skip it */
  			}
***************
*** 134,139 ****
--- 149,158 ----
  			i = 0;
  			while (--n >= 0) {
  				fread((char *)&sym, 1, sizeof(sym), fi);
+ 				if (swab_flg) {
+ 					sym.n_type = swab(sym.n_type);
+ 					sym.n_value = swab(sym.n_value);
+ 				}
  				if (globl_flg && (sym.n_type&N_EXT)==0)
  					continue;
  				switch (sym.n_type&N_TYPE) {
***************
*** 255,258 ****
--- 274,284 ----
  		++arsize;
  	off = ftell(af) + arsize;	/* offset to next element */
  	return(1);
+ }
+ 
+ short
+ swab(s)
+ short s;
+ {
+ 	return(((s&0377)<<8) | ((s>>8)&0377));
  }


From utzoo!utstat!geoff Wed Jan 18 23:07:52 EST 1989
To: utzoo!research!v8news
Subject: v8 troff fixes for large fonts and long words

These diffs to tdef.h permit fonts with 255 characters (or fewer) on position 0
(the position used for "mount-on-demand" fonts) and permits words and lines
long enough to accomodate our eqn output (we may have atypically large
equations, being a Statistics department).

110c110,111
< #define	EXTRAFONT 500	/* extra space for swapping a font */
---
> #define	EXTRAFONT 700	/* extra space for swapping a font (630 for 255 chars; */
> 			/* see t6.c and t10.c) */
127,128c128,129
< #define	WDSIZE	270	/* word buffer size */
< #define	LNSIZE	680	/* line buffer size */
---
> #define	WDSIZE	2700	/* word buffer size */
> #define	LNSIZE	6800	/* line buffer size */

This diff to t10.c permit fonts with 255 characters (or fewer) on position 0.
Apple LaserWriter fonts seem to run to around 210 characters and previously
provoked complaints about "font too big".

101c101,102
< 	fontbase[0]->nwfont = EXTRAFONT - dev.nchtab - (128-32) - sizeof (struct Font);
---
> 	nw = EXTRAFONT - dev.nchtab - (128-32) - sizeof(struct Font);
> 	fontbase[0]->nwfont = (nw > BYTEMASK? BYTEMASK: nw);

These diffs to t6.c improve error reporting when a font doesn't fit a position,
replace fontbase[pos]->nwfont by nwfont in a few places in setfp() and fix a
bug by closing a file descriptor before an early return.

621,622c621
< 	register k;
< 	int n;
---
> 	register int k, n, nwfont, want, got;
639,641c638,655
< 	n = fontbase[pos]->nwfont & BYTEMASK;
< 	read(k, (char *) fontbase[pos], 3*n + nchtab + 128 - 32 + sizeof(struct Font));
< 	kerntab[pos] = (char *) fontab[pos] + (fontbase[pos]->nwfont & BYTEMASK);
---
> 
> 	n = fontbase[pos]->nwfont & BYTEMASK;			/* old size */
> 	want = 3*n + (nchtab + 128 - 32 + sizeof(struct Font));
> 	got = read(k, (char *)fontbase[pos], want);
> 	/* n may be high (e.g. for position 0), so want may be high */
> 	if (got == 0) {
> 		errprint("Font %s is empty", shortname);
> 		close(k);
> 		return -1;
> 	}
> 	if (got < 0) {
> 		errprint("Font %s: read error", shortname);
> 		close(k);
> 		return -1;
> 	}
> 
> 	nwfont = fontbase[pos]->nwfont & BYTEMASK;		/* new size */
> 	kerntab[pos] = (char *)fontab[pos] + nwfont;
643,645c657,661
< 	fitab[pos] = (char *) fontab[pos] + 3 * (fontbase[pos]->nwfont & BYTEMASK);
< 	if ((fontbase[pos]->nwfont & BYTEMASK) > n) {
< 		errprint("Font %s too big for position %d", shortname, pos);
---
> 	fitab[pos] =   (char *)fontab[pos] + 3 * nwfont;
> 	if (nwfont > n) {
> 		errprint("Font %s too big (%d chars) for position %d (%d chars)",
> 			shortname, nwfont, pos, n);
> 		close(k);

Geoff Collyer	utzoo!utstat!geoff, geoff@utstat.toronto.edu


From andrew Thu Jul 20 14:19:16 EDT 1989
v8news:
	we are producing a new edition of the manual,
both volumes 1 and 2. we are looking for a couple of
volunteers outside the center to review both volumes.
volume 2 is about 42 papers, totalling about 650-700 pages.
please mail research!andrew if you would like to volunteer
or know someone who would.