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

page%swap@Sun.COM (Bob Page) (09/15/89)

Submitted-by: sas!walker@mcnc.org (Doug Walker)
Posting-number: Volume 89, Issue 176
Archive-name: devices/net.3

# 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:
#	handler/makefile
#	handler/mount.c
#	handler/netdnet.c
#	handler/process.c
#	handler/volume.c
#	iodnet.c
#	netcomm.h
#	netdev.h
#	netdnet.h
#	proto.h
#	request.c
#	sendpkt.c
#	server/device.c
#	server/dir.c
#	server/dispatch.c
#	server/file.c
# This is archive 3 of a 4-part kit.
# This archive created: Fri Sep 15 00:24:32 1989
if `test ! -d handler`
then
  mkdir handler
  echo "mkdir handler"
fi
echo "extracting handler/makefile"
sed 's/^X//' << \SHAR_EOF > handler/makefile
X
X#DEBUG  = -dDEBUG=1
XDEBUG =
X
X#LIBS   = lib:lc.lib lib:amiga.lib define _SysBase = _AbsExecBase
XLIBS   = lib:lc.lib lib:amiga.lib define _SysBase = 4
X
XLC1FLAGS = -cwusf -b -d $(DEBUG) -i/
XLC2FLAGS = -v
X
Xnetdnet-handler:  netdnet-handler.d
X   @blink from $+ to $@ nodebug
X
Xnetser-handler:  netser-handler.d
X   @blink from $+ to $@ nodebug
X
Xnetpar-handler:  netpar-handler.d
X   @blink from $+ to $@ nodebug
X
Xnetsing-handler:  netsing-handler.d
X   @blink from $+ to $@ nodebug
X
Xnetdnet-handler.d:  main.o /subs.o file.o dir.o io.o lock.o process.o\
X                  /sendpkt.o volume.o device.o /request.o mount.o devio.o\
X                  netdnet.o /iodnet.o /dnetlib.o /debug.o /timer.o
X  @echo >ram:tmp.with "from $+"
X  @assign blinkwith:
X  @blink with ram:tmp.with SC SD VERBOSE BATCH to $@ lib $(LIBS)\
X         map netdnet-handler.map hx
X  @protect $@ -e
X
Xnetsing-handler.d:  main.o /subs.o file.o dir.o io.o lock.o process.o\
X                  /sendpkt.o volume.o device.o /request.o mount.o devio.o\
X                  netsing.o iosing.o /debug.o /timer.o
X  @echo >ram:tmp.with "from $+"
X  @assign blinkwith:
X  @blink with ram:tmp.with SC SD VERBOSE BATCH to $@ lib $(LIBS)
X  @protect $@ -e
X
Xnetser-handler.d:  main.o /subs.o file.o dir.o io.o lock.o process.o \
X                 /sendpkt.o volume.o device.o /request.o mount.o devio.o\
X                 netser.o /ioser.o /debug.o /timer.o
X  @echo >ram:tmp.with "from $+"
X  @assign blinkwith:
X  @blink with ram:tmp.with SC SD VERBOSE BATCH to $@ lib $(LIBS)
X  @protect $@ -e
X
Xnetpar-handler.d:  main.o /subs.o file.o dir.o io.o lock.o process.o \
X                 /sendpkt.o volume.o device.o /request.o mount.o devio.o\
X                 netpar.o /iopar.o /debug.o /timer.o
X  @echo >ram:tmp.with "from $+"
X  @assign blinkwith:
X  @blink with ram:tmp.with SC SD VERBOSE BATCH to $@ lib $(LIBS)
X  @protect $@ -e
X
Xmain.o : main.c handler.h /netcomm.h
X @echo "Compiling $<"
X @lc1 -. $(LC1FLAGS) -oram:temp.q $<
X @lc2 -. $(LC2FLAGS) -y -o$@ ram:temp.q
X
X/dnetlib.o : /dnetlib.c
X @echo "Compiling $<"
X @lc1 -. $(LC1FLAGS) -oram:temp.q $<
X @lc2 -. $(LC2FLAGS) -y -o$@ ram:temp.qSHAR_EOF
echo "extracting handler/mount.c"
sed 's/^X//' << \SHAR_EOF > handler/mount.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery.  All Rights  */
X/* |. o.| || Reserved.  This program may not be distributed without the    */
X/* | .  | || permission of the authors:                            BBS:    */
X/* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
X/* |  . |//                                                                */
X/* ======                                                                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* Volume Manipulation */
X/* mount */
X#include "handler.h"
X
X/* Define a BCPL volume name as a default */
X#define NETNAME "\7Network"
X
Xvoid DisMount(global)
XGLOBAL global;
X{
X   struct DeviceList *volume;
X   struct DosInfo *info;
X   struct RootNode *root;
X
X   BUG(("Dismount: Entry\n"));
X
X   /* start at the root of the device list */
X   root   = (struct RootNode   *)DOSBase->dl_Root;
X   info   = (struct DosInfo    *)BADDR(root->rn_Info);
X   volume = (struct DeviceList *)BADDR(info->di_DevInfo);
X
X   /* See if we have a current volume that we have to get rid of ? */
X   /* Make sure there are no outstanding locks for the volume */
X   if ((global->volume != NULL) && (global->volume->dl_Lock == NULL))
X      {
X      /* This volume needs to be removed from the list */
X      /* First locate it on the list */
X      Forbid();
X
X      /* is it at the head of the list? */
X      if (volume == global->volume)
X         /* sure enough, just get rid of it */
X         info->di_DevInfo = volume->dl_Next;
X      else
X         {
X         /* Find it in the list */
X         while(volume != NULL &&
X            (struct DeviceList *)(BADDR(volume->dl_Next)) != global->volume)
X            volume = (struct DeviceList *)BADDR(volume->dl_Next);
X
X         /* if we found it then take it out of the chain */
X         if (volume != NULL)
X            volume->dl_Next = global->volume->dl_Next;
X         }
X      Permit();
X
X      if (global->volume)
X         {
X         DosFreeMem((char *)global->volume);
X         }
X      }
X
X   global->volume = NULL;
X}
X
Xvoid Mount(global, name)
XGLOBAL global;
Xchar *name;
X{
X   struct DeviceList *volume;
X   struct DosInfo *info;
X   struct RootNode *root;
X   short newlen; /* Cause memcmp to use the most efficient code */
X
X   BUGP("Mount: Entry")
X   BUG(("Mount: Entry\n"));
X
X   global->n.ErrorCount = 0;
X
X   if(name == NULL) name = NETNAME;
X   newlen = *name + 1;
X
X   /* Now find it on the device list. */
X   /* First start at the root of the device list */
X   root   = (struct RootNode   *)DOSBase->dl_Root;
X   info   = (struct DosInfo    *)BADDR(root->rn_Info);
X   volume = (struct DeviceList *)BADDR(info->di_DevInfo);
X
X   BUGBSTR("Volume name is : ", name);
X
X   /* Can't let the system change the list underneath us...        */
X   Forbid();
X   
X   /* Now run through the list until we come up empty OR we find it */
X   while(volume != NULL)
X      {
X      if (volume->dl_Type == DLT_VOLUME                               &&
X          !memcmp(name, (char *)BADDR(volume->dl_Name), newlen)    &&
X          volume->dl_VolumeDate.ds_Days   == 0L                       &&
X          volume->dl_VolumeDate.ds_Minute == 0L                       &&
X          volume->dl_VolumeDate.ds_Tick   == 0L)
X         break;
X      volume = (struct DeviceList *)BADDR(volume->dl_Next);
X      }
X
X   Permit();
X
X   BUG(("mount: Volume is %08lx\n", volume));
X
X   /* OK, now did we find it? */
X   if (volume != NULL)
X      {
X      BUGP("Got volume")
X      BUG(("Got a matching node\n"));
X
X      /* Sure did, We probably need to check to see if another handler has */
X      /* it to work with, but for now we assume only onw such volume can   */
X      /* exist.  This was a problem with all but the latest version of 1.2 */
X      /* If we have write access, we should probably nudge the ticks by one*/
X      /* just to make it unique                                            */
X      }
X   else
X      /* No such volume is known to the system.  So we will just have to   */
X      /* allocate a node to put everything on.                             */
X      {
X      BUGP("No volume")
X      volume = (struct DeviceList *)
X               DosAllocMem(global, sizeof(struct DeviceList)+newlen);
X
X      BUG(("Created new node at %08lx\n", volume));
X
X      /* Note that volume+1 gets us to the extra memory we allocated.  */
X      /* Just a lot simpler to write that in C than ...+sizeof(...)    */
X      MQ(name, (char *)(volume + 1), newlen);
X      volume->dl_VolumeDate.ds_Days   = 3800L;
X      volume->dl_VolumeDate.ds_Minute = 
X      volume->dl_VolumeDate.ds_Tick   = 0L;
X      volume->dl_Name = (BSTR)MKBADDR((volume + 1));
X      volume->dl_Lock = NULL;
X      volume->dl_Type = DLT_VOLUME;
X
X      /* Also we need to link it into the list */
X      Forbid();
X      volume->dl_Next = info->di_DevInfo;
X      info->di_DevInfo = MKBADDR(volume);
X      Permit();
X      }
X
X   /* Now we can own the volume by giving it our task id */
X   volume->dl_Task = global->n.port;
X   volume->dl_DiskType = ID_DOS_DISK;
X
X   /* all set up, remember what our base volume is */
X   global->volume = volume;
X
X   BUGP("Mount: Exit")
X}
X
SHAR_EOF
echo "extracting handler/netdnet.c"
sed 's/^X//' << \SHAR_EOF > handler/netdnet.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
X* |_o_o|\\ Copyright (c) 1988 The Software Distillery.  All Rights Reserved *
X* |. o.| ||          Written by Doug Walker                                 *
X* | .  | ||          The Software Distillery                                *
X* | o  | ||          235 Trillingham Lane                                   *
X* |  . |//           Cary, NC 27513                                         *
X* ======             BBS:(919)-471-6436                                     *
X\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X#include "netdnet.h"
X#include "handler.h"
X
X#ifdef CPR
Xchar *dbgwind = "CON:0/0/640/160/NETDNET-HANDLER/a";
X#endif
X
X#if 1
X
Xint ReSync(global, ioptr)
XGLOBAL global;
XAPTR ioptr;
X{
X   TermRDevice(global, 1);
X   return(InitRDevice(global));
X}
X
X#else
X
Xint ReSync(global, ioptr)
XGLOBAL global;
XAPTR ioptr;
X{
X   return(1);
X}
X
X#endif
X
Xint InitRDevice(global)
XGLOBAL global;
X{
X   struct MsgPort *chan;
X   struct NetNode *tmpnode;
X   struct RPacket RP;
X   static doinit = 1;
X
X   if(!doinit) 
X   {
X      BUG(("InitRDevice: Init loop, exiting\n"))
X      return(1);
X   }
X
X   doinit = 0;
X
X   BUG(("InitRDevice: Initializing for DNET operation on unit %d\n",
X        global->unitnum));
X
X   BUGP("InitRDevice: Entry")
X
X   if(!(chan=DOpen(NULL, (uword)(PORT_FHANDLER), 20, 15)))
X   {
X      BUG(("********ERROR: Can't DOpen!!\n"));
X      BUGR("Can't open channel!")
X   }
X   if(chan) DQueue((struct DChannel *)chan, 32);/* Is this really necessary? */
X   BUG(("DNET Channel %lx open\n", chan));
X
X   if(!global->netchain.next)
X   {
X      if(tmpnode=AddNode(global, "\3Foo", (APTR)chan))
X         strcpy(tmpnode->devname, "ROOT:");
X   }
X   else if(chan)
X   {
X      /* Preserve state of global->RP */
X       memcpy((char *)&RP, (char *)&global->RP, sizeof(struct RPacket));
X
X      for(tmpnode=global->netchain.next; tmpnode; tmpnode=tmpnode->next)
X      {
X         BUG(("ReSync: Trying to resync '%s'\n", tmpnode->devname))
X   
X         global->RP.Type = ACTION_NETWORK_KLUDGE;
X         strcpy(global->RP.Data, tmpnode->devname);
X         global->RP.DLen = strlen(global->RP.Data);
X         tmpnode->RootLock.RDevice = (RPTR)1L;
X         tmpnode->ioptr = (APTR)chan;
X         tmpnode->status = NODE_UP;
X         if(RemotePacket(global, &tmpnode->RootLock))
X         {
X            tmpnode->status = NODE_CRASHED;
X            BUG(("ReSync: Failed\n"))
X         }
X      }
X      memcpy((char *)&global->RP, (char *)&RP, sizeof(struct RPacket));
X   }
X
X
X   doinit = 1;
X
X   BUGP("InitRDevice: Exit")
X
X   return(chan != NULL);
X}
X
Xint TermRDevice(global, status)
XGLOBAL global;
Xint status;
X{
X   struct NetNode *netnode;
X
X   for(netnode=global->netchain.next; netnode; netnode=netnode->next)
X   {
X      if(netnode->ioptr)
X      {
X         netnode->status = NODE_DEAD;
X         if(!status) DClose((struct DChannel *)netnode->ioptr);
X         netnode->ioptr = NULL;
X      }
X   }
X
X   return(0);
X}
X
Xvoid ActNetHello(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X{
X}
SHAR_EOF
echo "extracting handler/process.c"
sed 's/^X//' << \SHAR_EOF > handler/process.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery.  All Rights  */
X/* |. o.| || Reserved.  This program may not be distributed without the    */
X/* | .  | || permission of the authors:                            BBS:    */
X/* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
X/* |  . |//                                                                */
X/* ======                                                                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* Process Control */
X
X/* ActDie ActInhibit ActFlush ActTimer */
X#include "handler.h"
X
Xvoid ActDie(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;              /* a pointer to the dos packet sent       */
X{
X   struct NetNode *netnode;
X   BUG(("ActDie\n"));
X   global->n.run = 0;
X   global->RP.Type = pkt->dp_Type;
X
X   for(netnode=global->netchain.next; netnode; netnode=netnode->next)
X   {
X      if(netnode->status == NODE_UP && netnode->RootLock.RDevice)
X      {
X         BUGBSTR("Shutting down node ", netnode->name);
X         RemotePacket(global, &netnode->RootLock);
X         netnode->status = NODE_DEAD;
X      }
X   }
X}
X
Xvoid ActInhibit(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;              /* a pointer to the dos packet sent       */
X{
X   BUG(("ActInhibit: %ld\n", pkt->dp_Arg1));
X   pkt->dp_Res1 = DOS_TRUE;
X   if(pkt->dp_Arg1 == 0)
X   {
X      /* Since the DISKCHANGE command uses ACTION_INHIBIT instead of */
X      /* ACTION_DISK_CHANGE, do a ACTION_DISK_CHANGE just in case    */
X      ActDiskChange(global, pkt);
X   }
X}
X
Xvoid ActFlush(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X{
X   BUG(("ActFlush\n"));
X}
X
X#if 0
Xvoid ActTimer(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;        /* a pointer to the dos packet sent */
X{
X   BUG(("ActTimer\n"));
X
X   if (global->run == -1)
X      global->run = 0;
X   else
X      PostTimerReq(global);
X
X   /* Prevent them from replying to the message */
X   global->reply = 0;
X}
X#endif
SHAR_EOF
echo "extracting handler/volume.c"
sed 's/^X//' << \SHAR_EOF > handler/volume.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery.  All Rights  */
X/* |. o.| || Reserved.  This program may not be distributed without the    */
X/* | .  | || permission of the authors:                            BBS:    */
X/* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
X/* |  . |//                                                                */
X/* ======                                                                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* Volume Manipulation */
X/* ActCurentVol  ActRenameDisk ActDiskInfo ActInfo ActDiskChange*/
X
X#include "handler.h"
X
Xstatic void GetInfo U_ARGS((GLOBAL, struct DosPacket *, struct InfoData *));
X
Xvoid ActCurentVol(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;              /* a pointer to the dos packet sent    */
X{
X   BUG(("ActCurentVol\n"));
X   pkt->dp_Res1 = MKBADDR(global->volume);
X}
X
Xvoid ActRenameDisk(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;              /* a pointer to the dos packet sent       */
X{
X   BUG(("ActRenameDisk\n"));
X
X   DisMount(global);
X   Mount(global, (char *)pkt->dp_Arg1);
X
X   pkt->dp_Res1 = DOS_TRUE;
X}
X
Xvoid GetInfo(global, pkt, info)
XGLOBAL global;
Xstruct DosPacket *pkt;
Xstruct InfoData *info;
X{
X   BUG(("GetInfo\n"));
X
X   if(global->volume == NULL)
X   {
X      info->id_DiskType = ID_NO_DISK_PRESENT;
X      pkt->dp_Res1 = DOS_FALSE;
X   }
X   else
X   {
X      info->id_NumSoftErrors = global->n.ErrorCount;
X      info->id_UnitNumber = global->unitnum;
X      if(global->upnodes>1)
X      {
X         info->id_DiskState = ID_VALIDATED;
X         info->id_DiskType  = ID_DOS_DISK;
X      }
X      else
X      {
X         info->id_DiskState = ID_VALIDATING;
X         info->id_DiskType  = ID_NO_DISK_PRESENT;
X      }
X      info->id_NumBlocks = global->numnodes;
X      info->id_NumBlocksUsed = global->upnodes;
X      info->id_VolumeNode = MKBADDR(global->volume);
X      info->id_InUse = 0;
X      pkt->dp_Res1 = DOS_TRUE;
X   }
X   BUG(("GetInfo: Exit\n"));
X}
X
Xvoid ActDiskInfo(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X{
X   BUG(("ActDiskInfo\n"));
X   GetInfo(global, pkt, (struct InfoData *)pkt->dp_Arg1);
X}
X
Xvoid ActInfo(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;              /* a pointer to the dos packet sent    */
X{
X   struct FileLock *flock;
X   NETPTR nlock;
X
X   BUG(("ActInfo\n"));
X
X   flock = (struct FileLock *)pkt->dp_Arg1;
X
X   if(flock == NULL || flock->fl_Volume != MKBADDR(global->volume) ||
X      (nlock=(NETPTR)flock->fl_Key)->RPtr == NULL)
X      GetInfo(global, pkt, (struct InfoData *)pkt->dp_Arg2);
X   else
X   {
X      /* It is a remote lock - query the remote fs */
X      global->RP.Type = pkt->dp_Type;
X      global->RP.Arg1 = (LONG)nlock->RPtr;
X      global->RP.DLen = 0;
X   
X      if(!RemotePacket(global, nlock))
X         MQ(global->RP.Data, pkt->dp_Arg2, sizeof(struct InfoData));
X   }
X}
X
Xvoid ActNetKludge(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X{
X   struct NetNode *netnode;
X   /* Arg1: BPTR to null-terminated BCPL string of name of network node */
X   /* Arg2: BPTR to null-terminated string of name of device to use     */
X
X   global->RP.Type = ACTION_NETWORK_KLUDGE;
X   strcpy(global->RP.Data, (char *)pkt->dp_Arg2);
X   global->RP.DLen = strlen((char *)pkt->dp_Arg2);
X   if(!(netnode = FindNode(global, (char *)pkt->dp_Arg1+1)) &&
X       global->netchain.next)
X   {
X      BUG(("ActNetKludge: Adding node %s len %d\n", 
X         pkt->dp_Arg1+1, (int)*((unsigned char *)pkt->dp_Arg1)));
X
X      if(netnode=AddNode(global, 
X             (char *)pkt->dp_Arg1, global->netchain.next->ioptr))
X         strcpy(netnode->devname, (char *)pkt->dp_Arg2);
X   }
X   else if(netnode->status != NODE_UP)
X      ReSync(global, netnode->ioptr);
X
X   if(!netnode || netnode->status != NODE_UP || !netnode->RootLock.RDevice)
X   {
X      BUG(("ActNetKludge: node %s netnode %08lx unavailable\n", 
X         pkt->dp_Arg1, netnode));
X      pkt->dp_Res1 = DOS_FALSE;
X      pkt->dp_Res2 = ERROR_NODE_DOWN;
X   }
X   else 
X      if(RemotePacket(global, &netnode->RootLock))
X         netnode->status = NODE_CRASHED;
X}
X
Xvoid ActDiskChange(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X{
X   BUG(("ActDiskChange\n"));
X}
SHAR_EOF
echo "extracting iodnet.c"
sed 's/^X//' << \SHAR_EOF > iodnet.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
X* |_o_o|\\ Copyright (c) 1988 The Software Distillery.  All Rights Reserved *
X* |. o.| ||          Written by Doug Walker                                 *
X* | .  | ||          The Software Distillery                                *
X* | o  | ||          235 Trillingham Lane                                   *
X* |  . |//           Cary, NC 27513                                         *
X* ======             BBS:(919)-471-6436                                     *
X\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X#define NETCOMMON
X#include "netdnet.h"
X#include "netcomm.h"
X#include "proto.h"
X
Xint PutRPacket(global, ioptr)
XNGLOBAL global;
XAPTR ioptr;
X{
X   int len;
X
X   BUG(("PutRPacket: type %d, Args %lx %lx %lx %lx\n", global->RP.Type, 
X       global->RP.Arg1, global->RP.Arg2, 
X       global->RP.Arg3, global->RP.Arg4));
X
X
XTOP:
X   BUG(("PutRPacket: writing %d to %lx. . .", RPSIZE, ioptr));
X   if((len=DWrite((struct DChannel *)ioptr,
X                   (char *)&global->RP, RPSIZE)) != RPSIZE)
X   {
X      BUG(("**********ERROR - wrote %d instead\n", len));
X      BUGR("Write error");
X      if(ReSync(global, ioptr)) return(1);
X      else goto TOP;
X   }
X   BUG(("%d written\n", len));
X
X   if(global->RP.DLen)
X   {
X      BUG(("PutRPacket: writing %d to %lx. . .", global->RP.DLen, ioptr));
X      if((len=DWrite((struct DChannel *)ioptr,
X                     global->RP.Data, global->RP.DLen)) != global->RP.DLen)
X      {
X         BUG(("**********ERROR - wrote %d instead\n", len));
X         BUGR("Write error 2");
X         if(ReSync(global, ioptr)) return(1);
X         else goto TOP;
X      }
X      BUG(("%d written\n", len));
X   }
X
X   if(global->n.infoport)
X   {
X      struct Message *m;
X      while(m=GetMsg(global->n.ntirec.m.mn_ReplyPort))
X      {
X         if(m == &global->n.ntirec.m)
X            global->n.inuse_rec = 0;
X         else
X            global->n.inuse_trans = 0;
X      }
X      global->n.inf_trans += RPSIZE + global->RP.DLen;
X         
X      if(!global->n.inuse_trans)
X      {
X         BUG(("PutRPacket: Writing status info to port %lx: TRANSMIT %ld\n", 
X            global->n.infoport, global->n.inf_trans))
X
X         global->n.ntitrans.nti_bytes = global->n.inf_trans;
X         global->n.ntitrans.nti_direction = NTI_TRANSMIT;
X         PutMsg(global->n.infoport, &global->n.ntitrans.m);
X
X         global->n.inuse_trans = 1;
X         global->n.inf_trans = 0;
X      }
X#if DEBUG
X      else
X         BUG(("PutRPacket: Skipping status write, packet outstanding\n"))
X#endif
X   }
X
X   return(0);
X}
X
Xint GetRPacket(global, ioptr)
XNGLOBAL global;
XAPTR ioptr;
X{
X   int len;
X
X   BUG(("GetRPacket: reading %d from %lx. . .", RPSIZE, ioptr));
X
XTOP:
X   if((len=DRead((struct DChannel *)ioptr, 
X                 (char *)&global->RP, RPSIZE)) != RPSIZE)
X   {
X      BUG(("**********ERROR - read %d instead\n", len));
X      BUGR("Read error")
X      if(ReSync(global, ioptr)) return(1);
X      else goto TOP;
X   }
X
X   BUG(("type %d, Args %lx %lx %lx %lx\n", global->RP.Type, 
X       global->RP.Arg1, global->RP.Arg2, 
X       global->RP.Arg3, global->RP.Arg4));
X
X   if(global->RP.DLen > 0) 
X   {
X      BUG(("Reading %d more. . .", global->RP.DLen));
X      if((len=DRead((struct DChannel *)ioptr, 
X             global->RP.Data, global->RP.DLen)) != global->RP.DLen)
X      {
X         BUG(("**********ERROR - read %d instead\n", len));
X         BUGR("Read error 2")
X         if(ReSync(global, ioptr)) return(1);
X         else goto TOP;
X      }
X   }
X   else
X      global->RP.Data[0] = '\0';
X
X   BUG(("Done\n"))
X
X   if(global->n.infoport)
X   {
X      struct Message *m;
X      while(m=GetMsg(global->n.ntirec.m.mn_ReplyPort))
X      {
X         if(m == &global->n.ntirec.m)
X            global->n.inuse_rec = 0;
X         else
X            global->n.inuse_trans = 0;
X      }
X      global->n.inf_rec += RPSIZE + global->RP.DLen;
X         
X      if(!global->n.inuse_rec)
X      {
X         BUG(("GetRPacket: Writing status info to port %lx: RECEIVE %ld\n",
X            global->n.infoport, global->n.inf_rec))
X
X         global->n.ntirec.nti_bytes = global->n.inf_rec;
X         global->n.ntirec.nti_direction = NTI_RECEIVE;
X         PutMsg(global->n.infoport, &global->n.ntirec.m);
X
X         global->n.inuse_rec = 1;
X         global->n.inf_rec = 0;
X      }
X#if DEBUG
X      else
X         BUG(("GetRPacket: Skipping status write, packet outstanding\n"))
X#endif
X   }
X
X   return(0);
X}
X
SHAR_EOF
echo "extracting netcomm.h"
sed 's/^X//' << \SHAR_EOF > netcomm.h
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1988, 1989 The Software Distillery.  All Rights  */
X/* |. o.| || Reserved.  This program may not be distributed without the    */
X/* | .  | || permission of the authors:                            BBS:    */
X/* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
X/* |  . |//                                                                */
X/* ======                                                                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X
X/* If PARANOID is defined >0, requesters will pop up for debugging */
X/* during the startup.  No need to define it unless we die before  */
X/* getting far enough to start up debugging.                       */
X
X#define PARANOID 0
X
X/* Defining CPR >0 will link in code to do a busy wait when the CPRWAIT */
X/* debug packet is received.  This allows CPR to catch the NET: task    */
X/* and lets us proceed with debugging;  if we are WAITing when CPR      */
X/* catches us, we're dead in the water.                                 */
X#define CPR 0
X
X/* Defining DEBUG >0 will link in code to print stuff to any debugging  */
X/* filehandles provided us by HANDD.  This slows us down quite a bit    */
X/* since the BUG macros all call a subroutine to print their messages   */
X/* even if we aren't debugging anything at the moment.                  */
X
X#ifdef DEBUG
X#undef DEBUG
X#endif
X
X#define DEBUG 0
X
X
X/* The NOEXT define is set by the including .c program to prevent system */
X/* include files from being reincluded here.  It is only used in dnetlib */
X#ifndef NOEXT
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#ifdef MANX
X#define U_ARGS(a) ()    /* No support for prototypes - oh well */
X#else
X#define U_ARGS(a) a     /* prototype checking to ensure all is well */
X#include <proto/exec.h>
X#include <proto/dos.h>
X#include <proto/timer.h>
X#endif
X#endif
X
X#ifndef min
X#define min(a,b) ((a)<(b)?(a):(b))
X#endif
X
X/* A macro to make good SAS Institute programmers feel at home */
X#define MQ(f,t,l) memcpy((char *)t,(char *)f,(int)l);
X
X#define MBSTR(f,t) memcpy((char *)t,(char *)f,(int)(*((char *)f))+1);
X#define BSTRLEN(s) ((int)(*((char *)(s))))
X
X#undef GLOBAL
X/* my version of BADDR() has no problems with casting */
X#undef  BADDR
X#define BADDR(x)        ((APTR)((long)x << 2))
X#define MKBADDR(x)      ((BPTR)((long)x >> 2))
X
X/* Define a few packet types that may not be in the system include files */
X
X#ifdef ACTION_END
X#undef ACTION_END
X#endif
X#ifdef ACTION_SEEK
X#undef ACTION_SEEK
X#endif
X
X#define ACTION_FIND_WRITE       1004L
X#define ACTION_FIND_INPUT       1005L /* please refer to DOS Tech. Ref. */
X#define ACTION_FIND_OUTPUT      1006L
X#define ACTION_END              1007L
X#define ACTION_SEEK             1008L
X#ifndef ACTION_MORE_CACHE
X#define ACTION_MORE_CACHE       18L
X#endif
X#ifndef ACTION_FLUSH
X#define ACTION_FLUSH            27L
X#endif
X#define ACTION_SET_FILE_DATE    34L
X#define ACTION_SET_RAW_MODE     994L
X
X/* Private packets */
X#define ACTION_HANDLER_DEBUG    2010L
X#define ACTION_SET_TRANS_TYPE   2011L
X#define ACTION_NETWORK_HELLO    2012L
X
X
X#define ACTION_NETWORK_KLUDGE   4674764L   /* Temporary until ROOT: done */
X
X
X#define ERROR_NODE_DOWN   ERROR_OBJECT_NOT_FOUND
X
X#define DOS_FALSE        0L
X#define DOS_TRUE        -1L           /* BCPL "TRUE" */
X
Xtypedef char *RPTR;    /* Pointer to remote node's memory    */
X
Xtypedef int (*fptr)();
X
X#define RNAMELEN 16    /* Max 16 byte names for remote nodes */
X
Xtypedef struct TimerPacket {
X   struct timerequest tm_req;
X   struct DosPacket   tm_pkt;
X};
X
X
X/* Define a struct to communicate with the NETSTAT program */
X#define NTI_TRANSMIT 0 
X#define NTI_RECEIVE  1
X
Xstruct NetTransInfo
X{
X   struct Message m;
X   long nti_bytes;      /* Number of bytes since last request */
X   int  nti_direction;  /* NTI_TRANSMIT or NTI_RECEIVE        */
X};
X
X/* The following defines the network buffer size.  Reads/writes larger */
X/* than this amount will be broken up into smaller chunks.             */
X/* Really should be set by querying the other side.                    */
X#define NETBUFSIZE 1024   /* Maximum amount of meaningful data to send */
X#define FILENAMELEN 120  /* Length of a filename */
X
Xstruct RPacket       /* Packet sent to remote node */
X{
X   LONG Type;          /* Type of request (AmigaDos packet type)       */
X   RPTR RDevice;       /* Pointer to remote MsgPort to send packet to  */
X   LONG Arg1,          /* Equivalent to dp_Arg? in normal devices      */
X        Arg2,          /* when transmitting, dp_Res? when receiving    */
X        Arg3,
X        Arg4;
X   long DLen;          /* Length of data in Data buffer                */
X   char Data[NETBUFSIZE]; /* Data buffer                               */
X};
X
X#define RPSIZE (sizeof(struct RPacket) - NETBUFSIZE)
X
Xstruct NetGlobal
X{
X   struct Process       *self;       /* my process                         */
X   struct MsgPort       *port;       /* our message port                   */
X   struct MsgPort       *devport;    /* msg port for device io             */
X   struct MsgPort       *infoport;   /* msg port for device status info    */
X   struct TimerPacket   *timerpkt;   /* pkt used for timer request         */
X   APTR                 devptr;      /* Device-defined                     */
X   int    run;                       /* flag to continue running           */
X   int    reply;                     /* flag to inhibit replying to message*/
X   long   ErrorCount;                /* Error count for current volume     */
X   short  histimeout;                /* Other side's timeout length        */
X   short  mytimeout;                 /* My timeout length                  */
X   char   *devname;                  /* pointer to device name             */
X   /* These are the fields of the autorequest structure we want to create  */
X   struct IntuiText line1;           /* Top Line of requester              */
X   struct IntuiText line2;           /* Second Line of requester           */
X   struct IntuiText line3;           /* Bottom Line of requester           */
X   struct IntuiText retrytxt;        /* Retry information                  */
X   struct IntuiText canceltxt;       /* CANCEL information                 */
X   char   buf3[16];                  /* Buffer to hold unit information    */
X   int    inuse_trans, inuse_rec;    /* NetTransInfo struct is in use      */
X   long   inf_trans, inf_rec;        /* Bytes trans & rec while nti in use */
X   struct NetTransInfo ntirec;       /* Send receive info to stat window   */
X   struct NetTransInfo ntitrans;     /* Send transmit info to stat window  */
X   union /* Union of driver-specific data - max one entry per driver */
X   {
X      struct MsgPort *LisPort;  /* For DNET protocol                   */
X   } d;
X};
X
Xtypedef struct
X{
X   struct NetGlobal n;
X   struct RPacket RP;
X   struct DosPacket     *pkt;        /* the packet we are processing       */
X} *NGLOBAL;
X
SHAR_EOF
echo "extracting netdev.h"
sed 's/^X//' << \SHAR_EOF > netdev.h
X
X/************************************************************************
X*                                                                       *
X*    Copyright (C) 1989, The Software Distillery.  All Rights Reserved. *
X*                                                                       *
X************************************************************************/
X
X
X
X#ifndef DEVICES_NETDEV_H
X#define DEVICES_NETDEV_H
X
X#ifndef EXEC_IO_H
X#include "exec/io.h"
X#endif !EXEC_IO_H
X
X#ifndef EXEC_DEVICES_H
X#include "exec/devices.h"
X#endif !EXEC_DEVICES_H
X
X
X
X/*
X *--------------------------------------------------------------------
X *
X * Driver Specific Commands
X *
X *--------------------------------------------------------------------
X */
X
X#define CHF_HANDLER (1<<15)              /* for internal use only! */
X#define CHF_SERVER  (1<<14)              /* for internal use only! */
X
X/*
X *--------------------------------------------------------------------
X *
X * Commands with the CHF_HANDLER bit set are only allowed on the handler
X * unit.  Reads and Writes with the handler bit set can only be
X * satisfied by Writes or Reads from the remote node with the CHF_SERVER
X * bit set.
X *
X *--------------------------------------------------------------------
X */
X#define HCH_READ         (CMD_READ|CHF_HANDLER) /* Read data from a server*/
X#define HCH_WRITE        (CMD_WRITE|CHF_HANDLER)/* Write data to a server */
X
X#define HCH_ATTACH       ((CMD_NONSTD+0)|CHF_HANDLER) /* Attach to new server */
X#define HCH_DETACH       ((CMD_NONSTD+1)|CHF_HANDLER) /* Detach from a server */
X#define HCH_STATUS       ((CMD_NONSTD+2)|CHF_HANDLER) /* Give node status     */
X#define HCH_ADDCHANGEINT ((CMD_NONSTD+3)|CHF_HANDLER) /* Install softint      */
X#define HCH_REMCHANGEINT ((CMD_NONSTD+4)|CHF_HANDLER) /* Remove softint set   */
X                                                      /*  by ADDCHANGEINT     */
X
X/*
X *--------------------------------------------------------------------
X *
X * Commands with the CHF_SERVER bit set are only allowed on the server  
X * unit.  Writes with the server bit set can only be satisfied by Reads  
X * from the node specified in the io_Offset field that have the          
X * CHF_HANDLER bit set.  Reads with the server bit set are posted with an
X * io_Offset of -1 specified, and may be satisfied by a write with the   
X * CHF_HANDLER bit set from any node.                                    
X *
X *--------------------------------------------------------------------
X */
X#define SCH_READ         (CMD_READ|CHF_SERVER)  /* Read data from a handler */
X#define SCH_WRITE        (CMD_WRITE|CHF_SERVER) /* Write data to a server */
X#define SCH_NAME         (CMD_NONSTD+5|CHF_SERVER) /* Set new name        */
X
X/*
X *--------------------------------------------------------------------
X *
X * Predefined unit numbers  :
X * Handlers open the CHU_HANDLER unit; servers open the CHU_SERVER
X * unit.  Commands with the CHF_HANDLER bit set are valid only on
X * the handler unit; commands with the CHF_SERVER bit set are valid
X * only on the server unit.
X *
X *--------------------------------------------------------------------
X */
X
X#define CHU_HANDLER -1   /* Handler unit number */
X#define CHU_SERVER  -2   /* Server unit number  */
X
X/*
X *--------------------------------------------------------------------
X *
X * Driver error defines
X *
X *--------------------------------------------------------------------
X */
X
X#define CHERR_NotSpecified  41  /* general catchall */
X#define CHERR_BadNodeID     42  /* Invalid node ID passed */
X#define CHERR_NodeDown      43  /* Specified node is down */
X#define CHERR_UnitInUse     44  /* Unit number in use */
X#define CHERR_BadRequest    45  /* IO request invalid or unknown */
X#define CHERR_IOErr         46  /* Physical I/O failure */
X#define CHERR_NameConflict  47  /* Name set request failed */
X                                        
X#endif DEVICES_COMMHAND_H
SHAR_EOF
echo "extracting netdnet.h"
sed 's/^X//' << \SHAR_EOF > netdnet.h
X#ifndef NET_DNET
X#define NET_DNET
X
X#include "dnet.h"
X
X#define STDFNLEN  0 
X
X#define PORT_FHANDLER 9492
X
X#define DNETTIMEOUT 2  /* tenths of a second */
X
X#endif
X
X
SHAR_EOF
echo "extracting proto.h"
sed 's/^X//' << \SHAR_EOF > proto.h
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery.  All Rights  */
X/* |. o.| || Reserved.  This program may not be distributed without the    */
X/* | .  | || permission of the authors:                            BBS:    */
X/* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
X/* |  . |//                                                                */
X/* ======                                                                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X#ifdef NETCOMMON
X#define GLOBAL NGLOBAL
X#endif
X
Xvoid cprwait    U_ARGS((GLOBAL));
X
X#if PARANOID
Xextern int paranoid;
X#define BUGP(x) if(paranoid) paranoid=request(global, REQ_GENERAL, x);
X#else
X#define BUGP(x)
X#endif
X
X#if CPR
X/* Debugging routines */
Xvoid myputbstr  U_ARGS((char *, ...));
Xvoid myputlstr  U_ARGS((char *, ...));
Xvoid myprintf   U_ARGS((char *, ...));
Xvoid xwrite     U_ARGS((char *, int));
Xvoid xgetcr     U_ARGS((void));
Xint sprintf     U_ARGS((char *, char *, ...));
Xvoid mydump     U_ARGS((char *, int));
XBPTR initdebug  U_ARGS((BPTR));
Xvoid termdebug  U_ARGS((void));
X
X#if DEBUG
X#define BUG(a) myprintf a;
X#define BUGBSTR(a,b) myputbstr(a,b);
X#define BUGLSTR(a,b,c) myputlstr(a,b,c);
X#define BUGGETC xgetcr();
X#define BUGTERM() termdebug();
X#define BUGR(x) request(global, REQ_GENERAL, x);
X
X#else
X
X#define BUG(a)
X#define BUGBSTR(a,b)
X#define BUGLSTR(a,b,c)
X#define BUGGETC
X#define BUGTERM()
X#define BUGR(x)
X#endif
X
X#else
X
X#define BUG(a)
X#define BUGBSTR(a,b)
X#define BUGLSTR(a,b,c)
X#define BUGGETC
X#define BUGTERM()
X#define BUGR(x)
X#endif
X
Xextern struct DosLibrary *DOSBase;
X#define alloc(a,b) DosAllocMem(a,b)
X#define free(p) DosFreeMem(p)
X
X/* io#?.c */
Xint PutRPacket  U_ARGS((GLOBAL, APTR));
Xint GetRPacket   U_ARGS((GLOBAL, APTR));
X
X/* Subs.c */
Xstruct DosPacket *taskwait     U_ARGS((GLOBAL));
Xvoid retpkt       U_ARGS((GLOBAL, struct DosPacket *));
Xchar *DosAllocMem U_ARGS((GLOBAL, long));
Xvoid DosFreeMem   U_ARGS((char *));
Xlong sendpkt U_ARGS((struct MsgPort *, long, long*, long));
XLONG checksum U_ARGS((char *, int));
Xvoid CheckRP U_ARGS((struct RPacket *));
X
X/* pause.c */
Xint Pause U_ARGS((ULONG));
X
X/* net#?.c */
Xint ReSync         U_ARGS((GLOBAL, APTR));
X
X/* timer.c */
Xint OpenTimer U_ARGS((GLOBAL, struct MsgPort *));
Xvoid CloseTimer U_ARGS((GLOBAL));
Xvoid PostTimerReq U_ARGS((GLOBAL, int));
X
X/* request.c */
Xint  request         U_ARGS((GLOBAL, int, char *));
X#define REQ_MUST    0
X#define REQ_ERROR   1
X#define REQ_GENERAL 2
SHAR_EOF
echo "extracting request.c"
sed 's/^X//' << \SHAR_EOF > request.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1988 The Software Distillery.  All Rights Reserved */
X/* |. o.| || This program may not be distributed without the permission of   */
X/* | .  | || the authors:                             BBS: (919) 481-6436    */
X/* | o  | ||   John Toebes     John Mainwaring    Jim Cooper                 */
X/* |  . |//    Bruce Drake     Gordon Keener      Dave Baker                 */
X/* ======                                                                    */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X#define NETCOMMON
X#include "netcomm.h"
X#include "proto.h"
X#include <proto/intuition.h>
X
Xint request(global, reqnum, msg)
XNGLOBAL global;
Xint reqnum;
Xchar *msg;
X{
X/* Possible requesters that we can see at this time */
X/* 1: 
X      You MUST replace volume
X       xxxxx
X      in Unit 0 !!!
X
X   2: I/O Error on volume
X       xxxxx
X      in Unit 0
X
X   ?: Unknown Error with volume
X       xxxxx
X      in Unit 0
X*/
X
X#if 0
X   if (global->volume == NULL)
X#endif
X      {
X      *(long *)&global->n.line3.LeftEdge     = 0x0004000EL;  /* 4,4  */
X      global->n.line1.NextText = &global->n.line2;
X      }
X#if 0
X   else
X      {
X      global->n.line1.NextText = &global->n.line2;
X      global->n.line2.IText = (UBYTE *)BADDR(global->volume->dl_Name)+1;
X      global->n.line2.NextText = &global->n.line3;
X      }
X#endif
X   global->n.line3.IText = (UBYTE *)&global->n.buf3;
X   *(long *)&global->n.buf3[0] = ('i'<<24)|('n'<<16)|(' '<<8)|'U';
X   *(long *)&global->n.buf3[4] = ('n'<<24)|('i'<<16)|('t'<<8)|' ';
X   *(long *)&global->n.buf3[8] = ('0'<<24)|(' '<<16)|('!'<<8)|'!';
X   /*global->n.buf3[8] += global->unitnum;*/
X   global->n.buf3[12] = 0;
X
X   switch(reqnum)
X      {
X      case REQ_MUST:
X         global->n.line1.IText = "You MUST replace volume";
X         break;
X      case REQ_ERROR:
X         global->n.line1.IText = "I/O Error on volume";
X         global->n.buf3[9] = 0;
X         break;
X      case REQ_GENERAL:
X         global->n.line1.IText = msg;
X         global->n.buf3[9] = 0;
X         break;
X      default:
X         global->n.line1.IText = "Unknown error on volume";
X         break;
X      }
X
X   /* Now we need to put up the requester */
X   if (IntuitionBase == NULL)
X      IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
X   /* We probably should check and put up an alert.. but later on that */
X
X   /* Now display the requester */
X   return(AutoRequest(NULL, &global->n.line1,
X                            &global->n.retrytxt,   &global->n.canceltxt,
X                            DISKINSERTED,        0,
X                            320,                 72));
X}
X
X
SHAR_EOF
echo "extracting sendpkt.c"
sed 's/^X//' << \SHAR_EOF > sendpkt.c
X/* From: ConPackets.c -  C. Scheppner, A. Finkel, P. Lindsay  CBM
X *   DOS packet example
X *   Requires 1.2
X * 
X */
X#include <exec/types.h>
X#include <exec/ports.h>
X#include <exec/memory.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <proto/exec.h>
X#include <proto/dos.h>
X
XLONG sendpkt(struct MsgPort *, LONG, LONG *, LONG);
X
XLONG sendpkt(pid,action,args,nargs)
Xstruct MsgPort *pid;  /* process indentifier ... (handlers message port ) */
XLONG action,          /* packet type ... (what you want handler to do )   */
X     args[],          /* a pointer to a argument list */
X     nargs;           /* number of arguments in list  */
X   {
X   struct MsgPort        *replyport;
X   struct StandardPacket *packet;
X 
X   LONG  count, *pargs, res1;
X
X   replyport = (struct MsgPort *) CreatePort(NULL,0);
X   if(!replyport) return(NULL);
X
X   packet = (struct StandardPacket *) 
X      AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
X   if(!packet) 
X      {
X      DeletePort(replyport);
X      return(NULL);
X      }
X
X   packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
X   packet->sp_Pkt.dp_Link         = &(packet->sp_Msg);
X   packet->sp_Pkt.dp_Port         = replyport;
X   packet->sp_Pkt.dp_Type         = action;
X
X   /* copy the args into the packet */
X   pargs = &(packet->sp_Pkt.dp_Arg1);       /* address of first argument */
X   for(count=0;count < nargs;count++) 
X      pargs[count]=args[count];
X 
X   PutMsg(pid,(struct Message *)packet); /* send packet */
X
X   WaitPort(replyport);
X   GetMsg(replyport); 
X
X   res1 = packet->sp_Pkt.dp_Res1;
X
X   FreeMem((char *)packet,(long)sizeof(struct StandardPacket));
X   DeletePort(replyport); 
X
X   return(res1);
X}
SHAR_EOF
if `test ! -d server`
then
  mkdir server
  echo "mkdir server"
fi
echo "extracting server/device.c"
sed 's/^X//' << \SHAR_EOF > server/device.c
X/* Device.c - Device support routines */
X
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
X#include "server.h"
X
Xint InitDevice(global)
XGLOBAL global;
X{
X   int rc;
X   struct StandardPacket *sp;
X   BUGP("InitDevice: Entry")
X   BUG(("InitDevice: Entry\n"));
X
X   if ((global->n.devport = (struct MsgPort *)CreatePort(NULL,0))==NULL)
X   {
X      BUG(("********CreatePort Failed\n"));
X      BUGR("Can't init server")
X      return(1);        /* error in createport */
X   }  
X
X   if(!(sp = global->stdpkt = (struct StandardPacket *)
X      AllocMem(sizeof(struct StandardPacket),MEMF_CLEAR)))
X   {
X      BUG(("********Couldn't allocate StandardPacket!!\n"));
X      BUGR("No memory!")
X      return(1);
X   }
X   sp->sp_Msg.mn_Node.ln_Name = (char *)(global->pkt= &(sp->sp_Pkt));
X   sp->sp_Pkt.dp_Link = &(sp->sp_Msg);
X
X   if(!(global->dosport=(struct MsgPort *)DeviceProc("ROOT:")) &&
X      !(global->dosport=(struct MsgPort *)DeviceProc("SYS:")))
X   {
X      BUG(("********DeviceProc of ROOT: and SYS: Failed\n"));
X      BUGR("No DeviceProc")
X      return(1);
X   }
X   global->RP.RDevice = (RPTR)global->dosport;
X
X   OpenTimer(global, global->n.port);
X
X   rc = InitRDevice(global);
X
X   BUGP("InitDevice: Exit")
X   return(rc);
X}
X
Xint TermDevice(global)
XGLOBAL global;
X{
X   CloseTimer(global);
X   TermRDevice(global);
X   return(1);
X}
X
Xvoid RmtDie(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X{
X   if(--global->n.run == 1) global->n.run = 0;
X}
SHAR_EOF
echo "extracting server/dir.c"
sed 's/^X//' << \SHAR_EOF > server/dir.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery.  All Rights  */
X/* |. o.| || Reserved.  This program may not be distributed without the    */
X/* | .  | || permission of the authors:                            BBS:    */
X/* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
X/* |  . |//                                                                */
X/* ======                                                                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* Directory Manipulation */
X/*  RmtCreateDir RmtExamine RmtExNext RmtParent */
X#include "server.h"
X
Xvoid RmtCreateDir(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X/* Arg1 - Lock */
X/* Arg2 - name */
X/* Arg3 (optional) Attributes */
X{
X   BUG(("RmtCreateDir\n"));
X   BUGBSTR("Creating directory '%s'\n", global->RP.Data);
X
X   pkt->dp_Arg1 = global->RP.Arg1;
X   MBSTR(global->RP.Data, global->fib);
X   pkt->dp_Arg2 = (LONG)MKBADDR(global->fib);
X   pkt->dp_Arg3 = global->RP.Arg3;
X
X   Dispatch(global);
X
X   global->RP.DLen = 0;
X}
X
Xvoid RmtExamine(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X/* Arg1: Lock of object to examine */
X/* Arg2: FileInfoBlock to fill in */
X{
X#if DEBUG
X   struct FileInfoBlock *fib;
X#endif
X   BUG(("RmtExamine/RmtExNext - lock %lx\n", global->RP.Arg1));
X
X   pkt->dp_Arg1 = global->RP.Arg1;
X   pkt->dp_Arg2 = (LONG)MKBADDR(global->fib);
X   MQ(global->RP.Data, global->fib, sizeof(struct FileInfoBlock));
X
X   Dispatch(global);
X
X#if DEBUG
X   fib = (struct FileInfoBlock *)global->fib;
X   BUG(("RmtEx: FIB name='%s' size=%ld numblocks=%ld\n", 
X      fib->fib_FileName+1, fib->fib_Size, fib->fib_NumBlocks));
X#endif
X
X   MQ(global->fib, global->RP.Data, sizeof(struct FileInfoBlock));
X
X   global->RP.DLen = sizeof(struct FileInfoBlock);
X}
X
Xvoid RmtParent(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X/* Arg1 - Lock */
X{
X   BUG(("RmtParent\n"));
X
X   pkt->dp_Arg1 = global->RP.Arg1;
X
X   Dispatch(global);
X
X   global->RP.DLen = 0;
X}
X
SHAR_EOF
echo "extracting server/dispatch.c"
sed 's/^X//' << \SHAR_EOF > server/dispatch.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
X* |_o_o|\\ Copyright (c) 1988 The Software Distillery.  All Rights Reserved *
X* |. o.| ||          Written by Doug Walker                                 *
X* | .  | ||          The Software Distillery                                *
X* | o  | ||          235 Trillingham Lane                                   *
X* |  . |//           Cary, NC 27513                                         *
X* ======             BBS:(919)-471-6436                                     *
X\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X#include "server.h"
X
Xvoid Dispatch(global)
XGLOBAL global;
X{
X   BUG(("Dispatch: Entry\n"))
X
X   /* This must be done each time - do not try to move it to InitDevice */
X   global->stdpkt->sp_Pkt.dp_Port = global->n.port;
X
X#if 1
X   if(global->RP.RDevice == NULL || global->RP.RDevice == (RPTR)1)
X      global->RP.RDevice = (RPTR)global->dosport;
X 
X   PutMsg((struct MsgPort *)global->RP.RDevice, 
X          (struct Message *)global->stdpkt);
X#else
X   PutMsg(global->dosport, (struct Message *)global->stdpkt);
X#endif
X
X   WaitPort(global->n.port);
X
X   GetMsg(global->n.port);
X
X   BUG(("Dispatch: local RC = %lx, %lx\n", 
X         global->pkt->dp_Res1, global->pkt->dp_Res2));
X   global->RP.Arg1 = global->pkt->dp_Res1;
X   global->RP.Arg2 = global->pkt->dp_Res2;
X
X   return;
X}SHAR_EOF
echo "extracting server/file.c"
sed 's/^X//' << \SHAR_EOF > server/file.c
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* |_o_o|\\ Copyright (c) 1987, 1988 The Software Distillery.  All Rights  */
X/* |. o.| || Reserved.  This program may not be distributed without the    */
X/* | .  | || permission of the authors:                            BBS:    */
X/* | o  | ||   John Toebes     Doug Walker    Dave Baker                   */
X/* |  . |//                                                                */
X/* ======                                                                  */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X/* File Manipulation  */
X/*  ActDelete ActRename ActSetProtection ActSetComment */
X#include "server.h"
X
Xvoid RmtDelete(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;              /* a pointer to the dos packet sent   */
X/* Arg1: Lock	*/
X/* Arg2: Name	*/
X{
X   BUG(("RmtDelete, lock %lx\n", global->RP.Arg1));
X   BUGBSTR("File to delete is ", global->RP.Data);
X
X   pkt->dp_Arg1 = global->RP.Arg1;
X   MBSTR(global->RP.Data, global->fib);
X   pkt->dp_Arg2 = (LONG)MKBADDR(global->fib);
X
X   Dispatch(global);
X
X   global->RP.DLen = 0;
X}
X
Xvoid RmtRename(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X/* Arg1: FromLock	*/
X/* Arg2: FromName	*/
X/* Arg3: ToLock		*/
X/* Arg4: ToName		*/
X{
X   char *name;
X   BUG(("RmtRename\n"));
X   BUGBSTR("Renaming ", global->RP.Data);
X   BUGBSTR("New Name ", global->RP.Data+FILENAMELEN);
X
X   pkt->dp_Arg1 = global->RP.Arg1;
X   MBSTR(global->RP.Data, global->fib);
X   pkt->dp_Arg2 = (LONG)MKBADDR(global->fib);
X   pkt->dp_Arg3 = global->RP.Arg3;
X   name = ((char *)global->fib)+FILENAMELEN;
X   MBSTR(global->RP.Data+FILENAMELEN, name);
X   pkt->dp_Arg4 = (LONG)MKBADDR(name);
X
X   Dispatch(global);
X
X   global->RP.DLen = 0;
X}
X
Xvoid RmtSetProtection(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X/* Arg1: Unused */
X/* Arg2: Lock */
X/* Arg3: Name */
X/* Arg4: Mask of protection */
X{
X   BUG(("RmtSetProtection\n"));
X
X   BUGBSTR("File to protect: ", global->RP.Data);
X
X   pkt->dp_Arg2 = global->RP.Arg2;
X   MBSTR(global->RP.Data, global->fib);
X   pkt->dp_Arg3 = (LONG)MKBADDR(global->fib);
X   pkt->dp_Arg4 = global->RP.Arg4;
X
X   Dispatch(global);
X
X   global->RP.DLen = 0;
X}
X
Xvoid RmtSetComment(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;              /* a pointer to the dos packet sent       */
X/* Arg1: Unused */
X/* Arg2: Lock */
X/* Arg3: Name */
X/* Arg4: Comment */
X{
X   char *comment;
X   BUG(("RmtSetComment\n"));
X
X   BUGBSTR("File to Comment: ", global->RP.Data);
X   BUGBSTR("New Comment Str: ", global->RP.Data+FILENAMELEN);
X
X   pkt->dp_Arg2 = global->RP.Arg2;
X   MBSTR(global->RP.Data, global->fib);
X   pkt->dp_Arg3 = (LONG)MKBADDR(global->fib);
X   comment = ((char *)global->fib)+FILENAMELEN;
X   MBSTR(global->RP.Data+FILENAMELEN, comment);
X   pkt->dp_Arg4 = (LONG)MKBADDR(comment);
X
X   Dispatch(global);
X
X   global->RP.DLen = 0;
X}
SHAR_EOF
echo "End of archive 3 (of 4)"
# if you want to concatenate archives, remove anything after this line
exit