[comp.sources.amiga] v90i186: UUCP 1.06D - UNIX compatible uucp/news/mail system, Part08/12

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (06/28/90)

Submitted-by: Matt Dillon <@uunet.uu.net:overload!dillon>
Posting-number: Volume 90, Issue 186
Archive-name: unix/uucp-1.06d/part08

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 8 (of 12)."
# Contents:  uucp2/src/getty/getty.c uucp2/src/uucico/gio.c
# Wrapped by tadguy@xanth on Thu Jun 28 08:21:31 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'uucp2/src/getty/getty.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uucp2/src/getty/getty.c'\"
else
echo shar: Extracting \"'uucp2/src/getty/getty.c'\" \(20766 characters\)
sed "s/^X//" >'uucp2/src/getty/getty.c' <<'END_OF_FILE'
X
X/*
X *  GETTY.C
X *
X *  $Header: Beta:src/uucp/src/getty/RCS/getty.c,v 1.1 90/02/02 12:13:30 dillon Exp Locker: dillon $
X *
X *  (C)Copyright 1989, Matthew Dillon, All Rights Reserved
X *
X *  Uses:
X *	GETTY:PASSWD
X *	GETTY:LOGFILE
X *	GETTY:Getty-Header
X *
X *  GETTY   <options>	<modem-commands>
X *
X *	-Sdevicenam Tells GETTY which serial.device to use, default
X *		    serial.device
X *
X *	-Uunitnum   Tells GETTY which unit number to use, default 0
X *
X *	-A	    Always talk to the modem at the first baud
X *		    rate in the -B list and ignore the baud rate
X *		    in the CONNECT message.
X *
X *	-7	    use SERF_7WIRE while online.
X *
X *	-Bn	    Set baud rate.  If specified multiple times the
X *		    first one is the default and remaining ones
X *		    switched to when a BREAK is received after a
X *		    connect.  Also determines how CONNECT messages
X *		    are interpreted.  A CONNECT with no number uses
X *		    the first -B entry while CONNECTs with numbers
X *		    use those numbers regardless of any -B entries.
X *
X *	-Mc	    Set modem type:
X *			c = m	= multimodem
X *			    h	= hays
X *			    d	= dumb (no AT or +++ cmds are ever sent),
X *				  normally used with only one specified
X *				  baud rate.
X *
X *	-m1	    Turn on the modem speaker during dialing/connect
X *		    (default is -m0)
X *
X *	-h0	    Ignore CD (carrier detect), default is to use
X *		    carrier detect.
X *
X *	-c0	    Ignore CONNECT message (i.e. you are not connected
X *		    to a modem, usually combined with -h0).  Default is
X *		    to expect a CONNECT message.
X *
X *	-d0	    do not use DTR to drop connection.	Default is
X *		    to drop DTR to drop a connection.  If this option
X *		    is chosen the +++ and ATH0 sequence will be used
X *		    to drop a connection.
X *
X *	-xn	    Set debug level.  Also causes log output to go
X *		    to stdout instead of GETTY:LOGFILE
X *
X *	-0	    QUIT - Kills any running getty for the specified
X *		    port.
X *
X *	Any fields specified without a '-' are considered modem commands
X *	used to initialize/reinitialize the modem.  Up to 16 fields may
X *	be specified (each is sent to the modem in 1 second intervals)
X */
X
X#include <exec/types.h>
X#include <exec/lists.h>
X#include <exec/devices.h>
X#include <devices/timer.h>
X#include <devices/serial.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <hardware/cia.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include "protos.h"
X#include <pwd.h>
X#include "version.h"
X
X#include "log.h"
X
XIDENT(".02");
X
X#ifndef IO_STATF_READBREAK
X#define IO_STATF_READBREAK (IOSTF_READBREAK<<8)
X#endif
X
X#define arysize(ary)    (sizeof(ary)/sizeof((ary)[0]))
X
X#define ST_WAITCD	0
X#define ST_CONNECT	1
X#define ST_LOGIN	2
X#define ST_PASSWD	3
X#define ST_RUN		4
X
Xtypedef struct IORequest    IOR;
Xtypedef struct timerequest  IOT;
Xtypedef struct IOExtSer     IOSER;
Xtypedef struct MsgPort	    PORT;
Xtypedef struct List	    LIST;
Xtypedef struct Node	    NODE;
Xtypedef struct Message	    MSG;
Xtypedef void (*FPTR)();
X
Xtypedef struct GMsg {
X    struct Message  Msg;
X    short   Cmd;
X    long    Data1;
X    void    *Data2;
X} GMsg;
X
Xextern struct ProcID *RunPasswdEntry();
X
Xchar	*CopyRight = "(c)Copyright 1989, Matthew Dillon, All Rights Reserved\r\n";
Xchar	*ComPortName;
X
Xchar	*DeviceName = "serial.device";
Xlong	DeviceUnit  = 0;
Xlong	NullFH;
Xchar	SpeakerLevel	= 0;
Xchar	AnswerRing	= 2;	/*  default, answer on second ring */
Xchar	SpeakerOpt	= 0;
Xchar	IgnoreCD	= 0;
Xchar	IgnoreConnect	= 0;
Xchar	IgnoreDTR	= 0;
Xchar	BaudAdjust	= 0;
Xchar	DropOnExit	= 1;
Xchar	ModemType	= 'h';
Xchar	ZeroOption	= 0;
Xchar	Wire7		= 0;		/*  use 7 wire while online */
Xchar	Locked		= 0;		/*  serial port is lcked    */
Xlong	Bauds[16] = { 9600 };		/*  up 16 baud rates	    */
Xchar	*AtFields[16];
X
XPORT	*ComPort;
XPORT	*IoSink;	/*  Sink for IO reqs.	*/
Xlong	IoSinkMask;
Xlong	ComPortMask;
X
XIOT	Iot;		/*  check-carrier	*/
XIOSER	Iosr;		/*  serial read-req	*/
XIOSER	Iosw;		/*  serial write-req	*/
X
Xchar	IotIP;		/*  Iot0 in progress	*/
Xchar	IosrIP;
X
Xchar	ScrBuf[256];
Xchar	ConnectBuf[64];
Xchar	LoginBuf[32];
Xchar	PasswdBuf[32];
Xchar	RxBuf[32];
Xchar	HaveConnectMsg;
Xchar	HaveLogin;
Xchar	HavePasswd;
X
Xshort	State;
Xshort	Index;
Xshort	BIndex;
X
Xshort CountDown;
Xshort GotOffPort;
X
Xvoid	SerPuts();
Xvoid	Set7Wire();
Xvoid	xexit();
Xvoid	Disconnect();
Xvoid	ClearRecv();
Xvoid	InitModem();
Xvoid	SetParams();
Xvoid	DoOptions();
Xvoid	SerialOff();
Xvoid	InterceptDeviceVector();
Xvoid	RestoreDeviceVector();
X
Xbrk()
X{
X    return(0);
X}
X
Xmain(ac, av)
Xchar *av[];
X{
X    extern int IAmGetty;
X    char termCr = 1;
X    char termLf = 1;
X
X    IAmGetty = 1;	/*  for LockSerialPort()/UnLockSerialPort()   */
X
X    puts(CopyRight);
X    fflush(stdout);
X    onbreak(brk);
X
X    LogProgram = "Getty";
X    LogWho = LoginBuf;
X    LogFile = "Getty:LOGFILE";
X    PasswdFile = "Getty:Passwd";
X
X    DoOptions(ac, av);
X
X    IoSink = CreatePort(NULL, 0);
X    IoSinkMask = 1 << IoSink->mp_SigBit;
X
X    ComPortName = malloc(strlen(DeviceName) + 20);
X    sprintf(ComPortName, "Getty.%s.%ld", DeviceName, DeviceUnit);
X
X    Forbid();
X    if (ComPort = FindPort(ComPortName)) {
X	GMsg msg;
X	msg.Cmd = 'O';
X	msg.Data1 = ac;
X	msg.Data2 = (void *)av;
X	msg.Msg.mn_ReplyPort = IoSink;
X	PutMsg(ComPort, &msg.Msg);
X	WaitPort(IoSink);
X	Remove(&msg.Msg.mn_Node);
X	Permit();
X	puts("Options updated");
X	xexit(0);
X    }
X    ComPort = CreatePort(ComPortName, 0L);
X    Permit();
X
X    ComPortMask = 1L << ComPort->mp_SigBit;
X
X    NullFH = Open("NULL:", 1006);
X    if (NullFH == NULL) {
X	ulog(-1, "GETTY REQUIRES NULL: HANDLER!");
X	puts("Requires NULL: handler!");
X	xexit(1);
X    }
X    if (LogToStdout == 0) {
X	freopen("NULL:", "r", stdin);
X	freopen("NULL:", "w", stdout);
X	freopen("NULL:", "w", stderr);
X    }
X
X
X    /*
X     *	Timer Device
X     */
X
X    Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
X    if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0L)) {
X	Iot.tr_node.io_Device = NULL;
X	xexit(20);
X    }
X    Iot.tr_node.io_Command = TR_ADDREQUEST;
X
X    /*
X     *	SERIAL.DEVICE
X     */
X
X    Iosr.IOSer.io_Message.mn_ReplyPort = IoSink;
X    Iosr.io_SerFlags = SERF_XDISABLED | SERF_7WIRE | SERF_RAD_BOOGIE | SERF_SHARED;
X    if (OpenDevice(DeviceName, DeviceUnit, &Iosr, 0L)) {
X	Iosr.IOSer.io_Device = NULL;
X	xexit(21);
X    }
X
X    InterceptDeviceVector(Iosr.IOSer.io_Device);
X
X    Iosw = Iosr;
X
X    Iosw.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
X    Iosw.io_ExtFlags = 0;
X    Iosw.io_Baud = Bauds[0];
X    Iosw.io_ReadLen = 8;
X    Iosw.io_WriteLen = 8;
X    Iosw.io_StopBits = 1;
X
X    SetParams(&Iosw);
X
X    /*
X     *	Run Operation
X     */
X
X    State = ST_WAITCD;
X    Iot.tr_time.tv_secs = 1;
X    Iot.tr_time.tv_micro= 0;
X    IotIP = 1;
X    SendIO(&Iot);
X
X    InitModem();
X
X    Signal(FindTask(NULL), IoSinkMask);
X
X    for (;;) {
X	long mask;
X	IOR  *ior;
X	GMsg *msg;
X	mask = Wait(SIGBREAKF_CTRL_C | IoSinkMask | ComPortMask);
X
X	ulog(2, "State = %d", State);
X
X	if (mask & SIGBREAKF_CTRL_C)
X	    break;
X
X	if (msg = (GMsg *)GetMsg(ComPort)) {
X	    do {
X		switch(msg->Cmd) {
X		case 'O':
X		    DoOptions(msg->Data1, msg->Data2);
X		    break;
X		}
X		ReplyMsg((MSG *)msg);
X		if (ZeroOption)
X		    xexit(0);
X	    } while (msg = (GMsg *)GetMsg(ComPort));
X	    if (State == ST_WAITCD && !GotOffPort)
X		Disconnect(0);
X	}
X
X	while (ior = (IOR *)GetMsg(IoSink)) {
X	    if (ior == (IOR *)&Iot) {
X		short diu;
X
X		IotIP = 0;
X		Iot.tr_time.tv_secs = 1;
X		Iot.tr_time.tv_micro= 0;
X
X		/*
X		 *  If OpenCnt > 1, disable all processing.
X		 *
X		 *  When returns to <= 1 reset serial port.
X		 */
X
X		diu = DeviceInUse();
X		if (diu) {
X		    if (GotOffPort == 0) {
X			ulog(-1, "Device in use");
X			if (Locked)
X			    ulog(-1, "getting off port");
X			SerialOff();
X			GotOffPort = 1;
X			State = ST_WAITCD;
X		    }
X		    SendIO(&Iot);
X		    IotIP = 1;
X		    continue;
X		}
X		if (GotOffPort) {
X		    if (Locked == 0) {
X			LockSerialPort(DeviceName, DeviceUnit);
X			Locked = 1;
X		    }
X		    GotOffPort = 0;
X		    ulog(-1, "Getty resetting");
X		    SendIO(&Iot);
X		    IotIP = 1;
X		    Disconnect(1);
X		    continue;
X		}
X		if (State == ST_WAITCD)
X		    SerialOff();
X
X		if (State != ST_WAITCD && IosrIP == 0) {
X		    if (Locked == 0)
X			LockSerialPort(DeviceName, DeviceUnit);
X		    Locked = 1;
X		    ulog(-1, "Serial Port Locked");
X
X		    Iosr.IOSer.io_Command = CMD_READ;
X		    Iosr.IOSer.io_Data = (APTR)RxBuf;
X		    Iosr.IOSer.io_Length = 1;
X		    SendIO(&Iosr);
X		    IosrIP = 1;
X		    ulog(1, "Carrier, Getty getting on port");
X		}
X
X		Iosw.IOSer.io_Command = SDCMD_QUERY;
X		DoIO(&Iosw);
X		if (IgnoreCD)
X		    Iosw.io_Status &= ~CIAF_COMCD;
X
X		/*
X		 *  If state connected and we loose carrier, disconnect.
X		 *
X		 *  If state connected and timeout occurs disconnect.
X		 */
X
X		if (State != ST_WAITCD) {
X		    if ((Iosw.io_Status & CIAF_COMCD) != 0) {
X			ulog(1, "Getty, Carrier lost");
X			Disconnect(0);
X		    } else {
X			if (--CountDown == 0) {
X			    ulog(1, "Getty, Timeout, Disconnecting");
X			    Disconnect(1);
X			    Iosw.io_Status |= CIAF_COMCD; /* for below */
X			}
X		    }
X		}
X
X		switch(State) {
X		case ST_WAITCD:
X		    if ((Iosw.io_Status & CIAF_COMCD) == 0) {
X			State = ST_CONNECT;
X			CountDown = 60;     /*	allow 60 seconds */
X			ulog(-1, "Carrier Detect");
X		    } else {
X			Iot.tr_time.tv_secs = 2;
X		    }
X		    break;
X		case ST_CONNECT:
X		    /*
X		     *	Wait for CONNECT message, then send Login:
X		     */
X
X		    if (IgnoreConnect && HaveConnectMsg == 0) {
X			if (Wire7)
X			    Set7Wire(&Iosw);
X			HaveConnectMsg = 1;
X			ulog(-1, "Connect");
X		    }
X
X		    if (HaveConnectMsg) {
X			FILE *fi;
X
X			Delay(50);
X			ClearRecv();
X			if (fi = fopen("Getty:Getty-Header", "r")) {
X			    while (fgets(ScrBuf, sizeof(ScrBuf), fi)) {
X				SerPuts(ScrBuf);
X				SerPuts("\r");
X			    }
X			    fclose(fi);
X			}
X			termCr = termLf = 1;
X			SerPuts("Login: ");
X			ulog(-1, "Getty, Connect, Login");
X			State = ST_LOGIN;
X			Index = 0;
X			HaveLogin = 0;
X			LoginBuf[0] = 0;
X		    }
X		    break;
X		case ST_LOGIN:	    /*	wait Login: response	*/
X		    if (HaveLogin) {
X			if (LoginBuf[0] == 0) {
X			    State = ST_CONNECT;
X			    break;
X			}
X			ClearRecv();
X			PasswdBuf[0] = 0;
X
X			/*
X			 *  If no password required, else request
X			 *  password.
X			 */
X
X			if (CheckLoginAndPassword()) {
X			    HavePasswd = 1;
X			    Index = 0;
X			    State = ST_PASSWD;
X			} else {
X			    SerPuts("Password: ");
X			    ulog(1, "Getty, Passwd");
X			    State = ST_PASSWD;
X			    HavePasswd = 0;
X			    Index = 0;
X			}
X		    }
X		    break;
X		case ST_PASSWD:     /*	wait Password: response */
X		    if (HavePasswd) {
X			if (CheckLoginAndPassword()) {
X			    ulog(-1, "login %s", LoginBuf);
X
X			    /*
X			     *	Disable read requests but leave serial
X			     *	port locked.
X			     */
X
X			    if (IosrIP) {
X				AbortIO(&Iosr);
X				WaitIO(&Iosr);
X				IosrIP = 0;
X			    }
X
X			    /*
X			     *	If run successful, leave read req and
X			     *	timer disabled.
X			     */
X
X			    RunPasswdEntry();
X
X			    if (DropOnExit)
X				Disconnect(1);
X			    else
X				State = ST_CONNECT;
X			    ulog(-1, "disconnect");
X			} else {
X			    SerPuts("Login Failed.\r\n\n");
X			    State = ST_CONNECT;
X			    ulog(-1, "LoginFailed user=%s pass=%s", LoginBuf, PasswdBuf);
X			}
X			HaveLogin = 0;
X			HavePasswd= 0;
X			LoginBuf[0] = 0;
X		    }
X		    break;
X		}
X
X		/*
X		 *  Make no read requests while running 3rd party
X		 *  program, else resend read request.
X		 */
X
X		if (IotIP == 0) {
X		    IotIP = 1;
X		    SendIO(&Iot);
X		}
X	    }
X
X	    /*
X	     *	RECEIVED SERIAL READ DATA
X	     */
X
X	    if (ior == (IOR *)&Iosr) {
X		IosrIP = 0;
X
X		Iosw.IOSer.io_Command = SDCMD_QUERY;
X		DoIO(&Iosw);
X		if (IgnoreCD)
X		    Iosw.io_Status &= ~CIAF_COMCD;
X
X		/*
X		 *  BREAK used to switch baud rates between allowed
X		 *  values
X		 */
X
X		if (Iosw.io_Status & IO_STATF_READBREAK) {
X		    if (BaudAdjust == 0 && (State == ST_LOGIN || State == ST_PASSWD)) {
X			if (++BIndex == arysize(Bauds))
X			    BIndex = 0;
X			if (Bauds[BIndex] == 0)
X			    BIndex = 0;
X			Iosw.io_Baud = Bauds[BIndex];
X			SetParams(&Iosw);
X			if (Wire7)
X			    Set7Wire(&Iosw);
X			ulog(1, "<BREAK> to %d baud", Iosw.io_Baud);
X			Delay(100);
X			ClearRecv();
X			Index = 0;
X			State = ST_CONNECT;
X		    }
X		} else
X		if (Iosr.IOSer.io_Actual == 1) {
X		    char *ptr;
X		    UBYTE c = (UBYTE)RxBuf[0];
X
X		    ulog(2, "Rx %02x %c", c, (c < 32) ? ' ' : c);
X		    c &= 0x7F;
X
X		    switch(State) {
X		    case ST_WAITCD:	/*  looking for CONNECT msg */
X		    case ST_CONNECT:	/*  looking for CONNECT msg */
X			ptr = ConnectBuf;
X			break;
X		    case ST_LOGIN:	/*  looking for login name  */
X			ptr = LoginBuf;
X			break;
X		    case ST_PASSWD:	/*  looking for password    */
X			ptr = PasswdBuf;
X			break;
X		    }
X		    if (State == ST_LOGIN && HaveLogin)
X			c = 0;
X		    if (State == ST_PASSWD && HavePasswd)
X			c = 0;
X
X		    switch(c) {
X		    case 0:
X			break;
X		    case 8:
X			if (State == ST_LOGIN && HaveLogin)
X			    break;
X			if (Index) {
X			    if (State == ST_LOGIN)
X				SerPuts("\010 \010");
X			    --Index;
X			}
X			break;
X		    case 10:
X			if (termLf == 0)
X			    break;
X			termCr = 0;
X		    case 13:
X			if (c == 13) {
X			    if (termCr == 0)
X				break;
X			    else
X				termLf = 0;
X			}
X			ptr[Index] = 0;
X			Index = 0;
X			switch(State) {
X			case ST_WAITCD:
X			case ST_CONNECT:
X			    if (strncmp(ptr, "CONNECT", 7)) {
X				ulog(1, "Looking for CONNECT, got '%s'", ptr);
X				break;
X			    }
X			    Delay(50);
X			    HaveConnectMsg = 1;
X			    if (BaudAdjust) {
X				ulog(-1, "Connect Auto-Baud %d", Iosw.io_Baud);
X			    } else {
X				char *str = ptr + 7;
X				while (*str && (*str == 9 || *str == ' '))
X				    ++str;
X				if (*str >= '0' && *str <= '9')
X				    Iosw.io_Baud = atoi(str);
X				else
X				    Iosw.io_Baud = Bauds[0];
X				SetParams(&Iosw);
X				ulog(-1, "Connect at %d baud", Iosw.io_Baud);
X			    }
X			    if (Wire7)
X				Set7Wire(&Iosw);
X			    break;
X			case ST_LOGIN:
X			    HaveLogin = 1;
X			    SerPuts("\r\n");
X			    ulog(1, "Login: %s", ptr);
X			    break;
X			case ST_PASSWD:
X			    HavePasswd = 1;
X			    SerPuts("\r\n");
X			    ulog(1, "Password: %s", ptr);
X			    break;
X			}
X			break;
X		    default:
X			if (Index == 31)
X			    break;
X			if (State == ST_LOGIN) {
X			    char cc[2];
X			    cc[0] = c;
X			    cc[1] = 0;
X			    SerPuts(cc);
X			}
X			ptr[Index++] = c;
X			break;
X		    }
X		}
X		if (IosrIP == 0) {
X		    Iosr.IOSer.io_Command = CMD_READ;
X		    Iosr.IOSer.io_Data = (APTR)RxBuf;
X		    Iosr.IOSer.io_Length = 1;
X		    SendIO(&Iosr);
X		    IosrIP = 1;
X		}
X	    }
X	}
X    }
X    xexit(0);
X}
X
Xvoid
XSerialOff()
X{
X    if (IosrIP) {
X	AbortIO(&Iosr);
X	WaitIO(&Iosr);
X	IosrIP = 0;
X    }
X    if (Locked) {
X	UnLockSerialPort(DeviceName, DeviceUnit);
X	Locked = 0;
X	ulog(1, "Serial Port UnLocked");
X    }
X}
X
Xvoid
Xxexit(code)
X{
X    if (ComPortMask) {
X	GMsg *msg;
X	Forbid();
X	while (msg = (GMsg *)GetMsg(ComPort))
X	    ReplyMsg((MSG *)msg);
X	DeletePort(ComPort);
X	Permit();
X    }
X    if (IotIP) {
X	AbortIO(&Iot);
X	WaitIO(&Iot);
X    }
X    if (Iot.tr_node.io_Device)
X	CloseDevice(&Iot);
X
X    if (IosrIP) {
X	AbortIO(&Iosr);
X	WaitIO(&Iosr);
X    }
X    if (Iosr.IOSer.io_Device) {
X	RestoreDeviceVector(Iosr.IOSer.io_Device);
X	CloseDevice(&Iosr);
X    }
X
X    if (IoSink)
X	DeletePort(IoSink);
X
X    if (NullFH)
X	Close(NullFH);
X
X    if (Locked)
X	UnLockSerialPort(DeviceName, DeviceUnit);
X
X    exit(code);
X}
X
Xvoid
XSerPuts(str)
Xchar *str;
X{
X    Iosw.IOSer.io_Command = CMD_WRITE;
X    Iosw.IOSer.io_Data = (APTR)str;
X    Iosw.IOSer.io_Length = strlen(str);
X    DoIO(&Iosw);
X}
X
Xstatic short RxDisableIP;
X
Xvoid
XRxDisable()
X{
X    RxDisableIP = IosrIP;
X    if (IosrIP) {
X	AbortIO(&Iosr);
X	WaitIO(&Iosr);
X	IosrIP = 0;
X    }
X}
X
Xvoid
XRxEnable()
X{
X    if (RxDisableIP && IosrIP == 0) {
X	Iosr.IOSer.io_Command = CMD_READ;
X	Iosr.IOSer.io_Data = (APTR)RxBuf;
X	Iosr.IOSer.io_Length = 1;
X	SendIO(&Iosr);
X	IosrIP = 1;
X    }
X}
X
Xvoid
XClearRecv()
X{
X    RxDisable();
X    ulog(1, "Clear beg");
X    for (;;) {
X	Iosr.IOSer.io_Command = SDCMD_QUERY;
X	DoIO(&Iosr);
X	if ((Iosr.IOSer.io_Length = Iosr.IOSer.io_Actual) <= 0)
X	    break;
X	if (Iosr.IOSer.io_Length > sizeof(RxBuf))
X	    Iosr.IOSer.io_Length = sizeof(RxBuf);
X	Iosr.IOSer.io_Data = (APTR)RxBuf;
X	Iosr.IOSer.io_Command = CMD_READ;
X	DoIO(&Iosr);
X    }
X    ulog(1, "Clear end");
X    RxEnable();
X}
X
Xvoid
XSetParams(ior)
XIOSER *ior;
X{
X    int error;
X
X    if (IosrIP)
X	AbortIO(&Iosr);
X    ior->IOSer.io_Command = SDCMD_SETPARAMS;
X    error = DoIO(ior);
X    if (error)
X	printf("SetParams, error %d\n", error);
X}
X
Xvoid
XSet7Wire(ior)
XIOSER *ior;
X{
X    short error;
X
X    if (IosrIP)
X	AbortIO(&Iosr);
X    ior->IOSer.io_Command = SDCMD_SETPARAMS;
X    ior->io_SerFlags |= SERF_7WIRE;
X    error = DoIO(ior);
X    ior->io_SerFlags &= ~SERF_7WIRE;
X    if (error)
X	printf("SetParams, error %d\n", error);
X}
X
Xvoid
XDisconnect(dropdtr)
X{
X    short retry = (IgnoreDTR) ? 2 : 10;
X
X    ulog(1, "Disconnect drop=%d", dropdtr);
X    HaveConnectMsg = 0;
X    HaveLogin	= 0;
X    HavePasswd	= 0;
X    LoginBuf[0] = 0;
X    PasswdBuf[0] = 0;
X    Index = 0;
X    State = ST_WAITCD;
X
X    while (dropdtr && DeviceInUse() == 0) {
X	short i;
X
X	RxDisable();
X
X	if (IgnoreDTR) {
X	    if (ModemType != 'd') {
X		Delay(70);
X		SerPuts("+++");
X		Delay(70);
X		SerPuts("\010\010\r");
X		Delay(10);
X		SerPuts("ATH0\r");
X		Delay(120);
X	    }
X	} else {
X	    CloseDevice(&Iosr);
X	    Iosr.IOSer.io_Device = NULL;    /*	so xexit doesn't reclose */
X	    for (i = 0; i < 5; ++i) {       /*  5 seconds   */
X		Delay(50);
X		if (SetSignal(SIGBREAKF_CTRL_C, 0) & SIGBREAKF_CTRL_C)
X		    xexit(23);
X	    }
X
X	   /*
X	    *  Use Iosr to re-open serial device so we don't loose
X	    *  our config.
X	    */
X
X	    if (OpenDevice(DeviceName, DeviceUnit, &Iosr, 0)) {
X		Iosr.IOSer.io_Device = NULL;
X		xexit(22);
X	    }
X	    Iosw.IOSer.io_Device = Iosr.IOSer.io_Device;
X	    Iosw.IOSer.io_Unit = Iosr.IOSer.io_Unit;
X	    SetParams(&Iosw);
X	}
X
X	/*
X	 *  Loop until carrier lost
X	 */
X
X	Iosw.IOSer.io_Command = SDCMD_QUERY;
X	DoIO(&Iosw);
X	if (IgnoreCD)
X	    Iosw.io_Status &= ~CIAF_COMCD;
X
X	RxEnable();
X
X	if ((Iosw.io_Status & CIAF_COMCD) != 0)
X	    break;
X	if (--retry == 0) {
X	    if (IgnoreDTR == 0)
X		puts("Getty: unable to disconnect!");
X	    break;
X	}
X    }
X    if (DeviceInUse() == 0)
X	InitModem();
X}
X
Xvoid
XInitModem()
X{
X    char buf[64];
X    short i;
X
X    RxDisable();
X    ulog(1, "Init Modem");
X    Iosw.io_Baud = Bauds[0];	/*  reset baud rate */
X    BIndex = 0;
X    SetParams(&Iosw);
X    RxEnable();
X
X    switch(ModemType) {
X    case 'm':               /*  Multi Modem     */
X	SerPuts("\010\010\r");
X	Delay(10);
X	SerPuts("AT\r");
X	Delay(50);
X	sprintf(buf, "ATM%dS0=%dX4$BA%d&E%d\r",
X	    SpeakerLevel,
X	    AnswerRing,
X	    !BaudAdjust,
X	    (Wire7) ? 4 : 3
X	);
X	SerPuts(buf);
X	break;
X    case 'h':
X	SerPuts("\010\010\r");
X	Delay(10);
X	SerPuts("ATZ\r");
X	Delay(120);
X	strcpy(buf, "AT");
X	if (SpeakerOpt)
X	    sprintf(buf + strlen(buf), "M%d", SpeakerLevel);
X	sprintf(buf + strlen(buf), "S0=%d", AnswerRing);
X	strcat(buf, "\r");
X	SerPuts(buf);
X	break;
X    case 'd':
X	SerPuts("\010\010\r");
X	break;
X    }
X    for (i = 0; i < arysize(AtFields) && AtFields[i]; ++i) {
X	Delay(50);
X	SerPuts(AtFields[i]);
X	SerPuts("\r");
X    }
X    Delay(20);
X    ClearRecv();
X    Index = 0;
X}
X
Xvoid
XDoOptions(ac, av)
Xchar *av[];
X{
X    short i;
X    short bi = 0;
X    short fi = 0;
X    long v;
X
X    for (i = 1; i < ac; ++i) {
X	char *ptr = av[i];
X	if (*ptr != '-') {
X	    if (fi != arysize(AtFields))
X		AtFields[fi++] = ptr;
X	    else
X		puts("AT field overflow");
X	    continue;
X	}
X	if (*++ptr)             /*  skip -      */
X	    ++ptr;		/*  and option	*/
X	v = atoi(ptr);
X	switch(ptr[-1]) {
X	case '0':
X	    ZeroOption = 1;
X	    break;
X	case '7':
X	    Wire7 = 1;
X	    break;
X	case 'S':
X	    DeviceName = ptr;
X	    break;
X	case 'U':
X	    DeviceUnit = v;
X	    break;
X	case 'M':
X	    ModemType = *ptr;
X	    break;
X	case 'A':
X	    BaudAdjust = 1;
X	    break;
X	case 'B':
X	    if (bi != arysize(Bauds))
X		Bauds[bi++] = v;
X	    else
X		puts("-B field overflow");
X	    break;
X	case 'm':
X	    SpeakerOpt = 1;
X	    SpeakerLevel = v;
X	    break;
X	case 'r':
X	    AnswerRing = v;
X	    break;
X	case 'h':
X	    IgnoreCD = !v;
X	    break;
X	case 'c':
X	    IgnoreConnect = !v;
X	    break;
X	case 'd':
X	    IgnoreDTR = !v;
X	    break;
X	case 'x':
X	    LogLevel = v;
X	    LogToStdout = (v >= 0);
X	    break;
X	default:
X	    printf("Warning, Bad option: -%s\n", ptr);
X	    break;
X	}
X    }
X    if (fi && fi != arysize(AtFields))
X	AtFields[fi] = NULL;
X    if (bi && bi != arysize(Bauds))
X	Bauds[bi] = 0;
X}
X
XDeviceInUse()
X{
X    return(Iosr.IOSer.io_Device->dd_Library.lib_OpenCnt > 1);
X}
X
X/*
X *  Device Vector Intercept, used to force SERF_SHARED on device open.
X */
X
Xextern void AsmIntercept();
Xextern void AsmRoute();
XFPTR OldVector;
X
Xvoid
XInterceptDeviceVector(dev)
Xstruct Device *dev;
X{
X    OldVector = SetFunction((struct Library *)dev, LIB_OPEN, AsmIntercept);
X    AsmRoute(OldVector);
X}
X
Xvoid
XRestoreDeviceVector(dev)
Xstruct Device *dev;
X{
X    SetFunction((struct Library *)dev, LIB_OPEN, OldVector);
X}
X
X
END_OF_FILE
if test 20766 -ne `wc -c <'uucp2/src/getty/getty.c'`; then
    echo shar: \"'uucp2/src/getty/getty.c'\" unpacked with wrong size!
fi
# end of 'uucp2/src/getty/getty.c'
fi
if test -f 'uucp2/src/uucico/gio.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uucp2/src/uucico/gio.c'\"
else
echo shar: Extracting \"'uucp2/src/uucico/gio.c'\" \(18871 characters\)
sed "s/^X//" >'uucp2/src/uucico/gio.c' <<'END_OF_FILE'
X
X/*
X *  GIO.C	WINDOWED G PROTOCOL
X *
X *  written from scratch, except the checksum routine which was
X *  rewritten but based on the old one.
X *
X *  WINDOW SIZE:    When changing the window size be sure there
X *		    are enough buffers available for pending txs.
X *
X *  GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
X *  extended to window size of 7 by Jack J. Rouse
X */
X
X#include "includes.h"
X
Xtypedef unsigned char	ubyte;
Xtypedef unsigned short	uword;
X
Xtypedef struct {
X    ubyte   Dle;	/*  Literal ASCII DLE				*/
X    ubyte   K;		/*  data size 2^(K+4) except K=0 means no data  */
X    ubyte   CL,CH;	/*  MAGIC - chksum(data) ^ C        */
X    ubyte   C;
X    ubyte   X;		/*  K ^ C0 ^ C1 ^ C		    */
X} Frame;
X
Xtypedef struct {
X    ubyte   CType;	/*  bits 7-6 of C	*/
X    ubyte   CCmd;	/*  bits 5-3 of C	*/
X    ubyte   CSeq;	/*  bits 2-0 of C	*/
X    ubyte   PLen;	/*  pre-data (2 bytes) for SHORTDATA type */
X    ubyte   *Data;	/*  implies CType=LONGDATA or SHORTDATA */
X    uword   DLen;	/*  length of data	*/
X} Packet;
X
XPrototype int gwrdata(FILE *);
XPrototype int gwrmsg(char *);
XPrototype int grddata(FILE *);
XPrototype int grdmsg(char *, int);
XPrototype int gturnon(int);
XPrototype int gturnoff(void);
XPrototype void ResetGIO(void);
X
XLocal	  char *GetTxBuf(void);
XLocal	  int SendDataPacket(unsigned char *, int);
XLocal	  int RecvDataPacket(char **);
XLocal	  int GetData(int, Packet *);
XLocal	  int RecvdAck(char);
XLocal	  int WriteCtlPacket(int);
XLocal	  int WritePacket(Packet *, int);
XLocal	  int ReadPacket(Packet *, int);
XLocal	  int CheckSum(unsigned char *, int);
XLocal	  void FrameToPacket(Frame *, Packet *, unsigned char *);
XLocal	  int LenToK(unsigned short);
X
Xextern int debug;
Xextern int WindowOne;
X
X#define SUCCESS 0
X#define FAIL	1
X
X#define MAGIC	    0125252
X#define DLE	    0x10
X#define WINDOWSIZE  7
X#define SEGSIZEK    2		/*  64 bytes ??     */
X
X#define SUB1(var)   (((var)-1)&7)
X
X
X#define CT_CONTROL	(0 << 6)
X#define CT_ALTCHN	(1 << 6)
X#define CT_LONGDATA	(2 << 6)
X#define CT_SHORTDATA	(3 << 6)
X#define CT_MASK 	(3 << 6)
X
X#define CC_CLOSE	(1 << 3)
X#define CC_RJ		(2 << 3)
X#define CC_SRJ		(3 << 3)
X#define CC_RR		(4 << 3)
X#define CC_INITC	(5 << 3)
X#define CC_INITB	(6 << 3)
X#define CC_INITA	(7 << 3)
X#define CC_MASK 	(7 << 3)
X
X#define SEQ_MASK	7
X
X#define WAIT_ACK	1
X#define WAIT_DATA	2
X#define WAIT_CONTROL	3
X
X#define MaxPktSize	4096
X
Xchar	RxBuf[MaxPktSize+4];
Xchar	*TxBuf[8];
X
X				/*  TRANSMIT STAGE	    */
Xchar	TxSeq = 0;		/*  Last send packet	    */
Xchar	TxPend= 0;		/*  hasn't been acked yet   */
Xuword	TxWinSize;		/*  1 or 2 (max 7)          */
Xuword	TxSegSize;		/*  maximum segment size    */
Xchar	TxSegK; 		/*  K for TxSegSize	    */
XPacket	TxPacket[8];		/*  contents of last packet */
X
X				/*  RECEIVE STAGE	    */
Xchar	RxSeq = 0;		/*  Last valid recv pkt     */
Xchar	RxRdy = 0;		/*  Has come in..	    */
Xchar	RxRetry = 8;
Xchar	RxNotAcked = 0; 	/*  We have yet to ack it   */
XPacket	RxPacket;		/*  The packet that has come in */
X
Xvoid
XResetGIO()
X{
X    TxSeq = 0;
X    TxPend= 0;
X    TxWinSize = 0;
X    TxSegSize = 0;
X    TxSegK = 0;
X    RxSeq = 0;
X    RxRdy = 0;
X    RxRetry = 8;
X    RxNotAcked = 0;
X}
X
X/*
X *  Get Transmit Buffer.  Note that some space to the left is available
X */
X
XLocal
Xchar *
XGetTxBuf()
X{
X    static int index = 0;
X
X    if (++index > TxWinSize)
X	index = 0;
X    if (TxBuf[index] == NULL
X    &&	(TxBuf[index] = (char *)malloc(MaxPktSize+4)) == NULL)
X    {
X	printf("Out of memory in GetTxBuf.");
X	/* could handle this case better, but it should be rare */
X	xexit(1);
X    }
X    return(TxBuf[index] + 2);
X}
X
Xint
Xgwrdata(fi)
XFILE *fi;
X{
X    int bytes;
X
X    if (debug > 7)
X	printf("GWRDATA: ");
X
X    for (;;) {
X	char *buf = GetTxBuf();
X	if ((bytes = fread(buf, 1, TxSegSize, fi)) <= 0)
X	    break;
X	if (SendDataPacket(buf, bytes) != SUCCESS) {
X	    if (debug > 7)
X		printf("GWR Failed\n");
X	    return(FAIL);
X	}
X	if (debug > 7)
X	    printf("\nGWROK ");
X    }
X    {
X	char *buf = GetTxBuf();
X	if (SendDataPacket(buf, 0) != SUCCESS) {
X	    if (debug > 7)
X		printf("GWR Failed (last)\n");
X	    return(FAIL);
X	}
X    }
X    if (debug > 7)
X	printf("\nGWFile Last Ack\n");
X    while (TxPend) {
X	if (GetData(WAIT_ACK, NULL) == FAIL)
X	    return(FAIL);
X    }
X    if (debug > 7)
X	printf("success\n");
X    return (SUCCESS);
X}
X
X/*
X *  Write message to the other guy.
X *
X *  NOTE: LONGDATA packets used exclusively and \0 fill to end.
X */
X
Xint
Xgwrmsg(str)
Xchar *str;
X{
X    int len = strlen(str) + 1;      /*  type + str + \0  */
X
X    if (debug > 7)
X	printf("GWRMSG: %s\n", str);
X
X    while (len > TxSegSize) {
X	char *buf = GetTxBuf();
X	movmem(str, buf, TxSegSize);
X	if (debug > 7)
X	    printf("GWR-SEND %d\n", TxSegSize);
X	if (SendDataPacket(buf, TxSegSize) != SUCCESS)
X	    return(FAIL);
X	len -= TxSegSize;
X	str += TxSegSize;
X    }
X
X    /*
X     *	Find optimal packet size (remember, we must force LONGDATA
X     *
X     *	Apparently packet sizes less than the agreed upon size are
X     *	not allowed ???
X     */
X
X    {
X	short siz = TxSegSize;
X	char *buf = GetTxBuf();
X#ifdef NOTDEF
X	short k = TxSegK;
X
X	while (k > 1 && (siz >> 1) >= len) {
X	    --k;
X	    siz >>= 1;
X	}
X#endif
X	if (debug > 7)
X	    printf("GWR-FNL %d %d\n", len, siz);
X
X	movmem(str, buf, len);
X	setmem(buf + len, siz - len, 0);
X	if (SendDataPacket(buf, siz) != SUCCESS) {
X	    if (debug > 7)
X		printf("GWR-FAIL\n");
X	    return(FAIL);
X	}
X    }
X    if (debug > 7)
X	printf("GWR Last Ack\n");
X    while (TxPend) {
X	if (GetData(WAIT_ACK, NULL) == FAIL)
X	    return(FAIL);
X    }
X    if (debug > 7)
X	printf("success\n");
X    return (SUCCESS);
X}
X
Xint
Xgrddata(fi)
XFILE *fi;
X{
X    int bytes;
X    char *buf;
X
X    if (debug > 7)
X	printf("GRDDATA\n");
X    while ((bytes = RecvDataPacket(&buf)) > 0) {
X	if (debug > 7)
X	    printf("GRDDATA blk %d\n", bytes);
X	fwrite(buf, 1, bytes, fi);
X    }
X    if (debug > 7)
X	printf("GRDDATA end %d\n", bytes);
X    if (bytes < 0)
X	return(FAIL);
X    else
X	return(SUCCESS);
X}
X
Xint
Xgrdmsg(buf, maxlen)
Xchar *buf;
X{
X    short i;
X    short n;
X    short slen;
X    char *ptr;
X
X    i = 0;
X    if (debug > 7)
X	printf("GRDMSG\n");
X    while ((n = RecvDataPacket(&ptr)) > 0) {
X	ptr[n] = 0;
X	slen = strlen(ptr);
X	if (slen > maxlen - 1) {
X	    printf("GRDMSG: Buffer overflow!\n");
X	    return (FAIL);
X	}
X	movmem(ptr, buf + i, slen);
X	buf[i + slen] = 0;
X	if (slen != n)
X	    break;
X	i += slen;
X	maxlen -= slen;
X    }
X    if (debug > 7)
X	printf("GRDMSGEND %d (%d) %s\n", n, i, buf);
X    if (n < 0) {
X	buf[0] = 0;
X	return(FAIL);
X    }
X    return(SUCCESS);
X}
X
XLocal
Xint
XSendDataPacket(buf, bytes)
Xubyte *buf;
Xint bytes;
X{
X    Packet  P;
X
X    /*
X     *	If window exhausted we must wait for at least one ack.
X     */
X
X    while (TxPend == TxWinSize) {
X	if (GetData(WAIT_ACK, NULL) == FAIL)
X	    return(FAIL);
X    }
X
X    TxSeq = (TxSeq + 1) & 7;        /*  next Tx packet  */
X
X    /*
X     *	Figure out best fit packet size.  Apparently packets smaller
X     *	then the agreed upon size are not allowed ???
X     */
X
X#ifdef NOTDEF
X    {
X	short k = TxSegK;
X	P.DLen = TxSegSize;
X	while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
X	    --k;
X	    P.DLen >>= 1;
X	}
X    }
X#else
X    P.DLen = TxSegSize;
X#endif
X
X    if (bytes < P.DLen) {
X	uword extra = P.DLen - bytes;
X	setmem(buf + bytes, extra, 0);
X	if (extra <= 127) {
X	    P.PLen = 1;
X	    buf[-1] = extra;
X	} else {
X	    P.PLen = 2;
X	    buf[-2] = 0x80 | extra;
X	    buf[-1] = (extra >> 7);
X	}
X	P.CType = CT_SHORTDATA;
X    } else {
X	P.PLen = 0;
X	P.CType = CT_LONGDATA;
X    }
X    P.CCmd = TxSeq << 3;	/*  transmit sequence number */
X    P.CSeq = RxSeq;		/*  last valid received pkt  */
X    P.Data = buf;
X
X    if (debug > 7)
X	printf("WRITE DATA PACKET txseq=%d rxack=%d\n", TxSeq, P.CSeq);
X
X    RxNotAcked = 0;		/*  We've acked the rx packet */
X
X    TxPacket[TxSeq] = P;
X    ++TxPend;
X
X    WritePacket(&TxPacket[TxSeq], 1);
X
X    return(SUCCESS);
X}
X
XLocal
Xint
XRecvDataPacket(pbuf)
Xchar **pbuf;
X{
X    if (RxRdy == 0) {
X	if (GetData(WAIT_DATA, NULL) != SUCCESS)
X	    return(-1);
X    }
X    *pbuf = RxPacket.Data;
X    RxRdy = 0;
X    return((int)RxPacket.DLen);
X}
X
Xint
Xgturnon(master)
Xint master;
X{
X    Packet P;
X    short retry = 5;
X    short windowsize = WINDOWSIZE;	/*  our prefered window size */
X    short segsize = SEGSIZEK;		/*  our prefered segment size */
X
X    if (WindowOne)
X	windowsize = 1;
X
X    if (master) {
X	while (retry > 0) {
X	    WriteCtlPacket(CC_INITA | windowsize);
X	    if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
X		if (P.CSeq && P.CSeq < windowsize)
X		    windowsize = P.CSeq;
X		break;
X	    }
X	    --retry;
X	}
X	while (retry > 0) {
X	    WriteCtlPacket(CC_INITB | (segsize - 1));
X	    if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
X		if (P.CSeq < segsize - 1)
X		    segsize = P.CSeq + 1;
X		break;
X	    }
X	    --retry;
X	}
X	while (retry > 0) {
X	    WriteCtlPacket(CC_INITC | windowsize);
X	    if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
X		if (P.CSeq && P.CSeq < windowsize)
X		    windowsize = P.CSeq;
X		break;
X	    }
X	    --retry;
X	}
X    } else {
X	while (retry > 0) {
X	    if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
X		WriteCtlPacket(CC_INITA | windowsize);
X		if (P.CSeq && windowsize > P.CSeq)
X		    windowsize = P.CSeq;
X		break;
X	    }
X	    --retry;
X	}
X	while (retry > 0) {
X	    if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
X		WriteCtlPacket(CC_INITB | (segsize - 1));
X		if (P.CSeq < segsize - 1)
X		    segsize = P.CSeq + 1;
X		break;
X	    }
X	    --retry;
X	}
X	while (retry > 0) {
X	    if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
X		WriteCtlPacket(CC_INITC | windowsize);
X		if (P.CSeq && windowsize > P.CSeq)
X		    windowsize = P.CSeq;
X		break;
X	    }
X	    --retry;
X	}
X    }
X    TxSegK = segsize;
X    TxSegSize = 1 << (TxSegK + 4);
X    TxWinSize = windowsize;
X    if (debug > 0)
X	printf("Window Size is %d\n", TxWinSize);
X    if (retry == 0)
X	return(FAIL);
X    return(SUCCESS);
X}
X
Xint
Xgturnoff()
X{
X    Packet P;
X
X    WriteCtlPacket(CC_CLOSE);
X    if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE) {
X	WriteCtlPacket(CC_RR | RxSeq);
X	return (SUCCESS);
X    }
X    return (FAIL);
X}
X
X/*
X *  GetData()
X *
X *  This is the core of the packet protocol.  As soon as we get a satisfactory
X *  terminating condition we return.  However, on unsatisfactory conditions
X *  such as having to send a reject, we attempt to drain any pending data
X *  (i.e. multiple returned rejects) so we do not do multiple resends.
X *
X *  The resend flag only applies on a failure return.
X */
X
XLocal
Xint
XGetData(waitfor, p)
Xint waitfor;
XPacket *p;
X{
X    Packet P;
X    short timeout;
X    short drainmode = 0;
X
X    /*
X     *	If we haven't acked the last packet we received we must do
X     *	so now before we can expect to receive another one!
X     */
X
X    if (debug > 7)
X	printf("Get-Data waitfor %s\n", (waitfor == WAIT_ACK) ? "WAIT_ACK" : "WAIT_DATA");
X    if (waitfor == WAIT_ACK)
X	timeout = 5;
X    else if (waitfor == WAIT_DATA)
X	timeout = 20;
X    else
X	timeout = 20;
X
X    for (;;) {
X	if (RxNotAcked) {                   /*  good, send ack for rx'd pkt */
X	    WriteCtlPacket(CC_RR | RxSeq);
X	    RxNotAcked = 0;
X	}				    /*	bad, timeout on read	    */
X	if (ReadPacket(&P, (drainmode) ? 0 : timeout) == FAIL) {
X	    drainmode = 0;
X
X	    /*
X	     *	If we have timed out waiting for data then send a reject
X	     */
X
X	    if (waitfor == WAIT_DATA) {
X		if (RxRetry) {
X		    --RxRetry;
X		    if (debug > 7)
X			printf("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
X		    WriteCtlPacket(CC_RJ | RxSeq);
X		    continue;
X		}
X	    }
X
X	    /*
X	     *	If we have timed out waiting for an ack send the entire
X	     *	window.  We must send the window sometime and it might as
X	     *	well be now.
X	     */
X
X	    if (waitfor == WAIT_ACK) {
X		if (RxRetry) {
X		    int i;
X
X		    if (debug > 7)
X			printf("RESEND %d packets\n", TxPend);
X		    for (i = 1; i <= TxPend; ++i) {
X			Packet *p = &TxPacket[(TxSeq - TxPend + i) & 7];
X			p->CSeq = RxSeq;
X			WritePacket(p, 1);
X		    }
X		    --RxRetry;
X		    continue;
X		}
X	    }
X	    if (debug > 7)
X		printf("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
X	    return(FAIL);
X	}
X
X	/*
X	 *  valid packet, terminating condition?
X	 */
X
X	RxRetry = 8;
X	switch(P.CType) {
X	case CT_CONTROL:
X	    switch(P.CCmd) {
X	    case CC_CLOSE:  /*	End of communication ... not an ACK!	   */
X		if (waitfor == WAIT_CONTROL) {
X		    *p = P;
X		    return(SUCCESS);
X		}
X		return(FAIL);
X	    case CC_RJ:     /*	Reject packet (P.CSeq == last good packet) */
X		(void)RecvdAck(P.CSeq);
X		drainmode = 1;
X		break;
X	    case CC_SRJ:    /*	Selective Reject (P.CSeq == bad packet # ) */
X		return(FAIL);
X	    case CC_RR:     /*	Ack to packet  (P.CSeq == packet # acked)   */
X#ifdef NOTDEF
X		if (P.CSeq == ((TxSeq - TxPend) & 7)) {
X		    /*
X		     * The CSeq packet was previously acknowledged
X		     * The receiver apparently has not seen anything since.
X		     * This is the same as a rejection.
X		     */
X		    goto resend;
X		}
X#endif
X		if (RecvdAck(P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
X		    return(SUCCESS);
X		break;
X	    case CC_INITC:
X	    case CC_INITB:
X	    case CC_INITA:
X		if (waitfor == WAIT_CONTROL) {
X		    *p = P;
X		    return(SUCCESS);
X		}
X		return(FAIL);
X	    }
X	    break;
X	case CT_ALTCHN:
X	    printf("ALTCHN packet ??\n");
X	    break;
X	case CT_LONGDATA:
X	case CT_SHORTDATA:
X	    {
X		char rxseq = P.CCmd >> 3;
X		char txack = P.CSeq;
X
X		if (RxRdy == 1) {
X		    printf("Got two receive packets without me acking!\n");
X		}
X
X		if (rxseq == RxSeq) {   /*  already got this packet */
X		    RxNotAcked = 1;
X		    continue;
X					/*  expected packet?	    */
X		} else if (rxseq != ((RxSeq + 1) & 7)) {
X		    drainmode = 1;
X		    printf("Received sequence %d, expected %d\n", rxseq, (RxSeq + 1) & 7);
X		    break;
X		}
X		if (debug > 6)
X		    printf("RECV SEQUENCE %d\n", rxseq);
X
X		RecvdAck(txack);    /*  woa */
X
X		/*
X		 *  Delay sending the ACK back in case we can combine
X		 *  it with the next transmitted packet.
X		 */
X
X		RxNotAcked = 1; 	/*  we haven't ack'd the rx packet */
X
X		RxSeq = (RxSeq + 1) & 7;
X		RxRdy = 1;
X		RxPacket = P;
X		if (waitfor == WAIT_DATA)
X		    return(SUCCESS);
X		if (TxPend == 0 && waitfor == WAIT_ACK)
X		    return(SUCCESS);
X	    }
X	    break;
X	}
X    }
X}
X
XLocal
Xint
XRecvdAck(seq)
Xchar seq;
X{
X    short i;
X
X    /*
X     *	which packet was acked?
X     */
X
X    for (i = 0; i < TxPend; ++i) {
X	if (seq == ((TxSeq - i) & 7))
X	    break;
X    }
X    if (i && i == TxPend) {
X	if (seq != ((TxSeq - TxPend) & 7))
X	    printf("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
X	return(FAIL);
X    }
X    if (debug > 7)
X	printf("TxPend %d -> %d\n", TxPend, i);
X    TxPend = i;
X    return(SUCCESS);
X}
X
XLocal
Xint
XWriteCtlPacket(cc)
Xint cc;
X{
X    Packet pk;
X
X    pk.CType = CT_CONTROL;
X    pk.CCmd  = cc & CC_MASK;
X    pk.CSeq  = cc & SEQ_MASK;
X    pk.PLen  = 0;
X    pk.DLen  = 0;
X    WritePacket(&pk, 0);
X    return(SUCCESS);
X}
X
XLocal
Xint
XWritePacket(pk, async)
XPacket *pk;
Xint async;
X{
X    Frame   F;
X    uword   sum;
X
X    F.Dle = DLE;
X    F.C   = pk->CType | pk->CCmd | pk->CSeq;
X    F.K   = 9;
X
X    if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
X	F.K = LenToK(pk->DLen);
X    else
X	pk->DLen = 0;
X
X    sum = MAGIC - (CheckSum(pk->Data - pk->PLen, pk->DLen) ^ F.C);
X
X    F.CH  = sum >> 8;
X    F.CL  = sum;
X    F.X   = F.K ^ F.CH ^ F.CL ^ F.C;
X
X    if (debug > 7)
X	printf("WritePacket: F.K = %d F.C = %d.%d.%d\n", F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
X
X    if (async)
X	xwritea(&F, sizeof(F));
X    else
X	xwrite(&F, sizeof(F));      /*  write header    */
X    if (pk->DLen) {             /*  write data      */
X	if (async)
X	    xwritea(pk->Data - pk->PLen, pk->DLen);
X	else
X	    xwrite(pk->Data - pk->PLen, pk->DLen);
X    }
X    return(SUCCESS);
X}
X
XLocal
Xint
XReadPacket(pk, timeout)
XPacket *pk;
Xint timeout;
X{
X    Frame   F;
X    short   c;
X    short   i = 0;
X
X    pk->Data = RxBuf;
X    pk->CType = 0xFF;
X    pk->CCmd  = 0;
X    pk->CSeq  = 0;
X
X    if (debug > 7)
X	printf("ReadPacket\n");
X    while ((c = xgetc(timeout)) != EOF) {
X	if (debug > 8)
X	    printf("RP %d %02x\n", i, c);
X
X	switch(i) {
X	case 0:
X	    if (c == DLE) {
X		F.Dle = c;
X		++i;
X		if (timeout == 0)
X		    timeout = 1;
X	    }
X	    break;
X	case 1:
X	    F.K = c;
X	    ++i;
X	    if (c == DLE) { /*  K only valid 1-9    */
X		F.Dle = c;
X		i = 1;
X	    }
X	    else if (c == 0 || c > 9)
X		i = 0;
X	    break;
X	case 2:
X	    F.CL = c;
X	    ++i;
X	    break;
X	case 3:
X	    F.CH = c;
X	    ++i;
X	    break;
X	case 4:
X	    F.C = c;
X	    ++i;
X	    break;
X	case 5:
X	    F.X = c;
X	    if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
X		printf("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
X		i = 0;
X	    } else {	    /*	get data segment if any */
X		++i;
X	    }
X	    break;
X	}
X	if (i == 6)
X	    break;
X    }
X    if (debug > 7) {
X	if (i)
X	    printf("RP Hdr i = %d, F.K = %d F.C = %d.%d.%d\n", i, F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
X	else
X	    printf("RP Hdr <rx timeout>\n");
X    }
X
X    if (i == 6) {       /*  Receive Data Portion    */
X	uword pktsize = 1 << (F.K + 4);
X	uword n;
X
X	if (F.K == 9)
X	    pktsize = 0;
X
X	if (pktsize > MaxPktSize) {
X	    printf("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
X	    return (FAIL);
X	}
X	for (n = 0; n < pktsize; ++n) {
X	    if ((c = xgetc(4)) == EOF)
X		break;
X	    pk->Data[n] = c;
X	}
X	if (c != EOF) {
X	    uword hissum;
X	    uword oursum;
X	    hissum = (F.CH << 8) | F.CL;
X	    oursum = MAGIC - (CheckSum(pk->Data, pktsize) ^ F.C);
X	    if (debug > 7)
X		printf("Got Data, checking: %04x %04x\n", hissum, oursum);
X	    if (hissum == oursum) {
X		FrameToPacket(&F, pk, pk->Data);
X		return (SUCCESS);
X	    }
X	} else {
X	    FrameToPacket(&F, pk, pk->Data);    /* mainly for pk->CType */
X	    return (FAIL);
X	}
X    }
X    /*
X     *	Timeout, retry?
X     */
X    return (FAIL);
X}
X
XLocal
Xint
XCheckSum(s, n)
Xubyte *s;
Xint n;
X{
X    uword sum;
X    uword x;
X    uword t;
X
X    if (n == 0)
X	return(0);
X    sum = -1;
X    x = 0;
X
X    while (n) {
X	if (sum & 0x8000)
X	    sum = (sum << 1) | 1;
X	else
X	    sum = (sum << 1);
X
X	t = sum;
X	sum += *s++;
X	x += sum ^ n;
X	if (sum <= t)
X	    sum ^= x;
X	--n;
X    }
X    return((int)sum);
X}
X
XLocal
Xvoid
XFrameToPacket(fr, pk, data)
XFrame *fr;
XPacket *pk;
Xubyte *data;
X{
X    pk->CType = fr->C & CT_MASK;
X    pk->CCmd  = fr->C & CC_MASK;
X    pk->CSeq  = fr->C & SEQ_MASK;
X    switch(pk->CType) {
X    case CT_LONGDATA:
X	pk->DLen = 1 << (fr->K + 4);
X	break;
X    case CT_SHORTDATA:
X	pk->DLen = 1 << (fr->K + 4);
X	if (pk->Data[0] & 0x80) {
X	    pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
X	    if (pk->DLen < 0) {
X		printf("DLEN ERROR %d\n", pk->DLen);
X		pk->DLen = 0;
X	    }
X	    pk->Data += 2;
X	} else {
X	    pk->DLen -= *pk->Data;
X	    ++pk->Data;
X	}
X	break;
X    default:
X	pk->DLen = 0;
X	break;
X    }
X}
X
XLocal
Xint
XLenToK(bytes)
Xuword bytes;
X{
X    uword n = 32;
X    uword k = 1;
X
X    while (n < bytes) {
X	n <<= 1;
X	++k;
X    }
X    if (k > 8) {
X	printf("Soft error, LenToK: %d %d %d\n", bytes, n, k);
X	k = 8;
X    }
X    return((int)k);
X}
X
END_OF_FILE
if test 18871 -ne `wc -c <'uucp2/src/uucico/gio.c'`; then
    echo shar: \"'uucp2/src/uucico/gio.c'\" unpacked with wrong size!
fi
# end of 'uucp2/src/uucico/gio.c'
fi
echo shar: End of archive 8 \(of 12\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.