/* * DNETLIB.C * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * Library Interface for DNET. */ #define NOEXT #include "/dnet/dnet.h" #include "/lib/dnetlib.h" #include #define CHANN struct _CHANN #define NAMELEN sizeof("DNET.PORT.XXXXX") #define NAMEPAT "DNET.PORT.%ld" CHANN { PORT port; /* receive data, replies */ PORT *dnetport; /* dnet's master port */ LIST rdylist; /* ready to be read */ uword chan; /* channel # for open channels */ ubyte eof; /* channel remotely closed/eof */ ubyte filler; int qlen; /* allowed write queue size */ int queued; /* current # packets queued */ }; /*BREAKUP vers.bc */ Version(name, ver, subver) char *name; char *ver; char *subver; { Write(Output(), name, strlen(name)); Write(Output(), " V", 2); Write(Output(), ver, strlen(ver)); Write(Output(), subver, strlen(subver)); Write(Output(), "\n", 1); } /*BREAKUP dlis.bc */ PORT * DListen(portnum) uword portnum; { PORT *port = NULL; char *ptr; ptr = AllocMem(NAMELEN, MEMF_PUBLIC); /* memory the the name */ sprintf(ptr, NAMEPAT, portnum); Forbid(); /* task-atomic operation */ if (FindPort(ptr) || !(port = CreatePort(ptr,0))) FreeMem(ptr, NAMELEN); Permit(); return(port); } /*BREAKUP dunl.bc */ void DUnListen(lisport) PORT *lisport; { if (lisport) { register char *ptr = lisport->mp_Node.ln_Name; Forbid(); /* task-atomic operation */ while (DNAAccept(lisport)); /* remove all pending requests */ DeletePort(lisport); /* gone! */ Permit(); FreeMem(ptr, NAMELEN); } } /*BREAKUP dacc.bc */ /* * DAccept() * * Note: This call will work even if called by a task which does not * own the listen port. */ PORT * DAccept(lisport) PORT *lisport; { register IOR *ior; register CHANN *chan = NULL; CHANN *MakeChannel(); while (!chan && (ior = GetMsg(lisport))) { switch(ior->io_Command) { case DNCMD_SOPEN: chan = MakeChannel(ior, NULL); break; default: ior->io_Error = 1; break; } ReplyMsg(ior); } if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail) SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit); return((PORT *)chan); } /*BREAKUP dnaac.bc */ /* * Refuse a connection */ DNAAccept(lisport) PORT *lisport; { IOR *ior; if (ior = GetMsg(lisport)) { ior->io_Error = 1; ReplyMsg(ior); } if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail) SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit); return(ior != NULL); } /*BREAKUP dpri.bc */ DPri(chan, pri) CHANN *chan; { } /*BREAKUP dopen.bc */ PORT * DOpen(host, portnum, txpri, rxpri) char *host; char txpri, rxpri; uword portnum; { IOR ior; CHANN *chan; CHANN *MakeChannel(); if (!host) host = "0"; chan = MakeChannel(&ior, host); if (rxpri > 126) rxpri = 126; if (rxpri < -127) rxpri = -127; if (txpri > 126) txpri = 126; if (txpri < -127) txpri = -127; if (chan->dnetport) { ior.io_Command = DNCMD_OPEN; ior.io_Unit = (void *)portnum; ior.io_Offset = (long)chan; ior.io_Message.mn_ReplyPort = (PORT *)chan; ior.io_Message.mn_Node.ln_Pri = txpri; ior.io_Message.mn_Node.ln_Name= (char *)rxpri; PutMsg(chan->dnetport, &ior); WaitMsg(&ior); if (ior.io_Error == 0) { chan->chan = (long)ior.io_Unit; FixSignal(chan); return((PORT *)chan); } } DeleteChannel(chan); return(NULL); } /*BREAKUP dceof.bc */ DCheckEof(chan) CHANN *chan; { return (chan->eof); } /*BREAKUP dgioc.bc */ DGetIoctl(chan, pval, paux) CHANN *chan; short *pval; char *paux; { register IOR *ior; short cmd = -1; if ((ior = GetHead(&chan->rdylist)) || (ior = GetHead(&chan->port.mp_MsgList))) { if (ior->io_Command == DNCMD_IOCTL) { CIOCTL *cio = (CIOCTL *)ior->io_Data; cmd = cio->cmd; *pval = (cio->valh << 8) | cio->vall; *paux = cio->valaux; Forbid(); Remove(ior); ReplyMsg(ior); Permit(); } } FixSignal(chan); if (chan->eof) SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit); return(cmd); } /*BREAKUP dnread.bc */ DNRead(chan, buf, bytes) CHANN *chan; char *buf; { register IOR *ior; int len = 0; long n; if (chan->eof) return(-1); while (bytes && ((ior = RemHead(&chan->rdylist)) || (ior = GetMsg(chan)))) { #ifdef DEBUG printf("IOR %08lx cmd %d len %d act %d\n", ior, ior->io_Command, ior->io_Length, ior->io_Actual); #endif if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) { if (!chan->queued) puts("DNRead: Software Error"); else --chan->queued; if (ior->io_Length) FreeMem(ior->io_Data, ior->io_Length); FreeMem(ior, sizeof(IOR)); continue; } switch(ior->io_Command) { case DNCMD_CLOSE: case DNCMD_EOF: chan->eof = 1; ReplyMsg(ior); break; case DNCMD_IOCTL: if (ior->io_Message.mn_Node.ln_Type == NT_REQUEUE) AddHead(&chan->rdylist, ior); else AddTail(&chan->rdylist, ior); ior->io_Message.mn_Node.ln_Type = NT_REQUEUE; if (len == 0) len = -2; goto done; case DNCMD_WRITE: #ifdef DEBUG printf("IOR LEN/ACT %ld/%ld\n", ior->io_Length, ior->io_Actual); #endif n = ior->io_Length - ior->io_Actual; if (n < 0) puts("len fail"); if (n <= bytes) { CopyMem((char *)ior->io_Data + ior->io_Actual, buf, n); bytes -= n; len += n; buf += n; ReplyMsg(ior); } else { CopyMem((char *)ior->io_Data + ior->io_Actual, buf, bytes); len += bytes; ior->io_Actual += bytes; bytes = 0; if (ior->io_Message.mn_Node.ln_Type == NT_REQUEUE) AddHead(&chan->rdylist, ior); else AddTail(&chan->rdylist, ior); ior->io_Message.mn_Node.ln_Type = NT_REQUEUE; } break; default: ior->io_Error = 1; ReplyMsg(ior); } } #ifdef DEBUG puts("DONE1"); #endif done: FixSignal(chan); if (chan->eof) SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit); #ifdef DEBUG printf("RETURN %ld\n", len); #endif return(len); } /*BREAKUP dread.bc */ DRead(chan, buf, bytes) char *buf; CHANN *chan; { long len = 0; long n = -1; if (chan->eof) return(-1); while (bytes) { if (n == 0) WaitPort(chan); n = DNRead(chan, buf, bytes); if (n < 0) break; len += n; buf += n; bytes -= n; if (chan->eof) break; } return(len); } /*BREAKUP dq.bc */ DQueue(chan, n) CHANN *chan; { chan->qlen = n; } /*BREAKUP dwr.bc */ DWrite(chan, buf, bytes) CHANN *chan; { int error = bytes; if (chan->qlen) { if (WaitQueue(chan, NULL) >= 0) { register IOR *ior = AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC); ior->io_Command = DNCMD_WRITE; ior->io_Unit = (void *)chan->chan; ior->io_Offset = (long)chan; ior->io_Message.mn_ReplyPort = (PORT *)chan; ior->io_Data = AllocMem(bytes, MEMF_PUBLIC); ior->io_Length = bytes; CopyMem(buf, ior->io_Data, bytes); PutMsg(chan->dnetport, ior); ++chan->queued; } else { error = -1; } } else { IOR ior; ior.io_Command = DNCMD_WRITE; ior.io_Unit = (void *)chan->chan; ior.io_Offset = (long)chan; ior.io_Message.mn_ReplyPort = (PORT *)chan; ior.io_Data = (APTR)buf; ior.io_Length = bytes; PutMsg(chan->dnetport, &ior); WaitMsg(&ior); if (ior.io_Error) error = -1; } FixSignal(chan); return(error); } /*BREAKUP deof.bc */ DEof(chan) CHANN *chan; { IOR ior; ior.io_Command = DNCMD_EOF; ior.io_Unit = (void *)chan->chan; ior.io_Offset = (long)chan; ior.io_Message.mn_ReplyPort = (PORT *)chan; PutMsg(chan->dnetport, &ior); WaitMsg(&ior); FixSignal(chan); } /*BREAKUP dioc.bc */ DIoctl(chan, cmd, val, aux) CHANN *chan; ubyte cmd; uword val; ubyte aux; { IOR ior; ior.io_Command = DNCMD_IOCTL; ior.io_Unit = (void *)chan->chan; ior.io_Offset = (long)chan; ior.io_Message.mn_ReplyPort = (PORT *)chan; ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd); PutMsg(chan->dnetport, &ior); WaitMsg(&ior); FixSignal(chan); } /*BREAKUP dst.bc */ DStat(host, buffer, max) char *host; APTR buffer; { IOR ior; char buf[sizeof(DNETPORTNAME)+32]; PORT *replyport = CreatePort(NULL, 0); PORT *dnetport; if (!host) host = "0"; sprintf(buf, "%s%s", DNETPORTNAME, host); if (dnetport = FindPort(buf)) { ior.io_Command = DNCMD_INFO; ior.io_Unit = 0; ior.io_Offset = 0; ior.io_Data = buffer; ior.io_Message.mn_ReplyPort = replyport; PutMsg(dnetport, &ior); WaitMsg(&ior); DeletePort(replyport); } return(dnetport != NULL); } /*BREAKUP dqu.bc */ DQuit(host) char *host; { IOR ior; char buf[sizeof(DNETPORTNAME)+32]; PORT *replyport = CreatePort(NULL, 0); PORT *dnetport; if (!host) host = "0"; sprintf(buf, "%s%s", DNETPORTNAME, host); if (dnetport = FindPort(buf)) { ior.io_Command = DNCMD_QUIT; ior.io_Unit = 0; ior.io_Offset = 0; ior.io_Message.mn_ReplyPort = replyport; PutMsg(dnetport, &ior); WaitMsg(&ior); DeletePort(replyport); } return(dnetport != NULL); } /*BREAKUP dcl.bc */ DClose(chan) CHANN *chan; { IOR ior; IOR *io; ior.io_Command = DNCMD_CLOSE; ior.io_Unit = (void *)chan->chan; ior.io_Offset = (long)chan; ior.io_Message.mn_ReplyPort = (PORT *)chan; PutMsg(chan->dnetport, &ior); ++chan->queued; chan->qlen = 0; WaitQueue(chan, &ior); while ((io = RemHead(&chan->rdylist)) || (io = GetMsg(chan))) { io->io_Error = 1; ReplyMsg(io); } DeleteChannel(chan); } /*BREAKUP wq.bc */ WaitQueue(chan, skipior) CHANN *chan; IOR *skipior; { register IOR *io; short error = 0; while (chan->queued > chan->qlen) { /* until done */ WaitPort(chan); /* something */ io = (IOR *)GetMsg(chan); if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) { if (error == 0) error = io->io_Error; if (io != skipior) { if (io->io_Length) FreeMem(io->io_Data, io->io_Length); FreeMem(io, sizeof(IOR)); } --chan->queued; } else { AddTail(&chan->rdylist, io); } } return(error); } /*BREAKUP mkchan.bc */ CHANN * MakeChannel(ior, host) register IOR *ior; char *host; { CHANN *chan = AllocMem(sizeof(CHANN), MEMF_PUBLIC|MEMF_CLEAR); /* Name, Pri */ chan->port.mp_Node.ln_Type = NT_MSGPORT; chan->port.mp_SigBit = AllocSignal(-1); chan->port.mp_SigTask = FindTask(NULL); NewList(&chan->port.mp_MsgList); NewList(&chan->rdylist); chan->chan = (long)ior->io_Unit; ior->io_Offset = (long)chan; if (host) { char buf[sizeof(DNETPORTNAME)+32]; sprintf(buf, "%s%s", DNETPORTNAME, host); ior->io_Message.mn_ReplyPort = FindPort(buf); } chan->dnetport = ior->io_Message.mn_ReplyPort; return(chan); } /*BREAKUP delchan.bc */ DeleteChannel(chan) CHANN *chan; { FreeSignal(chan->port.mp_SigBit); FreeMem(chan, sizeof(CHANN)); } /*BREAKUP fixsig.bc */ FixSignal(chan) register CHANN *chan; { if (chan->port.mp_MsgList.lh_Head != (NODE *)&chan->port.mp_MsgList.lh_Tail || chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail) SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit); } /*BREAKUP getev.bc */ GetEnvVal(str) char *str; { char *ptr = GetDEnv(str); long val = 0; if (ptr) val = atoi(ptr); free(ptr); return(val); } /*BREAKUP cfg.bc */ /* * CONFIGURATION FILE EXTRACTION */ static FILE *Fi; OpenCfgFile() { CloseCfgFile(); Fi = fopen("s:dnet.config", "r"); } char * GetCfgLine(what) char *what; { static char Buf[128]; register char *ptr; if (Fi) { while (fgets(Buf, sizeof(Buf), Fi)) { if (BCmp(Buf, what, 4) == 0) { Buf[strlen(Buf)-1] = 0; for (ptr = Buf + 4; *ptr == ' ' || *ptr == 9; ++ptr); return(ptr); } } } return(NULL); } CloseCfgFile() { if (Fi) fclose(Fi); Fi = NULL; } GetOneCfg(what) char *what; { char *str; OpenCfgFile(); str = GetCfgLine(what); CloseCfgFile(); } ExtractFieldVal(str, field, pidx) char *str, *field; short *pidx; { short idx = (pidx) ? *pidx : 0; short flen = strlen(field); while (*str) { if (strncmp(str, field, flen) == 0) { if (pidx) *pidx = idx + flen; /* past the field but not the val */ return(atoi(str + flen)); } ++str; ++idx; } return(-1); } /*BREAKUP prg.bc */ char *Program = ""; /* settable by other progs */ /*BREAKUP elog.bc */ _elog(line, file, how, ctl, data) char *file; char *ctl; { static char *logfile; FILE *fi; if (logfile == NULL) { OpenCfgFile(); logfile = GetCfgLine("LOGF"); CloseCfgFile(); } if (logfile && (fi = fopen(logfile, "a"))) { char *hdr = "?"; switch(how) { case EFATAL: hdr = "Fatal"; break; case EWARN: hdr = "Warn"; break; case EDEBUG: hdr = "Debug"; break; } fprintf(fi, "%s %s.%s/%ld ", hdr, Program, file, line); fprintf(fi, ctl, data); putc('\n', fi); fclose(fi); } }