home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * SUBS.C
- *
- * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
- *
- */
-
- #include "dnet.h"
- #include <stdio.h>
- #ifdef LATTICE
- #include <dos.h>
- #endif
-
- #ifndef LATTICE
- char *FakeArgs;
- long FakeLen;
- long FakeGo;
- long FakeCLI;
-
- extern char *malloc();
- #endif
-
- void dneterror();
-
- typedef struct CommandLineInterface CLI;
-
- /*
- * Add the high-level command to the queue of commands to be sent to
- * the remote DNET.
- */
-
- void
- WriteStream(sdcmd, buf, len, chan)
- int sdcmd;
- void *buf;
- int len;
- uword chan;
- {
- IOSTD *ior = AllocMem(sizeof(IOSTD), MEMF_PUBLIC);
-
- if (DDebug)
- printf("WriteStream: cmd %ld buflen %ld chan %ld\n", sdcmd, len, chan);
- ior->io_Message.mn_Node.ln_Name = (char *)PKT_REQ;
- ior->io_Message.mn_ReplyPort = IOSink;
- ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
- ior->io_Length = len;
- ior->io_Actual = 0;
- ior->io_Command = sdcmd;
- ior->io_Error = 0;
- ior->io_Message.mn_Node.ln_Pri = (chan > MAXCHAN) ? 126 : Chan[chan].pri;
- BMov(buf, ior->io_Data, len);
- Enqueue(&TxList, (NODE *)ior);
- do_wupdate();
- }
-
- /*
- * Send a packet to a port. Used to send data/eof/close to channel
- * ports, and to relay open requests to server ports.
- */
-
- void
- WritePort(port, scmd, buf, len, rettype, unit)
- PORT *port;
- int scmd;
- void *buf;
- int len;
- int rettype;
- int unit;
- {
- IOSTD *ior = AllocMem(sizeof(IOSTD), MEMF_PUBLIC);
-
- if (DDebug)
- printf("WritePort: cmd %ld buflen %ld rt %ld unit %ld\n", scmd, len, rettype, unit);
- ior->io_Message.mn_Node.ln_Name = (char *)rettype;
- ior->io_Message.mn_ReplyPort = (rettype) ? IOSink : DNetPort;
- ior->io_Unit = (struct Unit *)unit;
- ior->io_Command = scmd;
- ior->io_Error = 0;
- ior->io_Data = NULL;
- ior->io_Length = 0;
- ior->io_Actual = 0;
- if (buf) {
- ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
- ior->io_Length = len;
- BMov(buf, ior->io_Data, len);
- }
- PutMsg(port, (MSG *)ior);
- if (rettype == PKT_REQ)
- ++NumCon;
- }
-
- /*
- * ALLOC_CHANNEL()
- *
- * Allocate a channel. Starting at a random point, find the first
- * free channel. Return -1 if no free channels found.
- */
-
- alloc_channel()
- {
- static ulong ran = 13;
- long stamp[3];
- uword i;
-
- DateStamp(stamp);
- ran = ((ran * 13) + 1) ^ (ran >> 9) + stamp[0] + stamp[1] + stamp[2];
- for (i = ran % MAXCHAN; i < MAXCHAN; ++i) {
- if (Chan[i].state == 0) {
- return((int)i);
- }
- }
- for (i = ran % MAXCHAN; i != 0xFFFF; --i) { /* Fixed 28 September 1988 */
- if (Chan[i].state == 0) {
- return((int)i);
- }
- }
- return(-1);
- }
-
- /*
- * Get next node in a linked list. If a pointer to a list base
- * is passed, gets the first node in the linked list. Returns
- * NULL if no further nodes in the list.
- */
-
- GetNext(node)
- NODE *node;
- {
- NODE *next = node->ln_Succ;
- if (*(long *)next)
- return((long)next);
- return(NULL);
- }
-
- /*
- * CHKBUF
- *
- * Generate a two-byte checksum for data. Uses a very simple, but
- * effective algorithm.
- */
-
- chkbuf(buf, bytes)
- ubyte *buf;
- uword bytes;
- {
- uword i;
- ubyte c1,c2;
-
- for (i = c1 = c2 = 0; i < bytes; ++i) {
- c1 += buf[i];
- c2 += c1;
- }
- c1 = -(c1 + c2);
- return((c1<<8)|c2);
- }
-
- void
- TimerOpen(req, sink)
- IOT *req;
- PORT *sink;
- {
- if (OpenDevice("timer.device", UNIT_VBLANK, (IOR *)req, 0))
- dneterror("timer.device");
- req->tr_node.io_Message.mn_ReplyPort = sink;
- req->tr_node.io_Command = TR_ADDREQUEST;
- }
-
- void
- TimerClose(req)
- IOT *req;
- {
- CloseDevice((IOR *)req);
- req->tr_node.io_Device = NULL;
- }
-
-
- /*
- * RUNSERVER
- *
- * Search the file [S:]DNET.SERVERS for the specified server and
- * attempt to LoadSeg()/CreateProc() it. The port number must be
- * non-zero (allows commening out lines in DNET.SERVERS), and
- * regardless of whether the server is able to DListen(), it must
- * perform a small handshake sequence with DNET.
- */
-
- #ifdef LATTICE
-
- static struct ProcID *SvBase;
-
- void
- InitServers()
- {
- SvBase = NULL;
- }
-
- void
- RunServer(portnum)
- uword portnum;
- {
- FILE *fi;
- char buf[128];
- char s1[64], s2[64];
- long v1;
-
- if (!portnum)
- return;
- if ((fi = fopen("dnet.servers", "r")) == NULL)
- fi = fopen("s:dnet.servers", "r");
- if (fi) {
- while (fgets(buf, 128, fi)) {
- if (sscanf(buf, "%ld %s %s", &v1, s1, s2) == 3 && v1 == portnum)
- goto success;
- }
- fclose(fi);
- }
- return;
- success:
- fclose(fi);
-
- {
- PROC *myproc;
- MSG msg;
- struct ProcID *pid = malloc(sizeof(struct ProcID));
- int error;
-
- BZero(pid, sizeof(*pid));
- error = forkl(s1, "__dnet", "__dnet", NULL, NULL, pid);
-
- if (error < 0) {
- printf("Server not found: %s\n", s1);
- free(pid);
- } else {
- myproc = (PROC *)FindTask(NULL);
-
- msg.mn_ReplyPort = &myproc->pr_MsgPort;
- msg.mn_Node.ln_Name = s2;
- printf("Starting Server: %s proc %08lx ", s1, pid->process);
- fflush(stdout);
- PutMsg(&pid->process->pr_MsgPort, &msg); /* startup handshake */
- WaitPort(&myproc->pr_MsgPort);
- (void)GetMsg(&myproc->pr_MsgPort);
- puts("started");
- fflush(stdout);
- pid->nextID = SvBase;
- SvBase = pid;
- }
- }
- }
-
- void
- DeleteServers()
- {
- struct ProcID *pid, *pn;
-
- for (pid = SvBase; pid; pid = pn) {
- pn = pid->nextID;
- for (;;) {
- Signal((TASK *)pid->process, SIGBREAKF_CTRL_C);
- printf("Waiting for pid %08lx to die\n", pid->process);
- if (CheckPort(pid->parent))
- break;
- Delay(10);
- }
- wait(pid);
- free(pid);
- }
- }
-
- #else
-
- static MLIST SvList;
-
- void
- InitServers()
- {
- NewList(&SvList);
- }
-
- void
- RunServer(portnum)
- uword portnum;
- {
- FILE *fi;
- char buf[128];
- char s1[64], s2[64];
- long v1;
- long seg;
-
- if (!portnum)
- return;
- if ((fi = fopen("dnet.servers", "r")) == NULL)
- fi = fopen("s:dnet.servers", "r");
- if (fi) {
- while (fgets(buf, 128, fi)) {
- if (sscanf(buf, "%ld %s %s", &v1, s1, s2) == 3 && v1 == portnum)
- goto success;
- }
- fclose(fi);
- }
- return;
- success:
- fclose(fi);
-
- if (seg = (long)LoadSeg(s1)) {
- PNODE *pnode;
- PROC *myproc;
- PROC *proc;
- char *name;
- BSTR oldclicmd;
- CLI *cli;
- char *fakestr;
-
- MSG msg;
- void fakeseg();
-
- printf("Addr: %08lx\n", seg);
-
- myproc = (PROC *)FindTask(NULL);
- pnode = AllocMem(sizeof(PNODE), MEMF_PUBLIC);
- sprintf(pnode->name, "DNET.SERVER.%ld", portnum);
- pnode->seg = seg;
-
- FakeArgs= "__dnet";
- FakeLen = 6;
- FakeGo = ((long)pnode->seg << 2) + 4;
- FakeCLI = (long)myproc->pr_CLI;
-
- printf("Addr: %08lx %08lx\n", seg, FakeGo);
-
- fakestr = malloc(32);
- strcpy(fakestr, "\006__dnet");
- cli = BTOC(FakeCLI);
- oldclicmd = cli->cli_CommandName;
- cli->cli_CommandName = CTOB(fakestr);
-
- if (proc = CreateProc(pnode->name, 0, (long)fakeseg >> 2, 4096)) {
- proc = (PROC *)((char *)proc - OFFSET(proc,pr_MsgPort));
- msg.mn_ReplyPort = &myproc->pr_MsgPort;
- msg.mn_Node.ln_Name = s2;
- printf("Starting Server: %s %s\n", s1, pnode->name);
- PutMsg(&proc->pr_MsgPort, &msg); /* startup handshake */
- WaitPort(&myproc->pr_MsgPort);
- (void)GetMsg(&myproc->pr_MsgPort);
- AddTail(&SvList, pnode);
- } else {
- printf("Unable to start server: %s %s\n", s1, pnode->name);
- FreeMem(pnode, sizeof(PNODE));
- }
- cli->cli_CommandName = oldclicmd;
- free(fakestr);
- } else {
- printf("Server not found: %s\n", s1);
- }
- }
-
- void
- DeleteServers()
- {
- PNODE *pnode;
- PROC *proc;
- while (pnode = (PNODE *)RemHead(&SvList)) {
- Forbid();
- while (proc = (PROC *)FindTask(pnode->name)) {
- Signal(proc, SIGBREAKF_CTRL_C);
- Permit();
- printf("Waiting for server %s to exit\n", pnode->name);
- Forbid();
- }
- Permit();
- UnLoadSeg(pnode->seg);
- FreeMem(pnode, sizeof(PNODE));
- }
- }
-
- #asm
-
- INCLUDE "exec/types.i"
- INCLUDE "exec/alerts.i"
- INCLUDE "exec/nodes.i"
- INCLUDE "exec/lists.i"
- INCLUDE "exec/ports.i"
- INCLUDE "exec/libraries.i"
- INCLUDE "exec/tasks.i"
-
- INCLUDE "exec/memory.i"
- INCLUDE "exec/execbase.i"
- INCLUDE "libraries/dos.i"
- INCLUDE "libraries/dosextens.i"
-
-
- public _geta4
- public _LVOFindTask
-
- nop
- nop
- nop
- nop
- _fakeseg:
- nop
- nop
- nop
- nop
-
- bsr _geta4
- move.l 4,A6
- sub.l A1,A1
- jsr _LVOFindTask(A6)
- move.l D0,A0
- move.l _FakeCLI,pr_CLI(A0) ; dummy CLI so Lattice startup doesn't
- ; croak thinking its a workbench process
- move.l _FakeArgs,A0
- move.l _FakeLen,D0
- move.l _FakeGo,A1
- jmp (A1)
-
- #endasm
-
- #endif
-
- /*
- * This cleans up as best as possible, but if there are still ACTIVE
- * servers or any CLIENTS, this call will not completely get rid of
- * them...
- *
- * Note that this call will KILL any servers automatically started up
- * by DNET and then UnLoadSeg() them. If the server has already exited,
- * it simply unloads the server's segment.
- */
-
- void
- dneterror(str)
- char *str;
- {
- short i;
- if (str)
- puts(str);
- if (DNetPort) {
- IOSTD *ior;
- Forbid();
- while ((ior = (IOSTD *)RemHead(&TxList)) || (ior = (IOSTD *)GetMsg(DNetPort))) {
- ior->io_Error = -1;
- ReplyMsg((MSG *)ior);
- }
- DeletePort(DNetPort);
- Permit();
- DNetPort = NULL;
- }
- if (Wto.tr_node.io_Device) {
- if (Wto_act) {
- AbortIO((IOR *)&Wto);
- WaitIO((IOR *)&Wto);
- Wto_act = 0;
- }
- TimerClose(&Wto);
- }
- if (Rto.tr_node.io_Device) {
- if (Rto_act) {
- AbortIO((IOR *)&Rto);
- WaitIO((IOR *)&Rto);
- Rto_act = 0;
- }
- TimerClose(&Rto);
- }
- if (Cto.tr_node.io_Device) {
- if (Cto_act) {
- AbortIO((IOR *)&Cto);
- WaitIO((IOR *)&Cto);
- Cto_act = 0;
- }
- TimerClose(&Cto);
- }
-
- NetClose();
- if (IOSink)
- DeletePort(IOSink);
- IOSink = NULL;
- for (i = 0; i < MAXCHAN; ++i) {
- if (Chan[i].state != CHAN_FREE && Chan[i].ior) {
- Chan[i].ior->io_Error = -1;
- Chan[i].state = CHAN_FREE;
- ReplyMsg((MSG *)Chan[i].ior);
- }
- }
- DeleteServers();
-
- /*
- if (IPCPort)
- CloseIPC(IPCPort);
- if (DResBase)
- CloseLibrary(DResBase);
- */
- exit(1);
- }
-
- void
- fixsignal(port)
- PORT *port;
- {
- if ((long)port->mp_MsgList.lh_Head != (long)&port->mp_MsgList.lh_Tail)
- Signal(port->mp_SigTask, 1 << port->mp_SigBit);
- }
-
- void
- SetTimeouts(baud)
- {
- WTimeoutVal = ((MAXPKT * 2) * 1000 / (baud / 10 + 1));
- RTimeoutVal = ((MAXPKT + 50) * 1000 / (baud / 10 + 1));
- WTimeoutVal *= 1000;
- RTimeoutVal *= 1000;
- }
-
-