Article View: comp.sources.mac
Article #40UW v4.2 (part 7 of 9)
From: John Bruner
Date: Thu, 07 Apr 1988 14:00
Date: Thu, 07 Apr 1988 14:00
1580 lines
41050 bytes
41050 bytes
[UW v4.2 - part 7 of 9]
---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# server/uw_opt.c
# server/uw_pcl.c
# This archive created: Mon Apr 4 07:52:09 1988
# By: Roger L. Long (macintosh@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
if test ! -d server
then
echo shar: mkdir server
mkdir server
fi
echo shar: extracting "'server/uw_opt.c'" '(14287 characters)'
if test -f 'server/uw_opt.c'
then
echo shar: will not over-write existing file "'server/uw_opt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_opt.c'
X/*
X * uw_opt - window option handling for UW
X *
X * Copyright 1986 by John D. Bruner. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include <sys/types.h>
X
X#include "uw_param.h"
X#include "uw_opt.h"
X
X/*
X * The following variable is a kludge for efficiency. It is set to
X * a nonzero value when a bitmask is changed, indicating that opt_scan()
X * should be called.
X */
Xint calloptscan; /* pending,do,dont awaits opt_scan */
X
X/* option input state variables */
Xstatic caddr_t optwin; /* window */
Xstatic struct woptdefn *optwod; /* window option definition */
Xstatic woptcmd_t optcmd; /* option command */
Xstatic woption_t optnum; /* current option number */
Xstatic woptarg_t *optarg; /* current encoding */
Xstatic int optcnt; /* count in current encoding */
Xstatic char *optout; /* decoded option */
Xstatic char optbuf[512]; /* buffer for decoded option */
X
Xopt_new(wod, generic, unique)
Xregister struct woptdefn *wod, *generic, *unique;
X{
X register int n, mask;
X
X /*
X * Set up the option definition structure pointed to by "wod" to
X * correspond with the option definitions in "generic" (common to
X * all window types) and "unique" (per-window).
X */
X mask = (1<<(WONUM_GENERIC+1))-1;
X if (unique) {
X wod->wod_askrpt = unique->wod_askrpt & ~mask;
X wod->wod_pending = unique->wod_pending & ~mask;
X for (n=WONUM_GENERIC+1; n <= WONUM_MAX; n++)
X wod->wod_optlst[n] = unique->wod_optlst[n];
X } else {
X wod->wod_askrpt = 0;
X wod->wod_pending = 0;
X for (n=WONUM_GENERIC+1; n <= WONUM_MAX; n++)
X wod->wod_optlst[n].wol_argdefn = (woptarg_t *)0;
X }
X if (generic) {
X wod->wod_askrpt |= generic->wod_askrpt & mask;
X wod->wod_pending |= generic->wod_pending & mask;
X for (n=1; n <= WONUM_GENERIC; n++)
X wod->wod_optlst[n] = generic->wod_optlst[n];
X } else {
X for (n=1; n <= WONUM_GENERIC; n++)
X wod->wod_optlst[n].wol_argdefn = (woptarg_t *)0;
X }
X wod->wod_do = wod->wod_askrpt;
X wod->wod_dont = 0;
X wod->wod_inquire = 0;
X calloptscan = 1;
X}
X
Xopt_renew(wod, report)
Xregister struct woptdefn *wod;
Xint report;
X{
X /*
X * Reset "wod_do" for all window options that we want the Macintosh
X * to report to us. If "report" is nonzero, send the Mac the
X * current values of these options.
X */
X wod->wod_do = wod->wod_askrpt;
X wod->wod_dont = 0;
X if (report)
X wod->wod_pending = wod->wod_askrpt;
X calloptscan = 1;
X}
X
Xopt_newtype(wod, generic, unique)
Xregister struct woptdefn *wod, *generic, *unique;
X{
X register int n, bit;
X register woptbmask_t oldask;
X
X /*
X * Change the window options to reflect a new window emulation type.
X * The new emulation may not support all of the events that the old
X * one did, and in any event they may not mean the same thing.
X */
X oldask = wod->wod_askrpt;
X opt_new(wod, generic, unique);
X for (n=1, bit=2; n <= WONUM_GENERIC; n++,bit<<=1) {
X if ((oldask&bit) && !(wod->wod_askrpt&bit))
X wod->wod_dont |= bit;
X if (!(oldask&bit) && (wod->wod_askrpt&bit))
X wod->wod_do |= bit;
X }
X for ( ; n <= WONUM_MAX; n++, bit<<=1)
X if (wod->wod_askrpt&bit)
X wod->wod_do |= bit;
X calloptscan = 1;
X}
X
Xopt_setext(wod, fn)
Xregister struct woptdefn *wod;
Xregister void (*fn)();
X{
X register int n;
X
X /*
X * Set "wol_ext" to "fn" for each option that has a defined "wol_set".
X */
X for (n=1; n <= WONUM_MAX; n++)
X if (wod->wod_optlst[n].wol_set)
X wod->wod_optlst[n].wol_ext = fn;
X}
X
Xopt_scan(w, wod, fn, mfd, cmd)
Xcaddr_t w;
Xregister struct woptdefn *wod;
Xvoid (*fn)();
Xfildes_t mfd;
Xint cmd;
X{
X register struct woptlst *wol;
X register char *cp;
X register int n, bit, maxsize;
X char buf[512];
X
X /*
X * Scan the entire list of options for pending ones. For each
X * one, call "fn". "cmd" is the command that we are to pass as the
X * first argument to "fn".
X *
X * Note that we must send data (wod_pending) before processing
X * DO commands (wod_do); otherwise, the host and Mac may not
X * agree upon the value of a window option. (The Mac might
X * respond to the "do" command before it sees the new value.)
X */
X cp = buf;
X#ifdef notdef
X for (n=1,bit=2,wol=wod->wod_optlst+1; n<=WONUM_MAX; n++,bit<<=1,wol++) {
X#else
X for (n=WONUM_MAX, bit=(1<<WONUM_MAX), wol=wod->wod_optlst+WONUM_MAX;
X n > 0;
X n--, bit >>= 1, wol--) {
X#endif
X if (wod->wod_pending&bit) {
X wod->wod_pending &= ~bit;
X if (wol->wol_argdefn) {
X maxsize = 2 +
X opt_size(wol->wol_argdefn);
X if (cp > buf + sizeof buf - maxsize - 1) {
X *cp++ = 0;
X (*fn)(mfd, cmd, buf, cp-buf);
X cp = buf;
X }
X if (WONUM_USELONG(n)) {
X *cp++ = WOC_SET|WONUM_LPREFIX;
X *cp++ = WONUM_LENCODE(n);
X } else
X *cp++ = WOC_SET|WONUM_SENCODE(n);
X cp += opt_encode(cp, wol->wol_argdefn,
X (*wol->wol_get)(w, n));
X }
X }
X if (wod->wod_inquire&bit) {
X wod->wod_inquire &= ~bit;
X if (cp > buf + sizeof buf - 3) {
X *cp++ = 0;
X (*fn)(mfd, cmd, buf, cp-buf);
X cp = buf;
X }
X if (wol->wol_argdefn) {
X if (WONUM_USELONG(n)) {
X *cp++ = WOC_INQUIRE|WONUM_LPREFIX;
X *cp++ = WONUM_LENCODE(n);
X } else
X *cp++ = WOC_INQUIRE|WONUM_SENCODE(n);
X }
X }
X if ((wod->wod_do|wod->wod_dont)&bit) {
X if (cp > buf + sizeof buf - 3) {
X *cp++ = 0;
X (*fn)(mfd, cmd, buf, cp-buf);
X cp = buf;
X }
X if (wod->wod_do&bit) {
X wod->wod_do &= ~bit;
X wod->wod_dont &= ~bit;
X if (wol->wol_argdefn) {
X if (WONUM_USELONG(n)) {
X *cp++ = WOC_DO|WONUM_LPREFIX;
X *cp++ = WONUM_LENCODE(n);
X } else
X *cp++ = WOC_DO|WONUM_SENCODE(n);
X }
X } else if (wod->wod_dont&bit) {
X wod->wod_do &= ~bit;
X wod->wod_dont &= ~bit;
X if (wol->wol_argdefn) {
X if (WONUM_USELONG(n)) {
X *cp++ = WOC_DONT|WONUM_LPREFIX;
X *cp++ = WONUM_LENCODE(n);
X } else
X *cp++=WOC_DONT|WONUM_SENCODE(n);
X }
X }
X }
X if (cp > buf) {
X *cp++ = 0;
X (*fn)(mfd, cmd, buf, cp-buf);
X cp = buf;
X }
X }
X}
X
Xopt_size(woa)
Xregister woptarg_t *woa;
X{
X register int size, cnt;
X
X /*
X * Determine the maximum size of an option whose argument encoding
X * is specified by "woa". This does NOT include additional encoding
X * (e.g. for meta characters) at the protocol level.
X */
X if (woa) {
X for (size=0; *woa != WOA_END; woa++) {
X cnt = *woa & ~WOA_CMDMASK;
X switch (*woa & WOA_CMDMASK) {
X case WOA_CHARS(0):
X case WOA_STRING(0):
X size += cnt;
X break;
X case WOA_UDATA(0):
X size += (cnt + 5) / 6;
X break;
X }
X }
X } else
X size = 0;
X return(size);
X}
X
Xopt_encode(buf, woa, data)
Xchar *buf;
Xregister woptarg_t *woa;
Xchar *data;
X{
X register char *cp, *cq;
X register int n, cnt;
X register unsigned long ival;
X union {
X struct {
X char c1;
X short s;
X } cs;
X struct {
X char c2;
X long l;
X } cl;
X } u;
X
X /*
X * Encode "data" according to the option argument specifier "woa"
X * into the buffer "buf". Return the number of bytes of "buf"
X * actually used. The caller has already verified that "buf" is
X * large enough.
X */
X if (!data)
X return(0);
X for (cp=buf,cq=data; *woa != WOA_END; woa++) {
X cnt = *woa & ~WOA_CMDMASK;
X switch (*woa & WOA_CMDMASK) {
X case WOA_CHARS(0):
X for (n=0; n < cnt; n++)
X *cp++ = *cq++;
X break;
X case WOA_STRING(0):
X for (n=0; n < cnt-1 && *cq; n++)
X *cp++ = *cq++;
X if (n < cnt)
X cq += cnt-n;
X *cp++ = '\0';
X break;
X case WOA_UDATA(0):
X if (cnt <= NBBY) {
X ival = (unsigned char)*cq++;
X } else if (cnt <= sizeof(short)*NBBY) {
X while ((int)cq & ((char *)&u.cs.s-&u.cs.c1-1))
X cq++;
X ival = *(unsigned short *)cq;
X cq += sizeof(short);
X } else {
X while ((int)cq & ((char *)&u.cl.l-&u.cl.c2-1))
X cq++;
X ival = *(unsigned long *)cq;
X cq += sizeof(long);
X }
X if (cnt != sizeof(long)*NBBY)
X ival &= (1<<cnt) - 1;
X for (n=0; n < cnt; n += 6, ival >>= 6)
X *cp++ = (ival & 077) | 0100;
X break;
X }
X }
X return(cp-buf);
X}
X
Xopt_istart(w, wod)
Xcaddr_t w;
Xstruct woptdefn *wod;
X{
X /*
X * Start collecting input for a window option specification.
X */
X optwin = w;
X optwod = wod;
X optnum = 0;
X}
X
Xopt_input(c)
Xchar c;
X{
X register int cnt, bit;
X register struct woptdefn *wod;
X register struct woptlst *wol;
X register unsigned long ival;
X union {
X struct {
X char c1;
X short s;
X } cs;
X struct {
X char c2;
X long l;
X } cl;
X } u;
X
X /*
X * Add the received character "c" to the current option specification.
X * If it is complete, take the appropriate action. If option 0
X * (the endmarker) is received, return 0 (to notify the caller that
X * we are done). Otherwise, return 1 -- more option data remains
X * to be processed.
X *
X * This code isn't as readable as it should be; there are far too
X * many return statements floating around. Sorry about that.
X */
X if (optwin) {
X wod = optwod;
X if (optnum == 0 || optnum == WONUM_MAX+1) {
X /* start (or continue) decoding a new option */
X if (optnum == 0) {
X /* start new option (or decode endmarker) */
X if (c & WONUM_MASK) {
X /* new option */
X optcmd = c & WOC_MASK;
X if (WOC_BADCMD(optcmd)) {
X opt_iflush();
X return(0);
X }
X if (c == WONUM_LPREFIX) {
X optnum = WONUM_MAX+1;
X return(1);
X } else
X optnum = WONUM_SDECODE(c);
X } else {
X /* end of options */
X opt_iflush();
X return(0);
X }
X } else {
X /* read second byte of long option number */
X optnum = WONUM_LDECODE(c);
X if (optnum > WONUM_MAX) {
X opt_iflush();
X return(0);
X }
X }
X /*
X * This point is reached when the option number has
X * been completely decoded. If the command is not
X * WOC_SET, then it has no arguments and we can
X * process it immediately.
X */
X wol = &wod->wod_optlst[optnum];
X bit = 1<<optnum;
X if (optcmd == WOC_SET) {
X optout = optbuf;
X optcnt = 0;
X optarg = wol->wol_argdefn;
X if (!optarg) {
X opt_iflush();
X return(0);
X }
X } else {
X if (wol->wol_ext &&
X (optcmd == WOC_WILL || optcmd == WOC_WONT))
X (*wol->wol_ext)(optwin, optcmd,
X optnum, (char *)0, 0);
X switch (optcmd) {
X case WOC_INQUIRE:
X wod->wod_pending |= bit;
X calloptscan = 1;
X break;
X case WOC_DO:
X case WOC_DONT:
X break;
X case WOC_WILL:
X wod->wod_askrpt |= bit;
X wod->wod_do &= ~bit;
X break;
X case WOC_WONT:
X wod->wod_askrpt &= ~bit;
X wod->wod_dont &= ~bit;
X break;
X }
X optnum = 0;
X }
X return(1);
X } else {
X /* continue processing argument to option */
X wol = &wod->wod_optlst[optnum];
X bit = 1<<optnum;
X cnt = *optarg & ~WOA_CMDMASK;
X switch (*optarg & WOA_CMDMASK) {
X case WOA_CHARS(0):
X *optout++ = c;
X optcnt++;
X break;
X case WOA_STRING(0):
X *optout++ = c;
X optcnt++;
X if (!c) {
X optout += cnt - optcnt;
X optcnt = cnt;
X } else if (optcnt == cnt-1) {
X *optout++ = '\0';
X optcnt = cnt;
X }
X break;
X case WOA_UDATA(0):
X if (optcnt == 0) {
X if (cnt <= NBBY) {
X *optout = 0;
X } else if (cnt <= sizeof(short)*NBBY) {
X while ((int)optout & ((char *)&u.cs.s-&u.cs.c1-1))
X optout++;
X *(short *)optout = 0;
X } else {
X while ((int)optout & ((char *)&u.cl.l-&u.cl.c2-1))
X optout++;
X *(long *)optout = 0;
X }
X }
X ival = (c & 077) << optcnt;
X if (cnt != NBBY*sizeof(long))
X ival &= (1<<cnt) - 1;
X optcnt += 6;
X if (cnt <= NBBY) {
X *(unsigned char *)optout |= (unsigned char)ival;
X if (optcnt >= cnt)
X optout++;
X } else if (cnt <= sizeof(short)*NBBY) {
X *(unsigned short *)optout |= (unsigned short)ival;
X if (optcnt >= cnt)
X optout += sizeof(short);
X } else {
X *(unsigned long *)optout |= ival;
X if (optcnt >= cnt)
X optout += sizeof(long);
X }
X break;
X }
X if (optcnt >= cnt) {
X optcnt = 0;
X if (*++optarg == WOA_END) {
X wod->wod_pending &= ~bit;
X (*wol->wol_set)(optwin, optnum, optbuf);
X if (wol->wol_ext) {
X (*wol->wol_ext)(optwin, WOC_SET,
X optnum, optbuf,
X optout-optbuf);
X }
X optnum = 0;
X }
X }
X return(1);
X }
X /*NOTREACHED*/
X }
X return(0);
X}
X
Xopt_iflush()
X{
X optwin = (caddr_t)0;
X}
X
Xopt_extopt(w, wod, cmd, num, data, na)
Xcaddr_t w;
Xregister struct woptdefn *wod;
Xwoptcmd_t cmd;
Xwoption_t num;
Xchar *data;
Xstruct netadj *na;
X{
X register struct woptlst *wol;
X
X if (w != NULL && wod != NULL && num <= WONUM_MAX) {
X wol = wod->wod_optlst + num;
X if (wol->wol_argdefn) {
X switch (cmd) {
X case WOC_SET:
X if (data && wol->wol_set) {
X if (na) {
X opt_netadj(wol->wol_argdefn,
X data, na);
X }
X /*
X * Set the new value and notify the Mac.
X * Because of a race condition (the Mac
X * might concurrently be sending us its
X * value for this option), we ask the
X * Mac to send back the value after it
X * is set.
X */
X (*wol->wol_set)(w, num, data);
X WOPT_SET(wod->wod_pending, num);
X WOPT_SET(wod->wod_inquire, num);
X calloptscan = 1;
X }
X break;
X case WOC_INQUIRE:
X WOPT_SET(wod->wod_inquire, num);
X calloptscan = 1;
X break;
X case WOC_DO:
X WOPT_SET(wod->wod_do, num);
X WOPT_SET(wod->wod_askrpt, num);
X calloptscan = 1;
X break;
X case WOC_DONT:
X WOPT_SET(wod->wod_dont, num);
X WOPT_CLR(wod->wod_askrpt, num);
X calloptscan = 1;
X break;
X }
X }
X }
X}
X
Xopt_netadj(woa, data, na)
Xregister woptarg_t *woa;
Xchar *data;
Xregister struct netadj *na;
X{
X register char *cp;
X register int cnt;
X union {
X struct {
X char c1;
X short s;
X } cs;
X struct {
X char c2;
X long l;
X } cl;
X } u;
X
X /*
X * Convert an option (in internal format) from host byte order
X * to network byte order. If the two are the same then this is
X * a NOP.
X */
X if (data && na) {
X for (cp=data; *woa != WOA_END; woa++) {
X cnt = *woa & ~WOA_CMDMASK;
X switch (*woa & WOA_CMDMASK) {
X case WOA_CHARS(0):
X case WOA_STRING(0):
X cp += cnt;
X break;
X case WOA_UDATA(0):
X if (cnt <= NBBY) {
X cp++;
X } else if (cnt <= sizeof(short)*NBBY) {
X while ((int)cp & ((char *)&u.cs.s-&u.cs.c1-1))
X cp++;
X *(u_short *)cp =
X (*na->na_ushort)(*(u_short *)cp);
X cp += sizeof(short);
X } else {
X while ((int)cp & ((char *)&u.cl.l-&u.cl.c2-1))
X cp++;
X *(u_short *)cp =
X (*na->na_ushort)(*(u_short *)cp);
X cp += sizeof(long);
X }
X }
X }
X }
X}
SHAR_EOF
if test 14287 -ne "`wc -c < 'server/uw_opt.c'`"
then
echo shar: error transmitting "'server/uw_opt.c'" '(should have been 14287 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'server/uw_pcl.c'" '(21808 characters)'
if test -f 'server/uw_pcl.c'
then
echo shar: will not over-write existing file "'server/uw_pcl.c'"
else
sed 's/^X//' << \SHAR_EOF > 'server/uw_pcl.c'
X/*
X * uw_pcl - protocol handling for UW
X *
X * Copyright 1985,1986 by John D. Bruner. All rights reserved. Permission to
X * copy this program is given provided that the copy is not sold and that
X * this copyright notice is included.
X */
X
X#include <sys/types.h>
X#include <sys/ioctl.h>
X#include <errno.h>
X
X#include "uw_param.h"
X#include "uw_clk.h"
X#include "uw_opt.h"
X#include "uw_win.h"
X#include "uw_pcl.h"
X#include "openpty.h"
X
X#define XON 0021 /* ASCII XON */
X#define XOFF 0023 /* ASCII XOFF */
X#define RUB 0177 /* ASCII RUBout */
X#define META 0200 /* "meta" bit for whatever it's worth */
X
X/*
X * Protocol negotiation is performed by a finite state machine (implemented
X * in pcl_haggle()). The states are defined as the enumerated type
X * "pnstate_t". The inputs have type "pnreq_t".
X */
Xtypedef enum {
X PNST_NOP, /* no protocol negotiation */
X PNST_AWAIT, /* timing out an ASKPCL */
X PNST_CWAIT, /* timing out a CANPCL */
X PNST_OK, /* negotiations completed */
X PNST_FAIL /* negotiation failed */
X} pnstate_t;
X
Xtypedef unsigned short pnreq_t; /* finite state machine requests */
X#define PNRQ_PCL 0000377 /* protocol mask */
X#define PNRQ_CMD 0177400 /* command mask: */
X#define PNRQ_NONE (pnreq_t)(0<<8) /* no request */
X#define PNRQ_START (pnreq_t)(1<<8) /* start negotiation */
X#define PNRQ_AWAIT (pnreq_t)(2<<8) /* timeout waiting for ASKPCL */
X#define PNRQ_ASK (pnreq_t)(3<<8) /* process received ASKPCL */
X#define PNRQ_CAN (pnreq_t)(4<<8) /* process received CANPCL */
X#define PNRQ_SET (pnreq_t)(5<<8) /* process received SETPCL */
X#define PNRQ_CWAIT (pnreq_t)(6<<8) /* timeout waiting for CANPCL */
X#define PNRQ_INIT (pnreq_t)(7<<8) /* initialize everything */
X
Xstatic int p1_ctlch[] = { -1, P1_IAC, XON, XOFF, -1, -1, -1, -1 };
X
Xextern void p1_entry(), p1_renew(), p2_renew();
Xextern struct window *p1_neww(), *p2_neww();
Xextern void p1_killw(), p1_xmit(), p1_recv();
Xextern void p1_askpcl(), p1_canpcl(), p1_setpcl();
Xextern void p2_recv(), p2_chkopt(), p2_sendopt();
X
Xstatic struct protocol pcl_table[] = {
X {
X ' ',
X P1_NWINDOW,
X p1_ctlch, sizeof p1_ctlch / sizeof p1_ctlch[0],
X p1_entry, NULL, p1_renew,
X p1_neww, p1_killw,
X p1_xmit, p1_recv, NULL, NULL,
X p1_askpcl, p1_canpcl, p1_setpcl
X },
X {
X '!',
X P2_NWINDOW,
X p1_ctlch, sizeof p1_ctlch / sizeof p1_ctlch[0],
X p1_entry, NULL, p2_renew,
X p2_neww, p1_killw,
X p1_xmit, p2_recv, p2_chkopt, p2_sendopt,
X p1_askpcl, p1_canpcl, p1_setpcl
X },
X};
X
Xstruct protocol *protocol = pcl_table;
X
X/*
X * Two "current" windows are defined: the current input window (for
X * input from the Macintosh) and the current output window (for output
X * to the Macintosh).
X */
Xstatic struct {
X struct window *in;
X struct window *out;
X} curwin;
X
X
Xpcl_entry(mfd)
Xregister fildes_t mfd;
X{
X /*
X * This routine is called to start up protocol handling. We always
X * start with protocol 1 (the original UW protocol).
X */
X protocol = pcl_table;
X pcl_haggle(mfd, PNRQ_INIT);
X if (protocol->p_entry)
X (*protocol->p_entry)(mfd);
X}
X
Xpcl_exit(mfd)
Xregister fildes_t mfd;
X{
X /*
X * This routine is called when we shut down (just before the server
X * exits).
X */
X if (protocol->p_exit)
X (*protocol->p_exit)(mfd);
X protocol = pcl_table;
X}
X
Xstatic
Xpcl_newpcl(newproto)
Xstruct protocol *newproto;
X{
X extern void rc_kludge();
X
X /*
X * Switch to new protocol "newproto". Right now we can get away
X * with just changing the value of "protocol". Eventually we will
X * probably want to call protocol-dependent functions to shut down
X * the old protocol and start up the new one.
X */
X protocol = newproto;
X
X /*
X * This is a horrible kludge. See rc_kludge() in "main.c" for
X * further details.
X */
X rc_kludge();
X}
X
Xstatic
Xvoid
Xpcl_tohaggle(arg)
Xregister toarg_t arg;
X{
X /*
X * This is a kludge to get around the single-argument restriction
X * on clk_timeout. We split the argument "arg" into two 16-bit
X * pieces and invoke pcl_haggle.
X */
X pcl_haggle((fildes_t)((arg>>16)&0177777), (pnreq_t)(arg&0177777));
X}
X
Xstatic
Xpcl_haggle(mfd, req)
Xfildes_t mfd;
Xregister pnreq_t req;
X{
X register struct protocol *p, *q;
X register char pname;
X register int request;
X static pnstate_t pnstate;
X static int waitcnt;
X
X /*
X * This routine implements the finite-state machine that handles
X * protocol negotiation. This routine is called by routines which
X * recognize incoming protocol commands and at 5 second intervals
X * when negotiations are in progress. The current protocol is
X * described by the variable "protocol".
X */
X if (req == PNRQ_INIT) {
X waitcnt = 0;
X pnstate = PNST_NOP;
X req = PNRQ_NONE;
X }
X if (!(p = protocol) || !p->p_askpcl || !p->p_canpcl || !p->p_setpcl) {
X req = PNRQ_NONE;
X } else {
X pname = req & PNRQ_PCL;
X request = req & PNRQ_CMD;
X switch (request) {
X case PNRQ_START: /* start protocol negotiation */
X /*
X * The Macintosh is responsible for starting protocol
X * negotiation (if it wants something other than the
X * standard protocol). This code is present for
X * purposes of exposition only.
X */
X (*p->p_askpcl)(mfd);
X req = PNRQ_AWAIT | pname;
X waitcnt = 0;
X pnstate = PNST_AWAIT;
X break;
X case PNRQ_AWAIT: /* timeout an ASKPCL */
X /*
X * This state also is not reached on the host.
X */
X if (pnstate == PNST_AWAIT) {
X if (++waitcnt > 3) {
X pnstate = PNST_FAIL;
X req = PNRQ_NONE;
X } else
X (*p->p_askpcl)(mfd);
X } else
X req = PNRQ_NONE;
X break;
X case PNRQ_ASK: /* handle received ASKPCL */
X q = pcl_table+sizeof pcl_table/sizeof pcl_table[0] - 1;
X (*p->p_canpcl)(mfd, q->p_name);
X pnstate = PNST_CWAIT;
X req = PNRQ_CWAIT | q->p_name;
X waitcnt = 0;
X break;
X case PNRQ_CAN: /* handle received CANPCL */
X for (q=pcl_table+sizeof pcl_table/sizeof pcl_table[0]-1;
X q > pcl_table && q->p_name > pname;
X q--)
X ;
X if (q->p_name == pname || q == pcl_table) {
X (*p->p_setpcl)(mfd, q->p_name);
X pcl_newpcl(q);
X pnstate = PNST_OK;
X req = PNRQ_NONE;
X } else {
X (*p->p_canpcl)(mfd, q->p_name);
X pnstate = PNST_CWAIT;
X req = PNRQ_CWAIT | q->p_name;
X waitcnt = 0;
X }
X break;
X case PNRQ_CWAIT: /* timeout a CANPCL */
X if (pnstate == PNST_CWAIT) {
X if (++waitcnt > 3) {
X pnstate = PNST_FAIL;
X req = PNRQ_NONE;
X } else
X (*p->p_canpcl)(mfd, pname);
X } else
X req = PNRQ_NONE;
X break;
X case PNRQ_SET: /* handle a received SETPCL */
X for (q=pcl_table+sizeof pcl_table/sizeof pcl_table[0]-1;
X q > pcl_table && q->p_name != pname;
X q--)
X ;
X if (q->p_name == pname) {
X pcl_newpcl(q);
X pnstate = PNST_OK;
X req = PNRQ_NONE;
X } else {
X /*
X * We are in trouble now -- the Mac has
X * instructed us to switch to a protocol
X * that we can't support. We switch back
X * to protocol 1 and hope that our message
X * to the Mac (telling it to switch to
X * protocol 1) will be interpreted correctly.
X */
X pnstate = PNST_FAIL;
X req = PNRQ_NONE;
X (*p->p_setpcl)(mfd, ' ');
X if (p != pcl_table)
X pcl_newpcl(pcl_table);
X }
X break;
X }
X if (req != PNRQ_NONE)
X (void)clk_timeout(5*CLK_HZ,
X pcl_tohaggle, (toarg_t)(((long)mfd<<16)|req));
X }
X}
X
Xstatic
Xvoid
Xp1_entry(mfd)
Xfildes_t mfd;
X{
X static char cmdbuf[2] = { P1_IAC };
X
X cmdbuf[1] = P1_DIR_HTOM|P1_FN_MAINT|P1_MF_ENTRY;
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X}
X
Xstatic
Xstruct window *
Xp1_neww(mfd, wclass, wtype, wnum, wid, datafd, ctlfd)
Xfildes_t mfd;
Xwclass_t wclass;
Xwtype_t wtype;
Xnwin_t wnum;
Xlong wid;
Xfildes_t datafd;
Xfildes_t ctlfd;
X{
X register struct window *w;
X static char cmdbuf[2] = { P1_IAC, 0 };
X
X /*
X * Create a new window for the host. This routine is not called when
X * the Macintosh creates a window.
X */
X w = win_neww(wclass, wtype, wnum, protocol->p_maxwin, wid,
X datafd, ctlfd, (struct woptdefn *)0);
X if (w) {
X cmdbuf[1] = P1_DIR_HTOM|P1_FN_NEWW|WIN_NUM(w);
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X }
X return(w);
X}
X
Xstatic
Xvoid
Xp1_killw(mfd, w)
Xregister struct window *w;
X{
X static char cmdbuf[] = { P1_IAC, P1_DIR_HTOM|P1_FN_KILLW };
X
X /*
X * Kill window "w" and tell the Macintosh to do the same.
X */
X if (w && w->w_alloc) {
X if (curwin.in == w)
X curwin.in = (struct window *)0;
X if (curwin.out == w)
X curwin.out = (struct window *)0;
X cmdbuf[1] = P1_DIR_HTOM|P1_FN_KILLW|WIN_NUM(w);
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X win_killw(w);
X }
X}
X
Xstatic
Xvoid
Xp1_xmit(mfd, w)
Xfildes_t mfd;
Xregister struct window *w;
X{
X register char *cp, *cq;
X register int i, len;
X char ibuf[32], obuf[32];
X static char refresh;
X static char cmdbuf[] = { P1_IAC, 0 };
X extern int errno;
X
X /*
X * Transmit data to the Macintosh (via file descriptor "mfd)
X * on behalf of window "w". Be sure to convert any embedded
X * control characters and meta characters.
X *
X * Note that the input/output buffers should NOT be very large.
X * It is undesirable to perform large reads and effectively
X * "lock out" all other file descriptors. The chosen size
X * should preserve a reasonable amount of efficiency.
X *
X * The UW protocol only requires an OSELW command when the
X * output window changes. We issue this command more often
X * to "refresh" the Mac's idea of what the output window is.
X * This helps (slightly) to overcome spurious output redirects
X * caused by a noisy line.
X */
X if (w && w->w_alloc) {
X if (curwin.out != w || ++refresh == 0) {
X refresh = 0;
X curwin.out = w;
X cmdbuf[1] = P1_DIR_HTOM|P1_FN_OSELW|WIN_NUM(w);
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X }
X cq = obuf;
X if ((len = read(w->w_datafd, ibuf, sizeof ibuf)) < 0 &&
X errno != EWOULDBLOCK)
X (*protocol->p_killw)(mfd, w);
X for (cp=ibuf; cp < ibuf+len; cp++) {
X if (*cp&META) {
X if (cq > obuf) {
X (void)write(mfd, obuf, cq-obuf);
X cq = obuf;
X }
X cmdbuf[1] = P1_DIR_HTOM|P1_FN_META;
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X *cp &= ~META;
X }
X i = -1;
X if (*cp == RUB || *cp < ' ') {
X i = protocol->p_szctlch - 1;
X while (i >= 0 && protocol->p_ctlch[i] != *cp)
X i--;
X }
X if (i >= 0) {
X if (cq > obuf) {
X (void)write(mfd, obuf, cq-obuf);
X cq = obuf;
X }
X cmdbuf[1] = P1_DIR_HTOM|P1_FN_CTLCH|i;
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X } else {
X *cq++ = *cp;
X if (cq >= obuf+sizeof obuf) {
X (void)write(mfd, obuf, cq-obuf);
X cq = obuf;
X }
X }
X }
X if (cq > obuf)
X (void)write(mfd, obuf, cq-obuf);
X } else
X (void)read(w->w_datafd, ibuf, sizeof ibuf);
X}
X
Xstatic
Xvoid
Xp1_recv(mfd, cbuf, clen)
Xfildes_t mfd;
Xchar *cbuf;
Xint clen;
X{
X register int len;
X register char *buf, *cp, *cq;
X register struct window *w;
X nwin_t wnum;
X auto int nready;
X char ibuf[512], obuf[512];
X static int seen_iac, seen_meta;
X static pnreq_t pnrq_cmd;
X static char cmdbuf[2] = { P1_IAC };
X
X /*
X * The received bytestream is examined. Non-command bytes are
X * written to the file descriptor corresponding to the current
X * "input" window (relative to the Macintosh -- the window the
X * user types input to).
X *
X * If "clen" is nonzero, then the contents of the buffer "cbuf"
X * are processed before any input is read.
X */
X if (ioctl(mfd, (int)FIONREAD, (char *)&nready) < 0) {
X perror("FIONREAD");
X return;
X }
X nready += clen;
X
X for (cq = obuf; nready > 0; nready -= len) {
X if (clen > 0) {
X len = clen;
X buf = cbuf;
X clen = 0;
X } else {
X if (nready > sizeof ibuf)
X len = read(mfd, ibuf, sizeof ibuf);
X else
X len = read(mfd, ibuf, nready);
X if (len <= 0) {
X perror("read");
X return;
X }
X buf = ibuf;
X }
X for (cp=buf; cp < buf+len; cp++) {
X if (pnrq_cmd) {
X pcl_haggle(mfd, pnrq_cmd|*cp);
X pnrq_cmd = 0;
X /* pcl_haggle may have changed the protocol */
X if (protocol != pcl_table) {
X if (protocol->p_recv)
X (*protocol->p_recv)(mfd,
X cp+1, buf+len-cp-1);
X return;
X }
X } else if (seen_iac) {
X if ((*cp&P1_DIR) == P1_DIR_MTOH) {
X if (cq > obuf) {
X (void)write(curwin.in->w_datafd,
X obuf, cq-obuf);
X cq = obuf;
X }
X switch (*cp & P1_FN) {
X case P1_FN_NEWW:
X wnum = *cp & P1_WINDOW;
X if (!wnum)
X break;
X w = WIN_PTR(wnum);
X if (w->w_alloc)
X break;
X if (!win_neww(WC_INTERNAL,
X defwtype, wnum,
X protocol->p_maxwin, 0L,
X (fildes_t)-1, (fildes_t)-1,
X (struct woptdefn *)0)) {
X cmdbuf[1] = P1_DIR_HTOM|
X P1_FN_KILLW|wnum;
X (void)write(mfd, cmdbuf,
X sizeof cmdbuf);
X }
X break;
X case P1_FN_KILLW:
X wnum = *cp & P1_WINDOW;
X if (!wnum)
X break;
X win_killw(WIN_PTR(wnum));
X break;
X case P1_FN_ISELW:
X wnum = *cp & P1_WINDOW;
X if (!wnum)
X break;
X w = WIN_PTR(wnum);
X if (w->w_alloc)
X curwin.in = w;
X else
X curwin.in = NULL;
X break;
X case P1_FN_META:
X seen_meta = 1;
X break;
X case P1_FN_CTLCH:
X *cq = protocol->p_ctlch[*cp&P1_CC];
X if (seen_meta) {
X seen_meta = 0;
X *cq |= META;
X }
X if (curwin.in)
X cq++;
X break;
X case P1_FN_MAINT:
X switch (*cp & P1_MF) {
X case P1_MF_ENTRY:
X (*protocol->p_renew)(mfd);
X break;
X case P1_MF_ASKPCL:
X pcl_haggle(mfd,PNRQ_ASK);
X break;
X case P1_MF_CANPCL:
X pnrq_cmd = PNRQ_CAN;
X break;
X case P1_MF_SETPCL:
X pnrq_cmd = PNRQ_SET;
X break;
X case P1_MF_EXIT:
X done(0);
X break;
X }
X break;
X }
X }
X seen_iac = 0;
X } else if (*cp == P1_IAC)
X seen_iac++;
X else {
X if (seen_meta) {
X seen_meta = 0;
X *cq = *cp | META;
X } else
X *cq = *cp;
X if (curwin.in) {
X if (++cq >= obuf+sizeof obuf) {
X (void)write(curwin.in->w_datafd,
X obuf, cq-obuf);
X cq = obuf;
X }
X }
X }
X }
X }
X if (cq > obuf)
X (void)write(curwin.in->w_datafd, obuf, cq-obuf);
X}
X
Xstatic
Xvoid
Xp1_askpcl(mfd)
Xfildes_t mfd;
X{
X static char cmdbuf[2] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_ASKPCL };
X
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X}
X
Xstatic
Xvoid
Xp1_canpcl(mfd, pname)
Xfildes_t mfd;
Xchar pname;
X{
X static char cmdbuf[3] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_CANPCL };
X
X cmdbuf[2] = pname;
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X}
X
Xstatic
Xvoid
Xp1_setpcl(mfd, pname)
Xfildes_t mfd;
Xchar pname;
X{
X static char cmdbuf[3] = { P1_IAC,P1_DIR_HTOM|P1_FN_MAINT|P1_MF_SETPCL };
X
X cmdbuf[2] = pname;
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X}
X
Xstatic
Xvoid
Xp1_renew(mfd)
Xfildes_t mfd;
X{
X register struct window *w;
X static char cmdbuf[2] = { P1_IAC };
X
X /*
X * Re-init (re-NEW) an existing connection. Send a NEWW command
X * for each existing window. This function is invoked when the
X * Macintosh sends an ENTRY maintenance command.
X */
X for (w=window; w < window+protocol->p_maxwin; w++) {
X if (w->w_alloc) {
X win_renew(w, 0);
X cmdbuf[1] = P1_DIR_HTOM|P1_FN_NEWW|WIN_NUM(w);
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X }
X }
X}
X
Xstatic
Xvoid
Xp2_renew(mfd)
Xfildes_t mfd;
X{
X register struct window *w;
X static char cmdbuf[3] = { P2_IAC };
X
X /*
X * Re-init (re-NEW) an existing connection. Send a NEWW command
X * for each existing window. This function is invoked when the
X * Macintosh sends an ENTRY maintenance command.
X */
X for (w=window; w < window+protocol->p_maxwin; w++) {
X if (w->w_alloc) {
X win_renew(w, 1);
X cmdbuf[1] = P2_DIR_HTOM|P2_FN_NEWW|WIN_NUM(w);
X cmdbuf[2] = w->w_type + ' ';
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X }
X }
X}
X
Xstatic
Xstruct window *
Xp2_neww(mfd, wclass, wtype, wnum, wid, datafd, ctlfd)
Xfildes_t mfd;
Xwclass_t wclass;
Xwtype_t wtype;
Xnwin_t wnum;
Xlong wid;
Xfildes_t datafd;
Xfildes_t ctlfd;
X{
X register struct window *w;
X static char cmdbuf[3] = { P2_IAC };
X
X /*
X * Create a new window as requested by the host. This routine is not
X * called when the Macintosh creates a window.
X */
X w = win_neww(wclass, wtype, wnum, protocol->p_maxwin, wid,
X datafd, ctlfd, (struct woptdefn *)0);
X if (w) {
X cmdbuf[1] = P2_DIR_HTOM|P2_FN_NEWW|WIN_NUM(w);
X cmdbuf[2] = ' ' + wtype;
X (void)write(mfd, cmdbuf, sizeof cmdbuf);
X }
X return(w);
X}
X
Xstatic
Xvoid
Xp2_chkopt(mfd)
Xfildes_t mfd;
X{
X register struct window *w;
X nwin_t maxwin;
X
X /*
X * Ideally, this routine would call a routine in the window
X * module (perhaps win_chkopt()), passing the maximum window
X * number as one argument. The "for" loop would be in that
X * routine. However, I'm not willing to accept the overhead
X * for that conceptual nicety.
X */
X maxwin = protocol->p_maxwin;
X for (w=window; w < window+maxwin; w++)
X if (w->w_alloc)
X opt_scan((caddr_t)w, &w->w_optdefn, p2_sendopt, mfd,
X P2_FN_WOPT|WIN_NUM(w));
X}
X
Xstatic
Xvoid
Xp2_sendopt(mfd, fn, buf, len)
Xfildes_t mfd;
Xint fn;
Xregister char *buf;
Xregister int len;
X{
X register char *cp;
X register int i;
X char outbuf[512];
X
X /*
X * Encode and transmit the option string contained in "buf". The
X * initial command (which will be P2_FN_WOPT|WIN_NUM(w)) is
X * contained in "fn".
X *
X * The caller is responsible for handing us a correctly-formed
X * option string. This routine merely performs the protocol encoding
X * which is required for control and meta characters.
X */
X curwin.out = NULL;
X outbuf[0] = P2_IAC;
X outbuf[1] = fn|P2_DIR_HTOM;
X for (cp=outbuf+2; len > 0; buf++,len--) {
X if (cp > outbuf+sizeof outbuf - 4) {
X (void)write(mfd, outbuf, cp-outbuf);
X cp = outbuf;
X }
X if (*buf & META) {
X *cp++ = P2_IAC;
X *cp++ = P2_DIR_HTOM|P2_FN_META;
X *buf &= ~META;
X }
X i = -1;
X if (*buf == RUB || *buf < ' ') {
X i = protocol->p_szctlch - 1;
X while (i >= 0 && protocol->p_ctlch[i] != *buf)
X i--;
X }
X if (i >= 0) {
X *cp++ = P2_IAC;
X *cp++ = P2_DIR_HTOM|P2_FN_CTLCH|(i&7);
X } else
X *cp++ = *buf;
X }
X if (cp > outbuf)
X (void)write(mfd, outbuf, cp-outbuf);
X}
X
Xstatic
Xvoid
Xp2_recv(mfd, cbuf, clen)
Xfildes_t mfd;
Xchar *cbuf;
Xint clen;
X{
X register int len;
X register char *buf, *cp, *cq;
X register struct window *w;
X register char c;
X nwin_t wnum;
X auto int nready;
X char ibuf[512], obuf[512];
X static int seen_iac, seen_meta, is_option;
X static pnreq_t pnrq_cmd;
X static nwin_t neww;
X static char cmdbuf[2] = { P2_IAC };
X
X /*
X * The received bytestream is examined. Non-command bytes are
X * written to the file descriptor corresponding to the current
X * "input" window (relative to the Macintosh -- the window the
X * user types input to).
X *
X * If "clen" is nonzero, then the contents of the buffer "cbuf"
X * are processed before any input is read.
X */
X if (ioctl(mfd, (int)FIONREAD, (char *)&nready) < 0) {
X perror("FIONREAD");
X return;
X }
X nready += clen;
X
X for (cq = obuf; nready > 0; nready -= len) {
X if (clen > 0) {
X len = clen;
X buf = cbuf;
X clen = 0;
X } else {
X if (nready > sizeof ibuf)
X len = read(mfd, ibuf, sizeof ibuf);
X else
X len = read(mfd, ibuf, nready);
X if (len <= 0) {
X perror("read");
X return;
X }
X buf = ibuf;
X }
X for (cp=buf; cp < buf+len; cp++) {
X if (pnrq_cmd) {
X pcl_haggle(mfd, pnrq_cmd|*cp);
X pnrq_cmd = 0;
X /* pcl_haggle may have changed the protocol */
X if (protocol != pcl_table) {
X if (protocol->p_recv)
X (*protocol->p_recv)(mfd,
X cp+1, buf+len-cp-1);
X return;
X }
X } else if (neww) {
X w = WIN_PTR(neww);
X if (!w->w_alloc &&
X !win_neww(WC_INTERNAL, (wtype_t)(*cp-' '),
X neww, protocol->p_maxwin, 0L,
X (fildes_t)-1, (fildes_t)-1,
X (struct woptdefn *)0)) {
X cmdbuf[1] = P2_DIR_HTOM|
X P2_FN_KILLW|neww;
X (void)write(mfd, cmdbuf,
X sizeof cmdbuf);
X }
X neww = 0;
X } else if (seen_iac) {
X if ((*cp&P2_DIR) == P2_DIR_MTOH) {
X c = *cp & P2_FN;
X if (is_option &&
X c!=P2_FN_META && c!=P2_FN_CTLCH) {
X opt_iflush();
X is_option = 0;
X }
X if (cq > obuf) {
X (void)write(curwin.in->w_datafd,
X obuf, cq-obuf);
X cq = obuf;
X }
X switch (*cp & P2_FN) {
X case P2_FN_NEWW:
X neww = *cp & P2_WINDOW;
X break;
X case P2_FN_WOPT:
X wnum = *cp & P2_WINDOW;
X if (!wnum)
X break;
X w = WIN_PTR(wnum);
X if (!w->w_alloc) {
X curwin.in = NULL;
X break;
X }
X is_option = 1;
X opt_istart((caddr_t)w, &w->w_optdefn);
X break;
X case P2_FN_KILLW:
X wnum = *cp & P2_WINDOW;
X if (!wnum)
X break;
X win_killw(WIN_PTR(wnum));
X break;
X case P2_FN_ISELW:
X wnum = *cp & P2_WINDOW;
X if (!wnum)
X break;
X w = WIN_PTR(wnum);
X if (w->w_alloc)
X curwin.in = w;
X else
X curwin.in = NULL;
X break;
X case P2_FN_META:
X seen_meta = 1;
X if ((*cp&P2_CC) == 0)
X break;
X /* no break */
X case P2_FN_CTLCH:
X c=protocol->p_ctlch[*cp&P2_CC];
X if (seen_meta) {
X seen_meta = 0;
X c |= META;
X }
X if (is_option)
X is_option=opt_input(c);
X else
X if (curwin.in)
X *cq++ = c;
X break;
X case P2_FN_MAINT:
X switch (*cp & P2_MF) {
X case P2_MF_ENTRY:
X (*protocol->p_setpcl)(mfd, protocol->p_name);
X (*protocol->p_renew)(mfd);
X break;
X case P2_MF_ASKPCL:
X pcl_haggle(mfd,PNRQ_ASK);
X break;
X case P2_MF_CANPCL:
X pnrq_cmd = PNRQ_CAN;
X break;
X case P2_MF_SETPCL:
X pnrq_cmd = PNRQ_SET;
X break;
X case P2_MF_EXIT:
X done(0);
X break;
X }
X break;
X }
X }
X seen_iac = 0;
X } else if (*cp == P2_IAC)
X seen_iac++;
X else {
X if (seen_meta) {
X c = *cp | META;
X seen_meta = 0;
X } else
X c = *cp;
X if (is_option)
X is_option = opt_input(c);
X else
X if (curwin.in)
X *cq++ = c;
X if (cq >= obuf+sizeof obuf) {
X (void)write(curwin.in->w_datafd,
X obuf, cq-obuf);
X cq = obuf;
X }
X }
X }
X }
X if (cq > obuf)
X (void)write(curwin.in->w_datafd, obuf, cq-obuf);
X}
SHAR_EOF
if test 21808 -ne "`wc -c < 'server/uw_pcl.c'`"
then
echo shar: error transmitting "'server/uw_pcl.c'" '(should have been 21808 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
--- end of part 7 ---
Technical Details
Message-ID:
<6609@dhw68k.cts.com>Path:
arc1-ca.pugleaf.net!utzoo!mnetor!uunet!ccicpg!felix!dhw68k!macintoshReferences:
<6493@dhw68k.cts.com> <6497@dhw68k.cts.com> <6515@dhw68k.cts.com> <6538@dhw68k.cts.com> <6587@dhw68k.cts.com> <6602@dhw68k.cts.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!mnetor!uunet!ccicpg!felix!dhw68k!macintosh From: jdb@mordor.s1.gov (John Bruner) Newsgroups: comp.sources.mac Subject: UW v4.2 (part 7 of 9) Message-ID: <6609@dhw68k.cts.com> Date: 7 Apr 88 14:00:44 GMT References: <6493@dhw68k.cts.com> <6497@dhw68k.cts.com> <6515@dhw68k.cts.com> <6538@dhw68k.cts.com> <6587@dhw68k.cts.com> <6602@dhw68k.cts.com> Sender: macintosh@dhw68k.cts.com Organization: Lawrence Livermore National Laboratory, S-1 Project Lines: 1580 Approved: bytebug@dhw68k.cts.com (Roger L. Long)