121739Sdist /* 236942Skarels * Copyright (c) 1985, 1989 Regents of the University of California. 333737Sbostic * All rights reserved. 433737Sbostic * 542665Sbostic * %sccs.include.redist.c% 621739Sdist */ 721739Sdist 810296Ssam #ifndef lint 9*48507Srick static char sccsid[] = "@(#)ftp.c 5.38 (Berkeley) 04/22/91"; 1033737Sbostic #endif /* not lint */ 1110296Ssam 1236940Skarels #include <sys/param.h> 1310296Ssam #include <sys/stat.h> 1410296Ssam #include <sys/ioctl.h> 1510296Ssam #include <sys/socket.h> 1613614Ssam #include <sys/time.h> 1736935Skarels #include <sys/file.h> 1810296Ssam 1910296Ssam #include <netinet/in.h> 2044340Skarels #include <netinet/in_systm.h> 2144340Skarels #include <netinet/ip.h> 2212397Ssam #include <arpa/ftp.h> 2326048Sminshall #include <arpa/telnet.h> 2410296Ssam 2510296Ssam #include <stdio.h> 2610296Ssam #include <signal.h> 2710296Ssam #include <errno.h> 2810296Ssam #include <netdb.h> 2926048Sminshall #include <fcntl.h> 3026048Sminshall #include <pwd.h> 3138133Srick #include <varargs.h> 3210296Ssam 3336940Skarels #include "ftp_var.h" 3436940Skarels 3510296Ssam struct sockaddr_in hisctladdr; 3610296Ssam struct sockaddr_in data_addr; 3710296Ssam int data = -1; 3826048Sminshall int abrtflag = 0; 3926048Sminshall int ptflag = 0; 4010296Ssam struct sockaddr_in myctladdr; 4126496Sminshall uid_t getuid(); 4238133Srick sig_t lostpeer(); 4337225Skarels off_t restart_point = 0; 4410296Ssam 4538202Srick extern char *strerror(); 4640193Sbostic extern int connected, errno; 4738202Srick 4810296Ssam FILE *cin, *cout; 4910296Ssam FILE *dataconn(); 5010296Ssam 5125904Skarels char * 5210296Ssam hookup(host, port) 5310296Ssam char *host; 5410296Ssam int port; 5510296Ssam { 5625904Skarels register struct hostent *hp = 0; 5744340Skarels int s, len, tos; 5825904Skarels static char hostnamebuf[80]; 5910296Ssam 6010296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 6125904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 6225904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 6325904Skarels hisctladdr.sin_family = AF_INET; 6436940Skarels (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); 6536940Skarels } else { 6625100Sbloom hp = gethostbyname(host); 6725904Skarels if (hp == NULL) { 6835792Sbostic fprintf(stderr, "ftp: %s: ", host); 6935792Sbostic herror((char *)NULL); 7026048Sminshall code = -1; 7126048Sminshall return((char *) 0); 7225904Skarels } 7325904Skarels hisctladdr.sin_family = hp->h_addrtype; 7425904Skarels bcopy(hp->h_addr_list[0], 7525904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 7636940Skarels (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); 7710296Ssam } 7825904Skarels hostname = hostnamebuf; 7925904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 8010296Ssam if (s < 0) { 8110296Ssam perror("ftp: socket"); 8226048Sminshall code = -1; 8310296Ssam return (0); 8410296Ssam } 8510296Ssam hisctladdr.sin_port = port; 8638133Srick while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { 8725904Skarels if (hp && hp->h_addr_list[1]) { 8825904Skarels int oerrno = errno; 8938133Srick extern char *inet_ntoa(); 9025904Skarels 9125904Skarels fprintf(stderr, "ftp: connect to address %s: ", 9225904Skarels inet_ntoa(hisctladdr.sin_addr)); 9325904Skarels errno = oerrno; 9426496Sminshall perror((char *) 0); 9525904Skarels hp->h_addr_list++; 9625904Skarels bcopy(hp->h_addr_list[0], 9726048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 9826496Sminshall fprintf(stdout, "Trying %s...\n", 9925904Skarels inet_ntoa(hisctladdr.sin_addr)); 10026813Skarels (void) close(s); 10126813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 10226813Skarels if (s < 0) { 10326813Skarels perror("ftp: socket"); 10426813Skarels code = -1; 10526813Skarels return (0); 10626813Skarels } 10725904Skarels continue; 10825904Skarels } 10910296Ssam perror("ftp: connect"); 11026048Sminshall code = -1; 11110296Ssam goto bad; 11210296Ssam } 11311627Ssam len = sizeof (myctladdr); 11438133Srick if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { 11511627Ssam perror("ftp: getsockname"); 11626048Sminshall code = -1; 11710296Ssam goto bad; 11810296Ssam } 11944340Skarels #ifdef IP_TOS 12044340Skarels tos = IPTOS_LOWDELAY; 12144340Skarels if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 12244661Skarels perror("ftp: setsockopt TOS (ignored)"); 12344340Skarels #endif 12410296Ssam cin = fdopen(s, "r"); 12510296Ssam cout = fdopen(s, "w"); 12611219Ssam if (cin == NULL || cout == NULL) { 12710296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 12810296Ssam if (cin) 12926496Sminshall (void) fclose(cin); 13010296Ssam if (cout) 13126496Sminshall (void) fclose(cout); 13226048Sminshall code = -1; 13310296Ssam goto bad; 13410296Ssam } 13510296Ssam if (verbose) 13626067Sminshall printf("Connected to %s.\n", hostname); 13727687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 13826048Sminshall if (cin) 13926496Sminshall (void) fclose(cin); 14026048Sminshall if (cout) 14126496Sminshall (void) fclose(cout); 14226048Sminshall code = -1; 14326048Sminshall goto bad; 14426048Sminshall } 14527687Sminshall #ifdef SO_OOBINLINE 14627687Sminshall { 14727687Sminshall int on = 1; 14826048Sminshall 14940193Sbostic if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) 15027687Sminshall < 0 && debug) { 15127687Sminshall perror("ftp: setsockopt"); 15227687Sminshall } 15327687Sminshall } 15438133Srick #endif /* SO_OOBINLINE */ 15526048Sminshall 15625904Skarels return (hostname); 15710296Ssam bad: 15826496Sminshall (void) close(s); 15925904Skarels return ((char *)0); 16010296Ssam } 16110296Ssam 16225904Skarels login(host) 16325904Skarels char *host; 16410296Ssam { 16526048Sminshall char tmp[80]; 16635659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 16726048Sminshall int n, aflag = 0; 16810296Ssam 16926048Sminshall user = pass = acct = 0; 17026048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 17126048Sminshall code = -1; 17226048Sminshall return(0); 17326048Sminshall } 17437458Skarels while (user == NULL) { 17526048Sminshall char *myname = getlogin(); 17626048Sminshall 17726048Sminshall if (myname == NULL) { 17826048Sminshall struct passwd *pp = getpwuid(getuid()); 17926048Sminshall 18026448Slepreau if (pp != NULL) 18126048Sminshall myname = pp->pw_name; 18226048Sminshall } 18337458Skarels if (myname) 18437458Skarels printf("Name (%s:%s): ", host, myname); 18537458Skarels else 18637458Skarels printf("Name (%s): ", host); 18726048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 18826048Sminshall tmp[strlen(tmp) - 1] = '\0'; 18926448Slepreau if (*tmp == '\0') 19026048Sminshall user = myname; 19126448Slepreau else 19226048Sminshall user = tmp; 19326048Sminshall } 19410296Ssam n = command("USER %s", user); 19526048Sminshall if (n == CONTINUE) { 19626448Slepreau if (pass == NULL) 19735659Sbostic pass = getpass("Password:"); 19810296Ssam n = command("PASS %s", pass); 19926048Sminshall } 20010296Ssam if (n == CONTINUE) { 20126048Sminshall aflag++; 20235659Sbostic acct = getpass("Account:"); 20310296Ssam n = command("ACCT %s", acct); 20410296Ssam } 20510296Ssam if (n != COMPLETE) { 20610296Ssam fprintf(stderr, "Login failed.\n"); 20710296Ssam return (0); 20810296Ssam } 20926448Slepreau if (!aflag && acct != NULL) 21026048Sminshall (void) command("ACCT %s", acct); 21126448Slepreau if (proxy) 21226048Sminshall return(1); 21326048Sminshall for (n = 0; n < macnum; ++n) { 21426048Sminshall if (!strcmp("init", macros[n].mac_name)) { 21526496Sminshall (void) strcpy(line, "$init"); 21626048Sminshall makeargv(); 21726048Sminshall domacro(margc, margv); 21826048Sminshall break; 21926048Sminshall } 22026048Sminshall } 22110296Ssam return (1); 22210296Ssam } 22310296Ssam 22440193Sbostic void 22526048Sminshall cmdabort() 22626048Sminshall { 22726048Sminshall extern jmp_buf ptabort; 22826048Sminshall 22926048Sminshall printf("\n"); 23026048Sminshall (void) fflush(stdout); 23126048Sminshall abrtflag++; 23226448Slepreau if (ptflag) 23326048Sminshall longjmp(ptabort,1); 23426048Sminshall } 23526048Sminshall 23638133Srick /*VARARGS*/ 23738133Srick command(va_alist) 23838133Srick va_dcl 23938133Srick { 24038133Srick va_list ap; 24110296Ssam char *fmt; 24238133Srick int r; 24340193Sbostic sig_t oldintr; 24440193Sbostic void cmdabort(); 24510296Ssam 24626048Sminshall abrtflag = 0; 24710296Ssam if (debug) { 24810296Ssam printf("---> "); 24938133Srick va_start(ap); 25038133Srick fmt = va_arg(ap, char *); 25138133Srick if (strncmp("PASS ", fmt, 5) == 0) 25238133Srick printf("PASS XXXX"); 25338133Srick else 25438133Srick vfprintf(stdout, fmt, ap); 25538133Srick va_end(ap); 25610296Ssam printf("\n"); 25710296Ssam (void) fflush(stdout); 25810296Ssam } 25911219Ssam if (cout == NULL) { 26011219Ssam perror ("No control connection for command"); 26126048Sminshall code = -1; 26211219Ssam return (0); 26311219Ssam } 26438133Srick oldintr = signal(SIGINT, cmdabort); 26538133Srick va_start(ap); 26638133Srick fmt = va_arg(ap, char *); 26738133Srick vfprintf(cout, fmt, ap); 26838133Srick va_end(ap); 26910296Ssam fprintf(cout, "\r\n"); 27010296Ssam (void) fflush(cout); 27126048Sminshall cpend = 1; 27226048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 27326448Slepreau if (abrtflag && oldintr != SIG_IGN) 27446828Sbostic (*oldintr)(SIGINT); 27526048Sminshall (void) signal(SIGINT, oldintr); 27626048Sminshall return(r); 27710296Ssam } 27810296Ssam 27937229Skarels char reply_string[BUFSIZ]; /* last line of previous reply */ 28036935Skarels 28110296Ssam #include <ctype.h> 28210296Ssam 28310296Ssam getreply(expecteof) 28410296Ssam int expecteof; 28510296Ssam { 28611219Ssam register int c, n; 28726048Sminshall register int dig; 28836935Skarels register char *cp; 28938133Srick int originalcode = 0, continuation = 0; 29040193Sbostic sig_t oldintr; 29126048Sminshall int pflag = 0; 29226048Sminshall char *pt = pasv; 29340193Sbostic void cmdabort(); 29410296Ssam 29538133Srick oldintr = signal(SIGINT, cmdabort); 29610296Ssam for (;;) { 29710296Ssam dig = n = code = 0; 29837229Skarels cp = reply_string; 29910296Ssam while ((c = getc(cin)) != '\n') { 30027687Sminshall if (c == IAC) { /* handle telnet commands */ 30127687Sminshall switch (c = getc(cin)) { 30227687Sminshall case WILL: 30327687Sminshall case WONT: 30427687Sminshall c = getc(cin); 30538133Srick fprintf(cout, "%c%c%c", IAC, DONT, c); 30627687Sminshall (void) fflush(cout); 30727687Sminshall break; 30827687Sminshall case DO: 30927687Sminshall case DONT: 31027687Sminshall c = getc(cin); 31138133Srick fprintf(cout, "%c%c%c", IAC, WONT, c); 31227687Sminshall (void) fflush(cout); 31327687Sminshall break; 31427687Sminshall default: 31527687Sminshall break; 31627687Sminshall } 31727687Sminshall continue; 31827687Sminshall } 31910296Ssam dig++; 32010296Ssam if (c == EOF) { 32126048Sminshall if (expecteof) { 32226048Sminshall (void) signal(SIGINT,oldintr); 32326048Sminshall code = 221; 32410296Ssam return (0); 32526048Sminshall } 32610296Ssam lostpeer(); 32726048Sminshall if (verbose) { 32826048Sminshall printf("421 Service not available, remote server has closed connection\n"); 32926048Sminshall (void) fflush(stdout); 33026048Sminshall } 33133772Scsvsj code = 421; 33233772Scsvsj return(4); 33310296Ssam } 33426048Sminshall if (c != '\r' && (verbose > 0 || 33526048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 33626448Slepreau if (proxflag && 33726448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 33826048Sminshall printf("%s:",hostname); 33926496Sminshall (void) putchar(c); 34026048Sminshall } 34110296Ssam if (dig < 4 && isdigit(c)) 34210296Ssam code = code * 10 + (c - '0'); 34326448Slepreau if (!pflag && code == 227) 34426048Sminshall pflag = 1; 34526448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 34626048Sminshall pflag = 2; 34726048Sminshall if (pflag == 2) { 34826448Slepreau if (c != '\r' && c != ')') 34926048Sminshall *pt++ = c; 35026048Sminshall else { 35126048Sminshall *pt = '\0'; 35226048Sminshall pflag = 3; 35326048Sminshall } 35426048Sminshall } 35526048Sminshall if (dig == 4 && c == '-') { 35626448Slepreau if (continuation) 35726048Sminshall code = 0; 35810296Ssam continuation++; 35926048Sminshall } 36010296Ssam if (n == 0) 36110296Ssam n = c; 36237229Skarels if (cp < &reply_string[sizeof(reply_string) - 1]) 36337229Skarels *cp++ = c; 36410296Ssam } 36526048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 36626496Sminshall (void) putchar(c); 36711346Ssam (void) fflush (stdout); 36811346Ssam } 36910296Ssam if (continuation && code != originalcode) { 37010296Ssam if (originalcode == 0) 37110296Ssam originalcode = code; 37210296Ssam continue; 37310296Ssam } 37436935Skarels *cp = '\0'; 37526448Slepreau if (n != '1') 37626048Sminshall cpend = 0; 37726048Sminshall (void) signal(SIGINT,oldintr); 37826448Slepreau if (code == 421 || originalcode == 421) 37926048Sminshall lostpeer(); 38026448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 38146828Sbostic (*oldintr)(SIGINT); 38225907Smckusick return (n - '0'); 38310296Ssam } 38410296Ssam } 38510296Ssam 38626048Sminshall empty(mask, sec) 38727687Sminshall struct fd_set *mask; 38826048Sminshall int sec; 38926048Sminshall { 39026048Sminshall struct timeval t; 39126048Sminshall 39226048Sminshall t.tv_sec = (long) sec; 39326048Sminshall t.tv_usec = 0; 39427687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 39526048Sminshall } 39626048Sminshall 39710296Ssam jmp_buf sendabort; 39810296Ssam 39940193Sbostic void 40010296Ssam abortsend() 40110296Ssam { 40210296Ssam 40326048Sminshall mflag = 0; 40426048Sminshall abrtflag = 0; 40538133Srick printf("\nsend aborted\nwaiting for remote to finish abort\n"); 40626048Sminshall (void) fflush(stdout); 40710296Ssam longjmp(sendabort, 1); 40810296Ssam } 40910296Ssam 41036940Skarels #define HASHBYTES 1024 41136940Skarels 41237225Skarels sendrequest(cmd, local, remote, printnames) 41310296Ssam char *cmd, *local, *remote; 41437225Skarels int printnames; 41510296Ssam { 41640193Sbostic struct stat st; 41740193Sbostic struct timeval start, stop; 41840193Sbostic register int c, d; 41935659Sbostic FILE *fin, *dout = 0, *popen(); 42038133Srick int (*closefunc)(), pclose(), fclose(); 42140193Sbostic sig_t oldintr, oldintp; 42236940Skarels long bytes = 0, hashbytes = HASHBYTES; 42340193Sbostic char *lmode, buf[BUFSIZ], *bufp; 42440193Sbostic void abortsend(); 42510296Ssam 42637225Skarels if (verbose && printnames) { 42737225Skarels if (local && *local != '-') 42837225Skarels printf("local: %s ", local); 42937225Skarels if (remote) 43037225Skarels printf("remote: %s\n", remote); 43137225Skarels } 43226048Sminshall if (proxy) { 43326048Sminshall proxtrans(cmd, local, remote); 43426048Sminshall return; 43526048Sminshall } 43638033Skarels if (curtype != type) 43738033Skarels changetype(type, 0); 43810296Ssam closefunc = NULL; 43926048Sminshall oldintr = NULL; 44026048Sminshall oldintp = NULL; 44140193Sbostic lmode = "w"; 44226048Sminshall if (setjmp(sendabort)) { 44326048Sminshall while (cpend) { 44426048Sminshall (void) getreply(0); 44526048Sminshall } 44626048Sminshall if (data >= 0) { 44726048Sminshall (void) close(data); 44826048Sminshall data = -1; 44926048Sminshall } 45026448Slepreau if (oldintr) 45126048Sminshall (void) signal(SIGINT,oldintr); 45226448Slepreau if (oldintp) 45326048Sminshall (void) signal(SIGPIPE,oldintp); 45426048Sminshall code = -1; 45526048Sminshall return; 45626048Sminshall } 45710296Ssam oldintr = signal(SIGINT, abortsend); 45810296Ssam if (strcmp(local, "-") == 0) 45910296Ssam fin = stdin; 46010296Ssam else if (*local == '|') { 46126048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 46235659Sbostic fin = popen(local + 1, "r"); 46310296Ssam if (fin == NULL) { 46426048Sminshall perror(local + 1); 46526048Sminshall (void) signal(SIGINT, oldintr); 46626048Sminshall (void) signal(SIGPIPE, oldintp); 46726048Sminshall code = -1; 46826048Sminshall return; 46910296Ssam } 47035659Sbostic closefunc = pclose; 47110296Ssam } else { 47210296Ssam fin = fopen(local, "r"); 47310296Ssam if (fin == NULL) { 47438202Srick fprintf(stderr, "local: %s: %s\n", local, 47538202Srick strerror(errno)); 47626048Sminshall (void) signal(SIGINT, oldintr); 47726048Sminshall code = -1; 47826048Sminshall return; 47910296Ssam } 48010296Ssam closefunc = fclose; 48110296Ssam if (fstat(fileno(fin), &st) < 0 || 48210296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 48326496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 48426048Sminshall (void) signal(SIGINT, oldintr); 48536935Skarels fclose(fin); 48626048Sminshall code = -1; 48726048Sminshall return; 48810296Ssam } 48910296Ssam } 49026048Sminshall if (initconn()) { 49126048Sminshall (void) signal(SIGINT, oldintr); 49226448Slepreau if (oldintp) 49326048Sminshall (void) signal(SIGPIPE, oldintp); 49426048Sminshall code = -1; 49536935Skarels if (closefunc != NULL) 49636935Skarels (*closefunc)(fin); 49726048Sminshall return; 49826048Sminshall } 49926448Slepreau if (setjmp(sendabort)) 50026048Sminshall goto abort; 50136935Skarels 50237225Skarels if (restart_point && 50337225Skarels (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 50437225Skarels if (fseek(fin, (long) restart_point, 0) < 0) { 50538202Srick fprintf(stderr, "local: %s: %s\n", local, 50638202Srick strerror(errno)); 50737225Skarels restart_point = 0; 50837225Skarels if (closefunc != NULL) 50937225Skarels (*closefunc)(fin); 51037225Skarels return; 51137225Skarels } 51237225Skarels if (command("REST %ld", (long) restart_point) 51337225Skarels != CONTINUE) { 51437225Skarels restart_point = 0; 51537225Skarels if (closefunc != NULL) 51637225Skarels (*closefunc)(fin); 51737225Skarels return; 51837225Skarels } 51937225Skarels restart_point = 0; 52040193Sbostic lmode = "r+w"; 52137225Skarels } 52210296Ssam if (remote) { 52326048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 52426048Sminshall (void) signal(SIGINT, oldintr); 52526448Slepreau if (oldintp) 52626048Sminshall (void) signal(SIGPIPE, oldintp); 52736935Skarels if (closefunc != NULL) 52836935Skarels (*closefunc)(fin); 52926048Sminshall return; 53026048Sminshall } 53110296Ssam } else 53226048Sminshall if (command("%s", cmd) != PRELIM) { 53326048Sminshall (void) signal(SIGINT, oldintr); 53426448Slepreau if (oldintp) 53526048Sminshall (void) signal(SIGPIPE, oldintp); 53636935Skarels if (closefunc != NULL) 53736935Skarels (*closefunc)(fin); 53826048Sminshall return; 53926048Sminshall } 54040193Sbostic dout = dataconn(lmode); 54126448Slepreau if (dout == NULL) 54226048Sminshall goto abort; 54326496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 54436935Skarels oldintp = signal(SIGPIPE, SIG_IGN); 54542278Skarels switch (curtype) { 54611219Ssam 54711219Ssam case TYPE_I: 54811219Ssam case TYPE_L: 54911346Ssam errno = d = 0; 55036942Skarels while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { 55111219Ssam bytes += c; 55236942Skarels for (bufp = buf; c > 0; c -= d, bufp += d) 55336942Skarels if ((d = write(fileno(dout), bufp, c)) <= 0) 55436942Skarels break; 55511651Ssam if (hash) { 55636940Skarels while (bytes >= hashbytes) { 55736940Skarels (void) putchar('#'); 55836940Skarels hashbytes += HASHBYTES; 55936940Skarels } 56026496Sminshall (void) fflush(stdout); 56111651Ssam } 56211219Ssam } 56313213Ssam if (hash && bytes > 0) { 56436940Skarels if (bytes < HASHBYTES) 56536940Skarels (void) putchar('#'); 56626496Sminshall (void) putchar('\n'); 56726496Sminshall (void) fflush(stdout); 56811651Ssam } 56911219Ssam if (c < 0) 57038202Srick fprintf(stderr, "local: %s: %s\n", local, 57138202Srick strerror(errno)); 572*48507Srick if (d < 0) { 573*48507Srick if (errno != EPIPE) 57436935Skarels perror("netout"); 57536935Skarels bytes = -1; 57636935Skarels } 57711219Ssam break; 57811219Ssam 57911219Ssam case TYPE_A: 58011219Ssam while ((c = getc(fin)) != EOF) { 58111219Ssam if (c == '\n') { 58211651Ssam while (hash && (bytes >= hashbytes)) { 58326496Sminshall (void) putchar('#'); 58426496Sminshall (void) fflush(stdout); 58536940Skarels hashbytes += HASHBYTES; 58611651Ssam } 58711219Ssam if (ferror(dout)) 58811219Ssam break; 58926496Sminshall (void) putc('\r', dout); 59011219Ssam bytes++; 59111219Ssam } 59226496Sminshall (void) putc(c, dout); 59311219Ssam bytes++; 59426048Sminshall /* if (c == '\r') { */ 59526496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 59626048Sminshall /* bytes++; */ 59726048Sminshall /* } */ 59811219Ssam } 59911651Ssam if (hash) { 60013213Ssam if (bytes < hashbytes) 60126496Sminshall (void) putchar('#'); 60226496Sminshall (void) putchar('\n'); 60326496Sminshall (void) fflush(stdout); 60411651Ssam } 60511219Ssam if (ferror(fin)) 60638202Srick fprintf(stderr, "local: %s: %s\n", local, 60738202Srick strerror(errno)); 60836935Skarels if (ferror(dout)) { 60936935Skarels if (errno != EPIPE) 61036935Skarels perror("netout"); 61136935Skarels bytes = -1; 61236935Skarels } 61311219Ssam break; 61410296Ssam } 61526496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 61610296Ssam if (closefunc != NULL) 61726048Sminshall (*closefunc)(fin); 61810296Ssam (void) fclose(dout); 61926048Sminshall (void) getreply(0); 62026048Sminshall (void) signal(SIGINT, oldintr); 62136935Skarels if (oldintp) 62236935Skarels (void) signal(SIGPIPE, oldintp); 62335699Sbostic if (bytes > 0) 62437225Skarels ptransfer("sent", bytes, &start, &stop); 62510296Ssam return; 62626048Sminshall abort: 62726496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 62826048Sminshall (void) signal(SIGINT, oldintr); 62926448Slepreau if (oldintp) 63026048Sminshall (void) signal(SIGPIPE, oldintp); 63126048Sminshall if (!cpend) { 63226048Sminshall code = -1; 63326048Sminshall return; 63426048Sminshall } 63526048Sminshall if (data >= 0) { 63626048Sminshall (void) close(data); 63726048Sminshall data = -1; 63826048Sminshall } 63926448Slepreau if (dout) 64026048Sminshall (void) fclose(dout); 64126048Sminshall (void) getreply(0); 64226048Sminshall code = -1; 64310296Ssam if (closefunc != NULL && fin != NULL) 64426048Sminshall (*closefunc)(fin); 64535699Sbostic if (bytes > 0) 64637225Skarels ptransfer("sent", bytes, &start, &stop); 64710296Ssam } 64810296Ssam 64910296Ssam jmp_buf recvabort; 65010296Ssam 65140193Sbostic void 65210296Ssam abortrecv() 65310296Ssam { 65410296Ssam 65526048Sminshall mflag = 0; 65626048Sminshall abrtflag = 0; 65738133Srick printf("\nreceive aborted\nwaiting for remote to finish abort\n"); 65826048Sminshall (void) fflush(stdout); 65910296Ssam longjmp(recvabort, 1); 66010296Ssam } 66110296Ssam 66240193Sbostic recvrequest(cmd, local, remote, lmode, printnames) 66340193Sbostic char *cmd, *local, *remote, *lmode; 66410296Ssam { 66535659Sbostic FILE *fout, *din = 0, *popen(); 66638133Srick int (*closefunc)(), pclose(), fclose(); 66740193Sbostic sig_t oldintr, oldintp; 66838133Srick int is_retr, tcrflag, bare_lfs = 0; 66938133Srick char *gunique(); 67038133Srick static int bufsize; 67136944Skarels static char *buf; 67236940Skarels long bytes = 0, hashbytes = HASHBYTES; 67311346Ssam register int c, d; 67410296Ssam struct timeval start, stop; 67536940Skarels struct stat st; 67640193Sbostic off_t lseek(); 67740193Sbostic void abortrecv(); 67840193Sbostic char *malloc(); 67910296Ssam 68036935Skarels is_retr = strcmp(cmd, "RETR") == 0; 68137225Skarels if (is_retr && verbose && printnames) { 68237225Skarels if (local && *local != '-') 68337225Skarels printf("local: %s ", local); 68437225Skarels if (remote) 68537225Skarels printf("remote: %s\n", remote); 68637225Skarels } 68736935Skarels if (proxy && is_retr) { 68826048Sminshall proxtrans(cmd, local, remote); 68926048Sminshall return; 69026048Sminshall } 69110296Ssam closefunc = NULL; 69226048Sminshall oldintr = NULL; 69326048Sminshall oldintp = NULL; 69436935Skarels tcrflag = !crflag && is_retr; 69526048Sminshall if (setjmp(recvabort)) { 69626048Sminshall while (cpend) { 69726048Sminshall (void) getreply(0); 69826048Sminshall } 69926048Sminshall if (data >= 0) { 70026048Sminshall (void) close(data); 70126048Sminshall data = -1; 70226048Sminshall } 70326448Slepreau if (oldintr) 70426048Sminshall (void) signal(SIGINT, oldintr); 70526048Sminshall code = -1; 70626048Sminshall return; 70726048Sminshall } 70810296Ssam oldintr = signal(SIGINT, abortrecv); 70926048Sminshall if (strcmp(local, "-") && *local != '|') { 71010296Ssam if (access(local, 2) < 0) { 71126048Sminshall char *dir = rindex(local, '/'); 71210296Ssam 71326048Sminshall if (errno != ENOENT && errno != EACCES) { 71438202Srick fprintf(stderr, "local: %s: %s\n", local, 71538202Srick strerror(errno)); 71626048Sminshall (void) signal(SIGINT, oldintr); 71726048Sminshall code = -1; 71826048Sminshall return; 71910296Ssam } 72026048Sminshall if (dir != NULL) 72126048Sminshall *dir = 0; 72226048Sminshall d = access(dir ? local : ".", 2); 72326048Sminshall if (dir != NULL) 72426048Sminshall *dir = '/'; 72526048Sminshall if (d < 0) { 72638202Srick fprintf(stderr, "local: %s: %s\n", local, 72738202Srick strerror(errno)); 72826048Sminshall (void) signal(SIGINT, oldintr); 72926048Sminshall code = -1; 73026048Sminshall return; 73126048Sminshall } 73226048Sminshall if (!runique && errno == EACCES && 73336935Skarels chmod(local, 0600) < 0) { 73438202Srick fprintf(stderr, "local: %s: %s\n", local, 73538202Srick strerror(errno)); 73626048Sminshall (void) signal(SIGINT, oldintr); 73738202Srick (void) signal(SIGINT, oldintr); 73826048Sminshall code = -1; 73926048Sminshall return; 74026048Sminshall } 74126048Sminshall if (runique && errno == EACCES && 74226048Sminshall (local = gunique(local)) == NULL) { 74326048Sminshall (void) signal(SIGINT, oldintr); 74426048Sminshall code = -1; 74526048Sminshall return; 74626048Sminshall } 74710296Ssam } 74826048Sminshall else if (runique && (local = gunique(local)) == NULL) { 74926048Sminshall (void) signal(SIGINT, oldintr); 75026048Sminshall code = -1; 75126048Sminshall return; 75226048Sminshall } 75326048Sminshall } 75438033Skarels if (!is_retr) { 75538033Skarels if (curtype != TYPE_A) 75638033Skarels changetype(TYPE_A, 0); 75738033Skarels } else if (curtype != type) 75838033Skarels changetype(type, 0); 75926048Sminshall if (initconn()) { 76026048Sminshall (void) signal(SIGINT, oldintr); 76126048Sminshall code = -1; 76226048Sminshall return; 76326048Sminshall } 76426448Slepreau if (setjmp(recvabort)) 76526048Sminshall goto abort; 76638033Skarels if (is_retr && restart_point && 76738033Skarels command("REST %ld", (long) restart_point) != CONTINUE) 76838033Skarels return; 76910296Ssam if (remote) { 77026048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 77126048Sminshall (void) signal(SIGINT, oldintr); 77226048Sminshall return; 77326048Sminshall } 77426048Sminshall } else { 77526048Sminshall if (command("%s", cmd) != PRELIM) { 77626048Sminshall (void) signal(SIGINT, oldintr); 77726048Sminshall return; 77826048Sminshall } 77926048Sminshall } 78026048Sminshall din = dataconn("r"); 78126048Sminshall if (din == NULL) 78226048Sminshall goto abort; 78326448Slepreau if (strcmp(local, "-") == 0) 78410296Ssam fout = stdout; 78510296Ssam else if (*local == '|') { 78626048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 78735659Sbostic fout = popen(local + 1, "w"); 78826048Sminshall if (fout == NULL) { 78926048Sminshall perror(local+1); 79026048Sminshall goto abort; 79126048Sminshall } 79235659Sbostic closefunc = pclose; 79336940Skarels } else { 79440193Sbostic fout = fopen(local, lmode); 79526048Sminshall if (fout == NULL) { 79638202Srick fprintf(stderr, "local: %s: %s\n", local, 79738202Srick strerror(errno)); 79826048Sminshall goto abort; 79926048Sminshall } 80010296Ssam closefunc = fclose; 80110296Ssam } 80236940Skarels if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 80336940Skarels st.st_blksize = BUFSIZ; 80436940Skarels if (st.st_blksize > bufsize) { 80536940Skarels if (buf) 80636940Skarels (void) free(buf); 80738133Srick buf = malloc((unsigned)st.st_blksize); 80836940Skarels if (buf == NULL) { 80936940Skarels perror("malloc"); 81036944Skarels bufsize = 0; 81136940Skarels goto abort; 81236940Skarels } 81336940Skarels bufsize = st.st_blksize; 81436940Skarels } 81526496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 81638033Skarels switch (curtype) { 81711219Ssam 81811219Ssam case TYPE_I: 81911219Ssam case TYPE_L: 82037225Skarels if (restart_point && 82137225Skarels lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 82238202Srick fprintf(stderr, "local: %s: %s\n", local, 82338202Srick strerror(errno)); 82437225Skarels if (closefunc != NULL) 82537225Skarels (*closefunc)(fout); 82637225Skarels return; 82737225Skarels } 82811346Ssam errno = d = 0; 82936940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) { 83036944Skarels if ((d = write(fileno(fout), buf, c)) != c) 83111219Ssam break; 83211219Ssam bytes += c; 83311651Ssam if (hash) { 83436940Skarels while (bytes >= hashbytes) { 83536940Skarels (void) putchar('#'); 83636940Skarels hashbytes += HASHBYTES; 83736940Skarels } 83826496Sminshall (void) fflush(stdout); 83911651Ssam } 84011219Ssam } 84113213Ssam if (hash && bytes > 0) { 84236940Skarels if (bytes < HASHBYTES) 84336940Skarels (void) putchar('#'); 84426496Sminshall (void) putchar('\n'); 84526496Sminshall (void) fflush(stdout); 84611651Ssam } 84736935Skarels if (c < 0) { 84836935Skarels if (errno != EPIPE) 84936935Skarels perror("netin"); 85036935Skarels bytes = -1; 85136935Skarels } 85236942Skarels if (d < c) { 85336942Skarels if (d < 0) 85438202Srick fprintf(stderr, "local: %s: %s\n", local, 85538202Srick strerror(errno)); 85636942Skarels else 85736942Skarels fprintf(stderr, "%s: short write\n", local); 85836942Skarels } 85911219Ssam break; 86011219Ssam 86111219Ssam case TYPE_A: 86237225Skarels if (restart_point) { 86340193Sbostic register int i, n, ch; 86437225Skarels 86537225Skarels if (fseek(fout, 0L, L_SET) < 0) 86637225Skarels goto done; 86737225Skarels n = restart_point; 86840193Sbostic for (i = 0; i++ < n;) { 86940193Sbostic if ((ch = getc(fout)) == EOF) 87037225Skarels goto done; 87140193Sbostic if (ch == '\n') 87237225Skarels i++; 87337225Skarels } 87437225Skarels if (fseek(fout, 0L, L_INCR) < 0) { 87537225Skarels done: 87638202Srick fprintf(stderr, "local: %s: %s\n", local, 87738202Srick strerror(errno)); 87837225Skarels if (closefunc != NULL) 87937225Skarels (*closefunc)(fout); 88037225Skarels return; 88137225Skarels } 88237225Skarels } 88311219Ssam while ((c = getc(din)) != EOF) { 88438133Srick if (c == '\n') 88538133Srick bare_lfs++; 88627749Sminshall while (c == '\r') { 88711651Ssam while (hash && (bytes >= hashbytes)) { 88826496Sminshall (void) putchar('#'); 88926496Sminshall (void) fflush(stdout); 89036940Skarels hashbytes += HASHBYTES; 89111651Ssam } 89210296Ssam bytes++; 89326048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 89436940Skarels if (ferror(fout)) 89536940Skarels goto break2; 89636940Skarels (void) putc('\r', fout); 89736942Skarels if (c == '\0') { 89836942Skarels bytes++; 89936940Skarels goto contin2; 90036942Skarels } 90136942Skarels if (c == EOF) 90236942Skarels goto contin2; 90311219Ssam } 90411219Ssam } 90536940Skarels (void) putc(c, fout); 90611219Ssam bytes++; 90736940Skarels contin2: ; 90810296Ssam } 90936940Skarels break2: 91038133Srick if (bare_lfs) { 91138133Srick printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); 91238133Srick printf("File may not have transferred correctly.\n"); 91338133Srick } 91411651Ssam if (hash) { 91513213Ssam if (bytes < hashbytes) 91626496Sminshall (void) putchar('#'); 91726496Sminshall (void) putchar('\n'); 91826496Sminshall (void) fflush(stdout); 91911651Ssam } 92036944Skarels if (ferror(din)) { 92136935Skarels if (errno != EPIPE) 92236944Skarels perror("netin"); 92336935Skarels bytes = -1; 92436935Skarels } 92536940Skarels if (ferror(fout)) 92638202Srick fprintf(stderr, "local: %s: %s\n", local, 92738202Srick strerror(errno)); 92811219Ssam break; 92910296Ssam } 93026448Slepreau if (closefunc != NULL) 93126048Sminshall (*closefunc)(fout); 93226496Sminshall (void) signal(SIGINT, oldintr); 93326448Slepreau if (oldintp) 93426048Sminshall (void) signal(SIGPIPE, oldintp); 93526496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 93610296Ssam (void) fclose(din); 93726048Sminshall (void) getreply(0); 93836935Skarels if (bytes > 0 && is_retr) 93937225Skarels ptransfer("received", bytes, &start, &stop); 94026048Sminshall return; 94126048Sminshall abort: 94226048Sminshall 94327687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 94426048Sminshall 94526496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 94626448Slepreau if (oldintp) 94726048Sminshall (void) signal(SIGPIPE, oldintr); 94838133Srick (void) signal(SIGINT, SIG_IGN); 94926048Sminshall if (!cpend) { 95026048Sminshall code = -1; 95138133Srick (void) signal(SIGINT, oldintr); 95226048Sminshall return; 95326048Sminshall } 95426048Sminshall 95538133Srick abort_remote(din); 95626048Sminshall code = -1; 95726048Sminshall if (data >= 0) { 95826048Sminshall (void) close(data); 95926048Sminshall data = -1; 96026048Sminshall } 96126448Slepreau if (closefunc != NULL && fout != NULL) 96226048Sminshall (*closefunc)(fout); 96326448Slepreau if (din) 96426048Sminshall (void) fclose(din); 96535699Sbostic if (bytes > 0) 96637225Skarels ptransfer("received", bytes, &start, &stop); 96738133Srick (void) signal(SIGINT, oldintr); 96810296Ssam } 96910296Ssam 97010296Ssam /* 97140193Sbostic * Need to start a listen on the data channel before we send the command, 97240193Sbostic * otherwise the server's connect may fail. 97310296Ssam */ 97410296Ssam initconn() 97510296Ssam { 97610296Ssam register char *p, *a; 97726048Sminshall int result, len, tmpno = 0; 97826993Skarels int on = 1; 97910296Ssam 98011651Ssam noport: 98110296Ssam data_addr = myctladdr; 98211651Ssam if (sendport) 98311651Ssam data_addr.sin_port = 0; /* let system pick one */ 98411651Ssam if (data != -1) 98538133Srick (void) close(data); 98618287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 98710296Ssam if (data < 0) { 98810296Ssam perror("ftp: socket"); 98926448Slepreau if (tmpno) 99026048Sminshall sendport = 1; 99110296Ssam return (1); 99210296Ssam } 99312397Ssam if (!sendport) 99427687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 99533224Sbostic perror("ftp: setsockopt (reuse address)"); 99612397Ssam goto bad; 99712397Ssam } 99826496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 99910296Ssam perror("ftp: bind"); 100010296Ssam goto bad; 100110296Ssam } 100210296Ssam if (options & SO_DEBUG && 100327687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 100410296Ssam perror("ftp: setsockopt (ignored)"); 100511627Ssam len = sizeof (data_addr); 100638133Srick if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 100711627Ssam perror("ftp: getsockname"); 100810296Ssam goto bad; 100910296Ssam } 101026448Slepreau if (listen(data, 1) < 0) 101110296Ssam perror("ftp: listen"); 101211651Ssam if (sendport) { 101311651Ssam a = (char *)&data_addr.sin_addr; 101411651Ssam p = (char *)&data_addr.sin_port; 101510296Ssam #define UC(b) (((int)b)&0xff) 101611651Ssam result = 101711651Ssam command("PORT %d,%d,%d,%d,%d,%d", 101811651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 101911651Ssam UC(p[0]), UC(p[1])); 102011651Ssam if (result == ERROR && sendport == -1) { 102111651Ssam sendport = 0; 102226048Sminshall tmpno = 1; 102311651Ssam goto noport; 102411651Ssam } 102511651Ssam return (result != COMPLETE); 102611651Ssam } 102726448Slepreau if (tmpno) 102826048Sminshall sendport = 1; 102944340Skarels #ifdef IP_TOS 103044340Skarels on = IPTOS_THROUGHPUT; 103144340Skarels if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 103244661Skarels perror("ftp: setsockopt TOS (ignored)"); 103344340Skarels #endif 103411651Ssam return (0); 103510296Ssam bad: 103610296Ssam (void) close(data), data = -1; 103726448Slepreau if (tmpno) 103826048Sminshall sendport = 1; 103910296Ssam return (1); 104010296Ssam } 104110296Ssam 104210296Ssam FILE * 104340193Sbostic dataconn(lmode) 104440193Sbostic char *lmode; 104510296Ssam { 104610296Ssam struct sockaddr_in from; 104744340Skarels int s, fromlen = sizeof (from), tos; 104810296Ssam 104926496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 105010296Ssam if (s < 0) { 105110296Ssam perror("ftp: accept"); 105210296Ssam (void) close(data), data = -1; 105310296Ssam return (NULL); 105410296Ssam } 105510296Ssam (void) close(data); 105610296Ssam data = s; 105744340Skarels #ifdef IP_TOS 105844340Skarels tos = IPTOS_THROUGHPUT; 105944340Skarels if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 106044661Skarels perror("ftp: setsockopt TOS (ignored)"); 106144340Skarels #endif 106240193Sbostic return (fdopen(data, lmode)); 106310296Ssam } 106410296Ssam 106537225Skarels ptransfer(direction, bytes, t0, t1) 106637225Skarels char *direction; 106711651Ssam long bytes; 106810296Ssam struct timeval *t0, *t1; 106910296Ssam { 107010296Ssam struct timeval td; 107116437Sleres float s, bs; 107210296Ssam 107335699Sbostic if (verbose) { 107435699Sbostic tvsub(&td, t1, t0); 107535699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 107610296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 107735699Sbostic bs = bytes / nz(s); 107835699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 107935699Sbostic bytes, direction, s, bs / 1024.); 108035699Sbostic } 108110296Ssam } 108210296Ssam 108326496Sminshall /*tvadd(tsum, t0) 108410296Ssam struct timeval *tsum, *t0; 108510296Ssam { 108610296Ssam 108710296Ssam tsum->tv_sec += t0->tv_sec; 108810296Ssam tsum->tv_usec += t0->tv_usec; 108910296Ssam if (tsum->tv_usec > 1000000) 109010296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 109126496Sminshall } */ 109210296Ssam 109310296Ssam tvsub(tdiff, t1, t0) 109410296Ssam struct timeval *tdiff, *t1, *t0; 109510296Ssam { 109610296Ssam 109710296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 109810296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 109910296Ssam if (tdiff->tv_usec < 0) 110010296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 110110296Ssam } 110226048Sminshall 110340193Sbostic void 110426048Sminshall psabort() 110526048Sminshall { 110626048Sminshall extern int abrtflag; 110726048Sminshall 110826048Sminshall abrtflag++; 110926048Sminshall } 111026048Sminshall 111126048Sminshall pswitch(flag) 111226048Sminshall int flag; 111326048Sminshall { 111426048Sminshall extern int proxy, abrtflag; 111540193Sbostic sig_t oldintr; 111626048Sminshall static struct comvars { 111726048Sminshall int connect; 111828469Skarels char name[MAXHOSTNAMELEN]; 111926048Sminshall struct sockaddr_in mctl; 112026048Sminshall struct sockaddr_in hctl; 112126048Sminshall FILE *in; 112226048Sminshall FILE *out; 112326048Sminshall int tpe; 112438033Skarels int curtpe; 112526048Sminshall int cpnd; 112626048Sminshall int sunqe; 112726048Sminshall int runqe; 112826048Sminshall int mcse; 112926048Sminshall int ntflg; 113026048Sminshall char nti[17]; 113126048Sminshall char nto[17]; 113226048Sminshall int mapflg; 113326048Sminshall char mi[MAXPATHLEN]; 113426048Sminshall char mo[MAXPATHLEN]; 113538033Skarels } proxstruct, tmpstruct; 113626048Sminshall struct comvars *ip, *op; 113726048Sminshall 113826048Sminshall abrtflag = 0; 113926048Sminshall oldintr = signal(SIGINT, psabort); 114026048Sminshall if (flag) { 114126448Slepreau if (proxy) 114226048Sminshall return; 114326048Sminshall ip = &tmpstruct; 114426048Sminshall op = &proxstruct; 114526048Sminshall proxy++; 114638033Skarels } else { 114726448Slepreau if (!proxy) 114826048Sminshall return; 114926048Sminshall ip = &proxstruct; 115026048Sminshall op = &tmpstruct; 115126048Sminshall proxy = 0; 115226048Sminshall } 115326048Sminshall ip->connect = connected; 115426048Sminshall connected = op->connect; 115528469Skarels if (hostname) { 115628469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 115728469Skarels ip->name[strlen(ip->name)] = '\0'; 115828469Skarels } else 115928469Skarels ip->name[0] = 0; 116026048Sminshall hostname = op->name; 116126048Sminshall ip->hctl = hisctladdr; 116226048Sminshall hisctladdr = op->hctl; 116326048Sminshall ip->mctl = myctladdr; 116426048Sminshall myctladdr = op->mctl; 116526048Sminshall ip->in = cin; 116626048Sminshall cin = op->in; 116726048Sminshall ip->out = cout; 116826048Sminshall cout = op->out; 116926048Sminshall ip->tpe = type; 117026048Sminshall type = op->tpe; 117138033Skarels ip->curtpe = curtype; 117238033Skarels curtype = op->curtpe; 117326048Sminshall ip->cpnd = cpend; 117426048Sminshall cpend = op->cpnd; 117526048Sminshall ip->sunqe = sunique; 117626048Sminshall sunique = op->sunqe; 117726048Sminshall ip->runqe = runique; 117826048Sminshall runique = op->runqe; 117926048Sminshall ip->mcse = mcase; 118026048Sminshall mcase = op->mcse; 118126048Sminshall ip->ntflg = ntflag; 118226048Sminshall ntflag = op->ntflg; 118326496Sminshall (void) strncpy(ip->nti, ntin, 16); 118426048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 118526496Sminshall (void) strcpy(ntin, op->nti); 118626496Sminshall (void) strncpy(ip->nto, ntout, 16); 118726048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 118826496Sminshall (void) strcpy(ntout, op->nto); 118926048Sminshall ip->mapflg = mapflag; 119026048Sminshall mapflag = op->mapflg; 119126496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 119226048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 119326496Sminshall (void) strcpy(mapin, op->mi); 119426496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 119526048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 119626496Sminshall (void) strcpy(mapout, op->mo); 119726048Sminshall (void) signal(SIGINT, oldintr); 119826048Sminshall if (abrtflag) { 119926048Sminshall abrtflag = 0; 120046828Sbostic (*oldintr)(SIGINT); 120126448Slepreau } 120226048Sminshall } 120326048Sminshall 120426048Sminshall jmp_buf ptabort; 120526048Sminshall int ptabflg; 120626048Sminshall 120740193Sbostic void 120826048Sminshall abortpt() 120926048Sminshall { 121026048Sminshall printf("\n"); 121126496Sminshall (void) fflush(stdout); 121226048Sminshall ptabflg++; 121326048Sminshall mflag = 0; 121426048Sminshall abrtflag = 0; 121526048Sminshall longjmp(ptabort, 1); 121626048Sminshall } 121726048Sminshall 121826048Sminshall proxtrans(cmd, local, remote) 121926048Sminshall char *cmd, *local, *remote; 122026048Sminshall { 122140193Sbostic sig_t oldintr; 122238133Srick int secndflag = 0, prox_type, nfnd; 122326048Sminshall extern jmp_buf ptabort; 122426048Sminshall char *cmd2; 122526496Sminshall struct fd_set mask; 122640193Sbostic void abortpt(); 122726048Sminshall 122826448Slepreau if (strcmp(cmd, "RETR")) 122926048Sminshall cmd2 = "RETR"; 123026448Slepreau else 123126048Sminshall cmd2 = runique ? "STOU" : "STOR"; 123238033Skarels if ((prox_type = type) == 0) { 123338033Skarels if (unix_server && unix_proxy) 123438033Skarels prox_type = TYPE_I; 123538033Skarels else 123638033Skarels prox_type = TYPE_A; 123738033Skarels } 123838033Skarels if (curtype != prox_type) 123938033Skarels changetype(prox_type, 1); 124026048Sminshall if (command("PASV") != COMPLETE) { 124138033Skarels printf("proxy server does not support third party transfers.\n"); 124226048Sminshall return; 124326048Sminshall } 124426048Sminshall pswitch(0); 124526048Sminshall if (!connected) { 124626048Sminshall printf("No primary connection\n"); 124726048Sminshall pswitch(1); 124826048Sminshall code = -1; 124926048Sminshall return; 125026048Sminshall } 125138033Skarels if (curtype != prox_type) 125238033Skarels changetype(prox_type, 1); 125326048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 125426048Sminshall pswitch(1); 125526048Sminshall return; 125626048Sminshall } 125726448Slepreau if (setjmp(ptabort)) 125826048Sminshall goto abort; 125926048Sminshall oldintr = signal(SIGINT, abortpt); 126026048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 126126048Sminshall (void) signal(SIGINT, oldintr); 126226048Sminshall pswitch(1); 126326048Sminshall return; 126426048Sminshall } 126526048Sminshall sleep(2); 126626048Sminshall pswitch(1); 126726048Sminshall secndflag++; 126826448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 126926048Sminshall goto abort; 127026048Sminshall ptflag++; 127126048Sminshall (void) getreply(0); 127226048Sminshall pswitch(0); 127326048Sminshall (void) getreply(0); 127426048Sminshall (void) signal(SIGINT, oldintr); 127526048Sminshall pswitch(1); 127626048Sminshall ptflag = 0; 127726048Sminshall printf("local: %s remote: %s\n", local, remote); 127826048Sminshall return; 127926048Sminshall abort: 128026048Sminshall (void) signal(SIGINT, SIG_IGN); 128126048Sminshall ptflag = 0; 128226448Slepreau if (strcmp(cmd, "RETR") && !proxy) 128326048Sminshall pswitch(1); 128426448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 128526048Sminshall pswitch(0); 128626048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 128726048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 128826048Sminshall pswitch(0); 128938133Srick if (cpend) 129038133Srick abort_remote((FILE *) NULL); 129126048Sminshall } 129226048Sminshall pswitch(1); 129326448Slepreau if (ptabflg) 129426048Sminshall code = -1; 129526048Sminshall (void) signal(SIGINT, oldintr); 129626048Sminshall return; 129726048Sminshall } 129838133Srick if (cpend) 129938133Srick abort_remote((FILE *) NULL); 130026048Sminshall pswitch(!proxy); 130126048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 130226048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 130326048Sminshall pswitch(0); 130438133Srick if (cpend) 130538133Srick abort_remote((FILE *) NULL); 130626048Sminshall pswitch(1); 130726448Slepreau if (ptabflg) 130826048Sminshall code = -1; 130926048Sminshall (void) signal(SIGINT, oldintr); 131026048Sminshall return; 131126048Sminshall } 131226048Sminshall } 131338133Srick if (cpend) 131438133Srick abort_remote((FILE *) NULL); 131526048Sminshall pswitch(!proxy); 131626048Sminshall if (cpend) { 131727687Sminshall FD_ZERO(&mask); 131826496Sminshall FD_SET(fileno(cin), &mask); 131938133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 132027687Sminshall if (nfnd < 0) { 132127687Sminshall perror("abort"); 132227687Sminshall } 132326448Slepreau if (ptabflg) 132426048Sminshall code = -1; 132526048Sminshall lostpeer(); 132626048Sminshall } 132726048Sminshall (void) getreply(0); 132826048Sminshall (void) getreply(0); 132926048Sminshall } 133026448Slepreau if (proxy) 133126048Sminshall pswitch(0); 133226048Sminshall pswitch(1); 133326448Slepreau if (ptabflg) 133426048Sminshall code = -1; 133526048Sminshall (void) signal(SIGINT, oldintr); 133626048Sminshall } 133726048Sminshall 133826048Sminshall reset() 133926048Sminshall { 134026496Sminshall struct fd_set mask; 134126496Sminshall int nfnd = 1; 134226048Sminshall 134327687Sminshall FD_ZERO(&mask); 134430946Scsvsj while (nfnd > 0) { 134526496Sminshall FD_SET(fileno(cin), &mask); 134627687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 134726048Sminshall perror("reset"); 134826048Sminshall code = -1; 134926048Sminshall lostpeer(); 135026048Sminshall } 135127687Sminshall else if (nfnd) { 135226048Sminshall (void) getreply(0); 135326496Sminshall } 135426048Sminshall } 135526048Sminshall } 135626048Sminshall 135726048Sminshall char * 135826048Sminshall gunique(local) 135926048Sminshall char *local; 136026048Sminshall { 136126048Sminshall static char new[MAXPATHLEN]; 136226048Sminshall char *cp = rindex(local, '/'); 136326048Sminshall int d, count=0; 136426048Sminshall char ext = '1'; 136526048Sminshall 136626448Slepreau if (cp) 136726048Sminshall *cp = '\0'; 136826048Sminshall d = access(cp ? local : ".", 2); 136926448Slepreau if (cp) 137026048Sminshall *cp = '/'; 137126048Sminshall if (d < 0) { 137238202Srick fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); 137326048Sminshall return((char *) 0); 137426048Sminshall } 137526048Sminshall (void) strcpy(new, local); 137626048Sminshall cp = new + strlen(new); 137726048Sminshall *cp++ = '.'; 137826048Sminshall while (!d) { 137926048Sminshall if (++count == 100) { 138026048Sminshall printf("runique: can't find unique file name.\n"); 138126048Sminshall return((char *) 0); 138226048Sminshall } 138326048Sminshall *cp++ = ext; 138426048Sminshall *cp = '\0'; 138526448Slepreau if (ext == '9') 138626048Sminshall ext = '0'; 138726448Slepreau else 138826048Sminshall ext++; 138926448Slepreau if ((d = access(new, 0)) < 0) 139026048Sminshall break; 139126448Slepreau if (ext != '0') 139226048Sminshall cp--; 139326448Slepreau else if (*(cp - 2) == '.') 139426048Sminshall *(cp - 1) = '1'; 139526048Sminshall else { 139626048Sminshall *(cp - 2) = *(cp - 2) + 1; 139726048Sminshall cp--; 139826048Sminshall } 139926048Sminshall } 140026048Sminshall return(new); 140126048Sminshall } 140238133Srick 140338133Srick abort_remote(din) 140438133Srick FILE *din; 140538133Srick { 140638133Srick char buf[BUFSIZ]; 140738133Srick int nfnd; 140838133Srick struct fd_set mask; 140938133Srick 141038133Srick /* 141138133Srick * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 141238133Srick * after urgent byte rather than before as is protocol now 141338133Srick */ 141438133Srick sprintf(buf, "%c%c%c", IAC, IP, IAC); 141538133Srick if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 141638133Srick perror("abort"); 141738133Srick fprintf(cout,"%cABOR\r\n", DM); 141838133Srick (void) fflush(cout); 141938133Srick FD_ZERO(&mask); 142038133Srick FD_SET(fileno(cin), &mask); 142138133Srick if (din) { 142238133Srick FD_SET(fileno(din), &mask); 142338133Srick } 142438133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 142538133Srick if (nfnd < 0) { 142638133Srick perror("abort"); 142738133Srick } 142838133Srick if (ptabflg) 142938133Srick code = -1; 143038133Srick lostpeer(); 143138133Srick } 143238133Srick if (din && FD_ISSET(fileno(din), &mask)) { 143338133Srick while (read(fileno(din), buf, BUFSIZ) > 0) 143438133Srick /* LOOP */; 143538133Srick } 143638133Srick if (getreply(0) == ERROR && code == 552) { 143738133Srick /* 552 needed for nic style abort */ 143838133Srick (void) getreply(0); 143938133Srick } 144038133Srick (void) getreply(0); 144138133Srick } 1442