🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sys.amiga.tech
Article #13076

Re: I wanna have a DOSGate!

#13076
From: Matt Dillon
Date: Mon, 12 Jun 1989 23:12
318 lines
8752 bytes
:So use asynchronous I/O, and Wait() on both the pipe-handler and your
:events (I assume menupicks and timers and such?). See the latest
:AmyTransactor for John Toebes/et. al.'s excellent article on the
:subject. Also, Matt Dillon has a library somewhere for doing async
:I/O, to go with his libraries to do just about everything else under
:the sun :-). 
:
:Someone else suggested multitasking it off as a seperate task, but
:that won't work here. If the person doesn't type anything in the past,
:say, 5 minutes, the BBS has to assume he's gone to lunch, i.e. we have
:to be waiting on a timer as well as on file and modem i/o. Might as
:well just do it in the BBS instead of spawning it off. 

	Yes, it is in my suplib link library.  The code is pretty old and
not all that pretty, but here it is (below)

	Note that various system #include's are missing (I use a 
precompiled include file for all the system stuff).  There are references
to other routines in suplib but what they do ought to be obvious.

	I also just noticed (not having looked at the routines for
a year or two) that it doesn't error check the buffer allocations.. oops.
	

					-Matt


/*
 *  XFIO.C
 *
 *  Simple File IO with asyncronous READ and WRITE capability
 *  Perfect for protocol transfer applications
 *
 *  xfi = xfopen(name, modes, bufsize)  ("r", "w", "w+")
 *   n	= xfread(xfi, buf, bytes)   ASYNCRONOUS READ
 *  err = xfwrite(xfi, buf, bytes)  ASYNCRONOUS WRITE
 *  err = xfclose(xfi)
 *
 *  RESTRICTIONS:   NO seeking.  You can do one of xfread() or xfwrite()
 *  for a given open XFIle handle (not both).
 *
 *  xfwrite() returns a cumulative error (once an error occurs, it will not
 *  do any more writes).  xfclose() returns the cumulative write error
 *  (since the last write may have been asyncronous and thus the error
 *  unknown at the time).
 *
 *  Two buffers are created each bufsize/2 bytes in size.  for writing,
 *  one buffers is sent asyncronously while the other fills.  For reading,
 *  one buffer is filling while the other is being read.
 */

#define XFI	    struct _XFI
#define XFBUF	    struct _XFBUF
#define MSGPORT     struct MsgPort
#define FH	    struct FileHandle
#define STDPKT	    struct StandardPacket


XFBUF {
    long   bufsize;
    long   idx;
    long   max;
    char    buf[4];	/*  actually bufsize bytes long */
};

XFI {
    char    ro; 	/*  read only, else write only	*/
    char    pend;	/*  packet pending		*/
    char    err;	/*  cumulative error		*/
    char    reserved;
    XFBUF   *asbuf;
    XFBUF   *usbuf;
    FH	    *fh;
    STDPKT  sp; 	/*  asyncronous message 	*/
    MSGPORT rp; 	/*  reply port for pending pkts */
};

extern FH *Open();
extern void *malloc(), *FindTask();

/*BREAKUP   xfopen.c	*/

void *
xfopen(file, mode, bytes)
char *file;
char *mode;
{
    register XFI *xfi = malloc(sizeof(XFI));
    register long nbytes = bytes >> 1;
    int ap = 0;

    BZero(xfi, sizeof(XFI));
    if (mode[0] == 'w') {
	if (mode[1] == '+') {
	    ap = 1;
	    if ((xfi->fh = Open(file, 1005)) == NULL)
		xfi->fh = Open(file, 1006);
	    goto ok;
	}
	xfi->fh = Open(file, 1006);
	goto ok;
    }
    xfi->fh = Open(file, 1005);
ok:
    if (xfi->fh) {
	if (ap)
	    Seek(xfi->fh, 0, 1);
	xfi->fh = (FH *)((long)xfi->fh << 2);		/* BTOC()	    */
	xfi->asbuf = malloc(sizeof(XFBUF) + nbytes);    /* a little more    */
	xfi->usbuf = malloc(sizeof(XFBUF) + nbytes);    /* then we need     */
	BZero(xfi->asbuf, sizeof(XFBUF));
	BZero(xfi->usbuf, sizeof(XFBUF));
	xfi->ro = (mode[0] == 'r');
	xfi->asbuf->bufsize = xfi->usbuf->bufsize = nbytes;
	xfi->rp.mp_Node.ln_Type = NT_MSGPORT;
	xfi->rp.mp_Node.ln_Name = "XFIO-Async";
	xfi->rp.mp_Flags = PA_SIGNAL;
	xfi->rp.mp_SigBit = AllocSignal(-1);
	xfi->rp.mp_SigTask = FindTask(NULL);
	NewList(&xfi->rp.mp_MsgList);
	if (xfi->ro)
	    __xfstartasync(xfi, ACTION_READ);
    } else {
	free(xfi);
	xfi = NULL;
    }
    return(xfi);
}

/*BREAKUP   xfclose.c	*/


xfclose(xfi)
register XFI *xfi;
{
    int err = 1;
    if (xfi) {
	if (xfi->pend) {
	    xfi->pend = 0;
	    WaitPort (&xfi->rp);
	    GetMsg   (&xfi->rp);
	}
	if (!xfi->ro && xfi->usbuf->idx)
	    Write((long)xfi->fh >> 2, xfi->usbuf->buf, xfi->usbuf->idx);
	err = xfi->err;
	Close((long)xfi->fh >> 2);
	free(xfi->asbuf);
	free(xfi->usbuf);
	FreeSignal(xfi->rp.mp_SigBit);
	free(xfi);
    }
    return(err);
}

/*BREAKUP   xfseek.c	*/

xfseek(xfi, pos)	/* may not work */
XFI *xfi;
long pos;
{
    if (xfi) {
	if (xfi->pend) {
	    WaitPort (&xfi->rp);
	    GetMsg   (&xfi->rp);
	    xfi->pend = 0;
	    if (!xfi->ro) {
		if (xfi->sp.sp_Pkt.dp_Res1 != xfi->sp.sp_Pkt.dp_Arg3) {
		    xfi->err = 1;
		    return(1);
		}
	    }
	}
	if (!xfi->ro && xfi->usbuf->idx) {
	    Write((long)xfi->fh >> 2, xfi->usbuf->buf, xfi->usbuf->idx);
	    xfi->usbuf->idx = 0;
	}
	Seek((long)xfi->fh >> 2, pos, -1);
	if (xfi->ro) {
	    XFBUF *asbuf = xfi->asbuf;
	    xfi->asbuf = xfi->usbuf;
	    xfi->usbuf = asbuf;
	    xfi->usbuf->idx = xfi->usbuf->max = 0;
	    __xfstartasync(xfi, ACTION_READ);
	}
    }
}

/*BREAKUP xfgets.c  */

xfgets(xfi, buf, n)
XFI *xfi;
char *buf;
{
    register XFBUF *usbuf = xfi->usbuf;
    register int i, idx;
    if (!xfi->ro)
	return(-1);
    --n;
    for (i = 0;;) {
	for (idx = usbuf->idx; idx < usbuf->max && i < n; ++idx, ++i) {
	    if ((buf[i] = usbuf->buf[idx]) == '\n') {
		buf[i] = 0;
		usbuf->idx = idx+1;
		return(i);
	    }
	}
	usbuf->idx = idx;
	buf[i] = 0;
	if (i == n)
	    return(i);
	if (xfi->pend == 0)                             /* EOF      */
	    return(-1);
	WaitPort (&xfi->rp);
	GetMsg	 (&xfi->rp);
	xfi->pend = 0;
	if (xfi->sp.sp_Pkt.dp_Res1 <= 0) {              /* EOF      */
	    if (i == 0)
		return(-1);
	    return(i);
	}
	xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1;
	xfi->asbuf->idx = 0;
	usbuf = xfi->asbuf;				/* swap bufs*/
	xfi->asbuf = xfi->usbuf;
	xfi->usbuf = usbuf;
	__xfstartasync(xfi, ACTION_READ);                 /* new async*/
    }
}

/*BREAKUP xfread.c  */

xfread(xfi, buf, n)
XFI *xfi;
char *buf;
{
    register XFBUF *usbuf = xfi->usbuf;
    register int orig = n;
    register int diff;

    if (!xfi->ro)
	return(0);
    while ((diff = usbuf->max - usbuf->idx) < n) {
	movmem(usbuf->buf + usbuf->idx, buf, diff);     /* copy entire buf */
	buf += diff;
	n -= diff;
	if (xfi->pend == 0) {
	    xfi->usbuf->idx = xfi->usbuf->max;
	    return(orig - n);
	}
	WaitPort (&xfi->rp);
	GetMsg	 (&xfi->rp);
	xfi->pend = 0;
	if (xfi->sp.sp_Pkt.dp_Res1 <= 0) {              /* EOF      */
	    xfi->usbuf->idx = xfi->usbuf->max;
	    return(orig - n);
	}
	xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1;
	xfi->asbuf->idx = 0;
	usbuf = xfi->asbuf;				/* swap bufs*/
	xfi->asbuf = xfi->usbuf;
	xfi->usbuf = usbuf;
	__xfstartasync(xfi, ACTION_READ);                 /* new async*/
    }
    movmem(usbuf->buf + usbuf->idx, buf, n);
    usbuf->idx += n;
    return(orig);
}

/*BREAKUP   xfwrite.c	*/

xfwrite(xfi, buf, n)
XFI *xfi;
char *buf;
{
    register XFBUF *usbuf = xfi->usbuf;
    register int diff;

    if (xfi->ro || xfi->err)
	return(1);
    while ((diff = usbuf->bufsize - usbuf->idx) < n) {
	movmem(buf, usbuf->buf + usbuf->idx, diff);     /*  copy buf    */
	buf += diff;
	n -= diff;
	if (xfi->pend) {
	    WaitPort(&xfi->rp);
	    GetMsg  (&xfi->rp);
	    xfi->pend = 0;
	    if (xfi->sp.sp_Pkt.dp_Res1 != xfi->sp.sp_Pkt.dp_Arg3) {
		xfi->err = 1;
		return(1);
	    }
	}
	usbuf = xfi->asbuf;
	xfi->asbuf = xfi->usbuf;
	xfi->usbuf = usbuf;
	usbuf->idx = 0;
	__xfstartasync(xfi, ACTION_WRITE);
    }
    movmem(buf, usbuf->buf + usbuf->idx, n);
    usbuf->idx += n;
    return(xfi->err);
}

/*BREAKUP   xfstartasync.c  */

__xfstartasync(xfi, action)
register XFI *xfi;
{
    xfi->sp.sp_Msg.mn_Node.ln_Name = (char *)&(xfi->sp.sp_Pkt);
    xfi->sp.sp_Pkt.dp_Link = &(xfi->sp.sp_Msg);
    xfi->sp.sp_Pkt.dp_Port = &xfi->rp;
    xfi->sp.sp_Pkt.dp_Type = action;
    xfi->sp.sp_Pkt.dp_Arg1 = xfi->fh->fh_Arg1;
    xfi->sp.sp_Pkt.dp_Arg2 = (long)xfi->asbuf->buf;
    xfi->sp.sp_Pkt.dp_Arg3 = xfi->asbuf->bufsize;
    PutMsg (xfi->fh->fh_Type, &xfi->sp);
    xfi->pend = 1;
}
Technical Details
Message-ID: <8906122312.AA02273@hermes.Berkeley.EDU>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!ucbvax!HERMES.BERKELEY.EDU!dillon

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!ucbvax!HERMES.BERKELEY.EDU!dillon
From: dillon@HERMES.BERKELEY.EDU (Matt Dillon)
Newsgroups: comp.sys.amiga.tech
Subject: Re: I wanna have a DOSGate!
Message-ID: <8906122312.AA02273@hermes.Berkeley.EDU>
Date: 12 Jun 89 23:12:30 GMT
Sender: daemon@ucbvax.BERKELEY.EDU
Lines: 318