home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * 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
-