home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d450
/
uucp
/
src
/
getty
/
getty.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-03
|
22KB
|
1,122 lines
/*
* GETTY.C
*
* $Header: Beta:src/uucp/src/getty/RCS/getty.c,v 1.1 90/02/02 12:13:30 dillon Exp Locker: dillon $
*
* (C)Copyright 1989, Matthew Dillon, All Rights Reserved
*
* Uses:
* GETTY:PASSWD
* GETTY:LOGFILE
* GETTY:Getty-Header
*
* GETTY <options> <modem-commands>
*
* -Sdevicenam Tells GETTY which serial.device to use, default
* serial.device
*
* -Uunitnum Tells GETTY which unit number to use, default 0
*
* -A Always talk to the modem at the first baud
* rate in the -B list and ignore the baud rate
* in the CONNECT message.
*
* -7 use SERF_7WIRE while online.
*
* -Bn Set baud rate. If specified multiple times the
* first one is the default and remaining ones
* switched to when a BREAK is received after a
* connect. Also determines how CONNECT messages
* are interpreted. A CONNECT with no number uses
* the first -B entry while CONNECTs with numbers
* use those numbers regardless of any -B entries.
*
* -Mc Set modem type:
* c = m = multimodem
* h = hays
* d = dumb (no AT or +++ cmds are ever sent),
* normally used with only one specified
* baud rate.
*
* -m1 Turn on the modem speaker during dialing/connect
* (default is -m0)
*
* -h0 Ignore CD (carrier detect), default is to use
* carrier detect.
*
* -c0 Ignore CONNECT message (i.e. you are not connected
* to a modem, usually combined with -h0). Default is
* to expect a CONNECT message.
*
* -d0 do not use DTR to drop connection. Default is
* to drop DTR to drop a connection. If this option
* is chosen the +++ and ATH0 sequence will be used
* to drop a connection.
*
* -xn Set debug level. Also causes log output to go
* to stdout instead of GETTY:LOGFILE
*
* -0 QUIT - Kills any running getty for the specified
* port.
*
* Any fields specified without a '-' are considered modem commands
* used to initialize/reinitialize the modem. Up to 16 fields may
* be specified (each is sent to the modem in 1 second intervals)
*/
#include <exec/types.h>
#include <exec/lists.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <devices/timer.h>
#include <devices/serial.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <hardware/cia.h>
#include <stdio.h>
#include <stdlib.h>
#include "protos.h"
#include <pwd.h>
#include "version.h"
#include "log.h"
IDENT(".06");
#ifndef IO_STATF_READBREAK
#define IO_STATF_READBREAK (IOSTF_READBREAK<<8)
#endif
#define arysize(ary) (sizeof(ary)/sizeof((ary)[0]))
#define ST_WAITCD 0
#define ST_CONNECT 1
#define ST_LOGIN 2
#define ST_PASSWD 3
#define ST_RUN 4
typedef struct IORequest IOR;
typedef struct timerequest IOT;
typedef struct IOExtSer IOSER;
typedef struct MsgPort PORT;
typedef struct List LIST;
typedef struct Node NODE;
typedef struct Message MSG;
typedef void (*FPTR)();
typedef struct GMsg {
struct Message Msg;
short Cmd;
long Data1;
void *Data2;
} GMsg;
extern struct ProcID *RunPasswdEntry();
char *CopyRight = "(c)Copyright 1989, Matthew Dillon, All Rights Reserved\r\n";
char *ComPortName;
char *DeviceName = "serial.device";
long DeviceUnit = 0;
long RefCnt = 0; /* take into account ourselves */
long NullFH;
char SpeakerLevel = 0;
char AnswerRing = 2; /* default, answer on second ring */
char SpeakerOpt = 0;
char IgnoreCD = 0;
char IgnoreConnect = 0;
char IgnoreDTR = 0;
char BaudAdjust = 0;
char DropOnExit = 1;
char ModemType = 'h';
char ZeroOption = 0;
/*char NoBugs = 0;*/
char Wire7 = 0; /* use 7 wire while online */
long Bauds[16] = { 9600 }; /* up 16 baud rates */
char *AtFields[16];
void *GettyTask;
APTR UnitPtr;
PORT *ComPort;
PORT *IoSink; /* Sink for IO reqs. */
long IoSinkMask;
long ComPortMask;
IOT Iot; /* check-carrier */
IOSER Ios; /* parameters req */
IOSER Iosr; /* serial read-req */
IOSER Ioss; /* synchronous req */
char IotIP; /* Iot0 in progress */
char IosrIP;
char ScrBuf[256];
char ConnectBuf[64];
char LoginBuf[32];
char PasswdBuf[32];
char RxBuf[32];
char HaveConnectMsg;
char HaveLogin;
char HavePasswd;
short State;
short Index;
short BIndex;
short CountDown;
short GotOffPort;
long GetStatus();
void SerPuts();
void RxStop();
void RxStart();
void xexit();
void Disconnect();
void ClearRecv();
void ResetSP();
void InitModem();
void SetParams();
void DoOptions();
void InterceptDeviceVector();
void RestoreDeviceVector();
brk()
{
return(0);
}
main(ac, av)
char *av[];
{
extern int IAmGetty;
char termCr = 1;
char termLf = 1;
IAmGetty = 1; /* for LockSerialPort()/UnLockSerialPort() */
puts(CopyRight);
fflush(stdout);
onbreak(brk);
LogProgram = "Getty";
LogWho = LoginBuf;
LogFile = "Getty:LOGFILE";
PasswdFile = "Getty:Passwd";
DoOptions(ac, av);
IoSink = CreatePort(NULL, 0);
IoSinkMask = 1 << IoSink->mp_SigBit;
ComPortName = malloc(strlen(DeviceName) + 20);
sprintf(ComPortName, "Getty.%s.%ld", DeviceName, DeviceUnit);
Forbid();
if (ComPort = FindPort(ComPortName)) {
GMsg msg;
msg.Cmd = 'O';
msg.Data1 = ac;
msg.Data2 = (void *)av;
msg.Msg.mn_ReplyPort = IoSink;
PutMsg(ComPort, &msg.Msg);
WaitPort(IoSink);
Remove(&msg.Msg.mn_Node);
Permit();
puts("Options updated");
xexit(0);
}
ComPort = CreatePort(ComPortName, 0L);
Permit();
ComPortMask = 1L << ComPort->mp_SigBit;
NullFH = Open("NULL:", 1006);
if (NullFH == NULL) {
ulog(-1, "GETTY REQUIRES NULL: HANDLER!");
puts("Requires NULL: handler!");
xexit(1);
}
if (LogToStdout == 0) {
freopen("NULL:", "r", stdin);
freopen("NULL:", "w", stdout);
freopen("NULL:", "w", stderr);
}
/*
* Timer Device
*/
Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
if (OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0L)) {
Iot.tr_node.io_Device = NULL;
xexit(20);
}
Iot.tr_node.io_Command = TR_ADDREQUEST;
/*
* SERIAL.DEVICE
*/
Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
Ios.io_SerFlags = SERF_XDISABLED | SERF_SHARED;
if (Wire7)
Ios.io_SerFlags |= SERF_7WIRE;
if (OpenDevice(DeviceName, DeviceUnit, &Ios, 0L)) {
Ios.IOSer.io_Device = NULL;
xexit(21);
}
InterceptDeviceVector(Ios.IOSer.io_Device);
Iosr = Ios;
Ioss = Ios;
Iosr.IOSer.io_Command = CMD_READ;
Ios.IOSer.io_Command = SDCMD_QUERY;
DoIO(&Ios);
Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
Ios.io_ExtFlags = 0;
Ios.io_Baud = Bauds[0];
Ios.io_ReadLen = 8;
Ios.io_WriteLen = 8;
Ios.io_StopBits = 1;
SetParams(0);
/*
* Run Operation
*/
State = ST_WAITCD;
Iot.tr_time.tv_secs = 1;
Iot.tr_time.tv_micro= 0;
IotIP = 1;
SendIO(&Iot);
InitModem();
GettyTask = FindTask(NULL);
Signal(GettyTask, IoSinkMask);
for (;;) {
long mask;
IOR *ior;
GMsg *msg;
mask = Wait(SIGBREAKF_CTRL_C | IoSinkMask | ComPortMask);
ulog(9, "State = %d %d %08lx %08lx", State, RefCnt, UnitPtr, Ios.IOSer.io_Unit);
if (mask & SIGBREAKF_CTRL_C)
break;
if (msg = (GMsg *)GetMsg(ComPort)) {
do {
switch(msg->Cmd) {
case 'O':
DoOptions(msg->Data1, msg->Data2);
break;
}
ReplyMsg((MSG *)msg);
if (ZeroOption)
xexit(0);
} while (msg = (GMsg *)GetMsg(ComPort));
if (State == ST_WAITCD && !GotOffPort)
Disconnect(0);
}
while (ior = (IOR *)GetMsg(IoSink)) {
if (ior == (IOR *)&Iot) {
short diu;
long status;
IotIP = 0;
Iot.tr_time.tv_secs = 1;
Iot.tr_time.tv_micro= 0;
/*
* If # of references for unit is > 1 then device
* is in use. When refs fall <= 1 then reset the
* serial port.
*/
diu = DeviceInUse();
if (diu) {
if (GotOffPort == 0) {
ulog(1, "Device in use");
RxStop();
State = ST_WAITCD;
}
GotOffPort = 2;
SendIO(&Iot);
IotIP = 1;
continue;
}
if (GotOffPort) {
/*
* delay 5 seconds before getting back on port
*/
if (--GotOffPort) {
Iot.tr_time.tv_secs = 5;
SendIO(&Iot);
IotIP = 1;
} else {
ulog(1, "Getty resetting");
SendIO(&Iot);
IotIP = 1;
Disconnect(1);
}
continue;
}
if (State == ST_WAITCD)
RxStop();
if (State != ST_WAITCD && IosrIP == 0) {
RxStart();
ulog(2, "Carrier, Getty getting on port");
}
status = GetStatus();
/*
* If state connected and we loose carrier, disconnect.
*
* If state connected and timeout occurs disconnect.
*/
if (State != ST_WAITCD) {
if ((status & CIAF_COMCD) != 0) {
ulog(2, "Getty, Carrier lost");
Disconnect(1);
} else {
if (!IgnoreCD && --CountDown == 0) {
ulog(2, "Getty, Timeout, Disconnecting");
Disconnect(1);
status |= CIAF_COMCD; /* set lost carrier flag */
}
}
}
switch(State) {
case ST_WAITCD:
if ((status & CIAF_COMCD) == 0) {
State = ST_CONNECT;
CountDown = 60; /* allow 60 seconds */
ulog(2, "Carrier Detect");
} else {
Iot.tr_time.tv_secs = 2;
}
break;
case ST_CONNECT:
/*
* Wait for CONNECT message, then send Login:
*/
if (IgnoreConnect && HaveConnectMsg == 0) {
SetParams(1);
HaveConnectMsg = 1;
ulog(2, "Connect");
}
if (HaveConnectMsg) {
FILE *fi;
Delay(50);
ClearRecv();
if (fi = fopen("Getty:Getty-Header", "r")) {
while (fgets(ScrBuf, sizeof(ScrBuf), fi)) {
SerPuts(ScrBuf);
SerPuts("\r");
}
fclose(fi);
}
termCr = termLf = 1;
ClearRecv();
SerPuts("Login: ");
ulog(1, "Getty, Connect, Login");
State = ST_LOGIN;
Index = 0;
HaveLogin = 0;
LoginBuf[0] = 0;
}
break;
case ST_LOGIN: /* wait Login: response */
if (HaveLogin) {
if (LoginBuf[0] == 0) {
State = ST_CONNECT;
break;
}
ClearRecv();
PasswdBuf[0] = 0;
/*
* If no password required, else request
* password.
*/
if (CheckLoginAndPassword()) {
HavePasswd = 1;
Index = 0;
State = ST_PASSWD;
} else {
SerPuts("Password: ");
ulog(2, "Getty, Passwd");
State = ST_PASSWD;
HavePasswd = 0;
Index = 0;
}
}
break;
case ST_PASSWD: /* wait Password: response */
if (HavePasswd) {
if (CheckLoginAndPassword()) {
ulog(-1, "login %s", LoginBuf);
/*
* Disable read requests but leave serial
* port locked.
*/
RxStop();
/*
* If run successful, leave read req and
* timer disabled.
*/
RunPasswdEntry();
if (DropOnExit)
Disconnect(1);
else
State = ST_CONNECT;
ulog(-1, "disconnect");
} else {
SerPuts("Login Failed.\r\n\n");
State = ST_CONNECT;
ulog(0, "LoginFailed user=%s pass=%s", LoginBuf, PasswdBuf);
}
HaveLogin = 0;
HavePasswd= 0;
LoginBuf[0] = 0;
}
break;
}
/*
* Make no read requests while running 3rd party
* program, else resend read request.
*/
if (IotIP == 0) {
IotIP = 1;
SendIO(&Iot);
}
}
/*
* RECEIVED SERIAL READ DATA
*/
if (ior == (IOR *)&Iosr) {
long status;
IosrIP = 0;
status = GetStatus();
/*
* BREAK used to switch baud rates between allowed
* values
*/
if (status & IO_STATF_READBREAK) {
if (BaudAdjust == 0 && (State == ST_LOGIN || State == ST_PASSWD)) {
if (++BIndex == arysize(Bauds))
BIndex = 0;
if (Bauds[BIndex] == 0)
BIndex = 0;
Ios.io_Baud = Bauds[BIndex];
SetParams(1);
ulog(1, "<BREAK> to %d baud", Ios.io_Baud);
Delay(50);
ClearRecv();
Index = 0;
State = ST_CONNECT;
}
} else if (Iosr.IOSer.io_Actual == 1) {
char *ptr;
UBYTE c = (UBYTE)RxBuf[0];
ulog(9, "Rx %02x %c", c, (c < 32) ? ' ' : c);
c &= 0x7F;
switch(State) {
case ST_WAITCD: /* looking for CONNECT msg */
case ST_CONNECT: /* looking for CONNECT msg */
ptr = ConnectBuf;
break;
case ST_LOGIN: /* looking for login name */
ptr = LoginBuf;
break;
case ST_PASSWD: /* looking for password */
ptr = PasswdBuf;
break;
}
if (State == ST_LOGIN && HaveLogin)
c = 0;
if (State == ST_PASSWD && HavePasswd)
c = 0;
switch(c) {
case 0:
break;
case 8:
if (State == ST_LOGIN && HaveLogin)
break;
if (Index) {
if (State == ST_LOGIN)
SerPuts("\010 \010");
--Index;
}
break;
case 10:
if (termLf == 0)
break;
termCr = 0;
case 13:
if (c == 13) {
if (termCr == 0)
break;
else
termLf = 0;
}
ptr[Index] = 0;
Index = 0;
switch(State) {
case ST_WAITCD:
case ST_CONNECT:
if (strncmp(ptr, "CONNECT", 7)) {
ulog(9, "Looking for CONNECT, got '%s'", ptr);
break;
}
Delay(50);
HaveConnectMsg = 1;
if (BaudAdjust) {
ulog(9, "Connect Auto-Baud %d", Ios.io_Baud);
} else {
char *str = ptr + 7;
while (*str && (*str == 9 || *str == ' '))
++str;
if (*str >= '0' && *str <= '9')
Ios.io_Baud = atoi(str);
else
Ios.io_Baud = Bauds[0];
ulog(9, "Connect at %d baud", Ios.io_Baud);
}
SetParams(1);
break;
case ST_LOGIN:
HaveLogin = 1;
SerPuts("\r\n");
ulog(1, "Login: %s", ptr);
break;
case ST_PASSWD:
HavePasswd = 1;
SerPuts("\r\n");
ulog(2, "Password: %s", ptr);
break;
}
break;
default:
if (Index == 31)
break;
if (State == ST_LOGIN) {
char cc[2];
cc[0] = c;
cc[1] = 0;
SerPuts(cc);
}
ptr[Index++] = c;
break;
}
}
if (IosrIP == 0)
RxStart();
}
}
}
xexit(0);
}
void
RxStart()
{
Iosr.IOSer.io_Data = (APTR)RxBuf;
Iosr.IOSer.io_Length = 1;
Iosr.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
IosrIP = 1;
SendIO(&Iosr);
}
void
RxStop()
{
if (IosrIP) {
AbortIO(&Iosr);
WaitIO(&Iosr);
IosrIP = 0;
}
}
long
GetStatus()
{
int error;
long status = CIAF_COMCD; /* no carrier detect */
if (!DeviceInUse()) {
Ioss.IOSer.io_Command = SDCMD_QUERY;
Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
if (error = DoIO(&Ioss))
ulog(0, "Query Error %d", error);
status = Ioss.io_Status;
if (IgnoreCD)
status &= ~CIAF_COMCD;
}
return(status);
}
void
xexit(code)
{
if (ComPortMask) {
GMsg *msg;
Forbid();
while (msg = (GMsg *)GetMsg(ComPort))
ReplyMsg((MSG *)msg);
DeletePort(ComPort);
Permit();
}
if (IotIP) {
AbortIO(&Iot);
WaitIO(&Iot);
}
if (Iot.tr_node.io_Device)
CloseDevice(&Iot);
RxStop();
if (Ios.IOSer.io_Device) {
RestoreDeviceVector(Ios.IOSer.io_Device);
CloseDevice(&Ios);
}
if (IoSink)
DeletePort(IoSink);
if (NullFH)
Close(NullFH);
if (code)
ulog(-1, "Getty Exiting with code %d", code);
exit(code);
}
void
SerPuts(str)
char *str;
{
int error;
if (!DeviceInUse()) {
Ioss.IOSer.io_Command = CMD_WRITE;
Ioss.IOSer.io_Data = (APTR)str;
Ioss.IOSer.io_Length = strlen(str);
Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
if (error = DoIO(&Ioss))
ulog(0, "Write Error %d", error);
}
}
static short RxDisableIP;
void
RxDisable()
{
RxDisableIP = IosrIP;
RxStop();
}
void
RxEnable()
{
if (RxDisableIP && IosrIP == 0)
RxStart();
}
void
ClearRecv()
{
int error;
if (!DeviceInUse()) {
Ioss.IOSer.io_Command = CMD_CLEAR;
Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
if (error = DoIO(&Ioss))
ulog(0, "Clear Error %d", error);
if (IosrIP) {
AbortIO(&Iosr);
WaitIO(&Iosr);
IosrIP = 0;
RxStart();
}
}
}
void
ResetSP()
{
int error;
if (!DeviceInUse()) {
Ioss.IOSer.io_Command = CMD_RESET;
Ioss.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
if (error = DoIO(&Ioss))
ulog(0, "Reset Error %d", error);
}
}
void
SetParams(wire7)
{
int error;
/*if (NoBugs == 0)
wire7 = Wire7;*/
{
RxStop();
if (!DeviceInUse()) {
if (wire7 && Wire7)
Ios.io_SerFlags |= SERF_7WIRE;
else
Ios.io_SerFlags &= ~SERF_7WIRE;
Ios.IOSer.io_Command = SDCMD_SETPARAMS;
Ios.IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
if (error = DoIO(&Ios))
ulog(0, "SetParams Error %d", error);
}
}
}
void
Disconnect(dropdtr)
{
short retry = (IgnoreDTR) ? 2 : 10;
ulog(2, "Disconnect drop=%d", dropdtr);
HaveConnectMsg = 0;
HaveLogin = 0;
HavePasswd = 0;
LoginBuf[0] = 0;
PasswdBuf[0] = 0;
Index = 0;
State = ST_WAITCD;
if (IgnoreCD == 0) {
while (dropdtr && DeviceInUse() == 0) {
short i;
long status = GetStatus();
if (status & CIAF_COMCD) /* no carrier */
break;
RxDisable();
SetParams(0);
if (IgnoreDTR) {
if (ModemType != 'd') {
Delay(70);
if (DeviceInUse())
break;
SerPuts("+++");
Delay(70);
if (DeviceInUse())
break;
SerPuts("\010\010\r");
Delay(10);
if (DeviceInUse())
break;
SerPuts("ATH0\r");
Delay(120);
}
} else {
RefCnt += 2;
CloseDevice(&Ios);
Ios.IOSer.io_Device = NULL; /* so xexit doesn't reclose */
for (i = 0; i < 5; ++i) { /* 5 seconds */
Delay(50);
if (SetSignal(SIGBREAKF_CTRL_C, 0) & SIGBREAKF_CTRL_C)
xexit(23);
}
/*
* Use Iosr to re-open serial device so we don't loose
* our config.
*/
RefCnt -= 2;
if (Wire7)
Ios.io_SerFlags |= SERF_7WIRE;
else
Ios.io_SerFlags &= ~SERF_7WIRE;
if (OpenDevice(DeviceName, DeviceUnit, &Ios, 0)) {
Ios.IOSer.io_Device = NULL;
xexit(22);
}
Iosr.IOSer.io_Device = Ios.IOSer.io_Device;
Ioss.IOSer.io_Device = Ios.IOSer.io_Device;
Iosr.IOSer.io_Unit = Ios.IOSer.io_Unit;
Ioss.IOSer.io_Unit = Ios.IOSer.io_Unit;
SetParams(1);
}
/*
* Loop until carrier lost
*/
RxEnable();
if (--retry == 0) {
if (IgnoreDTR == 0)
puts("Getty: unable to disconnect!");
break;
}
}
}
if (!DeviceInUse()) {
ResetSP();
InitModem();
}
}
void
InitModem()
{
char buf[64];
short i;
RxDisable();
ulog(2, "Init Modem");
Ios.io_Baud = Bauds[0]; /* reset baud rate */
BIndex = 0;
SetParams(0);
RxEnable();
switch(ModemType) {
case 'm': /* Multi Modem */
SerPuts("\010\010\r");
Delay(10);
if (DeviceInUse())
break;
SerPuts("AT\r");
Delay(50);
if (DeviceInUse())
break;
sprintf(buf, "ATM%dS0=%dX4$BA%d&E%d\r",
SpeakerLevel,
AnswerRing,
!BaudAdjust,
(Wire7) ? 4 : 3
);
SerPuts(buf);
break;
case 'h':
SerPuts("\010\010\r");
Delay(10);
if (DeviceInUse())
break;
SerPuts("ATZ\r");
Delay(120);
if (DeviceInUse())
break;
strcpy(buf, "AT");
if (SpeakerOpt)
sprintf(buf + strlen(buf), "M%d", SpeakerLevel);
sprintf(buf + strlen(buf), "S0=%d", AnswerRing);
strcat(buf, "\r");
SerPuts(buf);
break;
case 'd':
SerPuts("\010\010\r");
break;
}
for (i = 0; i < arysize(AtFields) && AtFields[i]; ++i) {
Delay(50);
if (DeviceInUse())
break;
SerPuts(AtFields[i]);
SerPuts("\r");
}
Delay(20);
ClearRecv();
Index = 0;
}
void
DoOptions(ac, av)
char *av[];
{
short i;
short bi = 0;
short fi = 0;
long v;
LogLevel = 1;
for (i = 1; i < ac; ++i) {
char *ptr = av[i];
if (*ptr != '-') {
if (fi != arysize(AtFields))
AtFields[fi++] = ptr;
else
puts("AT field overflow");
continue;
}
if (*++ptr) /* skip - */
++ptr; /* and option */
v = atoi(ptr);
switch(ptr[-1]) {
case '0':
ZeroOption = 1;
break;
case '7':
Wire7 = 1;
break;
case 'S':
DeviceName = ptr;
break;
case 'U':
DeviceUnit = v;
break;
case 'M':
ModemType = *ptr;
break;
case 'A':
BaudAdjust = 1;
break;
case 'B':
if (bi != arysize(Bauds))
Bauds[bi++] = v;
else
puts("-B field overflow");
break;
case 'm':
SpeakerOpt = 1;
SpeakerLevel = v;
break;
case 'r':
AnswerRing = v;
break;
case 'h':
IgnoreCD = !v;
break;
case 'c':
IgnoreConnect = !v;
break;
case 'd':
IgnoreDTR = !v;
break;
case 'x':
LogLevel = v;
LogToStdout = (v >= 9);
break;
case 'n':
/*NoBugs = 1;*/
break;
default:
printf("Warning, Bad option: -%s\n", ptr);
break;
}
}
if (fi && fi != arysize(AtFields))
AtFields[fi] = NULL;
if (bi && bi != arysize(Bauds))
Bauds[bi] = 0;
}
DeviceInUse()
{
return(RefCnt > 0);
}
/*
* Device Vector Intercept, used to force SERF_SHARED on device open.
*/
extern void AsmOpenIntercept();
extern void AsmCloseIntercept();
/*extern void A2232BeginIOFix();*/
FPTR OldOpenVector;
FPTR OldCloseVector;
/*FPTR OldBeginIOVector;*/
void
InterceptDeviceVector(dev)
struct Library *dev;
{
Forbid();
OldOpenVector = SetFunction((struct Library *)dev, LIB_OPEN, AsmOpenIntercept);
OldCloseVector = SetFunction((struct Library *)dev, LIB_CLOSE, AsmCloseIntercept);
/*OldBeginIOVector = SetFunction((struct Library *)dev, DEV_BEGINIO, A2232BeginIOFix);*/
Permit();
}
void
RestoreDeviceVector(dev)
struct Library *dev;
{
FPTR oldFunc;
int error = 0;
/*
* must restore in same order as had openned
*/
for (;;) {
Forbid();
oldFunc = (FPTR)SetFunction((struct Library *)dev, LIB_OPEN, OldOpenVector);
if (oldFunc != (FPTR)AsmOpenIntercept) {
SetFunction((struct Library *)dev, LIB_OPEN, oldFunc);
Permit();
if (error == 0) {
error = 1;
ulog(-1, "UNABLE TO REVERSE SETVECTOR, YOU MUST DEINSTALL");
ulog(-1, "GETTYs ON THE SAME DEVICE IN REVERSE ORDER!");
}
Delay(50 * 5);
continue;
}
break;
}
SetFunction((struct Library *)dev, LIB_CLOSE, OldCloseVector);
/*SetFunction((struct Library *)dev, DEV_BEGINIO, OldBeginIOVector);*/
Permit();
}