home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 2
/
goldfish_vol2_cd1.bin
/
files
/
util
/
libs
/
fifolib
/
fifo-handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-03
|
25KB
|
1,110 lines
/*
* FIFO-HANDLER.C V37.4
*
* Provide an interface to the fifo.library
* Provide remote shell support, including "*" support and interactive
* support.
*
* !!! MUST BE RUN, CANNOT USE MOUNT !!!
*
* FIFO:fifo_name/flags
* r for reading
* w for writing
* c cooked (else raw)
* e EOF on close (if a writer)
* k allows writer to close before reader opens without
* any data lost.
* K a reader MUST exist or write(s) will fail
* q QUIT (debugging)
* m master
* t tee off the read stream (no interference with other
* readers)
* s shell
*
* d debug mode (read by running 'RemCLI DBFifo')
*/
#define CLI_START
#include "handler.h"
#include "fifo.h"
#include <lists.h>
#include <string.h>
#define FIFO_SIZE 2048
#define SIGS (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)
void myexit(int);
void Initialize(void);
void returnpacket(DosPacket *);
void HandleRequestMsg(Message *);
void WaitMsg(Message *);
void SigHandles(char *, long);
void xprintf(char *, ...);
void *DosAllocMem(long);
int OpenHandle(FHan *, char *, char *, long, long, long);
void CloseHandle(FHan *);
void DosFree(void *);
MsgPort *SpecPort(FHan *);
void MkDevice(char *);
void DelDevice(void);
short DDebug;
short NotDone = 1;
MsgPort *IoSink;
MsgPort *PktPort;
#ifndef CLI_START
DeviceNode *DevNode;
#endif
void *FifoBase;
long PktPortMask;
#ifdef DEBUG
long DBFifo;
#endif
List HanList;
extern struct DosLibrary *DOSBase;
__stkargs void
_main(arg, len)
char *arg;
long len;
{
DosPacket *packet;
NewList((MaxList *)&HanList);
Initialize();
/*
* Main Loop
*/
while (NotDone || GetHead(&HanList)) {
{
Message *msg;
while (msg = GetMsg(IoSink))
HandleRequestMsg(msg);
if ((msg = GetMsg(PktPort)) == NULL) {
if (Wait(SIGS | PktPortMask) & SIGBREAKF_CTRL_C)
NotDone = 0;
continue;
}
packet = (DosPacket *)msg->mn_Node.ln_Name;
}
if (packet->dp_Type != ACTION_WRITE)
packet->dp_Res1 = DOS_TRUE;
packet->dp_Res2 = 0;
#ifdef DEBUG
if (DDebug)
xprintf("packet %08lx (%d)\n", packet->dp_Type, packet->dp_Type);
#endif
switch(packet->dp_Type) {
case ACTION_DIE:
NotDone = 0;
break;
case ACTION_FINDUPDATE: /* FileHandle,Lock,Name Bool */
case ACTION_FINDINPUT: /* FileHandle,Lock,Name Bool */
case ACTION_FINDOUTPUT: /* FileHandle,Lock,Name Bool */
{
FileHandle *fh = BTOC(packet->dp_Arg1);
FHan *han;
char fifo_name_m[128];
char fifo_name_s[128];
short error = 0;
long han_flags = 0;
long opn_flags = FIFOF_NORMAL | FIFOF_NBIO;
long opn_size = FIFO_SIZE;
{
char *bas = BTOC(packet->dp_Arg3);
char *ptr;
unsigned char len = *(unsigned char *)bas;
long sigs = 0;
#ifdef DEBUG
if (DDebug)
xprintf("open: %*.*s\n", len, len, bas + 1);
#endif
for (ptr = ++bas; *ptr != ':' && len; ++ptr, --len);
if (len && *ptr == ':') {
++ptr;
--len;
} else {
len = ptr - bas;
ptr = bas;
}
bas = ptr;
for (ptr = bas; *ptr != '/' && len; ++ptr, --len);
{
int i = ptr - bas;
strncpy(fifo_name_m, bas, i);
strncpy(fifo_name_s, bas, i);
strcpy(fifo_name_m + i, "_m");
strcpy(fifo_name_s + i, "_s");
}
if (len && *ptr == '/') {
for (++ptr, --len; len; ++ptr, --len) {
switch(*ptr) {
case 'q':
NotDone = 0;
break;
case 'e':
han_flags |= FHF_CLOSEEOF;
break;
case 'c':
han_flags |= FHF_COOKED;
break;
case 'r':
han_flags |= FHF_READ;
break;
case 'w':
han_flags |= FHF_WRITE;
break;
case 'k':
opn_flags |= FIFOF_KEEPIFD;
break;
case 'K':
opn_flags |= FIFOF_RREQUIRED;
break;
case 'm':
han_flags |= FHF_MASTER;
break;
case 't':
han_flags |= FHF_TEE;
break;
case 'd':
#ifdef DEBUG
if (DDebug == 0) {
DDebug = 1;
DBFifo = OpenFifo("DBFifo_s", 1024, FIFOF_WRITE | FIFOF_NORMAL);
}
#endif
break;
case 'x':
#ifdef DEBUG
if (DDebug) {
DDebug = 0;
if (DBFifo)
CloseFifo(DBFifo, FIFOF_EOF);
DBFifo = NULL;
}
#endif
break;
case 's':
han_flags |= FHF_SHELL;
break;
case 'C':
sigs |= SIGBREAKF_CTRL_C;
break;
case 'D':
sigs |= SIGBREAKF_CTRL_D;
break;
case 'E':
sigs |= SIGBREAKF_CTRL_E;
break;
case 'F':
sigs |= SIGBREAKF_CTRL_F;
break;
default:
error = 1;
break;
}
}
}
if (sigs) {
if (han_flags & FHF_MASTER)
SigHandles(fifo_name_m, sigs);
else
SigHandles(fifo_name_s, sigs);
}
}
/*
* To handle the stderr channel, "*", an interactive
* shell must be openned with the 's' flag, which causes
* a special message port to be created for the interactive
* shell (and thus the pr_ConsoleTask field)
*
* To handle COOKED data mode, FIFO: itself must processed
* received data before the slave device, echoing it back
* on the master channel and doing other cooked processing.
*/
if (error == 0) {
if (strcmp(fifo_name_m, "*_m") == 0) {
if (fh->fh_Port && (long)fh->fh_Port != -1) {
han = (FHan *)fh->fh_Port->mp_Node.ln_Name;
++han->ff_Refs;
fh->fh_Arg1 = han;
fh->fh_Port = (MsgPort *)DOS_TRUE;
break;
}
fh->fh_Port = (MsgPort *)DOS_FALSE;
packet->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
if (han = AllocMem(sizeof(FHan) + strlen(fifo_name_s) + 1, MEMF_CLEAR | MEMF_PUBLIC)) {
han->ff_Node.ln_Name = (char *)(han + 1);
if (OpenHandle(han, fifo_name_s, fifo_name_m, han_flags, opn_size, opn_flags) >= 0) {
if (han_flags & FHF_SHELL) {
han->ff_Port = SpecPort(han);
fh->fh_Type = han->ff_Port;
}
fh->fh_Arg1 = han;
fh->fh_Port = (MsgPort *)DOS_TRUE;
AddTail((MaxList *)&HanList, &han->ff_Node);
++han->ff_Refs;
han->ff_Flags = han_flags;
han->ff_RdMsg.mn_ReplyPort = IoSink;
han->ff_RdMsg.mn_Node.ln_Name = (char *)han;
han->ff_WrMsg.mn_ReplyPort = IoSink;
han->ff_WrMsg.mn_Node.ln_Name = (char *)han;
han->ff_Task = packet->dp_Port->mp_SigTask;
/*
han->ff_Task = ((Message *)packet->dp_Link)->mn_ReplyPort->mp_SigTask;
*/
if (han_flags & FHF_WRITE)
han->ff_FBufSiz = BufSizeFifo(han->ff_FifoW);
NewList((MaxList *)&han->ff_RdWait);
NewList((MaxList *)&han->ff_WrWait);
if (han_flags & FHF_COOKED) {
RequestFifo(han->ff_FifoR, &han->ff_RdMsg, FREQ_RPEND);
han->ff_Flags |= FHF_RPEND;
han->ff_CookBuf = AllocMem(CB_SIZE, MEMF_PUBLIC | MEMF_CLEAR);
}
break;
}
AddTail((MaxList *)&HanList, &han->ff_Node);
CloseHandle(han);
}
}
fh->fh_Port = (MsgPort *)DOS_FALSE;
packet->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
#ifdef DEBUG
if (DDebug)
xprintf("open failed\n");
#endif
}
break;
case ACTION_READ: /* FHArg1,CPTRBuffer,Length ActLength */
/*
* read from fifo. If we are in cooked mode this action is
* only able to read from the cooked buffer, and then only
* if a line is complete.
*/
{
FHan *han = (FHan *)packet->dp_Arg1;
char *ptr;
long n;
if (!(han->ff_Flags & FHF_READ)) {
packet->dp_Res1 = -1;
break;
}
if (han->ff_Flags & FHF_REOF) {
han->ff_Flags &= ~FHF_REOF;
packet->dp_Res1 = 0;
break;
}
if (han->ff_Flags & FHF_COOKED) {
long n;
if ((n = strlen(han->ff_CookBuf)) != han->ff_CookIdx || han->ff_LRet) {
++n;
if (n > packet->dp_Arg3)
n = packet->dp_Arg3;
else
han->ff_CookBuf[n-1] = '\n';
movmem(han->ff_CookBuf, (void *)packet->dp_Arg2, n);
movmem(han->ff_CookBuf + n, han->ff_CookBuf, han->ff_CookIdx - n + 1);
han->ff_CookIdx -= n;
if (han->ff_CookIdx == 0)
han->ff_LRet = 0;
packet->dp_Res1 = n;
/*
* if we blocked on reading the fifo to cook more
* data, we unblock it here.
*/
han->ff_Flags &= ~FHF_COOKBFUL;
if ((han->ff_Flags & FHF_RPEND) == 0) {
RequestFifo(han->ff_FifoR, &han->ff_RdMsg, FREQ_RPEND);
han->ff_Flags |= FHF_RPEND;
}
break;
} else {
if (han->ff_Flags & FHF_REOF) {
han->ff_Flags &= ~FHF_REOF;
packet->dp_Res1 = 0;
break;
}
}
} else {
n = ReadFifo(han->ff_FifoR, &ptr, 0);
if (n < 0 || (n == 0 && (han->ff_Flags & FHF_REOF))) {
han->ff_Flags &= ~FHF_REOF;
packet->dp_Res1 = 0;
break;
}
if (n > 0) {
if (n > packet->dp_Arg3)
n = packet->dp_Arg3;
movmem(ptr, (void *)packet->dp_Arg2, n);
if (ReadFifo(han->ff_FifoR, &ptr, n) < 0)
han->ff_Flags |= FHF_REOF;
packet->dp_Res1 = n;
break;
}
}
/*
* blocked
*/
AddTail((MaxList *)&han->ff_RdWait, &((Message *)packet->dp_Link)->mn_Node);
if ((han->ff_Flags & FHF_RPEND) == 0) {
RequestFifo(han->ff_FifoR, &han->ff_RdMsg, FREQ_RPEND);
han->ff_Flags |= FHF_RPEND;
}
packet = NULL;
}
break;
case ACTION_WRITE: /* FHArg1,CPTRBuffer,Length ActLength */
{
FHan *han = (FHan *)packet->dp_Arg1;
long n;
long i;
if (!(han->ff_Flags & FHF_WRITE)) {
packet->dp_Res1 = -1;
break;
}
i = packet->dp_Arg3;
#ifdef DEBUG
if (DDebug)
xprintf("i = %d\n", i);
#endif
if (i < 0) { /* re-scan */
i = -i;
packet->dp_Arg3 = i;
} else { /* initial pkt */
packet->dp_Res1 = 0;
}
/*
* check for output stopped due to pending input line
*
* dp_Arg3 < 0 indicates a re-scan (so we do not clear
* our dp_Res1 field that is tracking the amnt written)
*/
if ((han->ff_Flags & FHF_COOKED) && han->ff_CookIdx && han->ff_LRet == 0) {
packet->dp_Arg3 = -packet->dp_Arg3;
AddTail((MaxList *)&han->ff_WrWait, &((Message *)packet->dp_Link)->mn_Node);
han->ff_Flags |= FHF_WIHOLD;
packet = NULL;
break;
}
/*
* limit size of writes to fifo to something the fifo can
* handle. If cooked mode writer, prepend CR to LF's.
*/
if (i > (han->ff_FBufSiz >> 1) - 1)
i = (han->ff_FBufSiz >> 1) - 1;
if (han->ff_Flags & FHF_COOKED) {
char *ptr = (char *)packet->dp_Arg2;
long j;
for (j = 0; j < i; ++j) {
if (ptr[j] == '\n') {
if (j == 0) {
n = WriteFifo(han->ff_FifoW, "\r\n", 2);
if (n == 2)
n = 1; /* skip LF */
break;
}
n = WriteFifo(han->ff_FifoW, ptr, j);
break;
}
}
if (i == j)
n = WriteFifo(han->ff_FifoW, (char *)packet->dp_Arg2, i);
} else {
n = WriteFifo(han->ff_FifoW, (char *)packet->dp_Arg2, i);
}
/*
* object too large or broken pipe
*/
if (n < 0) {
packet->dp_Res1 = -1;
packet->dp_Res2 = ERROR_OBJECT_TOO_LARGE;
break;
}
#ifdef DEBUG
if (DDebug)
xprintf("n = %d, res1 = %d, i=%d\n", n, packet->dp_Res1 + n, i);
#endif
packet->dp_Res1 += n;
if (n == packet->dp_Arg3)
break;
packet->dp_Arg3 = -(packet->dp_Arg3 - n);
packet->dp_Arg2 += n;
/*
* blocked
* n == 0
*/
#ifdef DEBUG
if (DDebug)
xprintf("AddTail:res1 = %d\n", packet->dp_Res1);
#endif
AddTail((MaxList *)&han->ff_WrWait, &((Message *)packet->dp_Link)->mn_Node);
if ((han->ff_Flags & FHF_WAVAIL) == 0) {
RequestFifo(han->ff_FifoW, &han->ff_WrMsg, FREQ_WAVAIL);
han->ff_Flags |= FHF_WAVAIL;
}
packet = NULL;
}
break;
case ACTION_REQUEST: /* FHArg1, msg, how Bool */
{
FHan *han = (FHan *)packet->dp_Arg1;
if ((unsigned short)packet->dp_Arg3 == FREQ_RPEND) {
if (han->ff_FifoR)
RequestFifo(han->ff_FifoR, (void *)packet->dp_Arg2, packet->dp_Arg3);
else
packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
break;
} else if ((unsigned short)packet->dp_Arg3 == FREQ_WAVAIL) {
if (han->ff_FifoW)
RequestFifo(han->ff_FifoW, (void *)packet->dp_Arg2, packet->dp_Arg3);
else
packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
break;
} else if ((unsigned short)packet->dp_Arg3 == FREQ_ABORT) {
if (han->ff_FifoR)
RequestFifo(han->ff_FifoR, (void *)packet->dp_Arg2, packet->dp_Arg3);
if (han->ff_FifoW)
RequestFifo(han->ff_FifoW, (void *)packet->dp_Arg2, packet->dp_Arg3);
} else {
packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
}
}
break;
case ACTION_END: /* FHArg1 Bool:TRUE */
{
FHan *han = (FHan *)packet->dp_Arg1;
Message *msg;
if (--han->ff_Refs == 0) {
if (han->ff_Flags & FHF_RPEND) {
RequestFifo(han->ff_FifoR, &han->ff_RdMsg, FREQ_ABORT);
WaitMsg(&han->ff_RdMsg);
}
if (han->ff_Flags & FHF_WAVAIL) {
RequestFifo(han->ff_FifoW, &han->ff_WrMsg, FREQ_ABORT);
WaitMsg(&han->ff_WrMsg);
}
returnpacket(packet); /* before ff_Port goes away */
CloseHandle(han);
packet = NULL;
}
}
break;
case ACTION_SCREEN_MODE:
if (packet->dp_Arg2 && packet->dp_Arg2 != -1) {
FHan *han = (FHan *)(((MsgPort *)packet->dp_Arg2)->mp_Node.ln_Name);
#ifdef DEBUG
if (DDebug)
xprintf("handle %s arg1 %d\n", han->ff_Node.ln_Name, packet->dp_Arg1);
#endif
switch (packet->dp_Arg1) {
case DOS_TRUE: /* RAW */
if (han->ff_Flags & FHF_COOKED) {
han->ff_Flags &= ~(FHF_COOKED|FHF_WIHOLD|FHF_COOKECHOBLK|FHF_COOKBFUL);
if ((han->ff_Flags & FHF_READ) && !(han->ff_Flags & FHF_RPEND)) {
RequestFifo(han->ff_FifoR, &han->ff_RdMsg, FREQ_RPEND);
han->ff_Flags |= FHF_RPEND;
}
if ((han->ff_Flags & FHF_WRITE) && !(han->ff_Flags & FHF_WAVAIL)) {
RequestFifo(han->ff_FifoW, &han->ff_WrMsg, FREQ_WAVAIL);
han->ff_Flags |= FHF_WAVAIL;
}
}
break;
case DOS_FALSE: /* COOKED */
if (!(han->ff_Flags & FHF_COOKED)) {
han->ff_Flags |= FHF_COOKED;
}
break;
}
}
break;
case ACTION_SEEK: /* FHArg1,Position,Mode OldPosition */
default:
packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
break;
}
if (packet) {
if (packet->dp_Res2)
packet->dp_Res1 = DOS_FALSE;
returnpacket(packet);
}
}
myexit(0);
}
int
OpenHandle(han, r_name, w_name, han_flags, opn_size, opn_flags)
FHan *han;
char *r_name; /* slave name */
char *w_name; /* master name */
long han_flags;
long opn_size;
long opn_flags;
{
if (han_flags & FHF_MASTER) {
strcpy(han->ff_Node.ln_Name, w_name);
} else {
char *swap;
strcpy(han->ff_Node.ln_Name, r_name);
swap = r_name;
r_name = w_name;
w_name = swap;
}
if ((han_flags & FHF_TEE) == 0 && (han_flags & FHF_READ)) {
FHan *h2;
for (h2 = (FHan *)HanList.mlh_Head; h2->ff_Node.ln_Succ; h2 = (FHan *)h2->ff_Node.ln_Succ) {
if (strcmp(h2->ff_Node.ln_Name, han->ff_Node.ln_Name) == 0) {
if ((h2->ff_Flags & FHF_TEE) == 0 && h2->ff_SRead) {
han->ff_SRead = h2->ff_SRead;
++han->ff_SRead->sr_Refs;
break;
}
}
}
}
if ((han_flags & FHF_READ) && han->ff_SRead == NULL) {
han->ff_SRead = AllocMem(sizeof(SharRead), MEMF_CLEAR | MEMF_PUBLIC);
han->ff_SRead->sr_FifoR = OpenFifo(r_name, opn_size, opn_flags | FIFOF_READ);
han->ff_SRead->sr_Refs = 1;
if (han->ff_FifoR == NULL)
return(-1);
}
if (han_flags & FHF_WRITE) {
han->ff_FifoW = OpenFifo(w_name, opn_size, opn_flags | FIFOF_WRITE);
if (han->ff_FifoW == NULL)
return(-1);
}
return(0);
}
void
CloseHandle(han)
FHan *han;
{
Remove(&han->ff_Node);
if (han->ff_SRead) {
if (--han->ff_SRead->sr_Refs == 0) {
if (han->ff_FifoR)
CloseFifo(han->ff_FifoR, 0);
FreeMem(han->ff_SRead, sizeof(SharRead));
}
han->ff_SRead = NULL;
}
if (han->ff_FifoW) {
if (han->ff_Flags & FHF_CLOSEEOF)
CloseFifo(han->ff_FifoW, FIFOF_EOF);
else
CloseFifo(han->ff_FifoW, 0);
han->ff_FifoW = NULL;
}
if (han->ff_Port) {
FreeMem(han->ff_Port, sizeof(MsgPort) + sizeof(Interrupt));
han->ff_Port = NULL;
}
if (han->ff_CookBuf)
FreeMem(han->ff_CookBuf, CB_SIZE);
FreeMem(han, sizeof(FHan) + strlen(han->ff_Node.ln_Name) + 1);
}
/*
* handle cooked data by actually reading it from the fifo, echoing it
* to the return channel (if it exists), and processing it. If a <CR>
* is processed, handle any
*/
void
HandleRequestMsg(msg)
Message *msg;
{
FHan *han = (FHan *)msg->mn_Node.ln_Name;
if (msg == &han->ff_WrMsg) {
han->ff_Flags &= ~FHF_WAVAIL;
while (msg = RemHead((MaxList *)&han->ff_WrWait)) /* retry operation */
PutMsg(PktPort, msg);
/*
* if we were blocked trying to echo, then read data pending,
* make sure read-request is queued and will be retried.
*/
if (han->ff_Flags & FHF_COOKECHOBLK) {
if ((han->ff_Flags & FHF_RPEND) == 0) {
RequestFifo(han->ff_FifoR, &han->ff_RdMsg, FREQ_RPEND);
han->ff_Flags |= FHF_RPEND;
}
han->ff_Flags &= ~FHF_COOKECHOBLK;
}
} else if (msg == &han->ff_RdMsg) {
han->ff_Flags &= ~FHF_RPEND;
if (han->ff_Flags & FHF_COOKED) {
long n;
long i;
short rwakeup = 0;
char *ptr;
n = ReadFifo(han->ff_FifoR, &ptr, 0);
if (n < 0) {
han->ff_Flags |= FHF_REOF;
rwakeup = 1;
}
for (i = 0; i < n; ++i) {
switch(ptr[i]) {
case 13:
case 10:
if (han->ff_CookIdx >= CB_SIZE - 2) {
han->ff_Flags |= FHF_COOKBFUL;
n = --i;
break;
}
if (han->ff_FifoW) {
if (WriteFifo(han->ff_FifoW, "\r\n", 2) != 2) {
han->ff_Flags |= FHF_COOKECHOBLK;
n = --i;
break;
}
}
han->ff_CookBuf[han->ff_CookIdx++] = 0;
han->ff_CookBuf[han->ff_CookIdx] = 0;
han->ff_LRet = 1;
rwakeup = 1;
break;
case 8:
if (han->ff_CookIdx && han->ff_CookBuf[han->ff_CookIdx-1] != 0) {
if (han->ff_FifoW) {
if (WriteFifo(han->ff_FifoW, "\010 \010", 3) != 3) {
han->ff_Flags |= FHF_COOKECHOBLK;
n = --i;
break;
}
}
han->ff_CookBuf[--han->ff_CookIdx] = 0;
if (han->ff_CookIdx && han->ff_CookBuf[han->ff_CookIdx-1] == 0)
han->ff_LRet = 1;
}
break;
default:
if (han->ff_CookIdx >= CB_SIZE - 2) {
han->ff_Flags |= FHF_COOKBFUL;
n = --i;
break;
}
if (han->ff_FifoW) {
if (WriteFifo(han->ff_FifoW, ptr + i, 1) != 1) {
han->ff_Flags |= FHF_COOKECHOBLK;
n = --i;
break;
}
}
han->ff_CookBuf[han->ff_CookIdx++] = ptr[i];
han->ff_CookBuf[han->ff_CookIdx] = 0;
han->ff_LRet = 0;
break;
}
}
/*
* if output was held due to cooked input pending, and the
* case is no longer true, then restart output
*/
if ((han->ff_Flags & FHF_WIHOLD) && (han->ff_LRet || han->ff_CookIdx == 0)) {
han->ff_Flags &= ~FHF_WIHOLD;
while (msg = RemHead((MaxList *)&han->ff_WrWait))
PutMsg(PktPort, msg);
}
if (i > 0) {
if (ReadFifo(han->ff_FifoR, &ptr, i) < 0) {
han->ff_Flags |= FHF_REOF;
rwakeup = 1;
}
}
if (n >= 0 && !(han->ff_Flags & (FHF_COOKECHOBLK|FHF_COOKBFUL|FHF_REOF))) {
RequestFifo(han->ff_FifoR, &han->ff_RdMsg, FREQ_RPEND);
han->ff_Flags |= FHF_RPEND;
}
if (!rwakeup)
return;
}
while (msg = RemHead((MaxList *)&han->ff_RdWait)) /* retry operation */
PutMsg(PktPort, msg);
}
}
void
WaitMsg(msg)
Message *msg;
{
while (msg->mn_Node.ln_Type == NT_MESSAGE)
Wait(1 << msg->mn_ReplyPort->mp_SigBit);
Forbid();
Remove(&msg->mn_Node);
Permit();
}
void
SigHandles(name, sigs)
char *name;
long sigs;
{
FHan *han;
for (han = (FHan *)HanList.mlh_Head; han->ff_Node.ln_Succ; han = (FHan *)han->ff_Node.ln_Succ) {
if (strcmp(han->ff_Node.ln_Name, name) == 0 && han->ff_Task)
Signal(han->ff_Task, sigs);
}
}
/*
* PACKET ROUTINES. Dos Packets are in a rather strange format as you
* can see by this and how the PACKET structure is extracted in the
* GetMsg() of the main routine.
*/
void
returnpacket(packet)
DosPacket *packet;
{
Message *mess;
MsgPort *replyPort;
replyPort = packet->dp_Port;
mess = packet->dp_Link;
packet->dp_Port = PktPort;
mess->mn_Node.ln_Name = (char *)packet;
PutMsg(replyPort, mess);
}
void
Initialize()
{
DeviceNode *dn;
Process *proc = FindTask(NULL);
DosPacket *packet;
/*
* Initialize port
*/
{
IoSink = CreatePort("FIFO-PORT", 0);
FreeSignal(IoSink->mp_SigBit);
IoSink->mp_SigBit = SIGBREAKB_CTRL_F;
}
PktPort = CreatePort(NULL, 0);
PktPortMask = 1 << PktPort->mp_SigBit;
#ifdef CLI_START
/*
* create DOS node
*/
MkDevice("FIFO");
FifoBase = OpenLibrary("fifo.library", 0);
#else
/*
* Handle initial message. We pull the message off the port before
* calling OpenLibrary() so if OpenLibrary() makes a DOS call it
* doesn't crash the machine (due to an unexpected packet). This
* will happen if the library needs to be loaded. There is no other
* safe time to do this.
*/
{
Message *msg;
WaitPort(&proc->pr_MsgPort);
msg = GetMsg(&proc->pr_MsgPort);
packet = (DosPacket *)msg->mn_Node.ln_Name;
}
/*
* Fifo Library
*/
FifoBase = OpenLibrary("fifo.library", 0);
{
DevNode = dn = BTOC(packet->dp_Arg3);
dn->dn_Task = PktPort;
packet->dp_Res1 = (FifoBase) ? DOS_TRUE : DOS_FALSE;
packet->dp_Res2 = 0;
returnpacket(packet);
}
#endif
if (FifoBase == NULL)
myexit(1);
}
void
myexit(code)
int code;
{
#ifdef CLI_START
DelDevice();
#else
/*
* Device Node
*/
{
DeviceNode *dn = DevNode;
dn->dn_Task = NULL;
dn->dn_SegList = NULL;
}
#endif
/*
* delete ports
*/
if (IoSink) {
IoSink->mp_SigBit = AllocSignal(-1);
DeletePort(IoSink);
}
if (PktPort)
DeletePort(PktPort);
#ifdef DEBUG
if (DBFifo) {
CloseFifo(DBFifo, FIFOF_EOF);
DBFifo = NULL;
}
#endif
if (FifoBase) {
CloseLibrary(FifoBase);
FifoBase = NULL;
}
_exit(code);
}
MsgPort *
SpecPort(han)
FHan *han;
{
MsgPort *port = AllocMem(sizeof(MsgPort) + sizeof(Interrupt), MEMF_CLEAR|MEMF_PUBLIC);
Interrupt *xint = (Interrupt *)(port + 1);
extern void AIntCode();
NewList(&port->mp_MsgList);
port->mp_Node.ln_Name = (char *)han;
port->mp_Node.ln_Type = NT_MSGPORT;
port->mp_Flags = PA_SOFTINT;
port->mp_SigTask = (void *)xint;
xint->is_Node.ln_Type = NT_INTERRUPT;
xint->is_Node.ln_Pri = -32;
xint->is_Data = (APTR)port;
xint->is_Code = AIntCode;
return(port);
}
__geta4 __stkargs void
IntCode(port)
MsgPort *port;
{
Message *msg;
DosPacket *packet;
FileHandle *fh;
#ifdef DEBUG
if (DDebug)
xprintf("port %08lx\n", port);
#endif
while (msg = GetMsg(port)) {
packet = (DosPacket *)msg->mn_Node.ln_Name;
#ifdef DEBUG
if (DDebug)
xprintf("type %08lx\n", packet->dp_Type);
#endif
switch(packet->dp_Type) {
case ACTION_FINDUPDATE:
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
fh = BTOC(packet->dp_Arg1);
fh->fh_Port = port;
break;
case ACTION_SCREEN_MODE:
packet->dp_Arg2 = port;
break;
}
PutMsg(PktPort, msg);
}
}
#ifdef DEBUG
void
xprintf(char *ctl, ...)
{
va_list va;
static char buf[256];
int n;
if (DBFifo) {
va_start(va, ctl);
n = vsprintf(buf, ctl, va);
if (n > 0)
WriteFifo(DBFifo, buf, n);
va_end(va);
}
}
#endif
#ifdef CLI_START
/*
* DEVICE CREATION AND DELETION
*/
DosList *Dl;
void
MkDevice(devName)
char *devName;
{
DosList *dl;
RootNode *root;
DosInfo *info;
Dl = dl = (struct DosList *)DosAllocMem(sizeof(struct DosList)+strlen(devName)+2);
strcpy((char *)(dl+1) + 1, devName);
*(char *)(dl + 1) = strlen(devName);
dl->dol_Type = DLT_DEVICE;
dl->dol_Task = PktPort;
dl->dol_Name = MKBADDR((char *)(dl+1));
Forbid();
root = (struct RootNode *)DOSBase->dl_Root;
info = (struct DosInfo *)BADDR(root->rn_Info);
dl->dol_Next = info->di_DevInfo;
info->di_DevInfo = MKBADDR(dl);
Permit();
}
void
DelDevice()
{
DosList *dl;
DosInfo *info;
RootNode *root;
DosList *dls;
BPTR *bpp;
if (dl = Dl) {
Forbid();
root = (struct RootNode *)DOSBase->dl_Root;
info = (struct DosInfo *)BADDR(root->rn_Info);
for (bpp = &info->di_DevInfo; dls = BADDR(*bpp); bpp = &dls->dol_Next) {
if (dls == dl)
break;
}
if (dls == dl) {
*bpp = dls->dol_Next;
} else {
Alert(0x07AAAAAA|AT_Recovery);
}
Permit();
DosFree(dl);
Dl = NULL;
}
}
void *
DosAllocMem(bytes)
long bytes;
{
long *ptr;
bytes += 4;
if (ptr = AllocMem(bytes, MEMF_PUBLIC | MEMF_CLEAR)) {
*ptr++ = bytes;
return((void *)ptr);
}
Alert(AG_NoMemory|AT_DeadEnd);
}
void
DosFree(vptr)
void *vptr;
{
long *ptr = vptr;
--ptr;
FreeMem(ptr, *ptr);
}
#endif