/* * GETFILES.C V1.30 * * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved. * * GETFILES [-dlocaldir] [-c] file/dir file/dir file/dir * * -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 #include #include #include #include "../server/servers.h" typedef unsigned char ubyte; typedef struct { char Cmd; char Str[64]; long Val; } HDR; char *NSpaces(); char Buf[1024]; short ContMode; char *NetId; long Chan = -1; main(ac,av) char *av[]; { HDR Hdr; short error; { char *ldir = "."; struct stat stat; ac = DoOption(ac, av, "N%sd%sc", &NetId, &ldir, &ContMode); if (ac <= 1) { puts("GETFILES [-Nnetid -dlocaldir -c] remotefile/dir ..."); fail(22); } if (chdir(ldir) < 0) { mkdir(ldir, 0777); if (chdir(ldir) < 0) { printf("Unable to CD or make local directory: \"%s\"\n",ldir); fail(21); } } } Chan = DOpen(NetId, PORT_GFILECOPY, 126, -80); if (Chan < 0) { 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; } { register short i; long val; 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) { char svpath[1024]; getwd(svpath); error = GetFile(&Hdr, 0); chdir(svpath); } break; case 'D': error = CheckNoPath(Hdr.Str); if (!error) { char svpath[1024]; getwd(svpath); error = GetDir(&Hdr, 0); chdir(svpath); } break; case 'S': printf("Access Violation: %s\n", Hdr.Str); break; default: error = UnknownCmd(&Hdr); break; } if (error) fail(error); } if (!error) { error = WriteHeader('E', "bye", 0); if (error) fail(LostChannel()); } } fail(0); } fail(code) { if (Chan >= 0) close(Chan); exit(code); } CheckNoPath(str) register char *str; { while (*str) { if (*str == '/' || *str == ':') { puts("SECURITY ALERT: Illegal path spec received"); return(40); } ++str; } return(0); } LostChannel() { puts("DATA CHANNEL LOST"); return(10); } 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. */ #define BSSTR "\010\010\010\010\010\010\010\010\010\010\010\010\010" GetFile(hdr, stab) HDR *hdr; { int fd = -1; long pos = 0; short error = 0; printf("%s%-20s ", NSpaces(stab), hdr->Str); fflush(stdout); if (ContMode) { if ((fd = open(hdr->Str, O_WRONLY)) >= 0) { /* already exists */ long len; len = lseek(fd, 0L, 2); if (len > hdr->Val) { close(fd); printf("Cont Error, local file is larger than remote!: %s\n", hdr->Str ); puts("(not downloaded)"); return(0); } if (len == hdr->Val) { close(fd); 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 (fd < 0) { fd = open(hdr->Str, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) { 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) { register long left = hdr->Val; register long cnt = pos; long total = pos + left; printf(" "); while (left) { register long n = (left > sizeof(Buf)) ? sizeof(Buf) : left; printf("%s%6ld/%6ld", BSSTR, cnt, total); fflush(stdout); if (ggread(Chan, Buf, n) != n) { error = 5; break; } if (write(fd, Buf, n) != n) { puts("Local Write failed!"); error = 6; break; } left -= n; cnt += n; } printf("%s%6ld/%6ld %s", BSSTR, cnt, total, ((cnt == total) ? "OK" : "INCOMPLETE") ); } puts(""); if (error) { fchmod(fd, 0222); close(fd); return(LostChannel()); } close(fd); return(error); } /* * Retrieve a directory. Create it if necessary. */ GetDir(hdr, stab) HDR *hdr; { short error = 0; long dirlock; static HDR Hdr; /* note: static */ char svpath[1024]; printf("%s%-20s(DIR)\n", NSpaces(stab), hdr->Str); getwd(svpath); if (chdir(hdr->Str) < 0) { mkdir(hdr->Str, 0777); if (chdir(hdr->Str) < 0) { 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 */ chdir(svpath); return(0); break; case 'F': error = CheckNoPath(Hdr.Str); if (!error) { char svpath2[1024]; getwd(svpath2); error = GetFile(&Hdr, stab + 4); chdir(svpath2); } break; case 'D': error = CheckNoPath(Hdr.Str); if (!error) { char svpath2[1024]; getwd(svpath2); error = GetDir(&Hdr, stab + 4); chdir(svpath2); } break; case 'S': printf("Access Violation: %s\n", Hdr.Str); break; case 'N': printf("REMOTE ERROR: %s\n", Hdr.Str); error = 10; break; default: error = UnknownCmd(&Hdr); break; } } chdir(svpath); return(LostChannel()); } WriteHeader(c, str, len) char c; char *str; long len; { ubyte sl; if (str == NULL) str = ""; sl = strlen(str); if (gwrite(Chan, &c, 1) < 0) return(1); if (gwrite(Chan, &sl,1) < 0) return(1); if (gwrite(Chan, str, sl) != sl) return(1); len = htonl68(len); if (gwrite(Chan, &len, 4) != 4) return(1); return(0); } ReadHeader(hdr) HDR *hdr; { ubyte sl; ubyte cmd; hdr->Cmd = -1; if (ggread(Chan, &cmd, 1) != 1) return(-1); if (ggread(Chan, &sl, 1) != 1) return(-1); if (sl >= sizeof(hdr->Str)) { puts("Software error: received file name length too long"); return(-1); } if (ggread(Chan, hdr->Str, sl) != sl) return(-1); hdr->Str[sl] = 0; if (ggread(Chan, &hdr->Val, 4) != 4) return(-1); hdr->Val = ntohl68(hdr->Val); hdr->Cmd = cmd; return(hdr->Cmd); } char * NSpaces(n) short n; { static char Buf[128]; static short in = 0; static short last; if (in == 0) { register short i; in = 1; for (i = 0; i < sizeof(Buf); ++i) Buf[i] = ' '; } Buf[last] = ' '; if (n < 127) Buf[n] = 0; last = n; return(Buf); }