121739Sdist /* 2*62010Sbostic * Copyright (c) 1985, 1989, 1993 3*62010Sbostic * The Regents of the University of California. All rights reserved. 433737Sbostic * 542665Sbostic * %sccs.include.redist.c% 621739Sdist */ 721739Sdist 810296Ssam #ifndef lint 9*62010Sbostic static char sccsid[] = "@(#)ftp.c 8.1 (Berkeley) 06/06/93"; 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 <signal.h> 2610296Ssam #include <netdb.h> 2726048Sminshall #include <fcntl.h> 2854192Sbostic #include <errno.h> 2926048Sminshall #include <pwd.h> 3038133Srick #include <varargs.h> 3154192Sbostic #include <unistd.h> 3254192Sbostic #include <stdlib.h> 3354192Sbostic #include <stdio.h> 3454192Sbostic #include <string.h> 3510296Ssam 3636940Skarels #include "ftp_var.h" 3736940Skarels 3810296Ssam struct sockaddr_in hisctladdr; 3910296Ssam struct sockaddr_in data_addr; 4010296Ssam int data = -1; 4126048Sminshall int abrtflag = 0; 4226048Sminshall int ptflag = 0; 4310296Ssam struct sockaddr_in myctladdr; 4438133Srick sig_t lostpeer(); 4537225Skarels off_t restart_point = 0; 4610296Ssam 4740193Sbostic extern int connected, errno; 4838202Srick 4910296Ssam FILE *cin, *cout; 5010296Ssam FILE *dataconn(); 5110296Ssam 5225904Skarels char * 5310296Ssam hookup(host, port) 5410296Ssam char *host; 5510296Ssam int port; 5610296Ssam { 5725904Skarels register struct hostent *hp = 0; 5844340Skarels int s, len, tos; 5925904Skarels static char hostnamebuf[80]; 6010296Ssam 6110296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 6225904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 6325904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 6425904Skarels hisctladdr.sin_family = AF_INET; 6536940Skarels (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); 6636940Skarels } else { 6725100Sbloom hp = gethostbyname(host); 6825904Skarels if (hp == NULL) { 6935792Sbostic fprintf(stderr, "ftp: %s: ", host); 7035792Sbostic herror((char *)NULL); 7126048Sminshall code = -1; 7226048Sminshall return((char *) 0); 7325904Skarels } 7425904Skarels hisctladdr.sin_family = hp->h_addrtype; 7525904Skarels bcopy(hp->h_addr_list[0], 7625904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 7736940Skarels (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); 7810296Ssam } 7925904Skarels hostname = hostnamebuf; 8025904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 8110296Ssam if (s < 0) { 8210296Ssam perror("ftp: socket"); 8326048Sminshall code = -1; 8410296Ssam return (0); 8510296Ssam } 8610296Ssam hisctladdr.sin_port = port; 8738133Srick while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { 8825904Skarels if (hp && hp->h_addr_list[1]) { 8925904Skarels int oerrno = errno; 9038133Srick extern char *inet_ntoa(); 9125904Skarels 9225904Skarels fprintf(stderr, "ftp: connect to address %s: ", 9325904Skarels inet_ntoa(hisctladdr.sin_addr)); 9425904Skarels errno = oerrno; 9526496Sminshall perror((char *) 0); 9625904Skarels hp->h_addr_list++; 9725904Skarels bcopy(hp->h_addr_list[0], 9826048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 9926496Sminshall fprintf(stdout, "Trying %s...\n", 10025904Skarels inet_ntoa(hisctladdr.sin_addr)); 10126813Skarels (void) close(s); 10226813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 10326813Skarels if (s < 0) { 10426813Skarels perror("ftp: socket"); 10526813Skarels code = -1; 10626813Skarels return (0); 10726813Skarels } 10825904Skarels continue; 10925904Skarels } 11010296Ssam perror("ftp: connect"); 11126048Sminshall code = -1; 11210296Ssam goto bad; 11310296Ssam } 11411627Ssam len = sizeof (myctladdr); 11538133Srick if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { 11611627Ssam perror("ftp: getsockname"); 11726048Sminshall code = -1; 11810296Ssam goto bad; 11910296Ssam } 12044340Skarels #ifdef IP_TOS 12144340Skarels tos = IPTOS_LOWDELAY; 12244340Skarels if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 12344661Skarels perror("ftp: setsockopt TOS (ignored)"); 12444340Skarels #endif 12510296Ssam cin = fdopen(s, "r"); 12610296Ssam cout = fdopen(s, "w"); 12711219Ssam if (cin == NULL || cout == NULL) { 12810296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 12910296Ssam if (cin) 13026496Sminshall (void) fclose(cin); 13110296Ssam if (cout) 13226496Sminshall (void) fclose(cout); 13326048Sminshall code = -1; 13410296Ssam goto bad; 13510296Ssam } 13610296Ssam if (verbose) 13726067Sminshall printf("Connected to %s.\n", hostname); 13827687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 13926048Sminshall if (cin) 14026496Sminshall (void) fclose(cin); 14126048Sminshall if (cout) 14226496Sminshall (void) fclose(cout); 14326048Sminshall code = -1; 14426048Sminshall goto bad; 14526048Sminshall } 14627687Sminshall #ifdef SO_OOBINLINE 14727687Sminshall { 14827687Sminshall int on = 1; 14926048Sminshall 15040193Sbostic if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) 15127687Sminshall < 0 && debug) { 15227687Sminshall perror("ftp: setsockopt"); 15327687Sminshall } 15427687Sminshall } 15538133Srick #endif /* SO_OOBINLINE */ 15626048Sminshall 15725904Skarels return (hostname); 15810296Ssam bad: 15926496Sminshall (void) close(s); 16025904Skarels return ((char *)0); 16110296Ssam } 16210296Ssam 16325904Skarels login(host) 16425904Skarels char *host; 16510296Ssam { 16626048Sminshall char tmp[80]; 16735659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 16826048Sminshall int n, aflag = 0; 16910296Ssam 17026048Sminshall user = pass = acct = 0; 17126048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 17226048Sminshall code = -1; 17326048Sminshall return(0); 17426048Sminshall } 17537458Skarels while (user == NULL) { 17626048Sminshall char *myname = getlogin(); 17726048Sminshall 17826048Sminshall if (myname == NULL) { 17926048Sminshall struct passwd *pp = getpwuid(getuid()); 18026048Sminshall 18126448Slepreau if (pp != NULL) 18226048Sminshall myname = pp->pw_name; 18326048Sminshall } 18437458Skarels if (myname) 18537458Skarels printf("Name (%s:%s): ", host, myname); 18637458Skarels else 18737458Skarels printf("Name (%s): ", host); 18826048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 18926048Sminshall tmp[strlen(tmp) - 1] = '\0'; 19026448Slepreau if (*tmp == '\0') 19126048Sminshall user = myname; 19226448Slepreau else 19326048Sminshall user = tmp; 19426048Sminshall } 19510296Ssam n = command("USER %s", user); 19626048Sminshall if (n == CONTINUE) { 19726448Slepreau if (pass == NULL) 19835659Sbostic pass = getpass("Password:"); 19910296Ssam n = command("PASS %s", pass); 20026048Sminshall } 20110296Ssam if (n == CONTINUE) { 20226048Sminshall aflag++; 20335659Sbostic acct = getpass("Account:"); 20410296Ssam n = command("ACCT %s", acct); 20510296Ssam } 20610296Ssam if (n != COMPLETE) { 20710296Ssam fprintf(stderr, "Login failed.\n"); 20810296Ssam return (0); 20910296Ssam } 21026448Slepreau if (!aflag && acct != NULL) 21126048Sminshall (void) command("ACCT %s", acct); 21226448Slepreau if (proxy) 21326048Sminshall return(1); 21426048Sminshall for (n = 0; n < macnum; ++n) { 21526048Sminshall if (!strcmp("init", macros[n].mac_name)) { 21626496Sminshall (void) strcpy(line, "$init"); 21726048Sminshall makeargv(); 21826048Sminshall domacro(margc, margv); 21926048Sminshall break; 22026048Sminshall } 22126048Sminshall } 22210296Ssam return (1); 22310296Ssam } 22410296Ssam 22540193Sbostic void 22626048Sminshall cmdabort() 22726048Sminshall { 22826048Sminshall extern jmp_buf ptabort; 22926048Sminshall 23026048Sminshall printf("\n"); 23126048Sminshall (void) fflush(stdout); 23226048Sminshall abrtflag++; 23326448Slepreau if (ptflag) 23426048Sminshall longjmp(ptabort,1); 23526048Sminshall } 23626048Sminshall 23738133Srick /*VARARGS*/ 23838133Srick command(va_alist) 23938133Srick va_dcl 24038133Srick { 24138133Srick va_list ap; 24210296Ssam char *fmt; 24338133Srick int r; 24440193Sbostic sig_t oldintr; 24540193Sbostic void cmdabort(); 24610296Ssam 24726048Sminshall abrtflag = 0; 24810296Ssam if (debug) { 24910296Ssam printf("---> "); 25038133Srick va_start(ap); 25138133Srick fmt = va_arg(ap, char *); 25238133Srick if (strncmp("PASS ", fmt, 5) == 0) 25338133Srick printf("PASS XXXX"); 25438133Srick else 25538133Srick vfprintf(stdout, fmt, ap); 25638133Srick va_end(ap); 25710296Ssam printf("\n"); 25810296Ssam (void) fflush(stdout); 25910296Ssam } 26011219Ssam if (cout == NULL) { 26111219Ssam perror ("No control connection for command"); 26226048Sminshall code = -1; 26311219Ssam return (0); 26411219Ssam } 26538133Srick oldintr = signal(SIGINT, cmdabort); 26638133Srick va_start(ap); 26738133Srick fmt = va_arg(ap, char *); 26838133Srick vfprintf(cout, fmt, ap); 26938133Srick va_end(ap); 27010296Ssam fprintf(cout, "\r\n"); 27110296Ssam (void) fflush(cout); 27226048Sminshall cpend = 1; 27326048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 27426448Slepreau if (abrtflag && oldintr != SIG_IGN) 27546828Sbostic (*oldintr)(SIGINT); 27626048Sminshall (void) signal(SIGINT, oldintr); 27726048Sminshall return(r); 27810296Ssam } 27910296Ssam 28037229Skarels char reply_string[BUFSIZ]; /* last line of previous reply */ 28136935Skarels 28210296Ssam #include <ctype.h> 28310296Ssam 28410296Ssam getreply(expecteof) 28510296Ssam int expecteof; 28610296Ssam { 28711219Ssam register int c, n; 28826048Sminshall register int dig; 28936935Skarels register char *cp; 29038133Srick int originalcode = 0, continuation = 0; 29140193Sbostic sig_t oldintr; 29226048Sminshall int pflag = 0; 29326048Sminshall char *pt = pasv; 29440193Sbostic void cmdabort(); 29510296Ssam 29638133Srick oldintr = signal(SIGINT, cmdabort); 29710296Ssam for (;;) { 29810296Ssam dig = n = code = 0; 29937229Skarels cp = reply_string; 30010296Ssam while ((c = getc(cin)) != '\n') { 30127687Sminshall if (c == IAC) { /* handle telnet commands */ 30227687Sminshall switch (c = getc(cin)) { 30327687Sminshall case WILL: 30427687Sminshall case WONT: 30527687Sminshall c = getc(cin); 30638133Srick fprintf(cout, "%c%c%c", IAC, DONT, c); 30727687Sminshall (void) fflush(cout); 30827687Sminshall break; 30927687Sminshall case DO: 31027687Sminshall case DONT: 31127687Sminshall c = getc(cin); 31238133Srick fprintf(cout, "%c%c%c", IAC, WONT, c); 31327687Sminshall (void) fflush(cout); 31427687Sminshall break; 31527687Sminshall default: 31627687Sminshall break; 31727687Sminshall } 31827687Sminshall continue; 31927687Sminshall } 32010296Ssam dig++; 32110296Ssam if (c == EOF) { 32226048Sminshall if (expecteof) { 32326048Sminshall (void) signal(SIGINT,oldintr); 32426048Sminshall code = 221; 32510296Ssam return (0); 32626048Sminshall } 32710296Ssam lostpeer(); 32826048Sminshall if (verbose) { 32926048Sminshall printf("421 Service not available, remote server has closed connection\n"); 33026048Sminshall (void) fflush(stdout); 33126048Sminshall } 33233772Scsvsj code = 421; 33333772Scsvsj return(4); 33410296Ssam } 33526048Sminshall if (c != '\r' && (verbose > 0 || 33626048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 33726448Slepreau if (proxflag && 33826448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 33926048Sminshall printf("%s:",hostname); 34026496Sminshall (void) putchar(c); 34126048Sminshall } 34210296Ssam if (dig < 4 && isdigit(c)) 34310296Ssam code = code * 10 + (c - '0'); 34426448Slepreau if (!pflag && code == 227) 34526048Sminshall pflag = 1; 34626448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 34726048Sminshall pflag = 2; 34826048Sminshall if (pflag == 2) { 34926448Slepreau if (c != '\r' && c != ')') 35026048Sminshall *pt++ = c; 35126048Sminshall else { 35226048Sminshall *pt = '\0'; 35326048Sminshall pflag = 3; 35426048Sminshall } 35526048Sminshall } 35626048Sminshall if (dig == 4 && c == '-') { 35726448Slepreau if (continuation) 35826048Sminshall code = 0; 35910296Ssam continuation++; 36026048Sminshall } 36110296Ssam if (n == 0) 36210296Ssam n = c; 36337229Skarels if (cp < &reply_string[sizeof(reply_string) - 1]) 36437229Skarels *cp++ = c; 36510296Ssam } 36626048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 36726496Sminshall (void) putchar(c); 36811346Ssam (void) fflush (stdout); 36911346Ssam } 37010296Ssam if (continuation && code != originalcode) { 37110296Ssam if (originalcode == 0) 37210296Ssam originalcode = code; 37310296Ssam continue; 37410296Ssam } 37536935Skarels *cp = '\0'; 37626448Slepreau if (n != '1') 37726048Sminshall cpend = 0; 37826048Sminshall (void) signal(SIGINT,oldintr); 37926448Slepreau if (code == 421 || originalcode == 421) 38026048Sminshall lostpeer(); 38126448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 38246828Sbostic (*oldintr)(SIGINT); 38325907Smckusick return (n - '0'); 38410296Ssam } 38510296Ssam } 38610296Ssam 38726048Sminshall empty(mask, sec) 38827687Sminshall struct fd_set *mask; 38926048Sminshall int sec; 39026048Sminshall { 39126048Sminshall struct timeval t; 39226048Sminshall 39326048Sminshall t.tv_sec = (long) sec; 39426048Sminshall t.tv_usec = 0; 39527687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 39626048Sminshall } 39726048Sminshall 39810296Ssam jmp_buf sendabort; 39910296Ssam 40040193Sbostic void 40110296Ssam abortsend() 40210296Ssam { 40310296Ssam 40426048Sminshall mflag = 0; 40526048Sminshall abrtflag = 0; 40638133Srick printf("\nsend aborted\nwaiting for remote to finish abort\n"); 40726048Sminshall (void) fflush(stdout); 40810296Ssam longjmp(sendabort, 1); 40910296Ssam } 41010296Ssam 41136940Skarels #define HASHBYTES 1024 41236940Skarels 41337225Skarels sendrequest(cmd, local, remote, printnames) 41410296Ssam char *cmd, *local, *remote; 41537225Skarels int printnames; 41610296Ssam { 41740193Sbostic struct stat st; 41840193Sbostic struct timeval start, stop; 41940193Sbostic register int c, d; 42035659Sbostic FILE *fin, *dout = 0, *popen(); 42138133Srick int (*closefunc)(), pclose(), fclose(); 42240193Sbostic sig_t oldintr, oldintp; 42336940Skarels long bytes = 0, hashbytes = HASHBYTES; 42440193Sbostic char *lmode, buf[BUFSIZ], *bufp; 42540193Sbostic void abortsend(); 42610296Ssam 42737225Skarels if (verbose && printnames) { 42837225Skarels if (local && *local != '-') 42937225Skarels printf("local: %s ", local); 43037225Skarels if (remote) 43137225Skarels printf("remote: %s\n", remote); 43237225Skarels } 43326048Sminshall if (proxy) { 43426048Sminshall proxtrans(cmd, local, remote); 43526048Sminshall return; 43626048Sminshall } 43738033Skarels if (curtype != type) 43838033Skarels changetype(type, 0); 43910296Ssam closefunc = NULL; 44026048Sminshall oldintr = NULL; 44126048Sminshall oldintp = NULL; 44240193Sbostic lmode = "w"; 44326048Sminshall if (setjmp(sendabort)) { 44426048Sminshall while (cpend) { 44526048Sminshall (void) getreply(0); 44626048Sminshall } 44726048Sminshall if (data >= 0) { 44826048Sminshall (void) close(data); 44926048Sminshall data = -1; 45026048Sminshall } 45126448Slepreau if (oldintr) 45226048Sminshall (void) signal(SIGINT,oldintr); 45326448Slepreau if (oldintp) 45426048Sminshall (void) signal(SIGPIPE,oldintp); 45526048Sminshall code = -1; 45626048Sminshall return; 45726048Sminshall } 45810296Ssam oldintr = signal(SIGINT, abortsend); 45910296Ssam if (strcmp(local, "-") == 0) 46010296Ssam fin = stdin; 46110296Ssam else if (*local == '|') { 46226048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 46335659Sbostic fin = popen(local + 1, "r"); 46410296Ssam if (fin == NULL) { 46526048Sminshall perror(local + 1); 46626048Sminshall (void) signal(SIGINT, oldintr); 46726048Sminshall (void) signal(SIGPIPE, oldintp); 46826048Sminshall code = -1; 46926048Sminshall return; 47010296Ssam } 47135659Sbostic closefunc = pclose; 47210296Ssam } else { 47310296Ssam fin = fopen(local, "r"); 47410296Ssam if (fin == NULL) { 47538202Srick fprintf(stderr, "local: %s: %s\n", local, 47638202Srick strerror(errno)); 47726048Sminshall (void) signal(SIGINT, oldintr); 47826048Sminshall code = -1; 47926048Sminshall return; 48010296Ssam } 48110296Ssam closefunc = fclose; 48210296Ssam if (fstat(fileno(fin), &st) < 0 || 48310296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 48426496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 48526048Sminshall (void) signal(SIGINT, oldintr); 48636935Skarels fclose(fin); 48726048Sminshall code = -1; 48826048Sminshall return; 48910296Ssam } 49010296Ssam } 49126048Sminshall if (initconn()) { 49226048Sminshall (void) signal(SIGINT, oldintr); 49326448Slepreau if (oldintp) 49426048Sminshall (void) signal(SIGPIPE, oldintp); 49526048Sminshall code = -1; 49636935Skarels if (closefunc != NULL) 49736935Skarels (*closefunc)(fin); 49826048Sminshall return; 49926048Sminshall } 50026448Slepreau if (setjmp(sendabort)) 50126048Sminshall goto abort; 50236935Skarels 50337225Skarels if (restart_point && 50437225Skarels (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 50537225Skarels if (fseek(fin, (long) restart_point, 0) < 0) { 50638202Srick fprintf(stderr, "local: %s: %s\n", local, 50738202Srick strerror(errno)); 50837225Skarels restart_point = 0; 50937225Skarels if (closefunc != NULL) 51037225Skarels (*closefunc)(fin); 51137225Skarels return; 51237225Skarels } 51337225Skarels if (command("REST %ld", (long) restart_point) 51437225Skarels != CONTINUE) { 51537225Skarels restart_point = 0; 51637225Skarels if (closefunc != NULL) 51737225Skarels (*closefunc)(fin); 51837225Skarels return; 51937225Skarels } 52037225Skarels restart_point = 0; 52140193Sbostic lmode = "r+w"; 52237225Skarels } 52310296Ssam if (remote) { 52426048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 52526048Sminshall (void) signal(SIGINT, oldintr); 52626448Slepreau if (oldintp) 52726048Sminshall (void) signal(SIGPIPE, oldintp); 52836935Skarels if (closefunc != NULL) 52936935Skarels (*closefunc)(fin); 53026048Sminshall return; 53126048Sminshall } 53210296Ssam } else 53326048Sminshall if (command("%s", cmd) != PRELIM) { 53426048Sminshall (void) signal(SIGINT, oldintr); 53526448Slepreau if (oldintp) 53626048Sminshall (void) signal(SIGPIPE, oldintp); 53736935Skarels if (closefunc != NULL) 53836935Skarels (*closefunc)(fin); 53926048Sminshall return; 54026048Sminshall } 54140193Sbostic dout = dataconn(lmode); 54226448Slepreau if (dout == NULL) 54326048Sminshall goto abort; 54426496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 54536935Skarels oldintp = signal(SIGPIPE, SIG_IGN); 54642278Skarels switch (curtype) { 54711219Ssam 54811219Ssam case TYPE_I: 54911219Ssam case TYPE_L: 55011346Ssam errno = d = 0; 55136942Skarels while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { 55211219Ssam bytes += c; 55336942Skarels for (bufp = buf; c > 0; c -= d, bufp += d) 55436942Skarels if ((d = write(fileno(dout), bufp, c)) <= 0) 55536942Skarels break; 55611651Ssam if (hash) { 55736940Skarels while (bytes >= hashbytes) { 55836940Skarels (void) putchar('#'); 55936940Skarels hashbytes += HASHBYTES; 56036940Skarels } 56126496Sminshall (void) fflush(stdout); 56211651Ssam } 56311219Ssam } 56413213Ssam if (hash && bytes > 0) { 56536940Skarels if (bytes < HASHBYTES) 56636940Skarels (void) putchar('#'); 56726496Sminshall (void) putchar('\n'); 56826496Sminshall (void) fflush(stdout); 56911651Ssam } 57011219Ssam if (c < 0) 57138202Srick fprintf(stderr, "local: %s: %s\n", local, 57238202Srick strerror(errno)); 57348507Srick if (d < 0) { 57448507Srick if (errno != EPIPE) 57536935Skarels perror("netout"); 57636935Skarels bytes = -1; 57736935Skarels } 57811219Ssam break; 57911219Ssam 58011219Ssam case TYPE_A: 58111219Ssam while ((c = getc(fin)) != EOF) { 58211219Ssam if (c == '\n') { 58311651Ssam while (hash && (bytes >= hashbytes)) { 58426496Sminshall (void) putchar('#'); 58526496Sminshall (void) fflush(stdout); 58636940Skarels hashbytes += HASHBYTES; 58711651Ssam } 58811219Ssam if (ferror(dout)) 58911219Ssam break; 59026496Sminshall (void) putc('\r', dout); 59111219Ssam bytes++; 59211219Ssam } 59326496Sminshall (void) putc(c, dout); 59411219Ssam bytes++; 59526048Sminshall /* if (c == '\r') { */ 59626496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 59726048Sminshall /* bytes++; */ 59826048Sminshall /* } */ 59911219Ssam } 60011651Ssam if (hash) { 60113213Ssam if (bytes < hashbytes) 60226496Sminshall (void) putchar('#'); 60326496Sminshall (void) putchar('\n'); 60426496Sminshall (void) fflush(stdout); 60511651Ssam } 60611219Ssam if (ferror(fin)) 60738202Srick fprintf(stderr, "local: %s: %s\n", local, 60838202Srick strerror(errno)); 60936935Skarels if (ferror(dout)) { 61036935Skarels if (errno != EPIPE) 61136935Skarels perror("netout"); 61236935Skarels bytes = -1; 61336935Skarels } 61411219Ssam break; 61510296Ssam } 61626496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 61710296Ssam if (closefunc != NULL) 61826048Sminshall (*closefunc)(fin); 61910296Ssam (void) fclose(dout); 62026048Sminshall (void) getreply(0); 62126048Sminshall (void) signal(SIGINT, oldintr); 62236935Skarels if (oldintp) 62336935Skarels (void) signal(SIGPIPE, oldintp); 62435699Sbostic if (bytes > 0) 62537225Skarels ptransfer("sent", bytes, &start, &stop); 62610296Ssam return; 62726048Sminshall abort: 62826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 62926048Sminshall (void) signal(SIGINT, oldintr); 63026448Slepreau if (oldintp) 63126048Sminshall (void) signal(SIGPIPE, oldintp); 63226048Sminshall if (!cpend) { 63326048Sminshall code = -1; 63426048Sminshall return; 63526048Sminshall } 63626048Sminshall if (data >= 0) { 63726048Sminshall (void) close(data); 63826048Sminshall data = -1; 63926048Sminshall } 64026448Slepreau if (dout) 64126048Sminshall (void) fclose(dout); 64226048Sminshall (void) getreply(0); 64326048Sminshall code = -1; 64410296Ssam if (closefunc != NULL && fin != NULL) 64526048Sminshall (*closefunc)(fin); 64635699Sbostic if (bytes > 0) 64737225Skarels ptransfer("sent", bytes, &start, &stop); 64810296Ssam } 64910296Ssam 65010296Ssam jmp_buf recvabort; 65110296Ssam 65240193Sbostic void 65310296Ssam abortrecv() 65410296Ssam { 65510296Ssam 65626048Sminshall mflag = 0; 65726048Sminshall abrtflag = 0; 65838133Srick printf("\nreceive aborted\nwaiting for remote to finish abort\n"); 65926048Sminshall (void) fflush(stdout); 66010296Ssam longjmp(recvabort, 1); 66110296Ssam } 66210296Ssam 66340193Sbostic recvrequest(cmd, local, remote, lmode, printnames) 66440193Sbostic char *cmd, *local, *remote, *lmode; 66510296Ssam { 66635659Sbostic FILE *fout, *din = 0, *popen(); 66738133Srick int (*closefunc)(), pclose(), fclose(); 66840193Sbostic sig_t oldintr, oldintp; 66938133Srick int is_retr, tcrflag, bare_lfs = 0; 67038133Srick char *gunique(); 67138133Srick static int bufsize; 67236944Skarels static char *buf; 67336940Skarels long bytes = 0, hashbytes = HASHBYTES; 67411346Ssam register int c, d; 67510296Ssam struct timeval start, stop; 67636940Skarels struct stat st; 67740193Sbostic void abortrecv(); 67810296Ssam 67936935Skarels is_retr = strcmp(cmd, "RETR") == 0; 68037225Skarels if (is_retr && verbose && printnames) { 68137225Skarels if (local && *local != '-') 68237225Skarels printf("local: %s ", local); 68337225Skarels if (remote) 68437225Skarels printf("remote: %s\n", remote); 68537225Skarels } 68636935Skarels if (proxy && is_retr) { 68726048Sminshall proxtrans(cmd, local, remote); 68826048Sminshall return; 68926048Sminshall } 69010296Ssam closefunc = NULL; 69126048Sminshall oldintr = NULL; 69226048Sminshall oldintp = NULL; 69336935Skarels tcrflag = !crflag && is_retr; 69426048Sminshall if (setjmp(recvabort)) { 69526048Sminshall while (cpend) { 69626048Sminshall (void) getreply(0); 69726048Sminshall } 69826048Sminshall if (data >= 0) { 69926048Sminshall (void) close(data); 70026048Sminshall data = -1; 70126048Sminshall } 70226448Slepreau if (oldintr) 70326048Sminshall (void) signal(SIGINT, oldintr); 70426048Sminshall code = -1; 70526048Sminshall return; 70626048Sminshall } 70710296Ssam oldintr = signal(SIGINT, abortrecv); 70826048Sminshall if (strcmp(local, "-") && *local != '|') { 70910296Ssam if (access(local, 2) < 0) { 71026048Sminshall char *dir = rindex(local, '/'); 71110296Ssam 71226048Sminshall if (errno != ENOENT && errno != EACCES) { 71338202Srick fprintf(stderr, "local: %s: %s\n", local, 71438202Srick strerror(errno)); 71526048Sminshall (void) signal(SIGINT, oldintr); 71626048Sminshall code = -1; 71726048Sminshall return; 71810296Ssam } 71926048Sminshall if (dir != NULL) 72026048Sminshall *dir = 0; 72126048Sminshall d = access(dir ? local : ".", 2); 72226048Sminshall if (dir != NULL) 72326048Sminshall *dir = '/'; 72426048Sminshall if (d < 0) { 72538202Srick fprintf(stderr, "local: %s: %s\n", local, 72638202Srick strerror(errno)); 72726048Sminshall (void) signal(SIGINT, oldintr); 72826048Sminshall code = -1; 72926048Sminshall return; 73026048Sminshall } 73126048Sminshall if (!runique && errno == EACCES && 73236935Skarels chmod(local, 0600) < 0) { 73338202Srick fprintf(stderr, "local: %s: %s\n", local, 73438202Srick strerror(errno)); 73526048Sminshall (void) signal(SIGINT, oldintr); 73638202Srick (void) signal(SIGINT, oldintr); 73726048Sminshall code = -1; 73826048Sminshall return; 73926048Sminshall } 74026048Sminshall if (runique && errno == EACCES && 74126048Sminshall (local = gunique(local)) == NULL) { 74226048Sminshall (void) signal(SIGINT, oldintr); 74326048Sminshall code = -1; 74426048Sminshall return; 74526048Sminshall } 74610296Ssam } 74726048Sminshall else if (runique && (local = gunique(local)) == NULL) { 74826048Sminshall (void) signal(SIGINT, oldintr); 74926048Sminshall code = -1; 75026048Sminshall return; 75126048Sminshall } 75226048Sminshall } 75338033Skarels if (!is_retr) { 75438033Skarels if (curtype != TYPE_A) 75538033Skarels changetype(TYPE_A, 0); 75638033Skarels } else if (curtype != type) 75738033Skarels changetype(type, 0); 75826048Sminshall if (initconn()) { 75926048Sminshall (void) signal(SIGINT, oldintr); 76026048Sminshall code = -1; 76126048Sminshall return; 76226048Sminshall } 76326448Slepreau if (setjmp(recvabort)) 76426048Sminshall goto abort; 76538033Skarels if (is_retr && restart_point && 76638033Skarels command("REST %ld", (long) restart_point) != CONTINUE) 76738033Skarels return; 76810296Ssam if (remote) { 76926048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 77026048Sminshall (void) signal(SIGINT, oldintr); 77126048Sminshall return; 77226048Sminshall } 77326048Sminshall } else { 77426048Sminshall if (command("%s", cmd) != PRELIM) { 77526048Sminshall (void) signal(SIGINT, oldintr); 77626048Sminshall return; 77726048Sminshall } 77826048Sminshall } 77926048Sminshall din = dataconn("r"); 78026048Sminshall if (din == NULL) 78126048Sminshall goto abort; 78226448Slepreau if (strcmp(local, "-") == 0) 78310296Ssam fout = stdout; 78410296Ssam else if (*local == '|') { 78526048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 78635659Sbostic fout = popen(local + 1, "w"); 78726048Sminshall if (fout == NULL) { 78826048Sminshall perror(local+1); 78926048Sminshall goto abort; 79026048Sminshall } 79135659Sbostic closefunc = pclose; 79236940Skarels } else { 79340193Sbostic fout = fopen(local, lmode); 79426048Sminshall if (fout == NULL) { 79538202Srick fprintf(stderr, "local: %s: %s\n", local, 79638202Srick strerror(errno)); 79726048Sminshall goto abort; 79826048Sminshall } 79910296Ssam closefunc = fclose; 80010296Ssam } 80136940Skarels if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 80236940Skarels st.st_blksize = BUFSIZ; 80336940Skarels if (st.st_blksize > bufsize) { 80436940Skarels if (buf) 80536940Skarels (void) free(buf); 80638133Srick buf = malloc((unsigned)st.st_blksize); 80736940Skarels if (buf == NULL) { 80836940Skarels perror("malloc"); 80936944Skarels bufsize = 0; 81036940Skarels goto abort; 81136940Skarels } 81236940Skarels bufsize = st.st_blksize; 81336940Skarels } 81426496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 81538033Skarels switch (curtype) { 81611219Ssam 81711219Ssam case TYPE_I: 81811219Ssam case TYPE_L: 81937225Skarels if (restart_point && 82054192Sbostic lseek(fileno(fout), (off_t)restart_point, L_SET) < 0) { 82138202Srick fprintf(stderr, "local: %s: %s\n", local, 82238202Srick strerror(errno)); 82337225Skarels if (closefunc != NULL) 82437225Skarels (*closefunc)(fout); 82537225Skarels return; 82637225Skarels } 82711346Ssam errno = d = 0; 82836940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) { 82936944Skarels if ((d = write(fileno(fout), buf, c)) != c) 83011219Ssam break; 83111219Ssam bytes += c; 83211651Ssam if (hash) { 83336940Skarels while (bytes >= hashbytes) { 83436940Skarels (void) putchar('#'); 83536940Skarels hashbytes += HASHBYTES; 83636940Skarels } 83726496Sminshall (void) fflush(stdout); 83811651Ssam } 83911219Ssam } 84013213Ssam if (hash && bytes > 0) { 84136940Skarels if (bytes < HASHBYTES) 84236940Skarels (void) putchar('#'); 84326496Sminshall (void) putchar('\n'); 84426496Sminshall (void) fflush(stdout); 84511651Ssam } 84636935Skarels if (c < 0) { 84736935Skarels if (errno != EPIPE) 84836935Skarels perror("netin"); 84936935Skarels bytes = -1; 85036935Skarels } 85136942Skarels if (d < c) { 85236942Skarels if (d < 0) 85338202Srick fprintf(stderr, "local: %s: %s\n", local, 85438202Srick strerror(errno)); 85536942Skarels else 85636942Skarels fprintf(stderr, "%s: short write\n", local); 85736942Skarels } 85811219Ssam break; 85911219Ssam 86011219Ssam case TYPE_A: 86137225Skarels if (restart_point) { 86240193Sbostic register int i, n, ch; 86337225Skarels 86437225Skarels if (fseek(fout, 0L, L_SET) < 0) 86537225Skarels goto done; 86637225Skarels n = restart_point; 86740193Sbostic for (i = 0; i++ < n;) { 86840193Sbostic if ((ch = getc(fout)) == EOF) 86937225Skarels goto done; 87040193Sbostic if (ch == '\n') 87137225Skarels i++; 87237225Skarels } 87337225Skarels if (fseek(fout, 0L, L_INCR) < 0) { 87437225Skarels done: 87538202Srick fprintf(stderr, "local: %s: %s\n", local, 87638202Srick strerror(errno)); 87737225Skarels if (closefunc != NULL) 87837225Skarels (*closefunc)(fout); 87937225Skarels return; 88037225Skarels } 88137225Skarels } 88211219Ssam while ((c = getc(din)) != EOF) { 88338133Srick if (c == '\n') 88438133Srick bare_lfs++; 88527749Sminshall while (c == '\r') { 88611651Ssam while (hash && (bytes >= hashbytes)) { 88726496Sminshall (void) putchar('#'); 88826496Sminshall (void) fflush(stdout); 88936940Skarels hashbytes += HASHBYTES; 89011651Ssam } 89110296Ssam bytes++; 89226048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 89336940Skarels if (ferror(fout)) 89436940Skarels goto break2; 89536940Skarels (void) putc('\r', fout); 89636942Skarels if (c == '\0') { 89736942Skarels bytes++; 89836940Skarels goto contin2; 89936942Skarels } 90036942Skarels if (c == EOF) 90136942Skarels goto contin2; 90211219Ssam } 90311219Ssam } 90436940Skarels (void) putc(c, fout); 90511219Ssam bytes++; 90636940Skarels contin2: ; 90710296Ssam } 90836940Skarels break2: 90938133Srick if (bare_lfs) { 91038133Srick printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); 91138133Srick printf("File may not have transferred correctly.\n"); 91238133Srick } 91311651Ssam if (hash) { 91413213Ssam if (bytes < hashbytes) 91526496Sminshall (void) putchar('#'); 91626496Sminshall (void) putchar('\n'); 91726496Sminshall (void) fflush(stdout); 91811651Ssam } 91936944Skarels if (ferror(din)) { 92036935Skarels if (errno != EPIPE) 92136944Skarels perror("netin"); 92236935Skarels bytes = -1; 92336935Skarels } 92436940Skarels if (ferror(fout)) 92538202Srick fprintf(stderr, "local: %s: %s\n", local, 92638202Srick strerror(errno)); 92711219Ssam break; 92810296Ssam } 92926448Slepreau if (closefunc != NULL) 93026048Sminshall (*closefunc)(fout); 93126496Sminshall (void) signal(SIGINT, oldintr); 93226448Slepreau if (oldintp) 93326048Sminshall (void) signal(SIGPIPE, oldintp); 93426496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 93510296Ssam (void) fclose(din); 93626048Sminshall (void) getreply(0); 93736935Skarels if (bytes > 0 && is_retr) 93837225Skarels ptransfer("received", bytes, &start, &stop); 93926048Sminshall return; 94026048Sminshall abort: 94126048Sminshall 94227687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 94326048Sminshall 94426496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 94526448Slepreau if (oldintp) 94626048Sminshall (void) signal(SIGPIPE, oldintr); 94738133Srick (void) signal(SIGINT, SIG_IGN); 94826048Sminshall if (!cpend) { 94926048Sminshall code = -1; 95038133Srick (void) signal(SIGINT, oldintr); 95126048Sminshall return; 95226048Sminshall } 95326048Sminshall 95438133Srick abort_remote(din); 95526048Sminshall code = -1; 95626048Sminshall if (data >= 0) { 95726048Sminshall (void) close(data); 95826048Sminshall data = -1; 95926048Sminshall } 96026448Slepreau if (closefunc != NULL && fout != NULL) 96126048Sminshall (*closefunc)(fout); 96226448Slepreau if (din) 96326048Sminshall (void) fclose(din); 96435699Sbostic if (bytes > 0) 96537225Skarels ptransfer("received", bytes, &start, &stop); 96638133Srick (void) signal(SIGINT, oldintr); 96710296Ssam } 96810296Ssam 96910296Ssam /* 97040193Sbostic * Need to start a listen on the data channel before we send the command, 97140193Sbostic * otherwise the server's connect may fail. 97210296Ssam */ 97310296Ssam initconn() 97410296Ssam { 97510296Ssam register char *p, *a; 97626048Sminshall int result, len, tmpno = 0; 97726993Skarels int on = 1; 97810296Ssam 97911651Ssam noport: 98010296Ssam data_addr = myctladdr; 98111651Ssam if (sendport) 98211651Ssam data_addr.sin_port = 0; /* let system pick one */ 98311651Ssam if (data != -1) 98438133Srick (void) close(data); 98518287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 98610296Ssam if (data < 0) { 98710296Ssam perror("ftp: socket"); 98826448Slepreau if (tmpno) 98926048Sminshall sendport = 1; 99010296Ssam return (1); 99110296Ssam } 99212397Ssam if (!sendport) 99327687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 99433224Sbostic perror("ftp: setsockopt (reuse address)"); 99512397Ssam goto bad; 99612397Ssam } 99726496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 99810296Ssam perror("ftp: bind"); 99910296Ssam goto bad; 100010296Ssam } 100110296Ssam if (options & SO_DEBUG && 100227687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 100310296Ssam perror("ftp: setsockopt (ignored)"); 100411627Ssam len = sizeof (data_addr); 100538133Srick if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 100611627Ssam perror("ftp: getsockname"); 100710296Ssam goto bad; 100810296Ssam } 100926448Slepreau if (listen(data, 1) < 0) 101010296Ssam perror("ftp: listen"); 101111651Ssam if (sendport) { 101211651Ssam a = (char *)&data_addr.sin_addr; 101311651Ssam p = (char *)&data_addr.sin_port; 101410296Ssam #define UC(b) (((int)b)&0xff) 101511651Ssam result = 101611651Ssam command("PORT %d,%d,%d,%d,%d,%d", 101711651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 101811651Ssam UC(p[0]), UC(p[1])); 101911651Ssam if (result == ERROR && sendport == -1) { 102011651Ssam sendport = 0; 102126048Sminshall tmpno = 1; 102211651Ssam goto noport; 102311651Ssam } 102411651Ssam return (result != COMPLETE); 102511651Ssam } 102626448Slepreau if (tmpno) 102726048Sminshall sendport = 1; 102844340Skarels #ifdef IP_TOS 102944340Skarels on = IPTOS_THROUGHPUT; 103044340Skarels if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 103144661Skarels perror("ftp: setsockopt TOS (ignored)"); 103244340Skarels #endif 103311651Ssam return (0); 103410296Ssam bad: 103510296Ssam (void) close(data), data = -1; 103626448Slepreau if (tmpno) 103726048Sminshall sendport = 1; 103810296Ssam return (1); 103910296Ssam } 104010296Ssam 104110296Ssam FILE * 104240193Sbostic dataconn(lmode) 104340193Sbostic char *lmode; 104410296Ssam { 104510296Ssam struct sockaddr_in from; 104644340Skarels int s, fromlen = sizeof (from), tos; 104710296Ssam 104826496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 104910296Ssam if (s < 0) { 105010296Ssam perror("ftp: accept"); 105110296Ssam (void) close(data), data = -1; 105210296Ssam return (NULL); 105310296Ssam } 105410296Ssam (void) close(data); 105510296Ssam data = s; 105644340Skarels #ifdef IP_TOS 105744340Skarels tos = IPTOS_THROUGHPUT; 105844340Skarels if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 105944661Skarels perror("ftp: setsockopt TOS (ignored)"); 106044340Skarels #endif 106140193Sbostic return (fdopen(data, lmode)); 106210296Ssam } 106310296Ssam 106437225Skarels ptransfer(direction, bytes, t0, t1) 106537225Skarels char *direction; 106611651Ssam long bytes; 106710296Ssam struct timeval *t0, *t1; 106810296Ssam { 106910296Ssam struct timeval td; 107016437Sleres float s, bs; 107110296Ssam 107235699Sbostic if (verbose) { 107335699Sbostic tvsub(&td, t1, t0); 107435699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 107510296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 107635699Sbostic bs = bytes / nz(s); 107735699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 107835699Sbostic bytes, direction, s, bs / 1024.); 107935699Sbostic } 108010296Ssam } 108110296Ssam 108226496Sminshall /*tvadd(tsum, t0) 108310296Ssam struct timeval *tsum, *t0; 108410296Ssam { 108510296Ssam 108610296Ssam tsum->tv_sec += t0->tv_sec; 108710296Ssam tsum->tv_usec += t0->tv_usec; 108810296Ssam if (tsum->tv_usec > 1000000) 108910296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 109026496Sminshall } */ 109110296Ssam 109210296Ssam tvsub(tdiff, t1, t0) 109310296Ssam struct timeval *tdiff, *t1, *t0; 109410296Ssam { 109510296Ssam 109610296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 109710296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 109810296Ssam if (tdiff->tv_usec < 0) 109910296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 110010296Ssam } 110126048Sminshall 110240193Sbostic void 110326048Sminshall psabort() 110426048Sminshall { 110526048Sminshall extern int abrtflag; 110626048Sminshall 110726048Sminshall abrtflag++; 110826048Sminshall } 110926048Sminshall 111026048Sminshall pswitch(flag) 111126048Sminshall int flag; 111226048Sminshall { 111326048Sminshall extern int proxy, abrtflag; 111440193Sbostic sig_t oldintr; 111526048Sminshall static struct comvars { 111626048Sminshall int connect; 111728469Skarels char name[MAXHOSTNAMELEN]; 111826048Sminshall struct sockaddr_in mctl; 111926048Sminshall struct sockaddr_in hctl; 112026048Sminshall FILE *in; 112126048Sminshall FILE *out; 112226048Sminshall int tpe; 112338033Skarels int curtpe; 112426048Sminshall int cpnd; 112526048Sminshall int sunqe; 112626048Sminshall int runqe; 112726048Sminshall int mcse; 112826048Sminshall int ntflg; 112926048Sminshall char nti[17]; 113026048Sminshall char nto[17]; 113126048Sminshall int mapflg; 113226048Sminshall char mi[MAXPATHLEN]; 113326048Sminshall char mo[MAXPATHLEN]; 113438033Skarels } proxstruct, tmpstruct; 113526048Sminshall struct comvars *ip, *op; 113626048Sminshall 113726048Sminshall abrtflag = 0; 113826048Sminshall oldintr = signal(SIGINT, psabort); 113926048Sminshall if (flag) { 114026448Slepreau if (proxy) 114126048Sminshall return; 114226048Sminshall ip = &tmpstruct; 114326048Sminshall op = &proxstruct; 114426048Sminshall proxy++; 114538033Skarels } else { 114626448Slepreau if (!proxy) 114726048Sminshall return; 114826048Sminshall ip = &proxstruct; 114926048Sminshall op = &tmpstruct; 115026048Sminshall proxy = 0; 115126048Sminshall } 115226048Sminshall ip->connect = connected; 115326048Sminshall connected = op->connect; 115428469Skarels if (hostname) { 115528469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 115628469Skarels ip->name[strlen(ip->name)] = '\0'; 115728469Skarels } else 115828469Skarels ip->name[0] = 0; 115926048Sminshall hostname = op->name; 116026048Sminshall ip->hctl = hisctladdr; 116126048Sminshall hisctladdr = op->hctl; 116226048Sminshall ip->mctl = myctladdr; 116326048Sminshall myctladdr = op->mctl; 116426048Sminshall ip->in = cin; 116526048Sminshall cin = op->in; 116626048Sminshall ip->out = cout; 116726048Sminshall cout = op->out; 116826048Sminshall ip->tpe = type; 116926048Sminshall type = op->tpe; 117038033Skarels ip->curtpe = curtype; 117138033Skarels curtype = op->curtpe; 117226048Sminshall ip->cpnd = cpend; 117326048Sminshall cpend = op->cpnd; 117426048Sminshall ip->sunqe = sunique; 117526048Sminshall sunique = op->sunqe; 117626048Sminshall ip->runqe = runique; 117726048Sminshall runique = op->runqe; 117826048Sminshall ip->mcse = mcase; 117926048Sminshall mcase = op->mcse; 118026048Sminshall ip->ntflg = ntflag; 118126048Sminshall ntflag = op->ntflg; 118226496Sminshall (void) strncpy(ip->nti, ntin, 16); 118326048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 118426496Sminshall (void) strcpy(ntin, op->nti); 118526496Sminshall (void) strncpy(ip->nto, ntout, 16); 118626048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 118726496Sminshall (void) strcpy(ntout, op->nto); 118826048Sminshall ip->mapflg = mapflag; 118926048Sminshall mapflag = op->mapflg; 119026496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 119126048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 119226496Sminshall (void) strcpy(mapin, op->mi); 119326496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 119426048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 119526496Sminshall (void) strcpy(mapout, op->mo); 119626048Sminshall (void) signal(SIGINT, oldintr); 119726048Sminshall if (abrtflag) { 119826048Sminshall abrtflag = 0; 119946828Sbostic (*oldintr)(SIGINT); 120026448Slepreau } 120126048Sminshall } 120226048Sminshall 120326048Sminshall jmp_buf ptabort; 120426048Sminshall int ptabflg; 120526048Sminshall 120640193Sbostic void 120726048Sminshall abortpt() 120826048Sminshall { 120926048Sminshall printf("\n"); 121026496Sminshall (void) fflush(stdout); 121126048Sminshall ptabflg++; 121226048Sminshall mflag = 0; 121326048Sminshall abrtflag = 0; 121426048Sminshall longjmp(ptabort, 1); 121526048Sminshall } 121626048Sminshall 121726048Sminshall proxtrans(cmd, local, remote) 121826048Sminshall char *cmd, *local, *remote; 121926048Sminshall { 122040193Sbostic sig_t oldintr; 122138133Srick int secndflag = 0, prox_type, nfnd; 122226048Sminshall extern jmp_buf ptabort; 122326048Sminshall char *cmd2; 122426496Sminshall struct fd_set mask; 122540193Sbostic void abortpt(); 122626048Sminshall 122726448Slepreau if (strcmp(cmd, "RETR")) 122826048Sminshall cmd2 = "RETR"; 122926448Slepreau else 123026048Sminshall cmd2 = runique ? "STOU" : "STOR"; 123138033Skarels if ((prox_type = type) == 0) { 123238033Skarels if (unix_server && unix_proxy) 123338033Skarels prox_type = TYPE_I; 123438033Skarels else 123538033Skarels prox_type = TYPE_A; 123638033Skarels } 123738033Skarels if (curtype != prox_type) 123838033Skarels changetype(prox_type, 1); 123926048Sminshall if (command("PASV") != COMPLETE) { 124038033Skarels printf("proxy server does not support third party transfers.\n"); 124126048Sminshall return; 124226048Sminshall } 124326048Sminshall pswitch(0); 124426048Sminshall if (!connected) { 124526048Sminshall printf("No primary connection\n"); 124626048Sminshall pswitch(1); 124726048Sminshall code = -1; 124826048Sminshall return; 124926048Sminshall } 125038033Skarels if (curtype != prox_type) 125138033Skarels changetype(prox_type, 1); 125226048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 125326048Sminshall pswitch(1); 125426048Sminshall return; 125526048Sminshall } 125626448Slepreau if (setjmp(ptabort)) 125726048Sminshall goto abort; 125826048Sminshall oldintr = signal(SIGINT, abortpt); 125926048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 126026048Sminshall (void) signal(SIGINT, oldintr); 126126048Sminshall pswitch(1); 126226048Sminshall return; 126326048Sminshall } 126426048Sminshall sleep(2); 126526048Sminshall pswitch(1); 126626048Sminshall secndflag++; 126726448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 126826048Sminshall goto abort; 126926048Sminshall ptflag++; 127026048Sminshall (void) getreply(0); 127126048Sminshall pswitch(0); 127226048Sminshall (void) getreply(0); 127326048Sminshall (void) signal(SIGINT, oldintr); 127426048Sminshall pswitch(1); 127526048Sminshall ptflag = 0; 127626048Sminshall printf("local: %s remote: %s\n", local, remote); 127726048Sminshall return; 127826048Sminshall abort: 127926048Sminshall (void) signal(SIGINT, SIG_IGN); 128026048Sminshall ptflag = 0; 128126448Slepreau if (strcmp(cmd, "RETR") && !proxy) 128226048Sminshall pswitch(1); 128326448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 128426048Sminshall pswitch(0); 128526048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 128626048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 128726048Sminshall pswitch(0); 128838133Srick if (cpend) 128938133Srick abort_remote((FILE *) NULL); 129026048Sminshall } 129126048Sminshall pswitch(1); 129226448Slepreau if (ptabflg) 129326048Sminshall code = -1; 129426048Sminshall (void) signal(SIGINT, oldintr); 129526048Sminshall return; 129626048Sminshall } 129738133Srick if (cpend) 129838133Srick abort_remote((FILE *) NULL); 129926048Sminshall pswitch(!proxy); 130026048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 130126048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 130226048Sminshall pswitch(0); 130338133Srick if (cpend) 130438133Srick abort_remote((FILE *) NULL); 130526048Sminshall pswitch(1); 130626448Slepreau if (ptabflg) 130726048Sminshall code = -1; 130826048Sminshall (void) signal(SIGINT, oldintr); 130926048Sminshall return; 131026048Sminshall } 131126048Sminshall } 131238133Srick if (cpend) 131338133Srick abort_remote((FILE *) NULL); 131426048Sminshall pswitch(!proxy); 131526048Sminshall if (cpend) { 131627687Sminshall FD_ZERO(&mask); 131726496Sminshall FD_SET(fileno(cin), &mask); 131838133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 131927687Sminshall if (nfnd < 0) { 132027687Sminshall perror("abort"); 132127687Sminshall } 132226448Slepreau if (ptabflg) 132326048Sminshall code = -1; 132426048Sminshall lostpeer(); 132526048Sminshall } 132626048Sminshall (void) getreply(0); 132726048Sminshall (void) getreply(0); 132826048Sminshall } 132926448Slepreau if (proxy) 133026048Sminshall pswitch(0); 133126048Sminshall pswitch(1); 133226448Slepreau if (ptabflg) 133326048Sminshall code = -1; 133426048Sminshall (void) signal(SIGINT, oldintr); 133526048Sminshall } 133626048Sminshall 133726048Sminshall reset() 133826048Sminshall { 133926496Sminshall struct fd_set mask; 134026496Sminshall int nfnd = 1; 134126048Sminshall 134227687Sminshall FD_ZERO(&mask); 134330946Scsvsj while (nfnd > 0) { 134426496Sminshall FD_SET(fileno(cin), &mask); 134527687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 134626048Sminshall perror("reset"); 134726048Sminshall code = -1; 134826048Sminshall lostpeer(); 134926048Sminshall } 135027687Sminshall else if (nfnd) { 135126048Sminshall (void) getreply(0); 135226496Sminshall } 135326048Sminshall } 135426048Sminshall } 135526048Sminshall 135626048Sminshall char * 135726048Sminshall gunique(local) 135826048Sminshall char *local; 135926048Sminshall { 136026048Sminshall static char new[MAXPATHLEN]; 136126048Sminshall char *cp = rindex(local, '/'); 136226048Sminshall int d, count=0; 136326048Sminshall char ext = '1'; 136426048Sminshall 136526448Slepreau if (cp) 136626048Sminshall *cp = '\0'; 136726048Sminshall d = access(cp ? local : ".", 2); 136826448Slepreau if (cp) 136926048Sminshall *cp = '/'; 137026048Sminshall if (d < 0) { 137138202Srick fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); 137226048Sminshall return((char *) 0); 137326048Sminshall } 137426048Sminshall (void) strcpy(new, local); 137526048Sminshall cp = new + strlen(new); 137626048Sminshall *cp++ = '.'; 137726048Sminshall while (!d) { 137826048Sminshall if (++count == 100) { 137926048Sminshall printf("runique: can't find unique file name.\n"); 138026048Sminshall return((char *) 0); 138126048Sminshall } 138226048Sminshall *cp++ = ext; 138326048Sminshall *cp = '\0'; 138426448Slepreau if (ext == '9') 138526048Sminshall ext = '0'; 138626448Slepreau else 138726048Sminshall ext++; 138826448Slepreau if ((d = access(new, 0)) < 0) 138926048Sminshall break; 139026448Slepreau if (ext != '0') 139126048Sminshall cp--; 139226448Slepreau else if (*(cp - 2) == '.') 139326048Sminshall *(cp - 1) = '1'; 139426048Sminshall else { 139526048Sminshall *(cp - 2) = *(cp - 2) + 1; 139626048Sminshall cp--; 139726048Sminshall } 139826048Sminshall } 139926048Sminshall return(new); 140026048Sminshall } 140138133Srick 140238133Srick abort_remote(din) 140338133Srick FILE *din; 140438133Srick { 140538133Srick char buf[BUFSIZ]; 140638133Srick int nfnd; 140738133Srick struct fd_set mask; 140838133Srick 140938133Srick /* 141038133Srick * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 141138133Srick * after urgent byte rather than before as is protocol now 141238133Srick */ 141338133Srick sprintf(buf, "%c%c%c", IAC, IP, IAC); 141438133Srick if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 141538133Srick perror("abort"); 141638133Srick fprintf(cout,"%cABOR\r\n", DM); 141738133Srick (void) fflush(cout); 141838133Srick FD_ZERO(&mask); 141938133Srick FD_SET(fileno(cin), &mask); 142038133Srick if (din) { 142138133Srick FD_SET(fileno(din), &mask); 142238133Srick } 142338133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 142438133Srick if (nfnd < 0) { 142538133Srick perror("abort"); 142638133Srick } 142738133Srick if (ptabflg) 142838133Srick code = -1; 142938133Srick lostpeer(); 143038133Srick } 143138133Srick if (din && FD_ISSET(fileno(din), &mask)) { 143238133Srick while (read(fileno(din), buf, BUFSIZ) > 0) 143338133Srick /* LOOP */; 143438133Srick } 143538133Srick if (getreply(0) == ERROR && code == 552) { 143638133Srick /* 552 needed for nic style abort */ 143738133Srick (void) getreply(0); 143838133Srick } 143938133Srick (void) getreply(0); 144038133Srick } 1441