[comp.sources.amiga] v89i174: net - network

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