page%swap@Sun.COM (Bob Page) (09/15/89)
Submitted-by: sas!walker@mcnc.org (Doug Walker)
Posting-number: Volume 89, Issue 175
Archive-name: devices/net.2
# 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/device.c
# handler/devio.c
# handler/dir.c
# handler/file.c
# handler/handler.h
# handler/io.c
# handler/lock.c
# handler/main.c
# This is archive 2 of a 4-part kit.
# This archive created: Fri Sep 15 00:24:30 1989
if `test ! -d handler`
then
mkdir handler
echo "mkdir handler"
fi
echo "extracting handler/device.c"
sed 's/^X//' << \SHAR_EOF > handler/device.c
X/* Device.c - Device support routines */
X
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#include "handler.h"
X
X#define MYNAME "\7NETWORK"
X
Xtypedef struct FileSysStartupMsg *FSSM;
X
Xint GetDevice (global, myfssmsg)
XGLOBAL global;
XFSSM myfssmsg;
X{
XFSSM fssmsg;
Xint devnum;
Xchar *defaultdev = "serial.device";
X
XBUGP("GetDevice entry")
X
X BUG(("devname:%s\n",global->n.devname));
X BUG(("Global->node = %08lx Global->node->dn_Startup = %08lx\n",
X global->node, BADDR(global->node->dn_Startup)));
X
X /* Did they give us any information in the device list ? */
X if( (fssmsg = (FSSM)BADDR(global->node->dn_Startup)) == NULL)
X {
XBUGP("Null FSSM")
X /* Initialize the device information */
X global->unitnum = myfssmsg->fssm_Unit = devnum = 0;
X myfssmsg->fssm_Device = (ULONG)defaultdev;
X myfssmsg->fssm_Flags = 0;
X BUG(("GetDevice-fssm_Device:%s\n", myfssmsg->fssm_Device));
X BUG(("GetDevice-fssm_Unit:%ld\n", myfssmsg->fssm_Unit));
X BUG(("GetDevice-fssm_Flags:%lx\n", myfssmsg->fssm_Flags));
X }
X else
X {
XBUGP("Good FSSM")
X /* They gave us all the device information in the mountlist */
X if(fssmsg->fssm_Device != NULL)
X myfssmsg->fssm_Device = (ULONG)BADDR(fssmsg->fssm_Device);
X else
X myfssmsg->fssm_Device = (ULONG)defaultdev;
X global->unitnum =
X myfssmsg->fssm_Unit = fssmsg->fssm_Unit;
X myfssmsg->fssm_Flags = (ULONG)BADDR(fssmsg->fssm_Flags);
X
X BUG(("fssm:%lx\n", fssmsg));
X BUG(("fssm_Device:%s\n", fssmsg->fssm_Device));
X BUG(("fssm_Unit:%ld\n", fssmsg->fssm_Unit));
X BUG(("fssm_Flags:%lx\n", fssmsg->fssm_Flags));
X }
X
XBUGP("GetDevice exit")
X return(-1);
X}
X
X
X
Xint InitDevice(global)
XGLOBAL global;
X{
X struct FileSysStartupMsg myfssmsg;
X int rc;
X
X BUGP("InitDevice: Enter")
X BUG(("InitDevice: Enter\n"));
X
X if (GetDevice(global,&myfssmsg) == NULL)
X {
X BUG(("GetDevice Failed \n"));
X return(0);
X }
X
X if(!(global->n.devport=CreatePort(NULL,0)))
X {
X BUG(("ERROR: Can't CreatePort\n"));
X return(0);
X }
X
X BUG(("fssm_Device:%s\n", myfssmsg.fssm_Device));
X BUG(("fssm_Unit:%ld\n", myfssmsg.fssm_Unit));
X BUG(("fssm_Flags:%lx\n", myfssmsg.fssm_Flags));
X
X BUGP("Init NetNode")
X
X /* Initialize NetNode struct for ourselves - at root of netnodes */
X global->netchain.next = NULL;
X global->netchain.status = NODE_UP;
X MBSTR(MYNAME, global->netchain.name);
X global->netchain.id = 0;
X global->netchain.ioptr = NULL;
X global->netchain.RootLock.NetNode = &global->netchain;
X /* A NULL RDevice indicates this is a lock on the local root */
X global->netchain.RootLock.RDevice = NULL;
X global->netchain.RootLock.RPtr = NULL;
X
X global->numnodes = global->upnodes = 1;
X#ifndef SMALLPACKET
X MBSTR(MYNAME, global->RP.handler);
X global->RP.handlerid = 0; /* Fix this! */
X#endif
X rc = InitRDevice(global);
X
X BUGP("InitDevice: Exit")
X
X return(rc);
X}
X
Xstruct NetNode *AddNode(global, name, ioptr)
XGLOBAL global;
Xchar *name;
XAPTR ioptr;
X{
X struct NetNode *node;
X
XBUGBSTR("AddNode: Adding ", name);
XBUG(("ioptr is %lx\n", ioptr));
X
X /* First see if the node's name is unique */
X for(node=&global->netchain; node; node=node->next)
X {
X if(!stricmp(node->name, name))
X {
X if(node->status == NODE_UP) global->upnodes--;
X break;
X }
X }
X if(!node)
X {
X BUG(("AddNode: Node not in chain\n"));
X /* Node is new, add it */
X if(!(node=(struct NetNode *)DosAllocMem(global,
X (long)sizeof(struct NetNode))))
X {
X BUG(("AddNode: Out of memory!\n"));
X return(NULL);
X }
X /* Chain the node into the list of network nodes */
X node->next = global->netchain.next;
X global->netchain.next = node;
X strcpy(node->name, name);
X node->devname[0] = '\0';
X node->id = 0;
X global->numnodes++;
X /* Set up dummy lock for lock templating */
X node->RootLock.NetNode = node;
X node->RootLock.RDevice = (RPTR)1L; /* For now - Obtain from remote */
X node->RootLock.RPtr = NULL; /* For always */
X }
X
X node->status = (ioptr ? NODE_UP
X : (node->status == NODE_UP ? NODE_CRASHED
X : NODE_DEAD));
X node->ioptr = ioptr;
X
X if(node->status == NODE_UP) global->upnodes++;
X
X return(node);
X}
X
Xint TermDevice(global)
XGLOBAL global;
X{
X TermRDevice(global, 0);
X return(1);
X}
SHAR_EOF
echo "extracting handler/devio.c"
sed 's/^X//' << \SHAR_EOF > handler/devio.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 "handler.h"
X
Xint RemotePacket(global, nptr)
XGLOBAL global;
XNETPTR nptr;
X{
X#if DEBUG
X if(nptr->RDevice == NULL)
X {
X BUGR("Bad NPTR to RPacket")
X BUG(("************ RemotePacket on root! ************\n"));
X return(1);
X }
X else
X BUG(("RemotePacket: RDevice %lx\n", nptr->RDevice));
X#endif
X
X#ifndef SMALLPACKET
X global->RP.serverid = nptr->NetNode->id;
X MBSTR(nptr->NetNode->name, global->RP.server);
X#endif
X global->RP.RDevice = nptr->RDevice;
X
X if(nptr->NetNode->status == NODE_CRASHED)
X ReSync(global, nptr->NetNode->ioptr);
X
X if(nptr->NetNode->status != NODE_UP ||
X PutRPacket(global, nptr->NetNode->ioptr) ||
X GetRPacket(global, nptr->NetNode->ioptr))
X {
X BUG(("RemotePacket: No connection\n"));
X if(nptr->NetNode->status == NODE_UP) global->upnodes--;
X nptr->NetNode->status = NODE_CRASHED;
X global->pkt->dp_Res1 = NULL;
X global->pkt->dp_Res2 = ERROR_NODE_DOWN;
X return(1);
X }
X else
X {
X BUG(("RemotePacket: Received codes %lx, %lx\n",
X global->RP.Arg1, global->RP.Arg2));
X global->pkt->dp_Res1 = global->RP.Arg1;
X global->pkt->dp_Res2 = global->RP.Arg2;
X
X /* The other side may have decided to change our RDevice */
X nptr->RDevice = global->RP.RDevice;
X return(0);
X }
X}
SHAR_EOF
echo "extracting handler/dir.c"
sed 's/^X//' << \SHAR_EOF > handler/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/* ActCreateDir ActExamine ActExNext ActParent */
X#include "handler.h"
X
X
Xvoid ActCreateDir(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1 - Lock */
X/* Arg2 - name */
X/* Arg3 (optional) Attributes */
X{
X struct FileLock *flock;
X NETPTR nlock;
X
X BUG(("ActCreateDir\n"));
X
X if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X /* The idiot is trying to create a directory in NET: */
X BUG(("ActCreateDir: Can't create dir in NET:, giving up\n"))
X pkt->dp_Res1 = NULL;
X pkt->dp_Res2 = ERROR_WRITE_PROTECTED;
X return;
X }
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nlock->RPtr;
X MBSTR(pkt->dp_Arg2, global->RP.Data);
X global->RP.Arg3 = pkt->dp_Arg3;
X global->RP.DLen = BSTRLEN(global->RP.Data)+1;
X if(global->RP.DLen == 1) global->RP.DLen = 0;
X
X if(!RemotePacket(global, nlock) && pkt->dp_Res1)
X {
X pkt->dp_Res1 = MKBADDR(CreateLock(global, nlock,
X (RPTR)pkt->dp_Res1, ACCESS_READ));
X }
X}
X
X/*-------------------------------------------------------------------------*/
X/* Structure of the FileInfoBlock */
X/* struct FileInfoBlock { */
X/* LONG fib_DiskKey; Location on disk of entry */
X/* LONG fib_DirEntryType; <0 plain file, >0 a directory */
X/* char fib_FileName[108]; Null terminated name of file */
X/* LONG fib_Protection; Protection bits for the file */
X/* LONG fib_EntryType; Internal for Dos use */
X/* LONG fib_Size; Length of file in bytes */
X/* LONG fib_NumBlocks; Length of file in blocks */
X/* struct DateStamp fib_Date; File creation date */
X/* char fib_Comment[116]; Comment associated with file */
X/* }; */
X/*-------------------------------------------------------------------------*/
X
Xstatic void PNum U_ARGS((char *, int));
X
X#define UPSPOT 17
X#define TOTSPOT 24
Xstatic char status[] = "\53Network status: xxx of xxx nodes responding";
X
Xstatic void PNum(string, num)
Xchar *string;
Xint num;
X{
X static char *digits = " 123456789";
X /* Format a number into 3 character positions of a string */
X /* Number must be between 1 and 999 inclusive */
X num %= 1000;
X string[0] = digits[num/100]; num %= 100;
X string[1] = digits[num/10]; num %= 10;
X string[2] = (num ? digits[num] : '0');
X}
X
Xvoid ExDotInfo U_ARGS((GLOBAL, struct FileInfoBlock *));
X
Xvoid ExDotInfo(global, info)
XGLOBAL global;
Xstruct FileInfoBlock *info;
X{
X BUGBSTR("ExDotInfo for ", info->fib_FileName);
X strcpy(info->fib_FileName+(info->fib_FileName[0]+1), ".info");
X info->fib_FileName[0] += 5;
X info->fib_EntryType =
X info->fib_DirEntryType = -3;
X info->fib_Protection = 0L;
X info->fib_Size = 974;
X info->fib_NumBlocks = 2;
X info->fib_Comment[0] = '\0';
X
X global->pkt->dp_Res1 = DOS_TRUE;
X}
X
X
Xstatic void ExRoot U_ARGS((GLOBAL, struct FileInfoBlock *));
X
Xstatic void ExRoot(global, info)
XGLOBAL global;
Xstruct FileInfoBlock *info;
X{
X BUG(("ExRoot\n"))
X /* Examine on the root of NET: */
X info->fib_DiskKey = (LONG)&global->netchain;
X info->fib_DirEntryType = info->fib_EntryType = 2;
X MBSTR(global->netchain.name, info->fib_FileName);
X info->fib_Protection = 0;
X info->fib_NumBlocks = global->numnodes;
X info->fib_Size = 0;
X info->fib_Date.ds_Days = 3000; /* Pick a number */
X info->fib_Date.ds_Minute =
X info->fib_Date.ds_Tick = 0L;
X strcpy(info->fib_Comment, status);
X PNum(info->fib_Comment+UPSPOT, global->upnodes);
X PNum(info->fib_Comment+TOTSPOT, global->numnodes);
X
X global->pkt->dp_Res1 = DOS_TRUE;
X}
X
Xstatic void ExRootNext U_ARGS((GLOBAL, struct FileInfoBlock *));
X
Xstatic void ExRootNext(global, info)
XGLOBAL global;
Xstruct FileInfoBlock *info;
X{
X struct NetNode *node;
X
X /* Examine next in the root of NET: */
X BUG(("ExRootNext\n"))
X
X node = (struct NetNode *)info->fib_DiskKey;
X
X /* If the node name is the same length as the filename, we haven't */
X /* returned the exnext of the .info file yet; do so */
X if(node != &global->netchain &&
X info->fib_FileName[0] > 0 &&
X node->name[0] == info->fib_FileName[0])
X {
X ExDotInfo(global, info);
X return;
X }
X
X#if 0
X for(node=node->next;
X node && node->status != NODE_UP;
X node=node->next);
X#else
X node = node->next;
X#endif
X
X if(!node)
X {
X global->pkt->dp_Res1 = DOS_FALSE;
X global->pkt->dp_Res2 = ERROR_NO_MORE_ENTRIES;
X BUG(("Returning ERROR_NO_MORE_ENTRIES\n"));
X return;
X }
X
X info->fib_DiskKey = (LONG)node;
X info->fib_DirEntryType = info->fib_EntryType = 2;
X MBSTR(node->name, info->fib_FileName);
X BUGBSTR("ExNext: Filename is ", info->fib_FileName);
X info->fib_Protection = 0L;
X info->fib_NumBlocks = 1;
X info->fib_Size = 0;
X info->fib_Date.ds_Days = 3000;
X info->fib_Date.ds_Minute =
X info->fib_Date.ds_Tick = 0L;
X info->fib_Comment[0] = '\0';
X
X global->pkt->dp_Res1 = DOS_TRUE;
X}
X
Xvoid ActExamine(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1: Lock of object to examine */
X/* Arg2: FileInfoBlock to fill in */
X{
X NETPTR nlock;
X struct FileLock *flock;
X struct FileInfoBlock *info;
X
X BUG(("ActExamine/ActExNext\n"));
X
X info = (struct FileInfoBlock *)pkt->dp_Arg2;
X
X if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X if(pkt->dp_Type == ACTION_EXAMINE_OBJECT)
X ExRoot(global, info);
X else
X ExRootNext(global, info);
X return;
X }
X
X BUG(("ActEx: Lock %lx on node %s\n",nlock->RPtr,nlock->NetNode->name+1));
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nlock->RPtr;
X
X MQ(info, global->RP.Data, sizeof(struct FileInfoBlock));
X BUGBSTR("ActEx: filename ", info->fib_FileName);
X
X global->RP.DLen = sizeof(struct FileInfoBlock);
X
X if(!RemotePacket(global, nlock))
X {
X MQ(global->RP.Data, info, sizeof(struct FileInfoBlock));
X BUGBSTR("ActEx: Returned filename ", info->fib_FileName);
X }
X}
X
Xvoid ActParent(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1 - Lock */
X{
X struct FileLock *flock;
X NETPTR nlock;
X
X BUG(("ActParent\n"));
X
X /* If this is the root of NET:, return NULL */
X if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X pkt->dp_Res1 = NULL;
X return;
X }
X
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)) return;
X
X if(pkt->dp_Res1 == NULL)
X {
X if(pkt->dp_Res2) return; /* Error on other side */
X
X /* Null lock from other side, return a lock on our root */
X nlock = &global->netchain.RootLock;
X }
X
X pkt->dp_Res1 = MKBADDR(CreateLock(global, nlock,
X (RPTR)pkt->dp_Res1, ACCESS_READ));
X}
SHAR_EOF
echo "extracting handler/file.c"
sed 's/^X//' << \SHAR_EOF > handler/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 "handler.h"
X
Xvoid ActDelete(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1: Lock */
X/* Arg2: Name */
X{
X NETPTR nlock;
X struct FileLock *flock;
X BUG(("ActDelete\n"));
X
X /* Can't delete in the root of NET: */
X if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X if(ParseName(global, (char *)pkt->dp_Arg2, &nlock, global->RP.Data) ||
X !nlock)
X {
X /* Either he is trying to delete a node or he got the name wrong */
X pkt->dp_Res1 = DOS_FALSE;
X pkt->dp_Res2 = (nlock ? ERROR_OBJECT_IN_USE
X : ERROR_WRITE_PROTECTED);
X return;
X }
X BUGBSTR("RmtDelete: Sending to node ", nlock->NetNode->name);
X }
X else
X MBSTR(pkt->dp_Arg2, global->RP.Data);
X
X BUGBSTR("RmtDelete: remote node name =", global->RP.Data);
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nlock->RPtr;
X global->RP.DLen = BSTRLEN(global->RP.Data)+1;
X if(global->RP.DLen == 1) global->RP.DLen = 0;
X
X RemotePacket(global, nlock);
X}
X
Xvoid ActRename(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1: FromLock */
X/* Arg2: FromName */
X/* Arg3: ToLock */
X/* Arg4: ToName */
X{
X NETPTR nlock, nlock2;
X struct FileLock *flock;
X char *tmpchar;
X
X BUG(("ActRename\n"));
X
X /* See if it is a local lock */
X if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X if(ParseName(global, (char *)pkt->dp_Arg2, &nlock, global->RP.Data) ||
X !nlock)
X {
X /* Trying to rename a node, or something that doesn't exist */
X pkt->dp_Res1 = DOS_FALSE;
X pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
X return;
X }
X }
X else
X MBSTR(pkt->dp_Arg2, global->RP.Data);
X
X /* See if the second lock is a local lock */
X if((!(flock=(struct FileLock *)pkt->dp_Arg3) ||
X !(nlock2=(NETPTR)flock->fl_Key)->RDevice))
X {
X if(ParseName(global, (char *)pkt->dp_Arg4, &nlock,
X global->RP.Data+FILENAMELEN) || !nlock2)
X {
X /* See if they are trying to rename a node */
X if(global->RP.Data[0] == 1 && global->RP.Data[1] == ':')
X {
X tmpchar = global->RP.Data+FILENAMELEN;
X if(tmpchar[0] > RNAMELEN) tmpchar[0] = RNAMELEN;
X MBSTR(tmpchar, nlock->NetNode->name);
X }
X else
X {
X pkt->dp_Res1 = DOS_FALSE;
X pkt->dp_Res2 = (nlock2 ? ERROR_OBJECT_EXISTS
X : ERROR_RENAME_ACROSS_DEVICES);
X }
X return;
X }
X }
X else
X MBSTR(pkt->dp_Arg4, global->RP.Data+FILENAMELEN);
X
X /* Check for rename across devices */
X if(nlock->NetNode != nlock2->NetNode)
X {
X pkt->dp_Res1 = DOS_FALSE;
X pkt->dp_Res2 = ERROR_RENAME_ACROSS_DEVICES;
X return;
X }
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nlock->RPtr;
X global->RP.Arg3 = (LONG)nlock2->RPtr;
X global->RP.DLen = FILENAMELEN + BSTRLEN(global->RP.Data+FILENAMELEN)+1;
X
X RemotePacket(global, nlock);
X}
X
Xvoid ActSetProtection(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: Mask of protection */
X{
X struct FileLock *flock;
X NETPTR nlock;
X
X BUG(("ActSetProtection\n"));
X
X BUGBSTR("File to protect: ", pkt->dp_Arg3);
X
X if((!(flock=(struct FileLock *)pkt->dp_Arg2) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X /* Local lock - protection not implemented yet */
X pkt->dp_Res1 = DOS_TRUE;
X return;
X }
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg2 = (LONG)nlock->RPtr;
X MBSTR(pkt->dp_Arg3, global->RP.Data);
X global->RP.Arg4 = pkt->dp_Arg4;
X global->RP.DLen = BSTRLEN(global->RP.Data)+1;
X if(global->RP.DLen == 1) global->RP.DLen = 0;
X
X RemotePacket(global, nlock);
X}
X
Xvoid ActSetComment(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 struct FileLock *flock;
X NETPTR nlock;
X
X BUG(("ActSetComment\n"));
X
X BUGBSTR("File to Comment: ", pkt->dp_Arg3);
X BUGBSTR("New Comment Str: ", pkt->dp_Arg4);
X
X if((!(flock=(struct FileLock *)pkt->dp_Arg2) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X /* Can't SetComment local nodes */
X pkt->dp_Res1 = DOS_TRUE;
X return;
X }
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg2 = (LONG)nlock->RPtr;
X MBSTR(pkt->dp_Arg3, global->RP.Data);
X MBSTR(pkt->dp_Arg4, global->RP.Data+FILENAMELEN);
X global->RP.DLen = FILENAMELEN + BSTRLEN(global->RP.Data+FILENAMELEN)+1;
X
X RemotePacket(global, nlock);
X}
X
Xvoid ActSetFileDate(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt;
X{
X pkt->dp_Res1 = DOS_FALSE;
X pkt->dp_Res2 = ERROR_NODE_DOWN;
X}
SHAR_EOF
echo "extracting handler/handler.h"
sed 's/^X//' << \SHAR_EOF > handler/handler.h
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 authors: BBS: */
X/* | o | || John Toebes Dave Baker John Mainwaring */
X/* | . |// */
X/* ====== */
X/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
X
X#include "netcomm.h"
X
X/* defines for NetNode status field */
X#define NODE_DEAD 0 /* The node has never been heard from */
X#define NODE_UP 1 /* The node is up and responding normally */
X#define NODE_CRASHED 2 /* The node was responding, but is now down */
X
X
X/* There is one NetNode structure for each node in the network. Within*/
X/* the NetNode structure is a definition for the NetPtr structure. A */
X/* NetPtr structure completely describes a FileHandle or Lock on a */
X/* remote system: The NetNode pointer points to the NetNode struct for */
X/* the appropriate node; the RDevice field gives the address ON THE */
X/* REMOTE NODE of the AmigaDOS device to communicate with; the RPtr */
X/* field gives the address ON THE REMOTE NODE of the FileHandle or Lock*/
X/* we are dealing with. To handle the NULL lock, we put an instance of*/
X/* the NetPtr struct in the NetNode struct. The NetNode field points */
X/* to the top of the struct, the RDevice field is normal and the RPTR */
X/* field is NULL. */
X/* The ioptr field of the NetNode contains information specific to the */
X/* communications driver for the node. I will eventually also put a */
X/* pointer to the MsgPort for the driver once I support multiple */
X/* drivers. */
Xstruct NetNode
X{
X struct NetNode *next; /* Next Net Node in chain */
X int status; /* Last known status - see above */
X char name[RNAMELEN+2]; /* Name of remote node */
X char devname[RNAMELEN+2]; /* TEMPORARY - name of remote device */
X short id; /* ID of remote node (timestamp) */
X APTR ioptr; /* Driver-defined pointer */
X /* The NetPtr instance here is a special case - its NetNode pointer */
X /* points to the root of its own struct, its RPtr pointer is NULL. */
X /* It is used when a 'template' NETPTR is needed for the net node. */
X struct NetPtr
X {
X struct NetNode *NetNode; /* Ptr to network address information */
X RPTR RDevice; /* Address of remote MsgPort */
X RPTR RPtr; /* Remote file system's lock/filehandle */
X } RootLock;
X};
X
X/* The following typedef is used to represent both remote locks and */
X/* remote filehandles, since the same information is needed for both. */
X/* Using a single struct allows us to use it as a parm to RemotePacket */
X/* whether we have a filehandle or a lock. */
Xtypedef struct NetPtr *NETPTR;
X
Xtypedef struct global
X {
X struct NetGlobal n; /* Globals in common with server */
X struct RPacket RP; /* Data area for remote node */
X struct DosPacket *pkt; /* the packet we are processing */
X struct DeviceNode *node; /* our device node */
X struct DeviceList *volume; /* currently mounted volume */
X struct NetNode netchain; /* Head of NetNode struct chain */
X int numnodes; /* Number of nodes in the chain */
X int upnodes; /* Number of up nodes in the chain */
X long unitnum;
X }* GLOBAL;
X
X/* file.c */
Xvoid ActDelete U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActRename U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActSetComment U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActSetProtection U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActSetFileDate U_ARGS((GLOBAL, struct DosPacket *));
X
X/* io.c */
Xvoid ActFindwrite U_ARGS((GLOBAL, struct DosPacket *));
X#define ActFindin ActFindWrite
X#define ActFindout ActFindWrite
Xvoid ActEnd U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActRead U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActWrite U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActSeek U_ARGS((GLOBAL, struct DosPacket *));
X
X/* dir.c */
Xvoid ActCreateDir U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActExamine U_ARGS((GLOBAL, struct DosPacket *));
X#define ActExNext ActExamine
Xvoid ActParent U_ARGS((GLOBAL, struct DosPacket *));
X
X/* main.c */
Xvoid ActSetDebug U_ARGS((GLOBAL, struct DosPacket *));
X
X/* lock.c */
Xstruct FileLock *CreateLock U_ARGS((GLOBAL, NETPTR /* nlock */,
X RPTR /* RLock */, LONG /* Access */));
Xvoid FreeLock U_ARGS((GLOBAL, struct FileLock *));
Xvoid ActLock U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActDupLock U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActUnLock U_ARGS((GLOBAL, struct DosPacket *));
Xint ParseName U_ARGS((GLOBAL, char *, NETPTR *, char *));
Xstruct NetNode *FindNode U_ARGS((GLOBAL, char *));
X
X/* Process.c */
Xvoid ActDie U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActInhibit U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActFlush U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActTimer U_ARGS((GLOBAL, struct DosPacket *));
X
X/* volume.c */
Xvoid ActCurentVol U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActRenameDisk U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActDiskInfo U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActInfo U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActNetKludge U_ARGS((GLOBAL, struct DosPacket *));
Xvoid ActDiskChange U_ARGS((GLOBAL, struct DosPacket *));
X
X/* device.c */
Xint GetDevice U_ARGS((GLOBAL, struct FileSysStartupMsg *));
Xint InitDevice U_ARGS((GLOBAL));
Xint TermDevice U_ARGS((GLOBAL));
Xstruct NetNode *AddNode U_ARGS((GLOBAL, char *, APTR));
X
X/* Devio.c */
Xint RemotePacket U_ARGS((GLOBAL, NETPTR));
X
X/* inhibit.c */
Xint inhibit U_ARGS((struct MsgPort *, long));
Xlong sendpkt U_ARGS((struct MsgPort *, long, long*, long));
X
X/* mount.c */
Xvoid Mount U_ARGS((GLOBAL, char *));
Xvoid DisMount U_ARGS((GLOBAL));
X
X/* Requester routine */
Xint request U_ARGS((GLOBAL, int, char *));
X#define REQ_MUST 0
X#define REQ_ERROR 1
X#define REQ_GENERAL 2
X
X/* Protocol-specific .c file: net#?.c */
XInitRDevice U_ARGS((GLOBAL));
XTermRDevice U_ARGS((GLOBAL, int));
Xvoid ActNetHello U_ARGS((GLOBAL, struct DosPacket *));
X
X#include "/proto.h"
X
SHAR_EOF
echo "extracting handler/io.c"
sed 's/^X//' << \SHAR_EOF > handler/io.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 Access: */
X/* ActRead ActWrite ActSeek ActWaitForChar */
X/* ActFindwrite ActFindin ActFindout ActEnd */
X
X#include "handler.h"
X
X/*-------------------------------------------------------------------------*/
X/* */
X/* ActRead( global, pkt ) */
X/* */
X/*-------------------------------------------------------------------------*/
X
Xvoid ActRead(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1: APTR EFileHandle */
X/* Arg2: APTR Buffer */
X/* Arg3: Length */
X{
X NETPTR nfile;
X long toread, total, amtread;
X char *data;
X
X BUG(("ActRead\n"));
X
X nfile = (NETPTR)pkt->dp_Arg1;
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nfile->RPtr;
X global->RP.Arg3 = toread = pkt->dp_Arg3;
X
X for(data=(char *)pkt->dp_Arg2, total=0L; toread>0; toread-=amtread)
X {
X global->RP.DLen = 0;
X if(RemotePacket(global, nfile))
X return;
X
X if ((amtread=global->RP.Arg1) == 0)
X break;
X
X if(amtread<0)
X {
X BUG(("Read error: codes %lx,m, %lx\n",
X global->RP.Arg1,global->RP.Arg2));
X total = global->RP.Arg1;
X goto AFTER;
X }
X
X MQ(global->RP.Data, data, amtread);
X total += amtread;
X data += amtread;
X }
XAFTER:
X pkt->dp_Res1 = total;
X pkt->dp_Res2 = global->RP.Arg2;
X}
X
X/*-------------------------------------------------------------------------*/
X/* */
X/* ActWrite( global, pkt ) */
X/* */
X/*-------------------------------------------------------------------------*/
X
X/* This should probably be changed to look for a confirmation after */
X/* each write in order to notice errors faster - djw */
X
Xvoid ActWrite(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1: APTR EFileHandle */
X/* Arg2: APTR Buffer */
X/* Arg3: Length */
X{
X NETPTR nfile;
X long towrite, total, amtwrite;
X char *data;
X
X BUG(("ActWrite\n"));
X
X nfile = (NETPTR)pkt->dp_Arg1;
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nfile->RPtr;
X towrite = pkt->dp_Arg3;
X
X for(data = (char *)pkt->dp_Arg2, total = 0L;
X towrite > 0;
X towrite -= amtwrite, data += amtwrite)
X {
X amtwrite = min(towrite, NETBUFSIZE);
X MQ(data, global->RP.Data, amtwrite);
X global->RP.DLen = global->RP.Arg3 = amtwrite;
X global->RP.Arg4 = (amtwrite == towrite ? 0 : 1);
X
X if(RemotePacket(global, nfile) || pkt->dp_Res1 == -1) break;
X
X total += pkt->dp_Res1;
X }
X
X if(pkt->dp_Res1 >= 0) pkt->dp_Res1 = total;
X
X BUG(("ActWrite: Ending, %d bytes written\n", total));
X}
X
X/*---------------------------------------------------------------------------*/
X/* */
X/* ActSeek( global, pkt ) */
X/* */
X/*---------------------------------------------------------------------------*/
X
Xvoid ActSeek(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1: APTR EFileHandle */
X/* Arg2: Position */
X/* Arg3: Mode */
X{
X NETPTR nfile;
X
X BUG(("ActSeek\n"));
X
X nfile = (NETPTR)pkt->dp_Arg1;
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nfile->RPtr;
X global->RP.Arg2 = pkt->dp_Arg2;
X global->RP.Arg3 = pkt->dp_Arg3;
X global->RP.DLen = 0;
X
X RemotePacket(global, nfile);
X}
X
X/*-------------------------------------------------------------------------*/
X/* */
X/* ActFindwrite( global, pkt ) */
X/* */
X/*-------------------------------------------------------------------------*/
X
Xvoid ActFindwrite(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* ARG1: FileHandle to fill in */
X/* ARG2: Lock for file relative to */
X/* Arg3: Name of file */
X{
X struct FileHandle *fh;
X NETPTR nlock, nfile;
X struct FileLock *flock;
X
X BUG(("ActFindwrite\n"));
X /* Code 1004 -
X If file does not exist, open should fail.
X If file does exist, open with an exclusive lock */
X
X fh = (struct FileHandle *)pkt->dp_Arg1;
X
X if((!(flock=(struct FileLock *)pkt->dp_Arg2) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X if(ParseName(global, (char *)pkt->dp_Arg3, &nlock, global->RP.Data) ||
X !nlock)
X {
X /* Can't open files in NET: itself */
X pkt->dp_Res1 = NULL;
X pkt->dp_Res2 = (nlock ? ERROR_OBJECT_NOT_FOUND
X : ERROR_OBJECT_WRONG_TYPE);
X return;
X }
X }
X else
X MBSTR(pkt->dp_Arg3, global->RP.Data);
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg2 = (LONG)nlock->RPtr;
X global->RP.DLen = BSTRLEN(global->RP.Data)+1;
X if(global->RP.DLen == 1) global->RP.DLen = 0;
X
X if(!RemotePacket(global, nlock) && pkt->dp_Res1 != DOS_FALSE)
X {
X BUG(("ActFind: Valid local filehandle = %lx\n", fh));
X if(!(nfile=(NETPTR)DosAllocMem(global,
X (long)sizeof(struct NetPtr))))
X {
X BUG(("******NO MEMORY FOR LOCAL LOCK"));
X pkt->dp_Res1 = DOS_FALSE;
X pkt->dp_Res2 = ERROR_NO_FREE_STORE;
X return;
X }
X
X nfile->NetNode = nlock->NetNode;
X nfile->RDevice = nlock->RDevice;
X /* Remote filehandle passed back in RP.Arg3 */
X nfile->RPtr = (RPTR)global->RP.Arg3;
X
X fh->fh_Arg1 = (LONG)nfile;
X }
X#if DEBUG
X else
X BUG(("ActFind: Remote file open failed, codes %d %d\n",
X pkt->dp_Res1, pkt->dp_Res2));
X#endif
X}
X
X/*-------------------------------------------------------------------------*/
X/* */
X/* ActEnd( global, pkt ) */
X/* */
X/*-------------------------------------------------------------------------*/
X
Xvoid ActEnd( global, pkt )
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X{
X NETPTR nfile;
X
X BUG(("ActEnd\n"));
X
X nfile = (NETPTR)pkt->dp_Arg1;
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nfile->RPtr;
X global->RP.DLen = 0;
X
X RemotePacket(global, nfile);
X
X DosFreeMem((char *)nfile);
X}
SHAR_EOF
echo "extracting handler/lock.c"
sed 's/^X//' << \SHAR_EOF > handler/lock.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
X/* Lock.c - lock manipulation */
X/* ActLock, ActDupLock, ActUnLock */
X
X/*-------------------------------------------------------------------------*/
X/* Structure of a Lock: */
X/* struct FileLock { */
X/* BPTR fl_Link; Next lock in the chain of device locks */
X/* LONG fl_Key; Block number of directory or file header */
X/* LONG fl_Access; Shared Read (-2) or Exclusive Write (-1) */
X/* struct MsgPort * fl_Task; Handler process for Lock (Us) */
X/* BPTR fl_Volume; Node in DevInfo structure for Lock */
X/* }; */
X/*-------------------------------------------------------------------------*/
X#include "handler.h"
X
X/* create a lock to be returned */
Xstruct FileLock *CreateLock(global, nlock, RLock, Access)
XGLOBAL global;
XNETPTR nlock;
XRPTR RLock;
XLONG Access;
X{
X struct FileLock *flock;
X NETPTR newnlock;
X
X if(!(flock=(struct FileLock *)
X DosAllocMem(global, sizeof(struct FileLock))) ||
X !(newnlock=(NETPTR) DosAllocMem(global, sizeof(struct NetPtr)))
X )
X return(NULL);
X
X flock->fl_Key = (LONG)newnlock;
X flock->fl_Access = Access;
X flock->fl_Task = global->n.port;
X flock->fl_Volume = MKBADDR(global->volume);
X newnlock->NetNode = nlock->NetNode;
X newnlock->RDevice = nlock->RDevice;
X newnlock->RPtr = RLock;
X
X /* Link the lock into the lock chain */
X Forbid();
X flock->fl_Link = global->volume->dl_Lock;
X global->volume->dl_Lock = MKBADDR(flock);
X Permit();
X
X return(flock);
X}
X
Xvoid FreeLock(global, flock)
XGLOBAL global;
Xstruct FileLock *flock;
X{
X struct FileLock *current, *next;
X
X if(!flock) return;
X
X Forbid();
X if((current=(struct FileLock *)BADDR(global->volume->dl_Lock)) == flock)
X {
X global->volume->dl_Lock = flock->fl_Link;
X Permit();
X BUG(("FreeLock: Head lock freed, new head = %lx\n",
X global->volume->dl_Lock));
X }
X else
X {
X for(next=NULL;
X current &&
X (next=(struct FileLock *)BADDR(current->fl_Link)) != flock;
X current = next);
X
X if(!next)
X {
X Permit();
X BUG(("****************************************\n"));
X BUG(("******* Lock not found in chain ********\n"));
X BUG(("****************************************\n"));
X return;
X }
X else
X {
X current->fl_Link = next->fl_Link;
X Permit();
X BUG(("Lock found and removed from chain\n"));
X }
X }
X
X /* If RDevice == NULL, we have a dummy nlock, so don't free it */
X /* Otherwise, free it */
X if(((NETPTR)flock->fl_Key)->RDevice)
X DosFreeMem((char *)flock->fl_Key); /* Free the net lock */
X
X DosFreeMem((char *)flock); /* Free the local lock */
X
X}
X
Xvoid ActLock(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X/* Arg1: Lock */
X/* Arg2: Name */
X/* Arg3: Mode: ACCESS_READ, ACCESS_WRITE */
X{
X NETPTR nlock;
X struct FileLock *flock;
X
X BUG(("Action Lock\n"));
X BUGBSTR("File to lock: ", pkt->dp_Arg2);
X
X /**********************************************************************/
X /* If the given lock is on the local root, call the ParseName routine */
X /* to determine if we need to call the remote nodes. If ParseName */
X /* returns 1, we have a name of the form "NET:" and we should return */
X /* a lock on the root of NET:. If it returns 0, we have a name of */
X /* the form "NET:FOO" or "NET:FOO/BAR", etc and we need to call the */
X /* remote node specified in the pseudo-lock returned. */
X /**********************************************************************/
X
X if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X /* ParseName returns 1 if we are locking the root. It fills in */
X /* nlock with a pointer to the pseudolock for the node. The */
X /* pseudolock is kept in the NetNode struct. */
X /* Any leftover parts of the name are left in RP.Data as a */
X /* BCPL string. */
X if(ParseName(global, (char *)pkt->dp_Arg2, &nlock, global->RP.Data))
X {
X BUG(("ActLock: Returning lock on root\n"));
X /* Return lock on root */
X /* ParseName has put the pseudolock for the root into nlock */
X pkt->dp_Res1 =
X MKBADDR(CreateLock(global, nlock, NULL, pkt->dp_Arg3));
X return;
X }
X else if(!nlock)
X {
X BUG(("ActLock: Couldn't find node\n"));
X pkt->dp_Res1 = NULL;
X pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
X return;
X }
X#if DEBUG
X else
X BUG(("ActLock: got nlock, falling through\n"));
X#endif
X }
X else
X {
X BUGBSTR("ActLock: Relative open, node ", nlock->NetNode->name);
X /* We are doing a relative open - put filename in Data */
X MBSTR(pkt->dp_Arg2, global->RP.Data);
X }
X
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nlock->RPtr;
X global->RP.Arg3 = pkt->dp_Arg3;
X global->RP.DLen = BSTRLEN(global->RP.Data)+1;
X if(global->RP.DLen == 1) global->RP.DLen = 0;
X
X if(!RemotePacket(global, nlock) && pkt->dp_Res1)
X {
X BUG(("ActLock: Returned RPTR is %lx\n", pkt->dp_Res1));
X pkt->dp_Res1 = MKBADDR(CreateLock(global, nlock,
X (RPTR)pkt->dp_Res1, pkt->dp_Arg3));
X }
X}
X
Xvoid ActDupLock(global,pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X{
X NETPTR nlock;
X struct FileLock *flock;
X
X BUG(("Action DupLock\n"));
X
X /* If this is a lock on the local root, it is a special case */
X if((!(flock=(struct FileLock *)pkt->dp_Arg1) ||
X !(nlock=(NETPTR)flock->fl_Key)->RDevice))
X {
X pkt->dp_Res1 = NULL;
X if(!flock) return; /* Dup of null lock is null lock */
X goto GETLOCK; /* Dup of real lock on root is real lock (?)*/
X }
X
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) && pkt->dp_Res1)
X {
XGETLOCK:
X pkt->dp_Res1 = MKBADDR(CreateLock(global, nlock,
X (RPTR)pkt->dp_Res1, flock->fl_Access));
X }
X}
X
Xvoid ActUnLock(global, pkt)
XGLOBAL global;
Xstruct DosPacket *pkt; /* a pointer to the dos packet sent */
X{
X NETPTR nlock;
X struct FileLock *flock;
X
X BUG(("Action UnLock\n"));
X
X if(!(flock = (struct FileLock *)pkt->dp_Arg1))
X {
X /* No lock - do nothing */
X pkt->dp_Res1 = DOS_TRUE;
X return;
X }
X
X /* If this lock exists on a remote node, delete it */
X if((nlock=(NETPTR)flock->fl_Key)->RDevice)
X {
X global->RP.Type = pkt->dp_Type;
X global->RP.Arg1 = (LONG)nlock->RPtr;
X global->RP.DLen = 0;
X RemotePacket(global, nlock);
X }
X else
X pkt->dp_Res1 = DOS_TRUE;
X
X FreeLock(global, flock);
X}
X
Xint ParseName(global, name, nlock, outname)
XGLOBAL global;
Xchar *name;
XNETPTR *nlock;
Xchar *outname;
X{
X int len, cur;
X struct NetNode *node;
X
XBUGBSTR("ParseName: Parsing name ", name);
X
X for(len=*(name++), cur=0; len && *name != '/'; len--, name++)
X {
X if(*name==':')
X cur=0;
X else
X outname[cur++] = *name;
X }
X outname[cur] = '\0';
X if(len>0 && *name == '/') name++, len--;
X
X if(len <= 1 && cur == 0)
X {
X /* It is the root of NET: */
X *nlock = &global->netchain.RootLock;
X return(1);
X }
X
X /* We have a network node name - find it */
X node = FindNode(global, outname);
X
X /* OK, check to see if it is a .info file for a node */
X if(!node && cur >= 6 && !stricmp(outname+cur-5, ".info"))
X {
X outname[cur-5] = '\0';
X if(node = FindNode(global, outname))
X {
X BUG(("Got a .info file for node '%s'\n", outname));
X name = "Node.rinfo";
X len = 10;
X }
X }
X
X /* No node found - return null nlock */
X if(!node)
X {
X BUG(("ParseName: No node found, nlock is NULL\n"));
X *nlock = NULL;
X }
X else
X {
X /* Node found - return template lock */
X *nlock = &node->RootLock;
X BUGBSTR("ParseName: Sending packet to node ", node->name);
X }
X
X /* Move the rest of the name into outname as a BSTR */
X outname[0] = (char)len+1;
X outname[1] = ':';
X if(len) MQ(name, outname+2, len);
X outname[len+2] = '\0';
X BUG(("Remote filename: len %d text '%s'\n", (int)*outname, outname+1));
X return(0);
X}
X
Xstruct NetNode *FindNode(global, name)
XGLOBAL global;
Xchar *name;
X{
X struct NetNode *node;
X
X for(node=global->netchain.next; node; node=node->next)
X if(!stricmp(name, node->name+1)) break;
X
X return(node);
X}
X
SHAR_EOF
echo "extracting handler/main.c"
sed 's/^X//' << \SHAR_EOF > handler/main.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
X#include "handler.h"
X
X/******************************************************************************/
X/******************************************************************************/
X/********************* Dispatch table to handle all packets *******************/
X/******************************************************************************/
X/******************************************************************************/
X#define BP1 1
X#define BP2 2
X#define BP3 4
X#define BP4 8
X
Xtypedef void (*ifuncp)(GLOBAL, struct DosPacket *);
Xstruct LookupTable
X {
X ifuncp subr;
X int flags;
X };
X
X#define LO_FIRST 0
X#define LO_LAST 34
Xstruct LookupTable lowork[LO_LAST+1] = {
X { NULL, 0 | 0 | 0 | 0 }, /* 0 - ACTION_NIL */
X { NULL, 0 | 0 | 0 | 0 }, /* 1 - Unknown */
X { NULL, BP1| BP2| BP3| 0 }, /* 2 - ACTION_GET_BLOCK */
X { NULL, 0 | BP2| BP3| 0 }, /* 3 - Unknown */
X { NULL, BP1| BP2| BP3| 0 }, /* 4 - ACTION_SET_MAP */
X { ActDie, 0 | 0 | 0 | 0 }, /* 5 - ACTION_DIE */
X { NULL, 0 | 0 | 0 | 0 }, /* 6 - ACTION_EVENT */
X { ActCurentVol, BP1| 0 | 0 | 0 }, /* 7 - ACTION_CURRENT_VOLUME*/
X { ActLock, BP1| BP2| 0 | 0 }, /* 8 - ACTION_LOCATE_OBJECT */
X { ActRenameDisk, BP1| BP2| 0 | 0 }, /* 9 - ACTION_RENAME_DISK */
X { NULL, 0 | 0 | 0 | 0 }, /* 10 - Unknown */
X { NULL, 0 | 0 | 0 | 0 }, /* 11 - Unknown */
X { NULL, 0 | 0 | 0 | 0 }, /* 12 - Unknown */
X { NULL, 0 | 0 | 0 | 0 }, /* 13 - Unknown */
X { NULL, 0 | 0 | 0 | 0 }, /* 14 - Unknown */
X { ActUnLock, BP1| 0 | 0 | 0 }, /* 15 - ACTION_FREE_LOCK */
X { ActDelete, BP1| BP2| 0 | 0 }, /* 16 - ACTION_DELETE_OBJECT */
X { ActRename, BP1| BP2| BP3| BP4 }, /* 17 - ACTION_RENAME_OBJECT */
X { NULL, 0 | 0 | 0 | 0 }, /* 18 - ACTION_MORE_CACHE */
X { ActDupLock, BP1| 0 | 0 | 0 }, /* 19 - ACTION_COPY_DIR */
X { NULL, 0 | 0 | 0 | 0 }, /* 20 - ACTION_WAIT_CHAR */
X { ActSetProtection, 0 | BP2| BP3| 0 }, /* 21 - ACTION_SET_PROTECT */
X { ActCreateDir, BP1| BP2| 0 | 0 }, /* 22 - ACTION_CREATE_DIR */
X { ActExamine, BP1| BP2| 0 | 0 }, /* 23 - ACTION_EXAMINE_OBJECT*/
X { ActExNext, BP1| BP2| 0 | 0 }, /* 24 - ACTION_EXAMINE_NEXT */
X { ActDiskInfo, BP1| 0 | 0 | 0 }, /* 25 - ACTION_DISK_INFO */
X { ActInfo, BP1| BP2| 0 | 0 }, /* 26 - ACTION_INFO */
X { ActFlush, 0 | 0 | 0 | 0 }, /* 27 - ACTION_FLUSH */
X { ActSetComment, 0 | BP2| BP3| BP4 }, /* 28 - ACTION_SET_COMMENT */
X { ActParent, BP1| 0 | 0 | 0 }, /* 29 - ACTION_PARENT */
X { NULL, BP1| 0 | 0 | 0 }, /* 30 - ACTION_TIMER */
X { ActInhibit, 0 | 0 | 0 | 0 }, /* 31 - ACTION_INHIBIT */
X { NULL, BP1| 0 | 0 | 0 }, /* 32 - ACTION_DISK_TYPE */
X { NULL, 0 | 0 | 0 | 0 }, /* 33 - ACTION_DISK_CHANGE */
X { ActSetFileDate, 0 | 0 | 0 | 0 } /* 34 - ACTION_SET_FILE_DATE */
X };
X
X#define HI_FIRST 1004
X#define HI_LAST 1008
Xstruct LookupTable hiwork[5] = {
X { ActFindwrite, BP1| BP2| BP3| 0 }, /* ACTION_FIND_WRITE - 1004 */
X { ActFindwrite, BP1| BP2| BP3| 0 }, /* ACTION_FIND_INPUT - 1005 */
X { ActFindwrite, BP1| BP2| BP3| 0 }, /* ACTION_FIND_OUTPUT - 1006 */
X { ActEnd, 0 | 0 | 0 | 0 }, /* ACTION_END - 1007 */
X { ActSeek, 0 | 0 | 0 | 0 } /* ACTION_SEEK - 1008 */
X };
X
X#define USER_FIRST 2010
X#define USER_LAST 2012
Xstruct LookupTable userwork[3] = {
X { ActSetDebug, 0 | 0 | 0 | 0 }, /* ACTION_HANDLER_DEBUG 2010 */
X { NULL, BP1| 0 | 0 | 0 }, /* ACTION_SET_TRANS_TYPE2011 */
X { ActNetHello, BP1| 0 | 0 | 0 }, /* ACTION_NETWORK_HELLO 2012 */
X };
X
Xstruct DosLibrary *DOSBase;
X
Xvoid _main(x)
Xchar *x;
X{
X struct DosPacket *mypkt; /* a pointer to the dos packet sent */
X int action;
X ifuncp subr;
X int flags;
X struct global global;
X
X DOSBase = (struct DosLibrary *)OpenLibrary(DOSNAME,0);
X
X /* Initialize our global data structure */
X memset((char *)&global, 0, sizeof(struct global));
X global.n.self = (struct Process *) FindTask(0L); /* find myself */
X global.n.run = 1;
X global.n.port = &(global.n.self->pr_MsgPort);
X /* install our taskid ... */
X
X
X /* Initialize the intuitext structures for the requesters we might have */
X /* to display */
X /* Because we have no scruples we can cheat and do this with a couple of */
X /* long word assignments. We leave the acual C code commented out here */
X /* so that if this structure ever changed we will still be able to work */
X#if 0
X global.n.line1.FrontPen = global.n.line1.BackPen = -1;
X global.n.line1.DrawMode = JAM1;
X global.n.line1.LeftEdge = global.n.line1.TopEdge = 4;
X global.n.line2 = global.n.line1;
X global.n.line3 = global.n.line1;
X global.n.retrytxt = global.n.line1;
X global.n.canceltxt = global.n.line1;
X#else
X *(long *)&global.n.line1.FrontPen = 0x00010000L | (JAM1<<8);
X *(long *)&global.n.line1.LeftEdge = 0x00040004L; /* 4,4 */
X *(long *)&global.n.line2.FrontPen = 0x00010000L | (JAM1<<8);
X *(long *)&global.n.line2.LeftEdge = 0x0004000EL; /* 4,14 */
X *(long *)&global.n.line3.FrontPen = 0x00010000L | (JAM1<<8);
X *(long *)&global.n.line3.LeftEdge = 0x00040018L; /* 4,24 */
X *(long *)&global.n.retrytxt.FrontPen = 0x00010000L | (JAM1<<8);
X *(long *)&global.n.retrytxt.LeftEdge = 0x00040004L;
X *(long *)&global.n.canceltxt.FrontPen = 0x00010000L | (JAM1<<8);
X *(long *)&global.n.canceltxt.LeftEdge = 0x00040004L;
X#endif
X global.n.retrytxt.IText = "Retry";
X global.n.canceltxt.IText = "Cancel";
X
X /* since we were started as a non-BCPL module we get sent the parameter */
X /* packet (ie. parameter packet not in D1) */
X
X mypkt = taskwait(&global); /* wait for parameter packet */
X
X global.n.devname = (((char *)BADDR(mypkt->dp_Arg1))+1); /* BSTR name */
X
X /* get pointer to our device node */
X global.node = (struct DeviceNode *) BADDR(mypkt->dp_Arg3);
X global.node->dn_Task = global.n.port;
X
X InitDevice(&global);
X
X Mount(&global, NULL);
X
X/* OpenTimer(&global); */
X
X mypkt->dp_Res1 = DOS_TRUE;
X retpkt(&global, mypkt);
X
X/* PostTimerReq(&global); */
X
X while(global.n.run) /* start of the real work */
X {
X BUG(("Waiting for packet. . ."));
X mypkt = taskwait(&global); /* wait for a packet */
X
X action = mypkt->dp_Type;
X
X BUG(("action #%ld\n", action));
X
X switch (action)
X {
X
X case ACTION_NETWORK_KLUDGE:
X subr = ActNetKludge;
X flags = (BP1 | BP2);
X break;
X
X case ACTION_READ:
X subr = ActRead;
X flags = 0;
X break;
X case ACTION_WRITE:
X subr = ActWrite;
X flags = 0;
X break;
X
X case ACTION_SET_RAW_MODE:
X subr = NULL;
X flags = 0;
X break;
X
X case ACTION_FIND_WRITE: /* 1004 */
X case ACTION_FIND_INPUT: /* 1005 */
X case ACTION_FIND_OUTPUT: /* 1006 */
X case ACTION_END: /* 1007 */
X case ACTION_SEEK: /* 1008 */
X subr = hiwork[action-HI_FIRST].subr;
X flags = hiwork[action-HI_FIRST].flags;
X break;
X
X case ACTION_HANDLER_DEBUG: /* 2010 */
X case ACTION_SET_TRANS_TYPE: /* 2011 */
X case ACTION_NETWORK_HELLO: /* 2012 */
X subr = userwork[action-USER_FIRST].subr;
X flags = userwork[action-USER_FIRST].flags;
X break;
X
X default:
X if ((action >= LO_FIRST) && (action <= LO_LAST))
X {
X subr = lowork[action-LO_FIRST].subr;
X flags = lowork[action-LO_FIRST].flags;
X }
X else
X subr = NULL;
X }
X
X mypkt->dp_Res1 = DOS_FALSE;
X mypkt->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
X
X if (subr != NULL)
X {
X global.n.reply = 1;
X if (flags & BP1)
X mypkt->dp_Arg1 <<= 2;
X if (flags & BP2)
X mypkt->dp_Arg2 <<= 2;
X if (flags & BP3)
X mypkt->dp_Arg3 <<= 2;
X if (flags & BP4)
X mypkt->dp_Arg4 <<= 2;
X
X (*subr)(&global, mypkt);
X
X }
X#if DEBUG
X else
X {
X BUG(("Unknown packet type %ld\n",mypkt->dp_Type));
X }
X#endif
X
X /* Now return the packet to them */
X if (global.n.reply)
X retpkt(&global, mypkt);
X
X BUG(("-----\n"));
X }
X
X /* do our final cleanup */
X global.node->dn_Task = FALSE; /* zero the taskid field of device node */
X global.node->dn_SegList = 0; /* make us be gone */
X
X DisMount(&global);
X TermDevice(&global);
X
X BUGTERM()
X}
X
Xvoid ActSetDebug(global, pkt) /* ACTION_HANDLER_DEBUG */
XGLOBAL global;
Xstruct DosPacket *pkt;
X/* DP_Arg1 - LONG type/flags 0=nodebug */
X/* DP_Arg2 - BPTR FileHandle to do debugging to or NULL */
X/* DP_Res1 - BPTR old filehandle */
X{
X /********************************************************************/
X /* */
X /* Several possibilities: */
X /* 1. Arg1 is 0: */
X /* All debugging is turned off. Arg2 is not looked at. */
X /* Res1 is DOS_TRUE, Res2 is a BPTR to the old filehandle. */
X /* */
X /* 2. Arg1 is a special handler-defined code: */
X /* If the second bit from the top is ON, the code is a special*/
X /* debugging command to the handler. If the handler knows the*/
X /* command, it returns DOS_TRUE in Res1. If it doesn't, it */
X /* returns DOS_FALSE in Res1 and Res2. */
X /* */
X /* 3. Neither of the above: */
X /* Arg2 contains a BPTR to a FileHandle to send debugging to. */
X /* Note that if this is NULL, debugging will be turned off. */
X /* Res1 contains DOS_TRUE, Res2 contains a BPTR to the old */
X /* debugging FileHandle, which may of course be NULL if no */
X /* debugging was on before. */
X /* */
X /********************************************************************/
X
X#define DEBUG_SPECIAL 0x40000000 /* Mask for handler-defined dbg type*/
X#define DEBUG_SERVER 0x20000000 /* Mask indicating server command */
X#define DEBUG_WAIT 0x40000001 /* Wait for debugger to catch us */
X#define DEBUG_INFO 0x40000002 /* Send transmit info to msgport in */
X /* dp_Arg2 */
X
X struct NetNode *netnode;
X extern BPTR debuglog;
X
X pkt->dp_Res1 = DOS_TRUE;
X if(pkt->dp_Arg1 & DEBUG_SPECIAL)
X {
X BUG(("ActSetDebug: Special debug packet %lx\n", pkt->dp_Arg1))
X if(pkt->dp_Arg1 == DEBUG_WAIT)
X {
X pkt->dp_Res2 = NULL;
X cprwait(global);
X }
X else if(pkt->dp_Arg1 == DEBUG_INFO)
X {
X global->n.infoport = (struct MsgPort *)BADDR(pkt->dp_Arg2);
X global->n.ntirec.m.mn_Node.ln_Type =
X global->n.ntitrans.m.mn_Node.ln_Type = NT_MESSAGE;
X if(!global->n.ntirec.m.mn_ReplyPort)
X global->n.ntirec.m.mn_ReplyPort =
X global->n.ntitrans.m.mn_ReplyPort = CreatePort(NULL,0);
X global->n.inf_rec = global->n.inf_trans = 0L;
X }
X else if(pkt->dp_Arg1 & DEBUG_SERVER)
X {
X global->RP.Type = ACTION_HANDLER_DEBUG;
X global->RP.Arg1 = pkt->dp_Arg1 & ~(DEBUG_SERVER|DEBUG_SPECIAL);
X BUG(("Remote debugging code %lx\n", global->RP.Arg1))
X for(netnode=global->netchain.next;
X netnode;
X netnode=netnode->next)
X {
X if(netnode->status == NODE_UP &&
X netnode->RootLock.RDevice)
X {
X RemotePacket(global, &netnode->RootLock);
X }
X }
X }
X else
X {
X pkt->dp_Res1 =
X pkt->dp_Res2 = DOS_FALSE;
X }
X }
X#if DEBUG
X else if(pkt->dp_Arg1)
X pkt->dp_Res2 = initdebug((BPTR)pkt->dp_Arg2);
X else
X {
X pkt->dp_Res2 = debuglog;
X debuglog = NULL;
X }
X#endif
X}
X
X
X
X
SHAR_EOF
echo "End of archive 2 (of 4)"
# if you want to concatenate archives, remove anything after this line
exit