/* * SCOPY.C V1.1 * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * COPY SERVER FOR PUTFILES (DOWNLOADS, i.e. receives files) * * The current version only accepts one connection at a time. This server * handles downloading of data. This server will eventually be replaced * by the SGCOPY server. Currently the SGCOPY server only handles * uploads. * * NOTE: The DNET_WRITE enviroment variable must be 9 or higher or this * server will refuse connections. * * Receive: * 'V' NLEN NAME FILELEN -receive compressed file (V1.1) * 'W' NLEN NAME FILELEN -receive file * 'X' NLEN NAME 0 -create and CD into directory * 'Y' 0 0 -restore previous directory * 'C' NLEN NAME 0 -set destination directory * * length in 68000 longword format. */ #include #include #include "servers.h" int Enable_Abort; char Buf[8192]; char Buf2[8192]; typedef struct FileInfoBlock FIB; typedef struct Process PROC; extern struct MsgPort *DListen(); extern PROC *FindTask(); extern char *AllocMem(); _main() { struct MsgPort *port; PROC *myproc = FindTask(NULL); long chan; long savedir; long mask, rmask; Enable_Abort = 0; if (myproc->pr_CLI) { Version("SCopy", VERSION, SCOPY_VERSION); _exit(0); } port = DListen(PORT_FILECOPY); { struct Message *GetMsg(); register struct Message *msg; register char *dir; WaitPort(&myproc->pr_MsgPort); msg = GetMsg(&myproc->pr_MsgPort); dir = (msg->mn_Node.ln_Name) ? msg->mn_Node.ln_Name : ""; savedir = Lock(dir, SHARED_LOCK); /* duplicate current dir */ ReplyMsg(msg); } if (!savedir) { DUnListen(port); _exit(1); } savedir = CurrentDir(savedir); /* CD dup, returns original */ mask = SIGBREAKF_CTRL_C|(1 << port->mp_SigBit); for (;;) { long dupdir = DupLock(myproc->pr_CurrentDir); rmask = Wait(mask); if (rmask & SIGBREAKF_CTRL_C) { UnLock(CurrentDir(dupdir)); break; } while (chan = DAccept(port)) { if (GetEnvVal(DNET_WRITE) >= 9) putdir(chan, ""); else DWrite(chan, "S", 1); DClose(chan); } UnLock(CurrentDir(dupdir)); } UnLock(CurrentDir(savedir)); /* restore original */ DUnListen(port); } static char Name[128]; putdir(chan, dirname) char *dirname; { FIB *fib; long lock; long oldlock; long len; int ret = -1; unsigned char co, nl, rc; fib = (FIB *)AllocMem(sizeof(FIB), MEMF_PUBLIC); if ((lock = Lock(dirname, SHARED_LOCK)) == NULL) { if (lock = CreateDir(dirname)) { UnLock(lock); lock = Lock(dirname, SHARED_LOCK); } } if (lock == NULL || !Examine(lock,fib) || fib->fib_DirEntryType < 0) { if (lock) UnLock(lock); rc = 'N'; DWrite(chan, &rc, 1); FreeMem(fib, sizeof(FIB)); return(1); } rc = 'Y'; DWrite(chan, &rc, 1); oldlock = CurrentDir(lock); while (DRead(chan, &co, 1) == 1) { if (DRead(chan, &nl, 1) != 1 || DRead(chan, Name, nl) != nl) break; if (DRead(chan, &len, 4) != 4) break; switch(co) { case 'C': { char co = 'N'; long lock = Lock(Name, SHARED_LOCK); /* CD to dir */ if (!lock) { if (lock = CreateDir(Name)) { /* or create */ UnLock(lock); lock = Lock(Name, SHARED_LOCK); } } if (lock) { co = 'Y'; UnLock(CurrentDir(lock)); } DWrite(chan, &co, 1); } break; case 'W': if (putfile(chan, Name, len) < 0) { ret = -1; goto fail; } break; case 'X': if (putdir(chan, Name) < 0) { ret = -1; goto fail; } break; case 'Y': ret = 1; co = 'Y'; DWrite(chan, &co, 1); goto fail; default: co = 'N'; DWrite(chan, &co, 1); break; } } fail: UnLock(CurrentDir(oldlock)); FreeMem(fib, sizeof(FIB)); return(ret); } putfile(chan, name, len) char *name; { long fh = Open(name, 1006); long n, r; char rc; if (fh == NULL) { rc = 'N'; DWrite(chan, &rc, 1); return(0); } rc = 'Y'; DWrite(chan, &rc, 1); while (len) { r = (len > sizeof(Buf)) ? sizeof(Buf) : len; n = DRead(chan, Buf, r); if (n != r) break; if (Write(fh, Buf, n) != n) break; len -= n; } Close(fh); if (len) { unlink(name); return(-1); } rc = 'Y'; DWrite(chan, &rc, 1); return(0); }