home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format 56
/
af056sub.adf
/
parnfs.lha
/
server.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-02
|
16KB
|
619 lines
/*
* $Id: server.c,v 1.1 1993/12/02 20:45:46 Rhialto Exp $
* $Log: server.c,v $
* Revision 1.1 1993/12/02 20:45:46 Rhialto
* Initial revision
*
* The bulk of the server code: receive packets and act upon them.
*/
#include "netfs.h"
#include <stdio.h>
#include <string.h>
#include "getopt.c"
#ifdef DEBUG
# include "syslog.h"
#else
# define debug(x)
#endif
long UnitNr;
char *DevName = "parnet.device";
ULONG DevFlags;
struct DosPacket *DosPkt;
ULONG WaitMask;
ULONG Validation;
ULONG MyValidation;
struct MsgPort *DosPort;
struct MsgPort *AsyncDosPort;
struct Process *Proc;
void *pr_WindowPtr = -2;
void
chkabort(void)
{
/* do not check for break */
}
void
dumppkt(Packet *pkt)
{
debug(("Packet: %08lx; %08lx, %08lx %08lx %08lx %08lx %08lx\n",
*(long *)pkt, pkt->p_Action,
pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2],
pkt->p_Arg[3], pkt->p_Arg[4], pkt->p_Arg[5]));
}
Prototype ULONG dopacket(struct DosPacket *packet, struct MsgPort *port);
ULONG
dopacket(struct DosPacket *packet, struct MsgPort *port)
{
packet->dp_Port = DosPort;
PutMsg(port, packet->dp_Link);
WaitPort(DosPort);
GetMsg(DosPort);
return packet->dp_Res1;
}
void
doasyncpacket(struct DosPacket *packet, struct MsgPort *port)
{
packet->dp_Port = AsyncDosPort;
PutMsg(port, packet->dp_Link);
}
/*
* Create a DOS style packet: a message and a dos packet linked to
* each other. The size of the message is variable so you can include
* extra information behind it, or use it as an I/O request.
*/
struct DosPacket *
CreateDosPkt(int size)
{
struct DosPacket *dp;
struct Message *msg;
size += sizeof(struct Message) + sizeof(struct DosPacket);
if (msg = AllocMem(size, MEMF_PUBLIC | MEMF_CLEAR)) {
dp = (char *)msg + size - sizeof(struct DosPacket);
dp->dp_Link = msg;
msg->mn_Node.ln_Name = (char *)dp;
msg->mn_Length = size;
}
return dp;
}
void
DeleteDosPkt(struct DosPacket *dp)
{
if (dp) {
struct Message *msg = dp->dp_Link;
FreeMem(msg, msg->mn_Length);
}
}
struct MsgPort *
FindProc(BPTR fl, char *bstr)
{
struct FileLock *lock;
if (strchr(bstr + 1, ':')) {
return DeviceProc(bstr + 1);
}
lock = BTOC(fl);
return lock->fl_Task;
}
UBYTE *
SkipString(UBYTE *s)
{
s = s + s[0] + 2;
s = (UBYTE *)((ULONG)(s + 3) & ~3);
return s;
}
/* ---------------------------------------------------------------------- */
void
HandleRequest(struct IOParReq *io, Packet *pkt)
{
LONG tmp;
ULONG replysize;
debug(("type %d action %d\n", pkt->p_Type, pkt->p_Action));
switch (DoProtocol(io, pkt)) {
case pt_Request:
break;
default:
return;
}
/* Now we know it's a request, we can do something about it. */
replysize = STDREPLY;
Proc->pr_Result2 = 0;
switch (pkt->p_Action) {
/* case ACTION_DIE: / * attempt to die? */
/* case ACTION_CURRENT_VOLUME:/ * - VolNode,UnitNr*/
case ACTION_RENAME_DISK: /* New name Bool */
{
char *newname;
newname = SkipString((char *)&pkt->p_Arg[0])+1;
debug(("Relabel '%s' -> '%s'\n", ((char *)&pkt->p_Arg[0])+1, newname));
pkt->p_Res1 = Relabel((char *)&pkt->p_Arg[0]+1, newname);
pkt->p_Res2 = Proc->pr_Result2;
}
break;
case ACTION_LOCATE_OBJECT: /* Lock,Name,Mode Lock */
tmp = CurrentDir(pkt->p_Arg[0]);
pkt->p_Res1 = Lock((char *)&pkt->p_Arg[2]+1, pkt->p_Arg[1]);
pkt->p_Res2 = Proc->pr_Result2;
CurrentDir(tmp);
break;
case ACTION_FREE_LOCK: /* Lock Bool */
UnLock(pkt->p_Arg[0]);
pkt->p_Res1 = DOSTRUE;
pkt->p_Res2 = Proc->pr_Result2;
break;
case ACTION_DELETE_OBJECT: /* Lock,Name Bool */
tmp = CurrentDir(pkt->p_Arg[0]);
pkt->p_Res1 = DeleteFile((char *)&pkt->p_Arg[1]+1);
pkt->p_Res2 = Proc->pr_Result2;
CurrentDir(tmp);
break;
case ACTION_RENAME_OBJECT: /* SLock,SName,DLock,DName Bool */
{
struct MsgPort *handler;
char *sname;
char *dname;
sname = (char *)(&pkt->p_Arg[2]);
dname = SkipString(sname);
DosPkt->dp_Action = ACTION_RENAME_OBJECT;
DosPkt->dp_Arg1 = pkt->p_Arg[0];
DosPkt->dp_Arg2 = CTOB(sname);
DosPkt->dp_Arg3 = pkt->p_Arg[1];
DosPkt->dp_Arg4 = CTOB(dname);
handler = FindProc(pkt->p_Arg[0], sname+1);
if (handler == NULL)
handler = FindProc(pkt->p_Arg[1], dname+1);
if (handler != NULL) {
dopacket(DosPkt, handler);
pkt->p_Res1 = DosPkt->dp_Res1;
pkt->p_Res2 = DosPkt->dp_Res2;
} else {
pkt->p_Res1 = DOSFALSE;
pkt->p_Res2 = ERROR_INVALID_LOCK;
}
}
break;
case ACTION_COPY_DIR: /* Lock Lock */
pkt->p_Res1 = DupLock(pkt->p_Arg[0]);
pkt->p_Res2 = Proc->pr_Result2;
break;
case ACTION_SET_PROTECT: /* -,Lock,Name,Mask Bool */
tmp = CurrentDir(pkt->p_Arg[0]);
pkt->p_Res1 = SetProtection((char *)&pkt->p_Arg[2]+1, pkt->p_Arg[1]);
pkt->p_Res2 = Proc->pr_Result2;
CurrentDir(tmp);
break;
case ACTION_CREATE_DIR: /* Lock,Name Lock */
tmp = CurrentDir(pkt->p_Arg[0]);
pkt->p_Res1 = CreateDir((char *)&pkt->p_Arg[1]+1);
pkt->p_Res2 = Proc->pr_Result2;
CurrentDir(tmp);
break;
/*
* Note that for ExNext() the FileInfoBlock is copied from the client
* to the server, and back again. This is because ExNext needs the fib
* to be initialised by a previous call. In fact, it even may insist
* on the *very same* fib to be used in each call in a sequence.
* Possibly it may even require that several simultaneous scans of the
* same directory use *different* fibs. Obviously, we can't comply with
* those requirements. For the moment it seems to work ok, but who knows
* it might break in the future!
* Also, because the fib is copied in and out, we refer to it through
* the incoming field names of the packet exclusively. Care must be
* taken with overlapping fields in request and reply.
*/
case ACTION_EXAMINE_OBJECT: /* Lock,Fib Bool */
case ACTION_EXAMINE_NEXT: /* Lock,Fib Bool */
DosPkt->dp_Action = pkt->p_Action;
DosPkt->dp_Arg1 = pkt->p_Arg[0];
DosPkt->dp_Arg2 = CTOB(&pkt->p_Arg[1]);
dopacket(DosPkt, ((struct FileLock *)BTOC(pkt->p_Arg[0]))->fl_Task);
pkt->p_Res2 = DosPkt->dp_Res2;
if (pkt->p_Res1 = DosPkt->dp_Res1)
replysize = STDREPLY + sizeof(struct FileInfoBlock);
#ifdef xDEBUG
{
struct FileInfoBlock *fib;
fib = (struct FileInfoBlock *)&pkt->p_Data[0];
debug(("key %x size %d name '%.*s'\n", fib->fib_DiskKey, fib->fib_Size,
fib->fib_FileName[0], &fib->fib_FileName[1]));
}
#endif
break;
/* case ACTION_DISK_INFO: / * InfoData Bool:TRUE */
case ACTION_INFO: /* Lock,InfoData Bool:TRUE */
pkt->p_Res1 = Info(pkt->p_Arg[0], (void *)&pkt->p_Data[0]);
pkt->p_Res2 = Proc->pr_Result2;
if (pkt->p_Res1)
replysize = STDREPLY + sizeof(struct InfoData);
break;
/* case ACTION_FLUSH: / * writeout bufs, disk motor off */
case ACTION_SET_COMMENT: /* -,Lock,Name,Comment Bool */
tmp = CurrentDir(pkt->p_Arg[0]);
pkt->p_Res1 = SetComment((char *)&pkt->p_Arg[1]+1,
SkipString((char *)&pkt->p_Arg[1])+1);
pkt->p_Res2 = Proc->pr_Result2;
CurrentDir(tmp);
break;
break;
case ACTION_PARENT: /* Lock ParentLock */
pkt->p_Res1 = ParentDir(pkt->p_Arg[0]);
pkt->p_Res2 = Proc->pr_Result2;
break;
/* case ACTION_INHIBIT: / * Bool Bool */
case ACTION_SET_DATE: /* -,Lock,Name,CPTRDateStamp Bool */
tmp = CurrentDir(pkt->p_Arg[0]);
/*V37*/ pkt->p_Res1 = SetFileDate((char *)&pkt->p_Arg[4]+1,
(struct DateStamp *)&pkt->p_Arg[1]);
pkt->p_Res2 = Proc->pr_Result2;
CurrentDir(tmp);
break;
case ACTION_SAME_LOCK: /* Lock1,Lock2 Result */
if (pkt->p_Arg[0] == 0 || pkt->p_Arg[1] == 0) {
/* We never send 0 locks */
pkt->p_Res1 = DOSFALSE;
pkt->p_Res2 = ERROR_INVALID_LOCK;
} else {
DosPkt->dp_Action = ACTION_SAME_LOCK;
DosPkt->dp_Arg1 = pkt->p_Arg[0];
DosPkt->dp_Arg2 = pkt->p_Arg[1];
dopacket(DosPkt, ((struct FileLock *)BTOC(pkt->p_Arg[0]))->fl_Task);
pkt->p_Res1 = DosPkt->dp_Res1;
pkt->p_Res2 = DosPkt->dp_Res2;
}
break;
case ACTION_READ: /* FHArg1,CPTRBuffer,Length ActLength */
tmp = Read(pkt->p_Arg[0], &pkt->p_Data[0], pkt->p_Arg[1]);
pkt->p_Res1 = tmp;
pkt->p_Res2 = Proc->pr_Result2;
if (tmp > 0)
replysize = STDREPLY + tmp;
break;
case ACTION_WRITE: /* FHArg1,CPTRBuffer,Length ActLength */
pkt->p_Res1 = Write(pkt->p_Arg[0], &pkt->p_Arg[2], pkt->p_Arg[1]);
pkt->p_Res2 = Proc->pr_Result2;
break;
case ACTION_OPENRW: /* FileHandle,Lock,Name Bool */
case ACTION_OPENOLD: /* FileHandle,Lock,Name Bool */
case ACTION_OPENNEW: /* FileHandle,Lock,Name Bool */
tmp = CurrentDir(pkt->p_Arg[0]);
pkt->p_Res1 = Open((char *)&pkt->p_Arg[1]+1, pkt->p_Action);
pkt->p_Res2 = Proc->pr_Result2;
CurrentDir(tmp);
break;
case ACTION_CLOSE: /* FHArg1 Bool:Success */
pkt->p_Res1 = Close(pkt->p_Arg[0]);
pkt->p_Res2 = Proc->pr_Result2;
break;
case ACTION_SEEK: /* FHArg1,Position,Mode OldPosition */
pkt->p_Res1 = Seek(pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2]);
pkt->p_Res2 = Proc->pr_Result2;
break;
#ifdef notdef
case ACTION_FORMAT: /* vol,type Bool:success */
break;
#endif
case ACTION_MAKE_LINK: /* parent,name,target,mode Bool */
{
ULONG soft;
tmp = CurrentDir(pkt->p_Arg[0]);
soft = pkt->p_Arg[1];
dumppkt(pkt);
if (soft) {
debug(("MakeLink soft '%s' -> '%s'\n",
SkipString((char *)&pkt->p_Arg[2])+1,
(char *)&pkt->p_Arg[2]+1));
/*V37*/ pkt->p_Res1 = MakeLink(SkipString((char *)&pkt->p_Arg[2])+1,
(ULONG)(char *)&pkt->p_Arg[2]+1,
soft);
} else {
pkt->p_Res1 = MakeLink((char *)&pkt->p_Arg[3]+1,
pkt->p_Arg[2],
soft);
}
pkt->p_Res2 = Proc->pr_Result2;
CurrentDir(tmp);
}
break;
case ACTION_READ_LINK: /* parent,name,target,size length */
{
struct FileLock *fl;
ULONG size;
fl = BTOC(pkt->p_Arg[0]);
size = min(pkt->p_Arg[1], MAXDATA);
/*V37*/ pkt->p_Res1 = ReadLink(fl->fl_Task,
pkt->p_Arg[0],
(char *)&pkt->p_Arg[2]+1,
(char *)&pkt->p_Data[0],
size);
pkt->p_Res2 = Proc->pr_Result2;
if (pkt->p_Res1 >= 0)
replysize = STDREPLY + pkt->p_Res1;
}
break;
case ACTION_SET_FILE_SIZE:
/*V37*/ pkt->p_Res1 = SetFileSize(pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2]);
pkt->p_Res2 = Proc->pr_Result2;
break;
/* case ACTION_WRITE_PROTECT: */
case ACTION_FH_FROM_LOCK: /* FH,Lock BOOL */
/*V37*/ pkt->p_Res1 = OpenFromLock(pkt->p_Arg[0]);
pkt->p_Res2 = Proc->pr_Result2;
break;
case ACTION_CHANGE_MODE:
/*V37*/ pkt->p_Res1 = ChangeMode(pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2]);
pkt->p_Res2 = Proc->pr_Result2;
break;
case ACTION_COPY_DIR_FH: /* fh_Arg1 Lock */
/*V37*/ pkt->p_Res1 = DupLockFromFH(pkt->p_Arg[0]);
pkt->p_Res2 = Proc->pr_Result2;
break;
case ACTION_PARENT_FH:
/*V37*/ pkt->p_Res1 = ParentOfFH(pkt->p_Arg[0]);
pkt->p_Res2 = Proc->pr_Result2;
break;
case ACTION_EXAMINE_FH: /* fh_Arg1,Fib Bool */
{
struct FileHandle *fh;
fh = (struct FileHandle *)BTOC(pkt->p_Arg[0]);
DosPkt->dp_Action = ACTION_EXAMINE_FH;
DosPkt->dp_Arg1 = fh->fh_Arg1;
DosPkt->dp_Arg2 = CTOB(&pkt->p_Data[0]);
dopacket(DosPkt, fh->fh_Type);
pkt->p_Res2 = DosPkt->dp_Res2;
if (pkt->p_Res1 = DosPkt->dp_Res1)
replysize = STDREPLY + sizeof(struct FileInfoBlock);
}
break;
case ACTION_LOCK_RECORD: /* fh,pos,len,mode,time Bool */
{
struct DosPacket *dp;
struct FileHandle *fh;
fh = (struct FileHandle *)BTOC(pkt->p_Arg[0]);
dp = CreateDosPkt(2*sizeof(long));
debug(("LOCK_RECORD %x, dp %x\n", fh, dp));
dp->dp_Action = ACTION_LOCK_RECORD;
dp->dp_Arg1 = fh->fh_Arg1;
dp->dp_Arg2 = pkt->p_Arg[1];
dp->dp_Arg3 = pkt->p_Arg[2];
dp->dp_Arg4 = pkt->p_Arg[3];
dp->dp_Arg5 = pkt->p_Arg[4];
((long *)dp)[-1] = pkt->p_Origin;
((long *)dp)[-2] = pkt->p_Arg[5]; /* client cookie */
doasyncpacket(dp, fh->fh_Type);
}
break;
case ACTION_FREE_RECORD: /* fh,pos,len Bool */
/*V37*/ pkt->p_Res1 = UnLockRecord(pkt->p_Arg[0], pkt->p_Arg[1], pkt->p_Arg[2]);
pkt->p_Res2 = Proc->pr_Result2;
break;
default:
pkt->p_Res1 = DOSFALSE;
pkt->p_Res2 = ERROR_ACTION_NOT_KNOWN;
break;
}
debug(("res: %d err: %d\n", pkt->p_Res1, pkt->p_Res2));
DoReply(io, pkt, replysize);
}
void
HandleAsyncDosPkt(struct Message *msg)
{
char buf[STDREPLY + 2*sizeof(long)];
Packet *p = buf;
struct DosPacket *dp = (struct DosPacket *)msg->mn_Node.ln_Name;
debug(("HandleAsyncDosPkt(msg %x) dp %x res: %x/%d\n",
msg, dp, dp->dp_Res1, dp->dp_Res2));
p->p_Res1 = dp->dp_Res1;
p->p_Res2 = dp->dp_Res2;
p->p_Data[0] = dp->dp_Action;
switch (dp->dp_Action) {
case ACTION_LOCK_RECORD:
p->p_Origin = ((long *)dp)[-1];
p->p_Data[1] = ((long *)dp)[-2]; /* client cookie */
break;
default:
debug(("Funny DOS packet returning %x %d\n", msg, dp->dp_Action));
goto end;
}
DoReplyAsync(ParReq, p, sizeof(buf));
DeleteDosPkt(dp);
end:;
}
/* ---------------------------------------------------------------------- */
Prototype void DoAsyncReply(Packet *pkt);
void
DoAsyncReply(Packet *pkt)
{
debug(("We're not supposed to get these!\n"));
}
/* ---------------------------------------------------------------------- */
ULONG
InitServer(void)
{
debug(("InitServer\n"));
DosPkt = CreateDosPkt(0);
DosPort = CreatePort("NetServer DosPort", -1);
AsyncDosPort = CreatePort("NetServer AsyncDosPort", -1);
WaitMask = 1L << RdPort->mp_SigBit |
1L << AsyncDosPort->mp_SigBit |
SIGBREAKF_CTRL_C;
Proc = (struct Process *)FindTask(NULL);
pr_WindowPtr = Proc->pr_WindowPtr;
Proc->pr_WindowPtr = (void *)-1;
return 0;
}
void
CleanupServer(void)
{
debug(("CleanupServer\n"));
if (pr_WindowPtr != (void *)-2)
Proc->pr_WindowPtr = pr_WindowPtr;
if (DosPkt) {
DeleteDosPkt(DosPkt);
DosPkt = NULL;
}
}
void
ServeLoop(void)
{
ULONG sigs;
while (1) {
debug(("ServeLoop: Wait ...\n"));
sigs = Wait(WaitMask);
{
struct Message *msg;
while (msg = GetMsg(AsyncDosPort)) {
HandleAsyncDosPkt(msg);
}
}
if (sigs & SIGBREAKF_CTRL_C)
break;
{
struct IOParReq *io;
Packet *pkt;
while (io = (struct IOParReq *)GetMsg(RdPort)) {
pkt = ((struct IOStdReq *)io)->io_Data;
if (((struct IOStdReq *)io)->io_Error == 0)
HandleRequest(io, pkt);
else
DoReset(ParReq);
SendRead(io, pkt, PKTSIZE);
}
}
}
}
/* ---------------------------------------------------------------------- */
int
main(int argc, char **argv)
{
int c;
#ifdef DEBUG
initsyslog();
#endif /* DEBUG */
if (DOSBase->dl_lib.lib_Version < 37) {
Write(Output(),
"You should upgrade to at least 2.0 as soon as possible!\n"
"If any client uses a 2.0+ packet, you will crash!\n", 106);
}
/* Primary defaults */
MyAddr = SRV_ADDR;
PeerAddr = CLI_ADDR;
NetFSPort = NETFS_PORT;
while ((c = getopt(argc, argv, "sd:u:f:p:a:c:")) != -1) {
switch (c) {
case 's':
/* Secundary server/client */
MyAddr = CLI_ADDR;
PeerAddr = SRV_ADDR;
NetFSPort = NETFS_PORT + 1;
break;
case 'd':
DevName = optarg;
break;
case 'u':
UnitNr = strtol(optarg, NULL, 0);
break;
case 'f':
DevFlags = strtol(optarg, NULL, 0);
break;
case 'p':
NetFSPort = strtol(optarg, NULL, 0);
break;
case 'a':
MyAddr = strtol(optarg, NULL, 0);
break;
case 'c':
PeerAddr = strtol(optarg, NULL, 0);
break;
case '?':
return 20;
}
}
debug(("call OpenNetwork\n"));
if (OpenNetwork())
return 20;
if (InitServer() == 0) {
ServeLoop();
CleanupServer();
}
CloseNetwork();
#ifdef DEBUG
uninitsyslog();
#endif /* DEBUG */
}