121739Sdist /* 226048Sminshall * Copyright (c) 1985 Regents of the University of California. 321739Sdist * All rights reserved. The Berkeley software License Agreement 421739Sdist * specifies the terms and conditions for redistribution. 521739Sdist */ 621739Sdist 710296Ssam #ifndef lint 8*26448Slepreau static char sccsid[] = "@(#)ftp.c 5.8 (Berkeley) 03/04/86"; 921739Sdist #endif not lint 1010296Ssam 1126048Sminshall #include "ftp_var.h" 1226048Sminshall 1310296Ssam #include <sys/stat.h> 1410296Ssam #include <sys/ioctl.h> 1510296Ssam #include <sys/socket.h> 1613614Ssam #include <sys/time.h> 1710296Ssam 1810296Ssam #include <netinet/in.h> 1912397Ssam #include <arpa/ftp.h> 2026048Sminshall #include <arpa/telnet.h> 2110296Ssam 2210296Ssam #include <stdio.h> 2310296Ssam #include <signal.h> 2410296Ssam #include <errno.h> 2510296Ssam #include <netdb.h> 2626048Sminshall #include <fcntl.h> 2726048Sminshall #include <pwd.h> 2810296Ssam 2910296Ssam struct sockaddr_in hisctladdr; 3010296Ssam struct sockaddr_in data_addr; 3110296Ssam int data = -1; 3226048Sminshall int telflag = 0; 3326048Sminshall int abrtflag = 0; 3426048Sminshall int ptflag = 0; 3510296Ssam int connected; 3610296Ssam struct sockaddr_in myctladdr; 3710296Ssam 3810296Ssam FILE *cin, *cout; 3910296Ssam FILE *dataconn(); 4010296Ssam 4125904Skarels char * 4210296Ssam hookup(host, port) 4310296Ssam char *host; 4410296Ssam int port; 4510296Ssam { 4625904Skarels register struct hostent *hp = 0; 4726048Sminshall int s,len,oldverbose; 4825904Skarels static char hostnamebuf[80]; 4926048Sminshall char msg[2]; 5010296Ssam 5110296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 5225904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 5325904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 5425904Skarels hisctladdr.sin_family = AF_INET; 5525904Skarels (void) strcpy(hostnamebuf, host); 5626048Sminshall } 5726048Sminshall else { 5825100Sbloom hp = gethostbyname(host); 5925904Skarels if (hp == NULL) { 6025904Skarels printf("%s: unknown host\n", host); 6126048Sminshall code = -1; 6226048Sminshall return((char *) 0); 6325904Skarels } 6425904Skarels hisctladdr.sin_family = hp->h_addrtype; 6525904Skarels bcopy(hp->h_addr_list[0], 6625904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 6725904Skarels (void) strcpy(hostnamebuf, hp->h_name); 6810296Ssam } 6925904Skarels hostname = hostnamebuf; 7025904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 7110296Ssam if (s < 0) { 7210296Ssam perror("ftp: socket"); 7326048Sminshall code = -1; 7410296Ssam return (0); 7510296Ssam } 7610296Ssam hisctladdr.sin_port = port; 7725904Skarels while (connect(s, (caddr_t)&hisctladdr, sizeof (hisctladdr)) < 0) { 7825904Skarels if (hp && hp->h_addr_list[1]) { 7925904Skarels int oerrno = errno; 8025904Skarels 8125904Skarels fprintf(stderr, "ftp: connect to address %s: ", 8225904Skarels inet_ntoa(hisctladdr.sin_addr)); 8325904Skarels errno = oerrno; 8425904Skarels perror(0); 8525904Skarels hp->h_addr_list++; 8625904Skarels bcopy(hp->h_addr_list[0], 8726048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 8825904Skarels fprintf(stderr, "Trying %s...\n", 8925904Skarels inet_ntoa(hisctladdr.sin_addr)); 9025904Skarels continue; 9125904Skarels } 9210296Ssam perror("ftp: connect"); 9326048Sminshall code = -1; 9410296Ssam goto bad; 9510296Ssam } 9611627Ssam len = sizeof (myctladdr); 9711627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 9811627Ssam perror("ftp: getsockname"); 9926048Sminshall code = -1; 10010296Ssam goto bad; 10110296Ssam } 10210296Ssam cin = fdopen(s, "r"); 10310296Ssam cout = fdopen(s, "w"); 10411219Ssam if (cin == NULL || cout == NULL) { 10510296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 10610296Ssam if (cin) 10710296Ssam fclose(cin); 10810296Ssam if (cout) 10910296Ssam fclose(cout); 11026048Sminshall code = -1; 11110296Ssam goto bad; 11210296Ssam } 11310296Ssam if (verbose) 11426067Sminshall printf("Connected to %s.\n", hostname); 11526048Sminshall if (getreply(0) != 2) { /* read startup message from server */ 11626048Sminshall if (cin) 11726048Sminshall fclose(cin); 11826048Sminshall if (cout) 11926048Sminshall fclose(cout); 12026048Sminshall code = -1; 12126048Sminshall goto bad; 12226048Sminshall } 12326048Sminshall 12426048Sminshall /* test to see if server command parser understands TELNET SYNC command */ 12526048Sminshall 12626048Sminshall fprintf(cout,"%c%c",IAC,NOP); 12726048Sminshall (void) fflush(cout); 12826048Sminshall *msg = IAC; 12926048Sminshall *(msg+1) = DM; 130*26448Slepreau if (send(s,msg,2,MSG_OOB) != 2) 13126048Sminshall perror("sync"); 13226048Sminshall oldverbose = verbose; 133*26448Slepreau if (!debug) 13426048Sminshall verbose = -1; 135*26448Slepreau if (command("NOOP") == COMPLETE) 13626048Sminshall telflag = 1; 137*26448Slepreau else 13826048Sminshall telflag = 0; 13926048Sminshall verbose = oldverbose; 14025904Skarels return (hostname); 14110296Ssam bad: 14210296Ssam close(s); 14325904Skarels return ((char *)0); 14410296Ssam } 14510296Ssam 14625904Skarels login(host) 14725904Skarels char *host; 14810296Ssam { 14926048Sminshall char tmp[80]; 15026048Sminshall char *user, *pass, *acct, *getlogin(), *getpass(); 15126048Sminshall int n, aflag = 0; 15210296Ssam 15326048Sminshall user = pass = acct = 0; 15426048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 15526048Sminshall disconnect(); 15626048Sminshall code = -1; 15726048Sminshall return(0); 15826048Sminshall } 15926048Sminshall if (user == NULL) { 16026048Sminshall char *myname = getlogin(); 16126048Sminshall 16226048Sminshall if (myname == NULL) { 16326048Sminshall struct passwd *pp = getpwuid(getuid()); 16426048Sminshall 165*26448Slepreau if (pp != NULL) 16626048Sminshall myname = pp->pw_name; 16726048Sminshall } 16826048Sminshall printf("Name (%s:%s): ", host, myname); 16926048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 17026048Sminshall tmp[strlen(tmp) - 1] = '\0'; 171*26448Slepreau if (*tmp == '\0') 17226048Sminshall user = myname; 173*26448Slepreau else 17426048Sminshall user = tmp; 17526048Sminshall } 17610296Ssam n = command("USER %s", user); 17726048Sminshall if (n == CONTINUE) { 178*26448Slepreau if (pass == NULL) 17926048Sminshall pass = getpass("Password:"); 18010296Ssam n = command("PASS %s", pass); 18126048Sminshall } 18210296Ssam if (n == CONTINUE) { 18326048Sminshall aflag++; 18426048Sminshall acct = getpass("Account:"); 18510296Ssam n = command("ACCT %s", acct); 18610296Ssam } 18710296Ssam if (n != COMPLETE) { 18810296Ssam fprintf(stderr, "Login failed.\n"); 18910296Ssam return (0); 19010296Ssam } 191*26448Slepreau if (!aflag && acct != NULL) 19226048Sminshall (void) command("ACCT %s", acct); 193*26448Slepreau if (proxy) 19426048Sminshall return(1); 19526048Sminshall for (n = 0; n < macnum; ++n) { 19626048Sminshall if (!strcmp("init", macros[n].mac_name)) { 19726048Sminshall strcpy(line, "$init"); 19826048Sminshall makeargv(); 19926048Sminshall domacro(margc, margv); 20026048Sminshall break; 20126048Sminshall } 20226048Sminshall } 20310296Ssam return (1); 20410296Ssam } 20510296Ssam 20626048Sminshall cmdabort() 20726048Sminshall { 20826048Sminshall extern jmp_buf ptabort; 20926048Sminshall 21026048Sminshall printf("\n"); 21126048Sminshall (void) fflush(stdout); 21226048Sminshall abrtflag++; 213*26448Slepreau if (ptflag) 21426048Sminshall longjmp(ptabort,1); 21526048Sminshall } 21626048Sminshall 21710296Ssam /*VARARGS 1*/ 21810296Ssam command(fmt, args) 21910296Ssam char *fmt; 22010296Ssam { 22126048Sminshall int r, (*oldintr)(), cmdabort(); 22210296Ssam 22326048Sminshall abrtflag = 0; 22410296Ssam if (debug) { 22510296Ssam printf("---> "); 22610296Ssam _doprnt(fmt, &args, stdout); 22710296Ssam printf("\n"); 22810296Ssam (void) fflush(stdout); 22910296Ssam } 23011219Ssam if (cout == NULL) { 23111219Ssam perror ("No control connection for command"); 23226048Sminshall code = -1; 23311219Ssam return (0); 23411219Ssam } 23526048Sminshall oldintr = signal(SIGINT,cmdabort); 23610296Ssam _doprnt(fmt, &args, cout); 23710296Ssam fprintf(cout, "\r\n"); 23810296Ssam (void) fflush(cout); 23926048Sminshall cpend = 1; 24026048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 241*26448Slepreau if (abrtflag && oldintr != SIG_IGN) 24226048Sminshall (*oldintr)(); 24326048Sminshall (void) signal(SIGINT, oldintr); 24426048Sminshall return(r); 24510296Ssam } 24610296Ssam 24710296Ssam #include <ctype.h> 24810296Ssam 24910296Ssam getreply(expecteof) 25010296Ssam int expecteof; 25110296Ssam { 25211219Ssam register int c, n; 25326048Sminshall register int dig; 25426048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 25526048Sminshall int pflag = 0; 25626048Sminshall char *pt = pasv; 25710296Ssam 25826048Sminshall oldintr = signal(SIGINT,cmdabort); 25910296Ssam for (;;) { 26010296Ssam dig = n = code = 0; 26110296Ssam while ((c = getc(cin)) != '\n') { 26210296Ssam dig++; 26310296Ssam if (c == EOF) { 26426048Sminshall if (expecteof) { 26526048Sminshall (void) signal(SIGINT,oldintr); 26626048Sminshall code = 221; 26710296Ssam return (0); 26826048Sminshall } 26910296Ssam lostpeer(); 27026048Sminshall if (verbose) { 27126048Sminshall printf("421 Service not available, remote server has closed connection\n"); 27226048Sminshall (void) fflush(stdout); 27326048Sminshall code = 421; 27426048Sminshall return(4); 27526048Sminshall } 27610296Ssam } 27726048Sminshall if (c != '\r' && (verbose > 0 || 27826048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 279*26448Slepreau if (proxflag && 280*26448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 28126048Sminshall printf("%s:",hostname); 28210296Ssam putchar(c); 28326048Sminshall } 28410296Ssam if (dig < 4 && isdigit(c)) 28510296Ssam code = code * 10 + (c - '0'); 286*26448Slepreau if (!pflag && code == 227) 28726048Sminshall pflag = 1; 288*26448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 28926048Sminshall pflag = 2; 29026048Sminshall if (pflag == 2) { 291*26448Slepreau if (c != '\r' && c != ')') 29226048Sminshall *pt++ = c; 29326048Sminshall else { 29426048Sminshall *pt = '\0'; 29526048Sminshall pflag = 3; 29626048Sminshall } 29726048Sminshall } 29826048Sminshall if (dig == 4 && c == '-') { 299*26448Slepreau if (continuation) 30026048Sminshall code = 0; 30110296Ssam continuation++; 30226048Sminshall } 30310296Ssam if (n == 0) 30410296Ssam n = c; 30510296Ssam } 30626048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 30710296Ssam putchar(c); 30811346Ssam (void) fflush (stdout); 30911346Ssam } 31010296Ssam if (continuation && code != originalcode) { 31110296Ssam if (originalcode == 0) 31210296Ssam originalcode = code; 31310296Ssam continue; 31410296Ssam } 315*26448Slepreau if (n != '1') 31626048Sminshall cpend = 0; 31726048Sminshall (void) signal(SIGINT,oldintr); 318*26448Slepreau if (code == 421 || originalcode == 421) 31926048Sminshall lostpeer(); 320*26448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 32126048Sminshall (*oldintr)(); 32225907Smckusick return (n - '0'); 32310296Ssam } 32410296Ssam } 32510296Ssam 32626048Sminshall empty(mask, sec) 32726048Sminshall long mask; 32826048Sminshall int sec; 32926048Sminshall { 33026048Sminshall struct timeval t; 33126048Sminshall 33226048Sminshall t.tv_sec = (long) sec; 33326048Sminshall t.tv_usec = 0; 334*26448Slepreau if (select(20, &mask, 0, 0, &t) < 0) 33526048Sminshall return(-1); 33626048Sminshall return (mask); 33726048Sminshall } 33826048Sminshall 33910296Ssam jmp_buf sendabort; 34010296Ssam 34110296Ssam abortsend() 34210296Ssam { 34310296Ssam 34426048Sminshall mflag = 0; 34526048Sminshall abrtflag = 0; 34626048Sminshall printf("\nsend aborted\n"); 34726048Sminshall (void) fflush(stdout); 34810296Ssam longjmp(sendabort, 1); 34910296Ssam } 35010296Ssam 35110296Ssam sendrequest(cmd, local, remote) 35210296Ssam char *cmd, *local, *remote; 35310296Ssam { 35426048Sminshall FILE *fin, *dout = 0, *popen(); 35526048Sminshall int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 35626048Sminshall int abortsend(); 35711219Ssam char buf[BUFSIZ]; 35811651Ssam long bytes = 0, hashbytes = sizeof (buf); 35911346Ssam register int c, d; 36010296Ssam struct stat st; 36110296Ssam struct timeval start, stop; 36210296Ssam 36326048Sminshall if (proxy) { 36426048Sminshall proxtrans(cmd, local, remote); 36526048Sminshall return; 36626048Sminshall } 36710296Ssam closefunc = NULL; 36826048Sminshall oldintr = NULL; 36926048Sminshall oldintp = NULL; 37026048Sminshall if (setjmp(sendabort)) { 37126048Sminshall while (cpend) { 37226048Sminshall (void) getreply(0); 37326048Sminshall } 37426048Sminshall if (data >= 0) { 37526048Sminshall (void) close(data); 37626048Sminshall data = -1; 37726048Sminshall } 378*26448Slepreau if (oldintr) 37926048Sminshall (void) signal(SIGINT,oldintr); 380*26448Slepreau if (oldintp) 38126048Sminshall (void) signal(SIGPIPE,oldintp); 38226048Sminshall code = -1; 38326048Sminshall return; 38426048Sminshall } 38510296Ssam oldintr = signal(SIGINT, abortsend); 38610296Ssam if (strcmp(local, "-") == 0) 38710296Ssam fin = stdin; 38810296Ssam else if (*local == '|') { 38926048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 39026048Sminshall fin = popen(local + 1, "r"); 39110296Ssam if (fin == NULL) { 39226048Sminshall perror(local + 1); 39326048Sminshall (void) signal(SIGINT, oldintr); 39426048Sminshall (void) signal(SIGPIPE, oldintp); 39526048Sminshall code = -1; 39626048Sminshall return; 39710296Ssam } 39810296Ssam closefunc = pclose; 39910296Ssam } else { 40010296Ssam fin = fopen(local, "r"); 40110296Ssam if (fin == NULL) { 40210296Ssam perror(local); 40326048Sminshall (void) signal(SIGINT, oldintr); 40426048Sminshall code = -1; 40526048Sminshall return; 40610296Ssam } 40710296Ssam closefunc = fclose; 40810296Ssam if (fstat(fileno(fin), &st) < 0 || 40910296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 41017949Sralph fprintf(stderr, "%s: not a plain file.\n", local); 41126048Sminshall (void) signal(SIGINT, oldintr); 41226048Sminshall code = -1; 41326048Sminshall return; 41410296Ssam } 41510296Ssam } 41626048Sminshall if (initconn()) { 41726048Sminshall (void) signal(SIGINT, oldintr); 418*26448Slepreau if (oldintp) 41926048Sminshall (void) signal(SIGPIPE, oldintp); 42026048Sminshall code = -1; 42126048Sminshall return; 42226048Sminshall } 423*26448Slepreau if (setjmp(sendabort)) 42426048Sminshall goto abort; 42510296Ssam if (remote) { 42626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 42726048Sminshall (void) signal(SIGINT, oldintr); 428*26448Slepreau if (oldintp) 42926048Sminshall (void) signal(SIGPIPE, oldintp); 43026048Sminshall return; 43126048Sminshall } 43210296Ssam } else 43326048Sminshall if (command("%s", cmd) != PRELIM) { 43426048Sminshall (void) signal(SIGINT, oldintr); 435*26448Slepreau if (oldintp) 43626048Sminshall (void) signal(SIGPIPE, oldintp); 43726048Sminshall return; 43826048Sminshall } 43910296Ssam dout = dataconn("w"); 440*26448Slepreau if (dout == NULL) 44126048Sminshall goto abort; 44210296Ssam gettimeofday(&start, (struct timezone *)0); 44311219Ssam switch (type) { 44411219Ssam 44511219Ssam case TYPE_I: 44611219Ssam case TYPE_L: 44711346Ssam errno = d = 0; 44811219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 44911346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 45011219Ssam break; 45111219Ssam bytes += c; 45211651Ssam if (hash) { 45311651Ssam putchar('#'); 45411651Ssam fflush(stdout); 45511651Ssam } 45611219Ssam } 45713213Ssam if (hash && bytes > 0) { 45811651Ssam putchar('\n'); 45911651Ssam fflush(stdout); 46011651Ssam } 46111219Ssam if (c < 0) 46211219Ssam perror(local); 46311346Ssam if (d < 0) 46411219Ssam perror("netout"); 46511219Ssam break; 46611219Ssam 46711219Ssam case TYPE_A: 46811219Ssam while ((c = getc(fin)) != EOF) { 46911219Ssam if (c == '\n') { 47011651Ssam while (hash && (bytes >= hashbytes)) { 47111651Ssam putchar('#'); 47211651Ssam fflush(stdout); 47311651Ssam hashbytes += sizeof (buf); 47411651Ssam } 47511219Ssam if (ferror(dout)) 47611219Ssam break; 47711219Ssam putc('\r', dout); 47811219Ssam bytes++; 47911219Ssam } 48011219Ssam putc(c, dout); 48111219Ssam bytes++; 48226048Sminshall /* if (c == '\r') { */ 48326048Sminshall /* putc('\0', dout); /* this violates rfc */ 48426048Sminshall /* bytes++; */ 48526048Sminshall /* } */ 48611219Ssam } 48711651Ssam if (hash) { 48813213Ssam if (bytes < hashbytes) 48913213Ssam putchar('#'); 49011651Ssam putchar('\n'); 49111651Ssam fflush(stdout); 49211651Ssam } 49311219Ssam if (ferror(fin)) 49411219Ssam perror(local); 49511346Ssam if (ferror(dout)) 49611219Ssam perror("netout"); 49711219Ssam break; 49810296Ssam } 49910296Ssam gettimeofday(&stop, (struct timezone *)0); 50010296Ssam if (closefunc != NULL) 50126048Sminshall (*closefunc)(fin); 50210296Ssam (void) fclose(dout); 50326048Sminshall (void) getreply(0); 50426048Sminshall (void) signal(SIGINT, oldintr); 50510296Ssam if (bytes > 0 && verbose) 50626048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 50710296Ssam return; 50826048Sminshall abort: 50926048Sminshall gettimeofday(&stop, (struct timezone *)0); 51026048Sminshall (void) signal(SIGINT, oldintr); 511*26448Slepreau if (oldintp) 51226048Sminshall (void) signal(SIGPIPE, oldintp); 51326048Sminshall if (!cpend) { 51426048Sminshall code = -1; 51526048Sminshall return; 51626048Sminshall } 51726048Sminshall if (data >= 0) { 51826048Sminshall (void) close(data); 51926048Sminshall data = -1; 52026048Sminshall } 521*26448Slepreau if (dout) 52226048Sminshall (void) fclose(dout); 52326048Sminshall (void) getreply(0); 52426048Sminshall code = -1; 52510296Ssam if (closefunc != NULL && fin != NULL) 52626048Sminshall (*closefunc)(fin); 52726048Sminshall if (bytes > 0 && verbose) 52826048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 52910296Ssam } 53010296Ssam 53110296Ssam jmp_buf recvabort; 53210296Ssam 53310296Ssam abortrecv() 53410296Ssam { 53510296Ssam 53626048Sminshall mflag = 0; 53726048Sminshall abrtflag = 0; 53826048Sminshall printf("\n"); 53926048Sminshall (void) fflush(stdout); 54010296Ssam longjmp(recvabort, 1); 54110296Ssam } 54210296Ssam 54311651Ssam recvrequest(cmd, local, remote, mode) 54411651Ssam char *cmd, *local, *remote, *mode; 54510296Ssam { 54626048Sminshall FILE *fout, *din = 0, *popen(); 54726048Sminshall int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 54826048Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag; 54926048Sminshall char buf[BUFSIZ], *gunique(); 55026048Sminshall long bytes = 0, hashbytes = sizeof (buf), mask; 55111346Ssam register int c, d; 55210296Ssam struct timeval start, stop; 55310296Ssam 55426048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 55526048Sminshall proxtrans(cmd, local, remote); 55626048Sminshall return; 55726048Sminshall } 55810296Ssam closefunc = NULL; 55926048Sminshall oldintr = NULL; 56026048Sminshall oldintp = NULL; 56126048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 56226048Sminshall if (setjmp(recvabort)) { 56326048Sminshall while (cpend) { 56426048Sminshall (void) getreply(0); 56526048Sminshall } 56626048Sminshall if (data >= 0) { 56726048Sminshall (void) close(data); 56826048Sminshall data = -1; 56926048Sminshall } 570*26448Slepreau if (oldintr) 57126048Sminshall (void) signal(SIGINT, oldintr); 57226048Sminshall code = -1; 57326048Sminshall return; 57426048Sminshall } 57510296Ssam oldintr = signal(SIGINT, abortrecv); 57626048Sminshall if (strcmp(local, "-") && *local != '|') { 57710296Ssam if (access(local, 2) < 0) { 57826048Sminshall char *dir = rindex(local, '/'); 57910296Ssam 58026048Sminshall if (errno != ENOENT && errno != EACCES) { 58110296Ssam perror(local); 58226048Sminshall (void) signal(SIGINT, oldintr); 58326048Sminshall code = -1; 58426048Sminshall return; 58510296Ssam } 58626048Sminshall if (dir != NULL) 58726048Sminshall *dir = 0; 58826048Sminshall d = access(dir ? local : ".", 2); 58926048Sminshall if (dir != NULL) 59026048Sminshall *dir = '/'; 59126048Sminshall if (d < 0) { 59226048Sminshall perror(local); 59326048Sminshall (void) signal(SIGINT, oldintr); 59426048Sminshall code = -1; 59526048Sminshall return; 59626048Sminshall } 59726048Sminshall if (!runique && errno == EACCES && 59826048Sminshall chmod(local,0600) < 0) { 59926048Sminshall perror(local); 60026048Sminshall (void) signal(SIGINT, oldintr); 60126048Sminshall code = -1; 60226048Sminshall return; 60326048Sminshall } 60426048Sminshall if (runique && errno == EACCES && 60526048Sminshall (local = gunique(local)) == NULL) { 60626048Sminshall (void) signal(SIGINT, oldintr); 60726048Sminshall code = -1; 60826048Sminshall return; 60926048Sminshall } 61010296Ssam } 61126048Sminshall else if (runique && (local = gunique(local)) == NULL) { 61226048Sminshall (void) signal(SIGINT, oldintr); 61326048Sminshall code = -1; 61426048Sminshall return; 61526048Sminshall } 61626048Sminshall } 61726048Sminshall if (initconn()) { 61826048Sminshall (void) signal(SIGINT, oldintr); 61926048Sminshall code = -1; 62026048Sminshall return; 62126048Sminshall } 622*26448Slepreau if (setjmp(recvabort)) 62326048Sminshall goto abort; 62426048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 62526048Sminshall oldtype = type; 62626048Sminshall oldverbose = verbose; 627*26448Slepreau if (!debug) 62826048Sminshall verbose = 0; 62926048Sminshall setascii(); 63026048Sminshall verbose = oldverbose; 63126048Sminshall } 63210296Ssam if (remote) { 63326048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 63426048Sminshall (void) signal(SIGINT, oldintr); 63526048Sminshall if (oldtype) { 636*26448Slepreau if (!debug) 63726048Sminshall verbose = 0; 63826048Sminshall switch (oldtype) { 63926048Sminshall case TYPE_I: 64026048Sminshall setbinary(); 64126048Sminshall break; 64226048Sminshall case TYPE_E: 64326048Sminshall setebcdic(); 64426048Sminshall break; 64526048Sminshall case TYPE_L: 64626048Sminshall settenex(); 64726048Sminshall break; 64826048Sminshall } 64926048Sminshall verbose = oldverbose; 65026048Sminshall } 65126048Sminshall return; 65226048Sminshall } 65326048Sminshall } else { 65426048Sminshall if (command("%s", cmd) != PRELIM) { 65526048Sminshall (void) signal(SIGINT, oldintr); 65626048Sminshall if (oldtype) { 657*26448Slepreau if (!debug) 65826048Sminshall verbose = 0; 65926048Sminshall switch (oldtype) { 66026048Sminshall case TYPE_I: 66126048Sminshall setbinary(); 66226048Sminshall break; 66326048Sminshall case TYPE_E: 66426048Sminshall setebcdic(); 66526048Sminshall break; 66626048Sminshall case TYPE_L: 66726048Sminshall settenex(); 66826048Sminshall break; 66926048Sminshall } 67026048Sminshall verbose = oldverbose; 67126048Sminshall } 67226048Sminshall return; 67326048Sminshall } 67426048Sminshall } 67526048Sminshall din = dataconn("r"); 67626048Sminshall if (din == NULL) 67726048Sminshall goto abort; 678*26448Slepreau if (strcmp(local, "-") == 0) 67910296Ssam fout = stdout; 68010296Ssam else if (*local == '|') { 68126048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 68226048Sminshall fout = popen(local + 1, "w"); 68326048Sminshall if (fout == NULL) { 68426048Sminshall perror(local+1); 68526048Sminshall goto abort; 68626048Sminshall } 68710296Ssam closefunc = pclose; 68826048Sminshall } 68926048Sminshall else { 69011651Ssam fout = fopen(local, mode); 69126048Sminshall if (fout == NULL) { 69226048Sminshall perror(local); 69326048Sminshall goto abort; 69426048Sminshall } 69510296Ssam closefunc = fclose; 69610296Ssam } 69710296Ssam gettimeofday(&start, (struct timezone *)0); 69811219Ssam switch (type) { 69911219Ssam 70011219Ssam case TYPE_I: 70111219Ssam case TYPE_L: 70211346Ssam errno = d = 0; 70311219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 70411346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 70511219Ssam break; 70611219Ssam bytes += c; 70711651Ssam if (hash) { 70811651Ssam putchar('#'); 70911651Ssam fflush(stdout); 71011651Ssam } 71111219Ssam } 71213213Ssam if (hash && bytes > 0) { 71311651Ssam putchar('\n'); 71411651Ssam fflush(stdout); 71511651Ssam } 71611219Ssam if (c < 0) 71711219Ssam perror("netin"); 71811346Ssam if (d < 0) 71910296Ssam perror(local); 72011219Ssam break; 72111219Ssam 72211219Ssam case TYPE_A: 72311219Ssam while ((c = getc(din)) != EOF) { 72411219Ssam if (c == '\r') { 72511651Ssam while (hash && (bytes >= hashbytes)) { 72611651Ssam putchar('#'); 72711651Ssam fflush(stdout); 72811651Ssam hashbytes += sizeof (buf); 72911651Ssam } 73010296Ssam bytes++; 73126048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 73211219Ssam if (ferror (fout)) 73311219Ssam break; 73411219Ssam putc ('\r', fout); 73511219Ssam } 73626048Sminshall /*if (c == '\0') { 73711219Ssam bytes++; 73811219Ssam continue; 73926048Sminshall }*/ 74011219Ssam } 74111219Ssam putc (c, fout); 74211219Ssam bytes++; 74310296Ssam } 74411651Ssam if (hash) { 74513213Ssam if (bytes < hashbytes) 74613213Ssam putchar('#'); 74711651Ssam putchar('\n'); 74811651Ssam fflush(stdout); 74911651Ssam } 75011219Ssam if (ferror (din)) 75111219Ssam perror ("netin"); 75211219Ssam if (ferror (fout)) 75311219Ssam perror (local); 75411219Ssam break; 75510296Ssam } 756*26448Slepreau if (closefunc != NULL) 75726048Sminshall (*closefunc)(fout); 75826048Sminshall signal(SIGINT, oldintr); 759*26448Slepreau if (oldintp) 76026048Sminshall (void) signal(SIGPIPE, oldintp); 76110296Ssam gettimeofday(&stop, (struct timezone *)0); 76210296Ssam (void) fclose(din); 76326048Sminshall (void) getreply(0); 76426048Sminshall if (bytes > 0 && verbose) 76526048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 76626048Sminshall if (oldtype) { 767*26448Slepreau if (!debug) 76826048Sminshall verbose = 0; 76926048Sminshall switch (oldtype) { 77026048Sminshall case TYPE_I: 77126048Sminshall setbinary(); 77226048Sminshall break; 77326048Sminshall case TYPE_E: 77426048Sminshall setebcdic(); 77526048Sminshall break; 77626048Sminshall case TYPE_L: 77726048Sminshall settenex(); 77826048Sminshall break; 77926048Sminshall } 78026048Sminshall verbose = oldverbose; 78126048Sminshall } 78226048Sminshall return; 78326048Sminshall abort: 78426048Sminshall 78526048Sminshall /* if server command parser understands TELNET commands, abort using */ 78626048Sminshall /* recommended IP,SYNC sequence */ 78726048Sminshall 78826048Sminshall gettimeofday(&stop, (struct timezone *)0); 789*26448Slepreau if (oldintp) 79026048Sminshall (void) signal(SIGPIPE, oldintr); 79126048Sminshall (void) signal(SIGINT,SIG_IGN); 79226048Sminshall if (oldtype) { 793*26448Slepreau if (!debug) 79426048Sminshall verbose = 0; 79526048Sminshall switch (oldtype) { 79626048Sminshall case TYPE_I: 79726048Sminshall setbinary(); 79826048Sminshall break; 79926048Sminshall case TYPE_E: 80026048Sminshall setebcdic(); 80126048Sminshall break; 80226048Sminshall case TYPE_L: 80326048Sminshall settenex(); 80426048Sminshall break; 80526048Sminshall } 80626048Sminshall verbose = oldverbose; 80726048Sminshall } 80826048Sminshall if (!cpend) { 80926048Sminshall code = -1; 81026048Sminshall (void) signal(SIGINT,oldintr); 81126048Sminshall return; 81226048Sminshall } 81326048Sminshall if (telflag) { 81426048Sminshall char msg[2]; 81526048Sminshall 81626048Sminshall fprintf(cout,"%c%c",IAC,IP); 81726048Sminshall (void) fflush(cout); 81826048Sminshall *msg = IAC; 81926048Sminshall *(msg+1) = DM; 820*26448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 82126048Sminshall perror("abort"); 82226048Sminshall } 82326048Sminshall fprintf(cout,"ABOR\r\n"); 82426048Sminshall (void) fflush(cout); 82526048Sminshall mask = (1 << fileno(cin)) | (din ? (1 << fileno(din)) : 0); 82626048Sminshall if ((mask = empty(mask,10)) < 0) { 82726048Sminshall perror("abort"); 82826048Sminshall code = -1; 82926048Sminshall lostpeer(); 83026048Sminshall } 831*26448Slepreau if (din && mask & (1 << fileno(din))) 832*26448Slepreau while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 833*26448Slepreau ; 83426048Sminshall if ((c = getreply(0)) == ERROR) { /* needed for nic style abort */ 83526048Sminshall if (data >= 0) { 83626048Sminshall close(data); 83726048Sminshall data = -1; 83826048Sminshall } 83925907Smckusick (void) getreply(0); 84025907Smckusick } 84126048Sminshall (void) getreply(0); 84226048Sminshall code = -1; 84326048Sminshall if (data >= 0) { 84426048Sminshall (void) close(data); 84526048Sminshall data = -1; 84626048Sminshall } 847*26448Slepreau if (closefunc != NULL && fout != NULL) 84826048Sminshall (*closefunc)(fout); 849*26448Slepreau if (din) 85026048Sminshall (void) fclose(din); 85110296Ssam if (bytes > 0 && verbose) 85226048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 85326048Sminshall (void) signal(SIGINT,oldintr); 85410296Ssam } 85510296Ssam 85610296Ssam /* 85710296Ssam * Need to start a listen on the data channel 85810296Ssam * before we send the command, otherwise the 85910296Ssam * server's connect may fail. 86010296Ssam */ 86111651Ssam static int sendport = -1; 86211651Ssam 86310296Ssam initconn() 86410296Ssam { 86510296Ssam register char *p, *a; 86626048Sminshall int result, len, tmpno = 0; 86717450Slepreau int on = 1; 86810296Ssam 86911651Ssam noport: 87010296Ssam data_addr = myctladdr; 87111651Ssam if (sendport) 87211651Ssam data_addr.sin_port = 0; /* let system pick one */ 87311651Ssam if (data != -1) 87411651Ssam (void) close (data); 87518287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 87610296Ssam if (data < 0) { 87710296Ssam perror("ftp: socket"); 878*26448Slepreau if (tmpno) 87926048Sminshall sendport = 1; 88010296Ssam return (1); 88110296Ssam } 88212397Ssam if (!sendport) 88317450Slepreau if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { 88426048Sminshall perror("ftp: setsockopt (resuse address)"); 88512397Ssam goto bad; 88612397Ssam } 88710296Ssam if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { 88810296Ssam perror("ftp: bind"); 88910296Ssam goto bad; 89010296Ssam } 89110296Ssam if (options & SO_DEBUG && 89217450Slepreau setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 89310296Ssam perror("ftp: setsockopt (ignored)"); 89411627Ssam len = sizeof (data_addr); 89511627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 89611627Ssam perror("ftp: getsockname"); 89710296Ssam goto bad; 89810296Ssam } 899*26448Slepreau if (listen(data, 1) < 0) 90010296Ssam perror("ftp: listen"); 90111651Ssam if (sendport) { 90211651Ssam a = (char *)&data_addr.sin_addr; 90311651Ssam p = (char *)&data_addr.sin_port; 90410296Ssam #define UC(b) (((int)b)&0xff) 90511651Ssam result = 90611651Ssam command("PORT %d,%d,%d,%d,%d,%d", 90711651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 90811651Ssam UC(p[0]), UC(p[1])); 90911651Ssam if (result == ERROR && sendport == -1) { 91011651Ssam sendport = 0; 91126048Sminshall tmpno = 1; 91211651Ssam goto noport; 91311651Ssam } 91411651Ssam return (result != COMPLETE); 91511651Ssam } 916*26448Slepreau if (tmpno) 91726048Sminshall sendport = 1; 91811651Ssam return (0); 91910296Ssam bad: 92010296Ssam (void) close(data), data = -1; 921*26448Slepreau if (tmpno) 92226048Sminshall sendport = 1; 92310296Ssam return (1); 92410296Ssam } 92510296Ssam 92610296Ssam FILE * 92710296Ssam dataconn(mode) 92810296Ssam char *mode; 92910296Ssam { 93010296Ssam struct sockaddr_in from; 93110296Ssam int s, fromlen = sizeof (from); 93210296Ssam 93310296Ssam s = accept(data, &from, &fromlen, 0); 93410296Ssam if (s < 0) { 93510296Ssam perror("ftp: accept"); 93610296Ssam (void) close(data), data = -1; 93710296Ssam return (NULL); 93810296Ssam } 93910296Ssam (void) close(data); 94010296Ssam data = s; 94110296Ssam return (fdopen(data, mode)); 94210296Ssam } 94310296Ssam 94426048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 94526048Sminshall char *direction, *local, *remote; 94611651Ssam long bytes; 94710296Ssam struct timeval *t0, *t1; 94810296Ssam { 94910296Ssam struct timeval td; 95016437Sleres float s, bs; 95110296Ssam 95210296Ssam tvsub(&td, t1, t0); 95316437Sleres s = td.tv_sec + (td.tv_usec / 1000000.); 95410296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 95516437Sleres bs = bytes / nz(s); 956*26448Slepreau if (local && *local != '-') 95726048Sminshall printf("local: %s ", local); 958*26448Slepreau if (remote) 95926048Sminshall printf("remote: %s\n", remote); 96016437Sleres printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 96116437Sleres bytes, direction, s, bs / 1024.); 96210296Ssam } 96310296Ssam 96410296Ssam tvadd(tsum, t0) 96510296Ssam struct timeval *tsum, *t0; 96610296Ssam { 96710296Ssam 96810296Ssam tsum->tv_sec += t0->tv_sec; 96910296Ssam tsum->tv_usec += t0->tv_usec; 97010296Ssam if (tsum->tv_usec > 1000000) 97110296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 97210296Ssam } 97310296Ssam 97410296Ssam tvsub(tdiff, t1, t0) 97510296Ssam struct timeval *tdiff, *t1, *t0; 97610296Ssam { 97710296Ssam 97810296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 97910296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 98010296Ssam if (tdiff->tv_usec < 0) 98110296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 98210296Ssam } 98326048Sminshall 98426048Sminshall psabort() 98526048Sminshall { 98626048Sminshall extern int abrtflag; 98726048Sminshall 98826048Sminshall abrtflag++; 98926048Sminshall } 99026048Sminshall 99126048Sminshall pswitch(flag) 99226048Sminshall int flag; 99326048Sminshall { 99426048Sminshall extern int proxy, abrtflag; 99526048Sminshall int (*oldintr)(); 99626048Sminshall static struct comvars { 99726048Sminshall int connect; 99826048Sminshall char name[32]; 99926048Sminshall struct sockaddr_in mctl; 100026048Sminshall struct sockaddr_in hctl; 100126048Sminshall FILE *in; 100226048Sminshall FILE *out; 100326048Sminshall int tflag; 100426048Sminshall int tpe; 100526048Sminshall int cpnd; 100626048Sminshall int sunqe; 100726048Sminshall int runqe; 100826048Sminshall int mcse; 100926048Sminshall int ntflg; 101026048Sminshall char nti[17]; 101126048Sminshall char nto[17]; 101226048Sminshall int mapflg; 101326048Sminshall char mi[MAXPATHLEN]; 101426048Sminshall char mo[MAXPATHLEN]; 101526048Sminshall } proxstruct, tmpstruct; 101626048Sminshall struct comvars *ip, *op; 101726048Sminshall 101826048Sminshall abrtflag = 0; 101926048Sminshall oldintr = signal(SIGINT, psabort); 102026048Sminshall if (flag) { 1021*26448Slepreau if (proxy) 102226048Sminshall return; 102326048Sminshall ip = &tmpstruct; 102426048Sminshall op = &proxstruct; 102526048Sminshall proxy++; 102626048Sminshall } 102726048Sminshall else { 1028*26448Slepreau if (!proxy) 102926048Sminshall return; 103026048Sminshall ip = &proxstruct; 103126048Sminshall op = &tmpstruct; 103226048Sminshall proxy = 0; 103326048Sminshall } 103426048Sminshall ip->connect = connected; 103526048Sminshall connected = op->connect; 103626048Sminshall strncpy(ip->name, hostname, 31); 103726048Sminshall (ip->name)[strlen(ip->name)] = '\0'; 103826048Sminshall hostname = op->name; 103926048Sminshall ip->hctl = hisctladdr; 104026048Sminshall hisctladdr = op->hctl; 104126048Sminshall ip->mctl = myctladdr; 104226048Sminshall myctladdr = op->mctl; 104326048Sminshall ip->in = cin; 104426048Sminshall cin = op->in; 104526048Sminshall ip->out = cout; 104626048Sminshall cout = op->out; 104726048Sminshall ip->tflag = telflag; 104826048Sminshall telflag = op->tflag; 104926048Sminshall ip->tpe = type; 105026048Sminshall type = op->tpe; 1051*26448Slepreau if (!type) 105226048Sminshall type = 1; 105326048Sminshall ip->cpnd = cpend; 105426048Sminshall cpend = op->cpnd; 105526048Sminshall ip->sunqe = sunique; 105626048Sminshall sunique = op->sunqe; 105726048Sminshall ip->runqe = runique; 105826048Sminshall runique = op->runqe; 105926048Sminshall ip->mcse = mcase; 106026048Sminshall mcase = op->mcse; 106126048Sminshall ip->ntflg = ntflag; 106226048Sminshall ntflag = op->ntflg; 106326048Sminshall strncpy(ip->nti, ntin, 16); 106426048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 106526048Sminshall strcpy(ntin, op->nti); 106626048Sminshall strncpy(ip->nto, ntout, 16); 106726048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 106826048Sminshall strcpy(ntout, op->nto); 106926048Sminshall ip->mapflg = mapflag; 107026048Sminshall mapflag = op->mapflg; 107126048Sminshall strncpy(ip->mi, mapin, MAXPATHLEN - 1); 107226048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 107326048Sminshall strcpy(mapin, op->mi); 107426048Sminshall strncpy(ip->mo, mapout, MAXPATHLEN - 1); 107526048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 107626048Sminshall strcpy(mapout, op->mo); 107726048Sminshall (void) signal(SIGINT, oldintr); 107826048Sminshall if (abrtflag) { 107926048Sminshall abrtflag = 0; 108026048Sminshall (*oldintr)(); 1081*26448Slepreau } 108226048Sminshall } 108326048Sminshall 108426048Sminshall jmp_buf ptabort; 108526048Sminshall int ptabflg; 108626048Sminshall 108726048Sminshall abortpt() 108826048Sminshall { 108926048Sminshall printf("\n"); 109026048Sminshall fflush(stdout); 109126048Sminshall ptabflg++; 109226048Sminshall mflag = 0; 109326048Sminshall abrtflag = 0; 109426048Sminshall longjmp(ptabort, 1); 109526048Sminshall } 109626048Sminshall 109726048Sminshall proxtrans(cmd, local, remote) 109826048Sminshall char *cmd, *local, *remote; 109926048Sminshall { 110026048Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0; 110126048Sminshall extern jmp_buf ptabort; 110226048Sminshall char *cmd2; 110326048Sminshall long mask; 110426048Sminshall 1105*26448Slepreau if (strcmp(cmd, "RETR")) 110626048Sminshall cmd2 = "RETR"; 1107*26448Slepreau else 110826048Sminshall cmd2 = runique ? "STOU" : "STOR"; 110926048Sminshall if (command("PASV") != COMPLETE) { 111026048Sminshall printf("proxy server does not support third part transfers.\n"); 111126048Sminshall return; 111226048Sminshall } 111326048Sminshall tmptype = type; 111426048Sminshall pswitch(0); 111526048Sminshall if (!connected) { 111626048Sminshall printf("No primary connection\n"); 111726048Sminshall pswitch(1); 111826048Sminshall code = -1; 111926048Sminshall return; 112026048Sminshall } 112126048Sminshall if (type != tmptype) { 112226048Sminshall oldtype = type; 112326048Sminshall switch (tmptype) { 112426048Sminshall case TYPE_A: 112526048Sminshall setascii(); 112626048Sminshall break; 112726048Sminshall case TYPE_I: 112826048Sminshall setbinary(); 112926048Sminshall break; 113026048Sminshall case TYPE_E: 113126048Sminshall setebcdic(); 113226048Sminshall break; 113326048Sminshall case TYPE_L: 113426048Sminshall settenex(); 113526048Sminshall break; 113626048Sminshall } 113726048Sminshall } 113826048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 113926048Sminshall switch (oldtype) { 114026048Sminshall case 0: 114126048Sminshall break; 114226048Sminshall case TYPE_A: 114326048Sminshall setascii(); 114426048Sminshall break; 114526048Sminshall case TYPE_I: 114626048Sminshall setbinary(); 114726048Sminshall break; 114826048Sminshall case TYPE_E: 114926048Sminshall setebcdic(); 115026048Sminshall break; 115126048Sminshall case TYPE_L: 115226048Sminshall settenex(); 115326048Sminshall break; 115426048Sminshall } 115526048Sminshall pswitch(1); 115626048Sminshall return; 115726048Sminshall } 1158*26448Slepreau if (setjmp(ptabort)) 115926048Sminshall goto abort; 116026048Sminshall oldintr = signal(SIGINT, abortpt); 116126048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 116226048Sminshall (void) signal(SIGINT, oldintr); 116326048Sminshall switch (oldtype) { 116426048Sminshall case 0: 116526048Sminshall break; 116626048Sminshall case TYPE_A: 116726048Sminshall setascii(); 116826048Sminshall break; 116926048Sminshall case TYPE_I: 117026048Sminshall setbinary(); 117126048Sminshall break; 117226048Sminshall case TYPE_E: 117326048Sminshall setebcdic(); 117426048Sminshall break; 117526048Sminshall case TYPE_L: 117626048Sminshall settenex(); 117726048Sminshall break; 117826048Sminshall } 117926048Sminshall pswitch(1); 118026048Sminshall return; 118126048Sminshall } 118226048Sminshall sleep(2); 118326048Sminshall pswitch(1); 118426048Sminshall secndflag++; 1185*26448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 118626048Sminshall goto abort; 118726048Sminshall ptflag++; 118826048Sminshall (void) getreply(0); 118926048Sminshall pswitch(0); 119026048Sminshall (void) getreply(0); 119126048Sminshall (void) signal(SIGINT, oldintr); 119226048Sminshall switch (oldtype) { 119326048Sminshall case 0: 119426048Sminshall break; 119526048Sminshall case TYPE_A: 119626048Sminshall setascii(); 119726048Sminshall break; 119826048Sminshall case TYPE_I: 119926048Sminshall setbinary(); 120026048Sminshall break; 120126048Sminshall case TYPE_E: 120226048Sminshall setebcdic(); 120326048Sminshall break; 120426048Sminshall case TYPE_L: 120526048Sminshall settenex(); 120626048Sminshall break; 120726048Sminshall } 120826048Sminshall pswitch(1); 120926048Sminshall ptflag = 0; 121026048Sminshall printf("local: %s remote: %s\n", local, remote); 121126048Sminshall return; 121226048Sminshall abort: 121326048Sminshall (void) signal(SIGINT, SIG_IGN); 121426048Sminshall ptflag = 0; 1215*26448Slepreau if (strcmp(cmd, "RETR") && !proxy) 121626048Sminshall pswitch(1); 1217*26448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 121826048Sminshall pswitch(0); 121926048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 122026048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 122126048Sminshall pswitch(0); 122226048Sminshall switch (oldtype) { 122326048Sminshall case 0: 122426048Sminshall break; 122526048Sminshall case TYPE_A: 122626048Sminshall setascii(); 122726048Sminshall break; 122826048Sminshall case TYPE_I: 122926048Sminshall setbinary(); 123026048Sminshall break; 123126048Sminshall case TYPE_E: 123226048Sminshall setebcdic(); 123326048Sminshall break; 123426048Sminshall case TYPE_L: 123526048Sminshall settenex(); 123626048Sminshall break; 123726048Sminshall } 123826048Sminshall if (cpend && telflag) { 123926048Sminshall char msg[2]; 124026048Sminshall 124126048Sminshall fprintf(cout,"%c%c",IAC,IP); 124226048Sminshall (void) fflush(cout); 124326048Sminshall *msg = IAC; 124426048Sminshall *(msg+1) = DM; 1245*26448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 124626048Sminshall perror("abort"); 124726048Sminshall } 124826048Sminshall if (cpend) { 124926048Sminshall fprintf(cout,"ABOR\r\n"); 125026048Sminshall (void) fflush(cout); 125126048Sminshall mask = 1 << fileno(cin); 125226048Sminshall if ((mask = empty(mask,10)) < 0) { 125326048Sminshall perror("abort"); 1254*26448Slepreau if (ptabflg) 125526048Sminshall code = -1; 125626048Sminshall lostpeer(); 125726048Sminshall } 125826048Sminshall (void) getreply(0); 125926048Sminshall (void) getreply(0); 126026048Sminshall } 126126048Sminshall } 126226048Sminshall pswitch(1); 1263*26448Slepreau if (ptabflg) 126426048Sminshall code = -1; 126526048Sminshall (void) signal(SIGINT, oldintr); 126626048Sminshall return; 126726048Sminshall } 126826048Sminshall if (cpend && telflag) { 126926048Sminshall char msg[2]; 127026048Sminshall 127126048Sminshall fprintf(cout,"%c%c",IAC,IP); 127226048Sminshall (void) fflush(cout); 127326048Sminshall *msg = IAC; 127426048Sminshall *(msg+1) = DM; 1275*26448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 127626048Sminshall perror("abort"); 127726048Sminshall } 127826048Sminshall if (cpend) { 127926048Sminshall fprintf(cout,"ABOR\r\n"); 128026048Sminshall (void) fflush(cout); 128126048Sminshall mask = 1 << fileno(cin); 128226048Sminshall if ((mask = empty(mask,10)) < 0) { 128326048Sminshall perror("abort"); 1284*26448Slepreau if (ptabflg) 128526048Sminshall code = -1; 128626048Sminshall lostpeer(); 128726048Sminshall } 128826048Sminshall (void) getreply(0); 128926048Sminshall (void) getreply(0); 129026048Sminshall } 129126048Sminshall pswitch(!proxy); 129226048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 129326048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 129426048Sminshall pswitch(0); 129526048Sminshall switch (oldtype) { 129626048Sminshall case 0: 129726048Sminshall break; 129826048Sminshall case TYPE_A: 129926048Sminshall setascii(); 130026048Sminshall break; 130126048Sminshall case TYPE_I: 130226048Sminshall setbinary(); 130326048Sminshall break; 130426048Sminshall case TYPE_E: 130526048Sminshall setebcdic(); 130626048Sminshall break; 130726048Sminshall case TYPE_L: 130826048Sminshall settenex(); 130926048Sminshall break; 131026048Sminshall } 131126048Sminshall if (cpend && telflag) { 131226048Sminshall char msg[2]; 131326048Sminshall 131426048Sminshall fprintf(cout,"%c%c",IAC,IP); 131526048Sminshall (void) fflush(cout); 131626048Sminshall *msg = IAC; 131726048Sminshall *(msg+1) = DM; 1318*26448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 131926048Sminshall perror("abort"); 132026048Sminshall } 132126048Sminshall if (cpend) { 132226048Sminshall fprintf(cout,"ABOR\r\n"); 132326048Sminshall (void) fflush(cout); 132426048Sminshall mask = 1 << fileno(cin); 132526048Sminshall if ((mask = empty(mask,10)) < 0) { 132626048Sminshall perror("abort"); 1327*26448Slepreau if (ptabflg) 132826048Sminshall code = -1; 132926048Sminshall lostpeer(); 133026048Sminshall } 133126048Sminshall (void) getreply(0); 133226048Sminshall (void) getreply(0); 133326048Sminshall } 133426048Sminshall pswitch(1); 1335*26448Slepreau if (ptabflg) 133626048Sminshall code = -1; 133726048Sminshall (void) signal(SIGINT, oldintr); 133826048Sminshall return; 133926048Sminshall } 134026048Sminshall } 134126048Sminshall if (cpend && telflag) { 134226048Sminshall char msg[2]; 134326048Sminshall 134426048Sminshall fprintf(cout,"%c%c",IAC,IP); 134526048Sminshall (void) fflush(cout); 134626048Sminshall *msg = IAC; 134726048Sminshall *(msg+1) = DM; 1348*26448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 134926048Sminshall perror("abort"); 135026048Sminshall } 135126048Sminshall if (cpend) { 135226048Sminshall fprintf(cout,"ABOR\r\n"); 135326048Sminshall (void) fflush(cout); 135426048Sminshall mask = 1 << fileno(cin); 135526048Sminshall if ((mask = empty(mask,10)) < 0) { 135626048Sminshall perror("abort"); 1357*26448Slepreau if (ptabflg) 135826048Sminshall code = -1; 135926048Sminshall lostpeer(); 136026048Sminshall } 136126048Sminshall (void) getreply(0); 136226048Sminshall (void) getreply(0); 136326048Sminshall } 136426048Sminshall pswitch(!proxy); 136526048Sminshall if (cpend) { 136626048Sminshall mask = 1 << fileno(cin); 136726048Sminshall if ((mask = empty(mask,10)) < 0) { 136826048Sminshall perror("abort"); 1369*26448Slepreau if (ptabflg) 137026048Sminshall code = -1; 137126048Sminshall lostpeer(); 137226048Sminshall } 137326048Sminshall (void) getreply(0); 137426048Sminshall (void) getreply(0); 137526048Sminshall } 1376*26448Slepreau if (proxy) 137726048Sminshall pswitch(0); 137826048Sminshall switch (oldtype) { 137926048Sminshall case 0: 138026048Sminshall break; 138126048Sminshall case TYPE_A: 138226048Sminshall setascii(); 138326048Sminshall break; 138426048Sminshall case TYPE_I: 138526048Sminshall setbinary(); 138626048Sminshall break; 138726048Sminshall case TYPE_E: 138826048Sminshall setebcdic(); 138926048Sminshall break; 139026048Sminshall case TYPE_L: 139126048Sminshall settenex(); 139226048Sminshall break; 139326048Sminshall } 139426048Sminshall pswitch(1); 1395*26448Slepreau if (ptabflg) 139626048Sminshall code = -1; 139726048Sminshall (void) signal(SIGINT, oldintr); 139826048Sminshall } 139926048Sminshall 140026048Sminshall reset() 140126048Sminshall { 140226048Sminshall long mask; 140326048Sminshall 140426048Sminshall mask = 1 << fileno(cin); 140526048Sminshall while (mask > 0) { 140626048Sminshall if ((mask = empty(mask,0)) < 0) { 140726048Sminshall perror("reset"); 140826048Sminshall code = -1; 140926048Sminshall lostpeer(); 141026048Sminshall } 1411*26448Slepreau if (mask > 0) 141226048Sminshall (void) getreply(0); 141326048Sminshall } 141426048Sminshall } 141526048Sminshall 141626048Sminshall char * 141726048Sminshall gunique(local) 141826048Sminshall char *local; 141926048Sminshall { 142026048Sminshall static char new[MAXPATHLEN]; 142126048Sminshall char *cp = rindex(local, '/'); 142226048Sminshall int d, count=0; 142326048Sminshall char ext = '1'; 142426048Sminshall 1425*26448Slepreau if (cp) 142626048Sminshall *cp = '\0'; 142726048Sminshall d = access(cp ? local : ".", 2); 1428*26448Slepreau if (cp) 142926048Sminshall *cp = '/'; 143026048Sminshall if (d < 0) { 143126048Sminshall perror(local); 143226048Sminshall return((char *) 0); 143326048Sminshall } 143426048Sminshall (void) strcpy(new, local); 143526048Sminshall cp = new + strlen(new); 143626048Sminshall *cp++ = '.'; 143726048Sminshall while (!d) { 143826048Sminshall if (++count == 100) { 143926048Sminshall printf("runique: can't find unique file name.\n"); 144026048Sminshall return((char *) 0); 144126048Sminshall } 144226048Sminshall *cp++ = ext; 144326048Sminshall *cp = '\0'; 1444*26448Slepreau if (ext == '9') 144526048Sminshall ext = '0'; 1446*26448Slepreau else 144726048Sminshall ext++; 1448*26448Slepreau if ((d = access(new, 0)) < 0) 144926048Sminshall break; 1450*26448Slepreau if (ext != '0') 145126048Sminshall cp--; 1452*26448Slepreau else if (*(cp - 2) == '.') 145326048Sminshall *(cp - 1) = '1'; 145426048Sminshall else { 145526048Sminshall *(cp - 2) = *(cp - 2) + 1; 145626048Sminshall cp--; 145726048Sminshall } 145826048Sminshall } 145926048Sminshall return(new); 146026048Sminshall } 1461