page%swap@Sun.COM (Bob Page) (09/15/89)
Submitted-by: sas!walker@mcnc.org (Doug Walker) Posting-number: Volume 89, Issue 174 Archive-name: devices/net.1 This is the Lattice C source code to the Software Distillery network file system. It also serves as a good working example file system. NET: uses Matt Dillon's DNET to allow an Amiga to read and write AmigaDOS devices on another Amiga as if they were mounted locally. # This is a shell archive. # Remove anything above and including the cut line. # Then run the rest of the file through 'sh'. # Unpacked files will be owned by you and have default permissions. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: SHell ARchive # Run the following text through 'sh' to create: # channel.h # debug.c # dnet.h # dnetlib.c # doc/README # doc/dnet.servers # doc/mountlist # doc/netsource.doc # This is archive 1 of a 4-part kit. # This archive created: Fri Sep 15 00:24:29 1989 echo "extracting channel.h" sed 's/^X//' << \SHAR_EOF > channel.h X X/* X * CHANNEL.H X * X * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. X * X * Channel structures for SCMD_* channel commands. X */ X X#ifndef DNET_H Xtypedef unsigned char ubyte; Xtypedef unsigned short uword; Xtypedef unsigned long ulong; Xtypedef struct MsgPort PORT; Xtypedef struct IOStdReq IOR; X#endif X X#define CSWITCH struct _CSWITCH X#define COPEN struct _COPEN X#define CCLOSE struct _CCLOSE X#define CACKCMD struct _CACKCMD X#define CEOFCMD struct _CEOFCMD X#define CIOCTL struct _CIOCTL X XCSWITCH { /* SWITCH current data channel */ X ubyte chanh; X ubyte chanl; X}; X XCOPEN { /* OPEN port on channel */ X ubyte chanh; X ubyte chanl; X ubyte porth; X ubyte portl; X ubyte error; /* error return 0=ok */ X ubyte pri; X}; X XCCLOSE { /* CLOSE a channel */ X ubyte chanh; X ubyte chanl; X}; X XCACKCMD { /* Acknowledge an open/close */ X ubyte chanh; X ubyte chanl; X ubyte error; /* ERETRY ENOPORT ECLOSE1 ECLOSE2 */ X ubyte filler; X}; X XCEOFCMD { /* Send [R/W] EOF */ X ubyte chanh; X ubyte chanl; X ubyte flags; X ubyte filler; X}; X XCIOCTL { X ubyte chanh; /* channel */ X ubyte chanl; X ubyte cmd; /* ioctl command */ X ubyte valh; /* ioctl value */ X ubyte vall; X ubyte valaux; /* auxillary field */ X}; X X#define CIO_SETROWS 1 /* PTY's only */ X#define CIO_SETCOLS 2 /* PTY's only */ X#define CIO_STOP 3 /* any channel, flow control */ X#define CIO_START 4 /* any channel, flow control */ X#define CIO_FLUSH 5 X X#define CHAN struct _CHAN X XCHAN { X PORT *port; X IOR *ior; X ubyte state; X ubyte flags; X char pri; /* transmit priority */ X}; X SHAR_EOF echo "extracting debug.c" sed 's/^X//' << \SHAR_EOF > debug.c X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X/* |_o_o|\\ Copyright (c) 1987 The Software Distillery. All Rights Reserved */ X/* |. o.| || This program may not be distributed without the permission of */ X/* | . | || the author. BBS: */ X/* | o | || John Toebes Dave Baker (919)-471-6436 */ X/* | . |// */ X/* ====== */ X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X#define NETCOMMON X#include "netcomm.h" X#include "proto.h" X#include <ctype.h> X X#if PARANOID Xint paranoid = 1; X#endif X X#if CPR X XBPTR debuglog = NULL; Xextern char *dbgwind; Xstatic void makehex U_ARGS((char *, char *)); Xstatic void termlog U_ARGS((void)); Xstatic void xclose U_ARGS((BPTR)); Xstatic BPTR xopen U_ARGS((char *)); X XBPTR initdebug(fh) XBPTR fh; X{ X BPTR ofh; X#if DEBUG X ofh = debuglog; X if(!(debuglog = fh)) debuglog = xopen(dbgwind); X#else X ofh = NULL; X#endif X X BUG(("DEBUGGING INITIALIZED\n")); X X return(ofh); X} X Xvoid termdebug() X{ X BUG(("Closing log\n")); X BUGGETC X X if(debuglog) xclose(debuglog); X debuglog = NULL; X} X XBPTR xopen(name) Xchar *name; X{ X return(Open(name, 1006)); X} X Xvoid xclose(log) XBPTR log; X{ X long args[1]; X struct FileHandle *fh; X X if(!log) return; X X fh = (struct FileHandle *)BADDR(log); X args[0] = (long)fh->fh_Arg1; X sendpkt(fh->fh_Type,ACTION_END,args,1); X} X Xvoid xwrite(str,len) Xchar *str; Xint len; X{ X long args[3]; X struct FileHandle *fh; X X if(!debuglog) return; X X fh = (struct FileHandle *)BADDR(debuglog); X args[0] = (long)fh->fh_Arg1; X args[1] = (long)str; X args[2] = (long)len; X sendpkt(fh->fh_Type,ACTION_WRITE,args,3); X} X X#define CRMSG "Hit RETURN to continue: " X Xvoid xgetcr() X{ X long args[3]; X struct FileHandle *fh; X char stuff[10]; X X if(!debuglog) return; X X xwrite(CRMSG, strlen(CRMSG)); X fh = (struct FileHandle *)BADDR(debuglog); X args[0] = (long)fh->fh_Arg1; X args[1] = (long)stuff; X args[2] = 9L; X sendpkt(fh->fh_Type,ACTION_READ,args,3); X} X Xvoid myprintf(str,p1,p2,p3,p4,p5,p6,p7,p8,p9) Xchar *str; Xchar *p1,*p2,*p3,*p4,*p5,*p6,*p7,*p8,*p9; X{ X char buf[128]; X int len; X X if(!debuglog) return; X X len = sprintf(buf,str,p1,p2,p3,p4,p5,p6,p7,p8,p9); X if (len>128) len = 128; X xwrite(buf,len); X} X Xvoid myputbstr(str, name) Xchar *str; Xchar *name; X{ X int len; X X if(!debuglog) return; X X xwrite(str, strlen(str)); X len = *name++; X xwrite(name, len); X xwrite("\n", 1); X} X Xvoid myputlstr(str, name, len) Xchar *str; Xchar *name; Xint len; X{ X if(!debuglog) return; X X xwrite(str, strlen(str)); X xwrite(name, len); X xwrite("\n", 1); X} X Xstatic void makehex(s, h) Xchar *s; Xchar *h; X{ X int i; X static char *digits = "0123456789ABCDEF"; X X if(!debuglog) return; X X for(i=0; i<8; i+=2) X { X h[i] = digits[ (s[i/2] & 0xf0) >> 4 ]; X h[i+1] = digits[ (s[i/2] & 0x0f) ]; X } X} X Xvoid mydump(s, l) Xunsigned char *s; Xint l; X{ X int i, j; X char h[9]; X X if(!debuglog) return; X X h[8] = 0; X BUG(("Dumping %ld bytes starting at addr %08.8x\n", l, s)); X for(i=0; i<l; i+=16) X { X BUG(("%08.8lx: ", i)); X X for(j=0; j<16; j+=4) X { X makehex(&s[i+j], h); X if(i+j<l){BUG(("%8.8s ", h));} X else {BUG((" "));} X } X X for(j=0; j<16 && i+j<l; j++) X if(isprint(s[i+j])) {BUG(("%c", s[i+j]));} X else {BUG(("."));} X X BUG(("\n")); X } X} X Xvoid cprwait(global) XGLOBAL global; X{ X int i, j, oldpri; X X if(!request(global, REQ_GENERAL, "Loop for debug?")) return; X X BUG(("********* DEBUG WAIT LOOP ***********\n")) X BUG(("******* CATCH TASK WITH CPR *********\n")) X oldpri = SetTaskPri(FindTask(NULL), -20); X i=1; X X /* This loop will go until you set i to 0 with CPR */ X while(i) X { X BUG((".")) X for(j=0; X i && j<100000; X j++); X } X X SetTaskPri(FindTask(NULL), oldpri); X return; X} X#else Xvoid cprwait(global) XGLOBAL global; X{return;} X#endif CPR SHAR_EOF echo "extracting dnet.h" sed 's/^X//' << \SHAR_EOF > dnet.h X X/* X * DNET.H X * X * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. X * X */ X X#define DNET_H X X#ifdef LATTICE X#include <exec/types.h> X#include <exec/nodes.h> X#include <exec/lists.h> X#include <exec/ports.h> X#include <exec/libraries.h> X#include <exec/devices.h> X#include <exec/io.h> X#include <exec/memory.h> X#include <exec/interrupts.h> X#include <intuition/intuition.h> X#include <devices/console.h> X#include <devices/timer.h> X#include <libraries/dos.h> X#include <libraries/dosextens.h> X#include <libraries/filehandler.h> X#include <string.h> X#include <stdlib.h> X#include <proto/exec.h> X#include <proto/dos.h> X X#define U_ARGS(a) a X X#else X X#define U_ARGS(a) () /* No support for prototypes - oh well */ X X#endif X X Xtypedef unsigned char ubyte; Xtypedef unsigned short uword; Xtypedef unsigned long ulong; X Xtypedef struct MsgPort PORT; Xtypedef struct timerequest IOT; Xtypedef struct IOStdReq IOR; Xtypedef struct List LIST; Xtypedef struct Node NODE; Xtypedef struct Process PROC; Xtypedef struct Message MSG; X X#include "channel.h" X X#ifndef MAX(a,b) X#define MAX(a,b) (((a)>(b))?(a):(b)) X#endif X X#define PKT struct _PKT X#define PNODE struct _PNODE X X#define BTOC(yow) ((ubyte *)((long)(yow) << 2)) X#define DNETPORTNAME "DNET.UNIT." X#define OFFSET(ptr,elem) ((long)((char *)&(ptr)->elem - (char *)(ptr))) X X#define EMPTY 0 /* empty (sent) */ X#define READY 1 /* data ready (not sent yet) */ X X#define MAXCHAN 128 /* Max # of channels supported */ X#define SYNC 0xFF /* SYNC character */ X#define MAXPKT 200 /* maximum packet size */ X#define MINPKT 32 /* minimum maximum packet size X (for priority scheme) */ X X#define OVERHEAD 7 /* for packets with data */ X XPNODE { X NODE node; X char name[32]; X ulong seg; X}; X XPKT { X uword iolength; /* send: length of packet, recv: length of data */ X ubyte state; /* EMPTY, READY */ X X ubyte sync; /* THE PACKET */ X ubyte ctl; X ubyte cchk; X ubyte lenh; X ubyte lenl; X ubyte data[MAXPKT+2]; X}; X X/* RECEIVER STATES */ X#define RS_SYNC 0 /* Waiting for sync */ X#define RS_CTL 1 /* Waiting for command */ X#define RS_CCHK 2 /* Waiting for check byte */ X#define RS_LEN1 3 /* Waiting for MSB length byte */ X#define RS_LEN2 4 /* Waiting for LSB length byte */ X#define RS_DATA 5 /* Waiting for data & checksum */ X X#define DNCMD_OPEN 32 /* Application open */ X#define DNCMD_SOPEN 33 /* Server open */ X#define DNCMD_CLOSE 34 /* Close a channel */ X#define DNCMD_EOF 35 /* Will no longer write to channel */ X X#define DNCMD_WRITE 36 /* Write data to a channel */ X#define DNCMD_QUIT 37 /* Kill the DNET server */ X#define DNCMD_IOCTL 38 X X/* REQUEST TYPES */ X#define RTO_REQ 1 /* Network read timeout */ X#define WTO_REQ 2 /* Network write-ack timeout */ X#define RNET_REQ 3 /* Network read data */ X#define WNET_REQ 4 /* Network write data sent */ X#define PKT_REQ 5 /* Returned packets from servers */ X#define OPEN_REQ 6 X#define IGWNET_REQ 7 X X/* PACKET CONTROL BYTE */ X#define PKF_SEQUENCE 0xE0 /* Sequence # */ X#define PKF_DATA 0x10 /* 1-65535 bytes */ X#define PKF_RESERVED 0x08 /* reserved bit */ X#define PKF_MASK 0x07 /* command mask */ X X#define PKCMD_WRITE 1 /* A DATA packet */ X#define PKCMD_CHECK 2 /* Request ACK or NAK for win */ X#define PKCMD_ACK 3 /* ACK a window */ X#define PKCMD_NAK 4 /* NAK a window */ X#define PKCMD_RESTART 5 /* Restart */ X#define PKCMD_ACKRSTART 6 /* Restart Acknowledge */ X#define PKCMD_RESERVE3 7 X/* CHANNEL COMMANDS */ X#define SCMD_SWITCH 0x00 /* switch active channel # */ X#define SCMD_OPEN 0x01 /* open a channel */ X#define SCMD_CLOSE 0x02 /* close a channel */ X#define SCMD_ACKCMD 0x03 /* ack an open/close request */ X#define SCMD_EOFCMD 0x04 /* Reof or Weof */ X#define SCMD_QUIT 0x05 /* crash dnet */ X#define SCMD_IOCTL 0x06 /* ioctl */ X X#define SCMD_DATA 0x08 /* stream command, DATA */ X X#define CHAN_FREE 0x01 /* free channel */ X#define CHAN_ROPEN 0x02 /* remote open, wait port msg */ X#define CHAN_LOPEN 0x03 /* local open, wait reply */ X#define CHAN_OPEN 0x04 X#define CHAN_CLOSE 0x05 /* see flags */ X#define CHANF_ROK 0x01 /* NOT read eof */ X#define CHANF_WOK 0x02 /* remote will accept data */ X#define CHANF_LCLOSE 0x04 X#define CHANF_RCLOSE 0x08 X Xstruct DChannel { X PORT port; /* receive data, replies */ X PORT *dnetport; /* dnet's master port */ X LIST rdylist; /* ready to be read */ X uword chan; /* channel # for open channels */ X ubyte eof; /* channel remotely closed/eof */ X ubyte filler; X int qlen; /* allowed write queue size */ X int queued; /* current # packets queued */ X}; X Xextern void *ArbitrateNext(); X X#ifndef NOEXT Xextern IOT Rto; /* Read-Timeout/reset */ Xextern IOT Wto; /* Write-Timeout/retry */ Xextern IOR *RNet; /* read-request */ Xextern IOR *WNet; /* write-request */ Xextern PKT Pkts[9]; Xextern PKT *Raux; /* next packet in */ Xextern PKT *RPak[4]; Xextern PKT *WPak[4]; Xextern PORT *DNetPort; /* Remote Command/Control in */ Xextern PORT *IOSink; /* Return port for ALL IO */ Xextern CHAN Chan[MAXCHAN]; Xextern LIST TxList; /* For pending DNCMD_WRITE reqs. */ Xextern LIST SvList; Xextern ubyte Rto_act; Xextern ubyte Wto_act; Xextern uword RChan; Xextern uword WChan; Xextern uword RPStart; Xextern uword WPStart; Xextern uword WPUsed; Xextern uword RState; Xextern ubyte DDebug; Xextern ubyte Restart; Xextern ubyte DeldQuit; Xextern ubyte AutoHangup; Xextern ulong NumCon; Xextern ulong WTimeoutVal; Xextern ulong RTimeoutVal; Xextern long Baud; Xextern char *HostName; /* The Amiga's HostName */ X Xextern ubyte RestartPkt[3]; Xextern ubyte AckPkt[8][3]; Xextern ubyte NakPkt[8][3]; Xextern ubyte CheckPkt[8][3]; X#endif X X#ifdef LATTICE X/* One #ifdef LATTICE is worth 1000 U_ARGS macros! */ XPORT *DListen(uword); Xvoid DUnListen(PORT *); XPORT *DAccept(PORT *); XDNAAccept(PORT *); Xvoid DPri(struct DChannel *, int); XPORT *DOpen(char * /*host*/, uword /*portnum*/, X char /*txpri*/, char /*rxpri*/); Xint DNRead(struct DChannel *, char *, int); Xint DRead(struct DChannel *, char *, int); Xvoid DQueue(struct DChannel *, int); XDWrite(struct DChannel *, char *, int); Xvoid DEof(struct DChannel *); Xvoid DIoctl(struct DChannel *, ubyte, uword, ubyte); Xint DQuit(char *); Xvoid DClose(struct DChannel *); Xvoid WaitMsg(IOR *); Xint WaitQueue(struct DChannel *, IOR *); X X#endif X SHAR_EOF echo "extracting dnetlib.c" sed 's/^X//' << \SHAR_EOF > dnetlib.c X/* X * DNETLIB.C X * X * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. X * X * Library Interface for DNET. X */ X X#define NOEXT X#define NETCOMMON X#include "dnet.h" X#include "netcomm.h" X#include "proto.h" X Xstatic struct DChannel *MakeChannel U_ARGS((IOR *, char *)); Xstatic void DeleteChannel U_ARGS((struct DChannel *)); Xstatic void FixSignal U_ARGS((struct DChannel *)); X X#define NAMELEN sizeof("DNET.PORT.XXXXX") X#define NAMEPAT "DNET.PORT.%ld" X XPORT *DListen(portnum) Xuword portnum; X{ X PORT *port; X char *ptr; X X port = NULL; X ptr = AllocMem(NAMELEN, MEMF_PUBLIC); /* memory the the name */ X sprintf(ptr, NAMEPAT, portnum); X Forbid(); /* task-atomic operation */ X if (FindPort(ptr) || !(port = CreatePort(ptr,0))) X FreeMem(ptr, NAMELEN); X Permit(); X return(port); X} X Xvoid XDUnListen(lisport) XPORT *lisport; X{ X register char *ptr; X ptr = lisport->mp_Node.ln_Name; X X if (lisport) X { X Forbid(); /* task-atomic operation */ X while (DNAAccept(lisport)); /* remove all pending requests */ X DeletePort(lisport); /* gone! */ X Permit(); X FreeMem(ptr, NAMELEN); X } X} X X/* X * DAccept() X * X * Note: This call will work even if called by a task which does not X * own the listen port. X */ X XPORT * XDAccept(lisport) XPORT *lisport; X{ X register IOR *ior; X register struct DChannel * chan; X XBUG(("DAccept: Entry, port %lx\n", lisport)) X X chan = NULL; X while (!chan && (ior = (IOR *)GetMsg(lisport))) { X switch(ior->io_Command) { X case DNCMD_SOPEN: X BUG(("DAccept: SOPEN command\n")) X chan = MakeChannel(ior, NULL); X break; X default: X BUG(("DAccept: Unrecognized command '%d'\n", ior->io_Command)) X ior->io_Error = 1; X break; X } X BUG(("DAccept: Replying\n")) X ReplyMsg(&ior->io_Message); X } X BUG(("DAccept: After while loop\n")) X if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail) X SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit); X X return(chan ? &chan->port : NULL); X} X X/* X * Refuse a connection X */ X XDNAAccept(lisport) XPORT *lisport; X{ X IOR *ior; X X if (ior = (IOR *)GetMsg(lisport)) { X ior->io_Error = 1; X ReplyMsg(&ior->io_Message); X } X if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail) X SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit); X return(ior != NULL); X} X Xvoid DPri(chan, pri) Xstruct DChannel * chan; Xint pri; X{ X} X X XPORT * XDOpen(host, portnum, txpri, rxpri) Xchar *host; Xchar txpri, rxpri; Xuword portnum; X{ X IOR ior; X struct DChannel *chan; X X if (!host) X host = "0"; X chan = MakeChannel(&ior, host); X if (rxpri > 126) X rxpri = 126; X if (rxpri < -127) X rxpri = -127; X if (txpri > 126) X txpri = 126; X if (txpri < -127) X txpri = -127; X if (chan->dnetport) { X ior.io_Command = DNCMD_OPEN; X ior.io_Unit = (void *)portnum; X ior.io_Offset = (long)chan; X ior.io_Message.mn_ReplyPort = &chan->port; X ior.io_Message.mn_Node.ln_Pri = txpri; X ior.io_Message.mn_Node.ln_Name= (char *)rxpri; X X PutMsg(chan->dnetport, &ior.io_Message); X WaitMsg(&ior); X if (ior.io_Error == 0) { X chan->chan = (long)ior.io_Unit; X FixSignal(chan); X return(&chan->port); X } X } X DeleteChannel(chan); X return(NULL); X} X X XDNRead(chan, buf, bytes) Xstruct DChannel * chan; Xchar *buf; Xint bytes; X{ X register IOR *ior; X int len; X long n; X X len = 0; X if (chan->eof) X return(-1); X while (bytes && ((ior = (IOR *) X RemHead((struct List *)&chan->rdylist)) || X (ior = (IOR *)GetMsg(&chan->port)))) { X if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) X { X if (!chan->queued) X { X BUG(("DNRead: Software Error")); X } X else X --chan->queued; X if (ior->io_Length) X FreeMem((char *)ior->io_Data, (long)ior->io_Length); X FreeMem((char *)ior, (long)sizeof(IOR)); X continue; X } X switch(ior->io_Command) X { X case DNCMD_CLOSE: X case DNCMD_EOF: X chan->eof = 1; X ReplyMsg(&ior->io_Message); X break; X X case DNCMD_WRITE: X n = ior->io_Length - ior->io_Actual; X if (n <= bytes) X { X memcpy(buf, ((char *)ior->io_Data) + ior->io_Actual, n); X bytes -= n; X len += n; X buf += n; X ReplyMsg(&ior->io_Message); X } X else X { X memcpy(buf, (char *)ior->io_Data + ior->io_Actual, bytes); X len += bytes; X ior->io_Actual += bytes; X bytes = 0; X Forbid(); /* DNET device is a task, no need to Disable() */ X ior->io_Message.mn_Node.ln_Type = NT_MESSAGE; X AddHead(&chan->port.mp_MsgList, (struct Node *)ior); X Permit(); X } X break; X default: X ior->io_Error = 1; X ReplyMsg(&ior->io_Message); X } X } X FixSignal(chan); X if (chan->eof) X SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit); X return(len); X} X Xint DRead(chan, buf, bytes) Xchar *buf; Xstruct DChannel * chan; Xint bytes; X{ X long len; X long n; X X len = 0; X if (chan->eof) X { X BUG(("****DNET EOF!!!\n")); X return(-1); X } X X while (bytes) X { X WaitPort(&chan->port); X n = DNRead(chan, buf, bytes); X len += n; X if (n < 0) break; X buf += n; X bytes -= n; X if (chan->eof) break; X } X return(len); X} X Xvoid DQueue(chan, n) Xstruct DChannel * chan; Xint n; X{ X chan->qlen = n; X} X XDWrite(chan, buf, bytes) Xstruct DChannel * chan; Xchar *buf; Xint bytes; X{ X IOR tmpior; X IOR *ior; X int error; X X error = bytes; X if (chan->qlen) X { X if (WaitQueue(chan, NULL) >= 0) X { X ior = (IOR *)AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC); X ior->io_Command = DNCMD_WRITE; X ior->io_Unit = (void *)chan->chan; X ior->io_Offset = (long)chan; X ior->io_Message.mn_ReplyPort = &chan->port; X ior->io_Data = (APTR)AllocMem(bytes, MEMF_PUBLIC); X ior->io_Length = bytes; X memcpy((char *)ior->io_Data, buf, (int)bytes); X PutMsg(chan->dnetport, &ior->io_Message); X ++chan->queued; X } X else X { X error = -1; X } X } X else X { X tmpior.io_Command = DNCMD_WRITE; X tmpior.io_Unit = (void *)chan->chan; X tmpior.io_Offset = (long)chan; X tmpior.io_Message.mn_ReplyPort = &chan->port; X tmpior.io_Data = (APTR)buf; X tmpior.io_Length = bytes; X PutMsg(chan->dnetport, &tmpior.io_Message); X WaitMsg(&tmpior); X if (tmpior.io_Error) X { X error = -1; X BUG(("*****DWrite: io_Error %d\n", tmpior.io_Error)); X BUGGETC X } X } X FixSignal(chan); X return(error); X} X Xvoid DEof(chan) Xstruct DChannel * chan; X{ X IOR ior; X X ior.io_Command = DNCMD_EOF; X ior.io_Unit = (void *)chan->chan; X ior.io_Offset = (long)chan; X ior.io_Message.mn_ReplyPort = &chan->port; X PutMsg(chan->dnetport, &ior.io_Message); X WaitMsg(&ior); X FixSignal(chan); X} X Xvoid DIoctl(chan, cmd, val, aux) Xstruct DChannel * chan; Xubyte cmd; Xuword val; Xubyte aux; X{ X IOR ior; X X ior.io_Command = DNCMD_IOCTL; X ior.io_Unit = (void *)chan->chan; X ior.io_Offset = (long)chan; X ior.io_Message.mn_ReplyPort = &chan->port; X ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd); X PutMsg(chan->dnetport, &ior.io_Message); X WaitMsg(&ior); X FixSignal(chan); X} X Xint DQuit(host) Xchar *host; X{ X IOR ior; X char buf[sizeof(DNETPORTNAME)+32]; X PORT *replyport; X PORT *dnetport; X X if (!host) X host = "0"; X sprintf(buf, "%s%s", DNETPORTNAME, host); X if (dnetport = FindPort(buf)) { X replyport = CreatePort(NULL, 0); X ior.io_Command = DNCMD_QUIT; X ior.io_Unit = 0; X ior.io_Offset = 0; X ior.io_Message.mn_ReplyPort = replyport; X PutMsg(dnetport, &ior.io_Message); X WaitMsg(&ior); X DeletePort(replyport); X } X return(dnetport != NULL); X} X X Xvoid DClose(chan) Xstruct DChannel * chan; X{ X IOR ior; X IOR *io; X XBUG(("DClose: Enter\n")) X X ior.io_Command = DNCMD_CLOSE; X ior.io_Unit = (void *)chan->chan; X ior.io_Offset = (long)chan; X ior.io_Message.mn_ReplyPort = &chan->port; X PutMsg(chan->dnetport, &ior.io_Message); X ++chan->queued; X chan->qlen = 0; X WaitQueue(chan, &ior); X while ((io = (IOR *)RemHead((struct List *)&chan->rdylist)) || X (io = (IOR *)GetMsg(&chan->port))) { X io->io_Error = 1; X ReplyMsg(&io->io_Message); X } X DeleteChannel(chan); X} X Xvoid WaitMsg(ior) XIOR *ior; X{ X while (ior->io_Message.mn_Node.ln_Type != NT_REPLYMSG) X Wait(1 << ior->io_Message.mn_ReplyPort->mp_SigBit); X Forbid(); X Remove((struct Node *)ior); X Permit(); X} X Xint WaitQueue(chan, skipior) Xstruct DChannel * chan; XIOR *skipior; X{ X register IOR *io; X short error; X X error = 0; X while (chan->queued > chan->qlen) { /* until done */ X WaitPort(&chan->port); /* something */ X io = (IOR *)GetMsg(&chan->port); X if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) { X if (error == 0) X error = io->io_Error; X if (io != skipior) { X if (io->io_Length) X FreeMem((char *)io->io_Data, io->io_Length); X FreeMem((char *)io, sizeof(IOR)); X } X --chan->queued; X } else { X AddTail(&chan->rdylist, (struct Node *)io); X } X } X return(error); X} X Xstatic struct DChannel *MakeChannel(ior, host) Xregister IOR *ior; Xchar *host; X{ X struct DChannel * chan; X char buf[sizeof(DNETPORTNAME)+32]; X XBUG(("MakeChannel: Entry\n")) X X chan = (struct DChannel *)AllocMem(sizeof(struct DChannel), X MEMF_PUBLIC|MEMF_CLEAR); X X /* Name, Pri */ X chan->port.mp_Node.ln_Type = NT_MSGPORT; X chan->port.mp_SigBit = AllocSignal(-1); X chan->port.mp_SigTask = FindTask(NULL); X NewList(&chan->port.mp_MsgList); X NewList(&chan->rdylist); X chan->chan = (long)ior->io_Unit; X ior->io_Offset = (long)chan; X if (host) { X sprintf(buf, "%s%s", DNETPORTNAME, host); X ior->io_Message.mn_ReplyPort = FindPort(buf); X } X chan->dnetport = ior->io_Message.mn_ReplyPort; X return(chan); X} X Xstatic void XDeleteChannel(chan) Xstruct DChannel * chan; X{ X FreeSignal(chan->port.mp_SigBit); X FreeMem((char *)chan, (long)sizeof(struct DChannel)); X} X Xstatic void XFixSignal(chan) Xregister struct DChannel * chan; X{ X if (chan->port.mp_MsgList.lh_Head != X (NODE *)&chan->port.mp_MsgList.lh_Tail || X chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail) X SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit); X} X SHAR_EOF if `test ! -d doc` then mkdir doc echo "mkdir doc" fi echo "extracting doc/README" sed 's/^X//' << \SHAR_EOF > doc/README X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ X* |_o_o|\\ Copyright (c) 1989 The Software Distillery. * X* |. o.| || All Rights Reserved * X* | . | || Written by John Toebes and Doug Walker * X* | o | || The Software Distillery * X* | . |// 235 Trillingham Lane * X* ====== Cary, NC 27513 * X* BBS:(919)-471-6436 * X\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X XThis material is Copyright (C) 1988 and 1989 The Software Distillery. XIt may be distributed freely as long as the following restrictions are met: X X 1. All files present in the distribution package must be redistributed X with the package, including this documentation file. If you X distribute on diskette, all files must be on a single diskette. X A list of files in this distribution is at the end of this file. X X 2. The distributor may charge a fee to recover distribution costs. X The fee for diskette distribution should not be more than the cost X to obtain the same diskette from Fred Fish or The Software Distillery, X whichever is greater. Current charge from The Software Distillery X is $6 per disk in the United States and Canada, $7 outside, including X all postage and handling charges. X X 3. The distributor agrees to cease distributing the programs and data X involved if requested to do so by authors or any member of The X Software Distillery. X X------------------------------DISCLAIMER X XNeither The Software Distillery nor any of its members will be liable for Xany damage arising from the failure of this program to perform as described, Xor any destruction of other programs or data residing on a system Xattempting to run the program. While we know of no damaging errors, the Xuser of this program uses it at his or her own risk. X X-----------------------------FUNCTIONALITY X XThe network handler in this distribution relies on DNET for communication, Xbut all dependencies on DNET are isolated. The intent is for a future Xrelease to support ANY COMMUNICATIONS METHOD, including serial, parallel, XAppleTalk, DecNET, NFS, you name it, all simultaneously via external Xcommunications servers. X X X============================================================================ X XRUNNING THE NETWORK HANDLER: X XThese instructions talk about a 'local' machine and a 'remote' machine. XThe network is symmetric, so for DNET at least, you can do the Xinstallation on both sides. Just install all files on both machines, Xand perform all commands on both machines. X X1. Install DNET on both machines. Add an entry to the dnet.servers X file on the remote machine for the network server. A sample X dnet.servers file is included in this distribution in the file X "dnet.servers". Note the server number for the network is 9492. You X will need to change the pathname specified in the sample dnet.servers X file to reflect the path you intend to use. X X2. Copy netdnet-server to the path specified in the dnet.servers file on X the remote machine. X X3. Put a mountlist entry for the network handler in the local machine's X DEVS:MOUNTLIST. A sample mountlist entry is included in this X distribution in the file "mountlist". If you do not want the network X handler in l:, replace the specified path with one of your own. X X4. Copy netdnet-handler to the path specified in the mountlist on the X local machine. X X5. Issue the CLI command "ASSIGN ROOT: <path>" on the remote machine. The X network handler mounts the ROOT: device on the remote node as a network X node on the local node; the place you point ROOT: to is where your X files will go. X X6. Copy the file NODE.INFO from the distribution disk to ROOT:. This file X contains the .info information for the remote node that will be X displayed on the workbench screen of the local node. Feel free to X replace it with any DRAWER type .info file. X X7. Issue the CLI command "MOUNT NET:" on the local node. The first X reference to NET: after the MOUNT command will load the handler. DNET X will load the server on the remote node automatically. X X8. If you want a two-way network, repeat steps 1-7, but this time switch X your idea of which node is 'local' and which is 'remote'. X X============================================================================ X XOnce the NET: device is running, you can use the provided NETMOUNT command Xto allow access to other devices besides ROOT: on the remote machine. XNETMOUNT is a temporary stopgap until a real ROOT: device is implemented Xthat allows access to all devices on a machine via a single handler. X XFor now, the NETMOUNT command format is X XNETMOUNT <local device> <node name> <remote device> X Xwhere <local device> is the name you MOUNTed (usually NET:) X <node name> is the name you want to refer to the new entry as X <remote device> is the name of the device on the remote node to use X XFor example, X XNETMOUNT NET: DF0 DF0: X Xwould allow you to access the floppy on the remote node by using the path XNET:DF0. Thus, X XDIR NET:DF0 X Xwould produce the same results as doing a DIR DF0: on the remote machine. X X============================================================================ X XThe provided NETSTAT command gives you a visual idea of how much work your Xnetwork is doing. Run it with the command X XRUN NETSTAT <devicename> X Xwhere <devicename> is the name of your network device (probably NET:). XClick on the close gadget in the upper left corner to exit. X X============================================================================ X XDifferences and enhancements: X XVERSION 05/09/89: X First version released X XVERSION 07/18/89: X X- Speed improved due to decreasing minimum packet size X Should help when loading executables over the network and when doing X directory operations. X X- Debugging code removed X This makes the code smaller and faster X X- Bug fixed in the ACTION_CREATE_DIR packet X X============================================================================ X XCONTENTS: This distribution should contain the following files: X X server (dir) X device.c dir.c X dispatch.c file.c X io.c lock.c X main.c makefile X netdnet-server netdnet.c X server.h struct.h X volume.c X handler (dir) X device.c devio.c X dir.c file.c X handler.h io.c X lock.c main.c X makefile mount.c X netdnet-handler netdnet.c X process.c volume.c X doc (dir) X dnet.servers mountlist X netsource.doc README X util (dir) X handd handd.c X netmount netmount.c X netstat netstat.c X netstat.h netstat.lnk X shutdown shutdown.c X channel.h debug.c X dnet.h dnetlib.c X iodnet.c netcomm.h X netdev.h netdnet.h X proto.h request.c X sendpkt.c subs.c X timer.c SHAR_EOF echo "extracting doc/dnet.servers" sed 's/^X//' << \SHAR_EOF > doc/dnet.servers X X8192 sys:dnet/scopy ram: ;File Transfer server X8195 sys:dnet/sterm ram: ;Terminal Window server X8196 sys:dnet/scli ram: ;Shell Server (needs pipe:) X8197 sys:dnet/sloadav ram: ;Load Average Server X9492 sys:dnet/netdnet-server ram: ;File-handler Server X SHAR_EOF echo "extracting doc/mountlist" sed 's/^X//' << \SHAR_EOF > doc/mountlist X XNET: Stacksize = 8000 X Priority = 5 X GlobVec = -1 X Unit = 0 X Handler = l:netdnet-handler X# SHAR_EOF echo "extracting doc/netsource.doc" sed 's/^X//' << \SHAR_EOF > doc/netsource.doc X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ X* |_o_o|\\ Copyright (c) 1989 The Software Distillery. * X* |. o.| || All Rights Reserved * X* | . | || Written by John Toebes and Doug Walker * X* | o | || The Software Distillery * X* | . |// 235 Trillingham Lane * X* ====== Cary, NC 27513 * X* BBS:(919)-471-6436 * X\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ X XSOFTWARE DISTILLERY NETWORK FILE SYSTEM, VERSION 1.0 X XThis material is Copyright (C) 1988 and 1989 The Software Distillery. X X------------------------------DISCLAIMER X XNeither The Software Distillery nor any of its members will be liable for Xany damage arising from the failure of this program to perform as described, Xor any destruction of other programs or data residing on a system Xattempting to run the program. While we know of no damaging errors, the Xuser of this program uses it at his or her own risk. X X-----------------------------FUNCTIONALITY X XThe network handler in this distribution relies on DNET for communication, Xbut all dependancies on DNET are isolated. The intent is for a future Xrelease to support ANY COMMUNICATIONS METHOD, including serial, parallel, XAppleTalk, DecNET, NFS, you name it, all simultaneously via external Xcommunications servers. X X============================================================================ X XSETTING UP THE SOURCE DIRECTORY X XIf you received this software as a ZOO archive, you should use the Xx// option to de-archive it into its original directory structure. XIf you didn't, delete the files produced and start over with X X ZOO x// netsrc1.zoo X XYou should de-zoo the archive into its own directory, since there are Xmany files in the root of the directory structure. X X============================================================================ X XRUNNING THE NETWORK HANDLER: X XThese instructions talk about a 'local' machine and a 'remote' machine. XThe network is symmetrical, so for DNET at least, you can do the Xinstallation on both sides. Just install all files on both machines, Xand perform all commands on both machines. X X1. Install DNET on both machines. Add an entry to the dnet.servers X file on the remote machine for the network server. A sample X dnet.servers file is included in this distribution in the file X "dnet.servers". Note the server number for the network is 9492. You X will need to change the pathname specified in the sample dnet.servers X file to reflect the path you intend to use. X X2. Copy netdnet-server to the path specified in the dnet.servers file on X the remote machine. X X3. Put a mountlist entry for the network handler in the local machine's X DEVS:MOUNTLIST. A sample mountlist entry is included in this X distribution in the file "mountlist". If you do not want the network X handler in l:, replace the specified path with one of your own. X X4. Copy netdnet-handler from the HANDLER subdirectory to the path specified X in the mountlist on the local machine. X X5. Issue the CLI command "ASSIGN ROOT: <path>" on the remote machine. The X network handler mounts the ROOT: device on the remote node as a network X node on the local node; the place you point ROOT: to is where your X files will go. Copy the file NODE.INFO from the distribution disk X to ROOT:. This file contains the .info information for the remote node X that will be displayed on the workbench screen of the local node. Feel X free to replace it with any DRAWER type .info file. X X6. Issue the CLI command "MOUNT NET:" on the local node. The first X reference to NET: after the MOUNT command will load the handler. DNET X will load the server on the remote node automatically. X X============================================================================ X XOnce the NET: device is running, you can use the provided NETMOUNT command Xto allow access to other devices besides ROOT: on the remote machine. XNETMOUNT is a temporary stopgap until a real ROOT: device is implemented Xthat allows access to all devices on a machine via a single handler. X XFor now, the NETMOUNT command format is X XNETMOUNT <local device> <node name> <remote device> X Xwhere <local device> is the name you MOUNTed (usually NET:) X <node name> is the name you want to refer to the new entry as X <remote device> is the name of the device on the remote node to use X XFor example, X XNETMOUNT NET: DF0 DF0: X Xwould allow you to access the floppy on the remote node by using the path XNET:DF0. Thus, X XDIR NET:DF0 X Xwould produce the same results as doing a DIR DF0: on the remote machine. X X X============================================================================ X XThis version of NET: is dependent on DNET. However, all DNET-specific calls Xare isolated in the files iodnet.c, handler/netdnet.c and server/netdnet.c. XFunctions in these files refer to functions in dnetlib.c; dnetlib.c is Xpart of Matt Dillon's DNET distribution and will not be required if you Xreplace the functions in the three previously named files. X XThe source directory contains all .c and .h files common to both the handler Xand the server ends of the network file system. Handler-specific code Xresides in the 'handler' subdirectory; server-specific code resides in the X'server' subdirectory; and utilities such as the 'handd' debugging tool, Xthe 'netstat' tool to give statistics, the 'shutdown' command to kill the Xnetwork, and so forth reside in the 'utilities' subdirectory. X X XContact us with any problems: X XPLINK: DWALKER, JTOEBES XBIX: DJWALKER, JTOEBES XUSENET: ...mcnc!rti!sas!walker, ...mcnc!rti!sas!toebes X (Usenet connection is flakey) XUS MAIL: X Doug Walker X 405 B3 Gooseneck Dr X Cary, NC 27513 X USA X X John Toebes X 235 Trillingham Lane X Cary, NC 27513 X USA SHAR_EOF echo "End of archive 1 (of 4)" # if you want to concatenate archives, remove anything after this line exit