home *** CD-ROM | disk | FTP | other *** search
- /*
- * $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 */
- }
-