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.