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