/* * GETFILES.C V1.30 * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * * GETFILES [-Nnetid] [-dlocaldir] [-c] file/dir file/dir file/dir * * -Nnetid network identifier * * -dlocaldir local directory to place files * * -c Continue from where you left off before. Files that already * exist on the local machine will not be re-transfered. This * will also re-start in the middle of a file that was * partially transfered previously. * * This command assumes the file(s) on both machines have not * been modified since the first attempt. No other checking * is done at the moment. */ #include "defs.h" void main ARGS((int, char **)); typedef struct { char Cmd; char Str[128]; long Val; } HDR; extern int Enable_Abort; char Buf[4096]; short ContMode; char *NetId; long LocalDirLock; void *Chan; void fail ARGS((int)); int CheckNoPath ARGS((char *)); int LostChannel ARGS((void)); void UnknownCmd ARGS((HDR *)); int GetFile ARGS((HDR *, int)); int GetDir ARGS((HDR *, int)); int WriteHeader ARGS((char, char *, long)); int ReadHeader ARGS((HDR *)); char *NSpaces ARGS((int)); int CheckBreak ARGS((void)); void ResetBreak ARGS((void)); int brk() { return(0); } void main(ac,av) int ac; char *av[]; { HDR Hdr; short error; onbreak(brk); #ifndef LATTICE Enable_Abort = 0; #endif printf("GetFiles V%s%s\n", VERSION, GETFILES_VERSION); ResetBreak(); { char *ldir = ""; FIB *fib = malloc(sizeof(FIB)); ac = DoOption(ac, av, "N%sd%sc", &NetId, &ldir, &ContMode); if (ac <= 1) { puts("GETFILES [-Nnetid -dlocaldir -c] remotefile/dir ..."); fail(22); } LocalDirLock = Lock(ldir, SHARED_LOCK); if (!LocalDirLock && ldir[0]) { /* couldn't find it, try to make it */ if (LocalDirLock = (long)CreateDir(ldir)) { UnLock(LocalDirLock); LocalDirLock = Lock(ldir, SHARED_LOCK); } } if (!LocalDirLock || !Examine(LocalDirLock, fib) || fib->fib_DirEntryType < 0) { printf("Unable to CD or create local directory: \"%s\"\n", ldir); fail(21); } } Chan = DOpen(NetId, PORT_GFILECOPY, 126, -80); if (!Chan) { puts("Unable to connect"); fail(20); } error = WriteHeader('H', "Hello, getfiles client V1.30", 0); if (error) fail(LostChannel()); switch(ReadHeader(&Hdr)) { case -1: fail(LostChannel()); case 'H': printf("%s\n", Hdr.Str); break; } { short i; for (i = 1; i < ac; ++i) { short error; error = WriteHeader('G', av[i], 0); if (error) fail(LostChannel()); switch(ReadHeader(&Hdr)) { case -1: fail(LostChannel()); case 'N': printf("Remote error on %s: %s\n", av[i], Hdr.Str); break; case 'F': error = CheckNoPath(Hdr.Str); if (!error) { long olddir = (long)CurrentDir(LocalDirLock); error = GetFile(&Hdr, 0); CurrentDir(olddir); } break; case 'D': error = CheckNoPath(Hdr.Str); if (!error) { long olddir = (long)CurrentDir(LocalDirLock); error = GetDir(&Hdr, 0); CurrentDir(olddir); } break; case 'S': printf("Access Violation: %s\n", Hdr.Str); break; default: UnknownCmd(&Hdr); error = 1; break; } if (error) fail(error); } if (!error) { error = WriteHeader('E', "bye", 0); if (error) fail(LostChannel()); } } fail(0); } void fail(code) { if (Chan) DClose(Chan); if (LocalDirLock) UnLock(LocalDirLock); exit(code); } int CheckNoPath(str) char *str; { while (*str) { if (*str == '/' || *str == ':') { puts("SECURITY ALERT: Illegal path spec received"); return(40); } ++str; } return(0); } int LostChannel() { puts("DATA CHANNEL LOST"); return(10); } void UnknownCmd(hdr) HDR *hdr; { printf("UnRecognized command code: %02x\n", hdr->Cmd); } /* * retrieve a file. If ContMode set and file exists, try to append to * it. */ int GetFile(hdr, stab) HDR *hdr; int stab; { long Fh = NULL; long pos = 0; short error = 0; printf("%s%-20s ", NSpaces(stab), hdr->Str); fflush(stdout); if (ContMode) { SetProtection(hdr->Str, 0); /* make sure it's r/w */ if (Fh = Open(hdr->Str, 1005)) { /* already exists */ long len; Seek(Fh, 0L, 1); len = Seek(Fh, 0L, 0); /* get length */ if (len > hdr->Val) { Close(Fh); printf("Cont Error, local file is larger than remote!: %s\n", hdr->Str); puts("(not downloaded)"); return(0); } if (len == hdr->Val) { Close(Fh); if (error = WriteHeader('S', NULL, 0)) return(LostChannel()); puts("HAVE IT, SKIP"); return(0); } printf("(HAVE %ld/%ld) ", len, hdr->Val); hdr->Val -= len; /* that much less */ pos = len; /* start at offset */ } } if (!Fh) { Fh = Open(hdr->Str, 1006); if (!Fh) { error = WriteHeader('N', "open error", 0); printf("Unable to open %s for output\n", hdr->Str); if (error) return(LostChannel()); return(1); } } error = WriteHeader('Y', NULL, pos); /* yes, gimme gimme */ /* * Retrieve the data */ if (!error) { long left = hdr->Val; long cnt = pos; long total = pos + left; while (left) { long n = (left > sizeof(Buf)) ? sizeof(Buf) : left; printf("%6ld/%6ld\23313D", cnt, total); fflush(stdout); if (DRead(Chan, Buf, n) != n) { error = 5; break; } if (CheckBreak()) { error = 1; break; } if (Write(Fh, Buf, n) != n) { puts("Local Write failed!"); error = 6; break; } left -= n; cnt += n; if (CheckBreak()) { error = 1; break; } } printf("%6ld/%6ld %s", cnt, total, ((cnt == total) ? "OK" : "INCOMPLETE")); } Close(Fh); puts(""); if (error) { SetProtection(hdr->Str, 10); /* disallow reads! */ return(LostChannel()); } return((int)error); } /* * Retrieve a directory. Create it if necessary. */ int GetDir(hdr, stab) HDR *hdr; int stab; { short error = 0; long dirlock; static HDR Hdr; /* note: static */ if (CheckBreak()) return(1); printf("%s%-20s(DIR)\n", NSpaces(stab), hdr->Str); dirlock = Lock(hdr->Str, SHARED_LOCK); /* try to lock directory */ if (!dirlock) { if (dirlock = (long)CreateDir(hdr->Str)) { UnLock(dirlock); dirlock = Lock(hdr->Str, SHARED_LOCK); } } if (!dirlock) { error = WriteHeader('N', "couldn't create", 0); printf("Unable to create local directory: %s\n", hdr->Str); if (error) return(LostChannel()); return(1); } error = WriteHeader('Y', NULL, 0); /* yes, gimme gimme */ while (!error) { switch(ReadHeader(&Hdr)) { case -1: error = 1; break; case 'E': /* end of directory */ UnLock(dirlock); return(0); break; case 'F': error = CheckNoPath(Hdr.Str); if (!error) { long olddir = (long)CurrentDir(dirlock); error = GetFile(&Hdr, stab + 4); CurrentDir(olddir); } break; case 'D': error = CheckNoPath(Hdr.Str); if (!error) { long olddir = (long)CurrentDir(dirlock); error = GetDir(&Hdr, stab + 4); CurrentDir(olddir); } break; case 'S': printf("Access Violation: %s\n", Hdr.Str); break; case 'N': printf("REMOTE ERROR: %s\n", Hdr.Str); error = 10; break; default: UnknownCmd(&Hdr); error = 1; break; } } UnLock(dirlock); return(LostChannel()); } int WriteHeader(c, str, len) char c; char *str; long len; { ubyte sl; if (str == NULL) str = ""; sl = strlen(str); if (DWrite(Chan, &c, 1) < 0) return(1); if (DWrite(Chan, &sl,1) < 0) return(1); if (DWrite(Chan, str, sl) != sl) return(1); if (DWrite(Chan, &len, 4) != 4) return(1); return(0); } int ReadHeader(hdr) HDR *hdr; { ubyte sl; ubyte cmd; hdr->Cmd = -1; if (DRead(Chan, &cmd, 1) != 1) return(-1); if (DRead(Chan, &sl, 1) != 1) return(-1); if (sl >= sizeof(hdr->Str)) { puts("Software error: received file name length too long"); return(-1); } if (DRead(Chan, hdr->Str, sl) != sl) return(-1); hdr->Str[sl] = 0; if (DRead(Chan, &hdr->Val, 4) != 4) return(-1); hdr->Cmd = cmd; return((int)hdr->Cmd); } char * NSpaces(n) int n; { static char Buf[128]; static short in = 0; static short last; if (in == 0) { in = 1; BSet(Buf, sizeof(Buf)-1, ' '); } Buf[last] = ' '; if (n < 127) Buf[n] = 0; last = n; return(Buf); } int CheckBreak() { if (SetSignal(0,0) & (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D)) { puts("^C"); return(1); } return(0); } void ResetBreak() { SetSignal(0, SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D); }