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 = 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.