home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
newc_dev
/
uucicosd.lha
/
sysdep.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-02
|
14KB
|
742 lines
/*
* SYSDEP.C
*
* $Header: Beta:src/uucp/src/uucico/RCS/sysdep.c,v 1.1 90/02/02 11:56:16 dillon Exp Locker: dillon $
*
* (C) Copyright 1987 by John Gilmore
* Copying and use of this program are controlled by the terms of the Free
* Software Foundation's GNU Emacs General Public License.
*
* Amiga Changes Copyright 1988 by William Loftus. All rights reserved.
* Additional chgs Copyright 1989 by Matthew Dillon, All Rights Reserved.
*/
#include <exec/types.h>
#include <exec/exec.h>
#include "includes.h"
#include <hardware/cia.h>
#include <devices/timer.h>
#include <devices/serial.h>
#include <libraries/dos.h>
#include <pwd.h>
#include "uucp.h"
#include "version.h"
#include <OwnDevUnit.h>
#define Assert(x) if (!(x)) _assert_failed(__LINE__);
Prototype int openout(char *, int);
Prototype int sigint(void);
Prototype void cleanup(void);
Prototype int xdatardy(void);
Prototype int xgetc(int,int);
Prototype int xwrite(const void *, int);
Prototype int xwritea(const void *, int);
Prototype int xxwrite(const void *, int, int);
Prototype void SendBreak(void);
Prototype int CheckCarrier(void);
Prototype void *bzero(void *, long);
Prototype void *bcopy(const void *, void *, long);
Prototype void munge_filename(char *, char *);
Prototype int hangup(void);
Prototype int work_scan(char *);
Prototype char *work_next(void);
Prototype void amiga_setup(void);
Prototype void set_baud(int);
Prototype void OpenSerial(int);
Prototype void CloseSerial(int);
Prototype void xexit(int);
Prototype void printc(unsigned char);
Prototype void NiceAbortIO(void *);
static void _assert_failed(int);
IDENT(".03");
/*
* Split out of uuslave.c by John Gilmore, 8 August 1987.
* ported to the Amiga by William Loftus, 20 September 1987.
* rewritten by Matthew Dillon, October 1989
*/
/* FIXME -- System dependent defines (not really -- should be in a .h) */
/*
* Timeout for raw characters -- if we don't hear a char within BYTE_TIMEOUT
* seconds, we assume the other side has gone away. Has nothing to do with
* retransmission timeouts (if any!).
*/
extern int debug;
extern int SevenWire;
#define FAILURE 1
struct IOExtSer Iosr;
struct IOExtSer Iosw;
struct IOExtSer Ioss;
struct timerequest Iot0;
char *OldTaskName;
char *DeviceName = "serial.device";
long DeviceUnit = 0;
unsigned char XInBuf[512]; /* for xgetc() */
char LockFileName[128];
short XInIdx = 0;
short XInLen = 0;
short IoswIP = 0;
short IosrIP = 0;
short IotIP = 0;
short InExitRoutine = 0;
short debugRead = 0;
extern char path[];
extern int Getty;
extern int IgnoreCD;
int
openout(acu, baud)
char *acu;
int baud;
{
set_baud(baud);
return SUCCESS;
}
/*
* Basement level I/O routines
*
* xwrite() writes a character string to the serial port
* xgetc() returns a character from the serial port, or an EOF for timeout.
* sigint() restores the state of the serial port on exit.
*/
int
sigint()
{
xexit(10);
return(0);
}
void
cleanup()
{
signal(SIGINT, SIG_IGN);
++InExitRoutine;
if (InExitRoutine == 1 && Iosr.IOSer.io_Device && CheckCarrier())
reset_modem();
CloseSerial(1);
{
struct Task *task = (struct Task *)FindTask(NULL);
if (OldTaskName)
task->tc_Node.ln_Name = OldTaskName;
}
if (Iot0.tr_node.io_Device) {
CloseDevice(&Iot0);
Iot0.tr_node.io_Device = NULL;
}
if (Iot0.tr_node.io_Message.mn_ReplyPort) {
DeletePort(Iot0.tr_node.io_Message.mn_ReplyPort);
Iot0.tr_node.io_Message.mn_ReplyPort = NULL;
}
chdir(path);
mountrequest(1);
UnLockFiles(); /* unlock any hanging locks */
}
int
xdatardy()
{
if (XInIdx != XInLen)
return(1);
CheckCarrier();
return (Ioss.IOSer.io_Actual > 0);
}
int
xgetc(byteto,delay_flg)
int byteto;
{
int ch, n;
long smask;
long tmask;
short bytetimeout;
top:
if (XInIdx != XInLen) {
if (debug > 8) {
if (debugRead == 0)
printf("\nREAD: ");
debugRead = 1;
printc(XInBuf[XInIdx]);
}
xfer.bytes_recv++;
return((int)XInBuf[XInIdx++]);
}
XInIdx = 0;
XInLen = 0;
/*Mod by Steve Drew:
* at high speeds and fast machines we can end up going through all
* layers for only 1 byte. Delaying a small amount here give the serial
* device a chance to buffer a few chars and then we will grab them all
* saving many cpu cycles. On a 030 system with 14.4K modem have seen
* cpu load go from %70 down to %10 with this one line change.
*/
if (byteto && delay_flg) {
Delay(3L); /* .06 sec */
}
if (!CheckCarrier()) /* carrier lost? */
return(EOF);
Assert(Iosr.IOSer.io_Device);
if ((n = Ioss.IOSer.io_Actual) > 0) { /* at least one.. */
Iosr.IOSer.io_Command = CMD_READ;
Iosr.IOSer.io_Data = (APTR)XInBuf;
if (n > sizeof(XInBuf))
n = sizeof(XInBuf);
Iosr.IOSer.io_Length = n;
DoIO(&Iosr);
if (Iosr.IOSer.io_Actual > 0) {
if (debug > 8)
printf("(r%d/%d)\n", n, Iosr.IOSer.io_Actual);
XInIdx = 0;
XInLen = Iosr.IOSer.io_Actual;
goto top;
}
}
/*
* no bytes ready, byteto is 0 (no wait)
*/
if (byteto == 0)
return(EOF);
/*
* no bytes ready, wait for one.
*
* once every 3 seconds check carrier detect.
*/
bytetimeout = byteto;
Iot0.tr_time.tv_secs = 3;
Iot0.tr_time.tv_micro= 0;
SendIO(&Iot0);
IotIP = 1;
Iosr.IOSer.io_Command = CMD_READ;
Iosr.IOSer.io_Data = (APTR)XInBuf;
Iosr.IOSer.io_Length = 1;
Iosr.IOSer.io_Actual = 0; /* trying to find a bug... */
SendIO(&Iosr);
IosrIP = 1;
smask = 1L << Iosr.IOSer.io_Message.mn_ReplyPort->mp_SigBit;
tmask = 1L << Iot0.tr_node.io_Message.mn_ReplyPort->mp_SigBit;
for (;;) {
long mask = Wait(tmask | smask | SIGBREAKF_CTRL_C);
if (mask & SIGBREAKF_CTRL_C) {
NiceAbortIO(&Iosr);
WaitIO(&Iosr);
IosrIP = 0;
AbortIO(&Iot0);
WaitIO(&Iot0);
IotIP = 0;
xexit(10);
}
if (CheckIO(&Iosr)) {
WaitIO(&Iosr);
IosrIP = 0;
AbortIO(&Iot0);
WaitIO(&Iot0);
IotIP = 0;
ch = (int)XInBuf[0];
if (debug > 8) {
if (debugRead == 0)
printf("\nREAD ");
debugRead = 1;
printf("(waitc%d)", Iosr.IOSer.io_Actual);
printc((unsigned char)ch);
}
xfer.bytes_recv++;
return(ch);
}
if (CheckIO(&Iot0)) {
WaitIO(&Iot0);
IotIP = 0;
Iot0.tr_time.tv_secs = 3;
Iot0.tr_time.tv_micro= 0;
bytetimeout -= Iot0.tr_time.tv_secs;
if (bytetimeout > 0) {
if (CheckCarrier() == 0) {
NiceAbortIO(&Iosr);
WaitIO(&Iosr);
IosrIP = 0;
break;
}
SendIO(&Iot0);
IotIP = 1;
} else {
NiceAbortIO(&Iosr);
WaitIO(&Iosr);
IosrIP = 0;
if (Iosr.IOSer.io_Actual == 1) {
xfer.bytes_recv++;
return((int)XInBuf[0]);
}
break;
}
}
}
if (debug > 8)
printf("\nRecv-EOF\n");
return(EOF);
}
int
xwrite(buf, ctr)
const void *buf;
int ctr;
{
return(xxwrite(buf, ctr, 0));
}
int
xwritea(buf, ctr)
const void *buf;
int ctr;
{
xxwrite(buf, ctr, 1);
return(ctr);
}
int
xxwrite(buf, ctr, async)
const void *buf;
int ctr;
int async;
{
Assert(Iosr.IOSer.io_Device);
if (debug > 8) {
short i;
if (debugRead)
printf("\nWRITE ");
debugRead = 0;
for (i = 0; i < ctr; ++i) {
printc(((unsigned char *)buf)[i]);
}
printf("\n");
}
if (IoswIP) {
WaitIO(&Iosw);
IoswIP = 0;
}
Iosw.IOSer.io_Command = CMD_WRITE;
Iosw.IOSer.io_Length = ctr;
Iosw.IOSer.io_Data = (APTR)buf;
if (async) {
SendIO(&Iosw);
IoswIP = 1;
} else {
DoIO(&Iosw);
}
xfer.bytes_send += ctr;
return ctr;
}
void
SendBreak()
{
Assert(Iosr.IOSer.io_Device);
Ioss.IOSer.io_Command = SDCMD_BREAK;
DoIO(&Ioss);
}
int
CheckCarrier()
{
Assert(Iosr.IOSer.io_Device);
Ioss.IOSer.io_Command = SDCMD_QUERY;
DoIO(&Ioss);
if (IgnoreCD)
return(1);
if (Ioss.io_Status & CIAF_COMCD) /* non-zero == no carrier */
return(0);
return(1);
}
void *
bzero(s, cnt)
void *s;
long cnt;
{
setmem(s, cnt, 0);
return(s);
}
void *
bcopy(from, to, cnt)
const void *from;
void *to;
long cnt;
{
movmem(from, to, cnt);
return(to);
}
/*
* Transform a filename from a uucp packet (in Unix format) into a local
* filename that will work in the local file system.
*/
void
munge_filename(s, d)
char *s, *d;
{
if (*s != '~') {
if (s != d)
strcpy(d, s);
return;
}
/*
* ~/ ... convert to UUPUB:
* ~user/... convert to <homedir>/...
*/
{
short i;
short c;
char *t;
struct passwd *pw;
for (i = 1; s[i] && s[i] != '/'; ++i);
c = s[i];
s[i] = 0;
if (i == 1)
pw = NULL;
else
pw = getpwnam(s + 1);
s[i] = c;
if (c == '/')
++i;
if (pw) {
t = malloc(strlen(pw->pw_dir) + strlen(s + i) + 1);
strcpy(t, pw->pw_dir);
} else {
t = malloc(strlen(s + i) + 32);
strcpy(t, GetConfigDir(UUPUB));
}
strcat(t, s + i);
strcpy(d, t);
free(t);
}
}
int
hangup()
{
static char buf[128];
reset_modem();
sprintf(buf, "run >nil: <nil: %s", GetConfigProgram(UUXQT));
if (PriMode)
SetTaskPri(FindTask(NULL), OldPri - 1);
if (Execute(buf, NULL, NULL) == 0)
puts("Unable to run UUXQT");
if (PriMode)
SetTaskPri(FindTask(NULL), OldPri + 1);
return SUCCESS;
}
static char names[MAXFILES*16];
static char *pointers[MAXFILES];
static int file_pointer;
int
bp_strcmp(s1, s2)
char **s1;
char **s2;
{
return(strcmp(*s1, *s2));
}
int
work_scan(system_name)
char *system_name;
{
static char name[128];
int count;
file_pointer = 0;
if (strlen(system_name) > 7)
system_name[7] = '\0';
sprintf(name, "%sC.%s#?", MakeConfigPath(UUSPOOL, ""), system_name);
if (debug > 2)
printf("Looking for %s\n",name);
count = getfnl(name,names,sizeof(names),0);
if (count > 0) {
if (strbpl(pointers,MAXFILES,names) != count) {
printf("Too many command files for %s.\n",system_name);
return(0);
}
} else {
return(0);
}
qsort(pointers, count, sizeof(char *), bp_strcmp);
if (debug > 2)
printf("Found -> %s\n", pointers[file_pointer]);
return(1);
}
char *
work_next()
{
char *ptr;
if (ptr = pointers[file_pointer]) {
if (debug > 2)
printf("Found -> %s\n", ptr);
++file_pointer;
}
return(ptr);
}
void
amiga_setup()
{
mountrequest(0); /* disallow requesters */
OpenSerial(1);
if (OpenDevice(TIMERNAME, UNIT_VBLANK, &Iot0, 0)) {
Iot0.tr_node.io_Device = NULL;
printf("Can't open timer device.");
xexit(10);
}
Iot0.tr_node.io_Message.mn_ReplyPort = (struct MsgPort *)CreatePort("UUCICO-Timer", 0L);
Iot0.tr_node.io_Command = TR_ADDREQUEST;
Iot0.tr_node.io_Error = 0;
{
struct Task *task = (struct Task *)FindTask(NULL);
OldTaskName = task->tc_Node.ln_Name;
task->tc_Node.ln_Name = "uucico";
}
}
void
set_baud(baud)
int baud;
{
Assert(Iosr.IOSer.io_Device);
/*
* only modify serial parameters if not run from a Getty. This is
* to get around a bug in the A2232 serial.device (possibly also
* the normal serial.device) having to do with hanging semaphores.
*
* it is also possible that this might be desirable for operation.
*/
if (Getty == 0) {
Iosr.IOSer.io_Command = SDCMD_SETPARAMS;
Iosr.io_SerFlags = SERF_SHARED | SERF_XDISABLED;
Iosr.io_Baud = baud;
Iosr.io_ReadLen = 8L;
Iosr.io_WriteLen = 8L;
Iosr.io_CtlChar = 0x11130000L;
Iosr.io_RBufLen = 4096;
Iosr.io_StopBits= 1;
Iosr.io_BrkTime = 500000;
if (SevenWire)
Iosr.io_SerFlags |= SERF_7WIRE;
DoIO(&Iosr);
}
}
extern short DoAttempt;
void
OpenSerial(lock)
int lock;
{
unsigned char *error;
if (Iosr.IOSer.io_Device) {
puts("softerror, OpenSerial: Serial Port already open!");
return;
}
Iosr.io_SerFlags = SERF_SHARED | SERF_XDISABLED;
Iosr.IOSer.io_Message.mn_ReplyPort = (struct MsgPort *)CreatePort("Read_RS",0);
if (SevenWire)
Iosr.io_SerFlags |= SERF_7WIRE;
if (lock && Getty == 0) {
if (DoAttempt)
error = AttemptDevUnit(DeviceName, DeviceUnit, "UUcico", 0);
else
error = LockDevUnit(DeviceName, DeviceUnit, "UUcico", 0);
if (error) {
if (error[0] == ODUERR_LEADCHAR[0])
printf("Unable to lock serial port: %s\n", &error[1]);
else
printf("%s unit %d already owned by %s\n",
DeviceName, DeviceUnit, error);
xexit(10);
}
}
if (OpenDevice(DeviceName, DeviceUnit, &Iosr, NULL)) {
Iosr.IOSer.io_Device = NULL;
DeletePort(Iosr.IOSer.io_Message.mn_ReplyPort);
Iosr.IOSer.io_Message.mn_ReplyPort = NULL;
printf("Can not open serial port for read.\n");
xexit(TRUE);
}
Iosw = Iosr;
Iosw.IOSer.io_Message.mn_ReplyPort = (struct MsgPort *)CreatePort("Write_RS", 0);
Ioss = Iosw;
Iosr.IOSer.io_Command = SDCMD_QUERY;
DoIO(&Iosr);
set_baud(Iosr.io_Baud);
}
void
CloseSerial(lock)
int lock;
{
if (IosrIP) {
NiceAbortIO(&Iosr);
WaitIO(&Iosr);
IosrIP = 0;
}
if (IotIP) {
AbortIO(&Iot0);
WaitIO(&Iot0);
IotIP = 0;
}
if (IoswIP) {
WaitIO(&Iosw);
IoswIP = 0;
}
if (Iosr.IOSer.io_Device) {
CloseDevice(&Iosr);
Iosr.IOSer.io_Device = NULL;
Iosw.IOSer.io_Device = NULL;
Ioss.IOSer.io_Device = NULL;
} else {
puts("softerr, CloseSerial: Serial Port already closed!");
}
if (Iosr.IOSer.io_Message.mn_ReplyPort) {
DeletePort(Iosr.IOSer.io_Message.mn_ReplyPort);
Iosr.IOSer.io_Message.mn_ReplyPort = NULL;
}
if (Iosw.IOSer.io_Message.mn_ReplyPort) {
DeletePort(Iosw.IOSer.io_Message.mn_ReplyPort);
Iosw.IOSer.io_Message.mn_ReplyPort = NULL;
}
if (lock && Getty == 0)
FreeDevUnit(DeviceName, DeviceUnit);
}
void
xexit(code)
int code;
{
cleanup();
if (code)
printf("\nAbnormal Termination, code %d.\n", code);
exit(code);
}
void
printc(c)
unsigned char c;
{
c &= 0x7F;
if (c < 32)
printf("^%c", c | 0x40);
else if (c == 32)
printf("_");
else if (c < 128)
printf("%c", c);
else
printf("(%02x)", c);
}
void
_assert_failed(line)
{
static short reent;
if (reent == 0) {
++reent;
printf("Software Error line %d sysdep.c (uucico)\n", line);
xexit(20);
}
}
/*
* bug fix for older A2232 serial.device's
*/
void
NiceAbortIO(ior)
void *ior;
{
Disable();
if (((struct Message *)ior)->mn_Node.ln_Type != NT_REPLYMSG)
AbortIO(ior);
Enable();
}