121739Sdist /* 236942Skarels * Copyright (c) 1985, 1989 Regents of the University of California. 333737Sbostic * All rights reserved. 433737Sbostic * 5*42665Sbostic * %sccs.include.redist.c% 621739Sdist */ 721739Sdist 810296Ssam #ifndef lint 9*42665Sbostic static char sccsid[] = "@(#)ftp.c 5.34 (Berkeley) 06/01/90"; 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> 2012397Ssam #include <arpa/ftp.h> 2126048Sminshall #include <arpa/telnet.h> 2210296Ssam 2310296Ssam #include <stdio.h> 2410296Ssam #include <signal.h> 2510296Ssam #include <errno.h> 2610296Ssam #include <netdb.h> 2726048Sminshall #include <fcntl.h> 2826048Sminshall #include <pwd.h> 2938133Srick #include <varargs.h> 3010296Ssam 3136940Skarels #include "ftp_var.h" 3236940Skarels 3310296Ssam struct sockaddr_in hisctladdr; 3410296Ssam struct sockaddr_in data_addr; 3510296Ssam int data = -1; 3626048Sminshall int abrtflag = 0; 3726048Sminshall int ptflag = 0; 3810296Ssam struct sockaddr_in myctladdr; 3926496Sminshall uid_t getuid(); 4038133Srick sig_t lostpeer(); 4137225Skarels off_t restart_point = 0; 4210296Ssam 4338202Srick extern char *strerror(); 4440193Sbostic extern int connected, errno; 4538202Srick 4610296Ssam FILE *cin, *cout; 4710296Ssam FILE *dataconn(); 4810296Ssam 4925904Skarels char * 5010296Ssam hookup(host, port) 5110296Ssam char *host; 5210296Ssam int port; 5310296Ssam { 5425904Skarels register struct hostent *hp = 0; 5527687Sminshall int s,len; 5625904Skarels static char hostnamebuf[80]; 5710296Ssam 5810296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 5925904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 6025904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 6125904Skarels hisctladdr.sin_family = AF_INET; 6236940Skarels (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); 6336940Skarels } else { 6425100Sbloom hp = gethostbyname(host); 6525904Skarels if (hp == NULL) { 6635792Sbostic fprintf(stderr, "ftp: %s: ", host); 6735792Sbostic herror((char *)NULL); 6826048Sminshall code = -1; 6926048Sminshall return((char *) 0); 7025904Skarels } 7125904Skarels hisctladdr.sin_family = hp->h_addrtype; 7225904Skarels bcopy(hp->h_addr_list[0], 7325904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 7436940Skarels (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); 7510296Ssam } 7625904Skarels hostname = hostnamebuf; 7725904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 7810296Ssam if (s < 0) { 7910296Ssam perror("ftp: socket"); 8026048Sminshall code = -1; 8110296Ssam return (0); 8210296Ssam } 8310296Ssam hisctladdr.sin_port = port; 8438133Srick while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { 8525904Skarels if (hp && hp->h_addr_list[1]) { 8625904Skarels int oerrno = errno; 8738133Srick extern char *inet_ntoa(); 8825904Skarels 8925904Skarels fprintf(stderr, "ftp: connect to address %s: ", 9025904Skarels inet_ntoa(hisctladdr.sin_addr)); 9125904Skarels errno = oerrno; 9226496Sminshall perror((char *) 0); 9325904Skarels hp->h_addr_list++; 9425904Skarels bcopy(hp->h_addr_list[0], 9526048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 9626496Sminshall fprintf(stdout, "Trying %s...\n", 9725904Skarels inet_ntoa(hisctladdr.sin_addr)); 9826813Skarels (void) close(s); 9926813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 10026813Skarels if (s < 0) { 10126813Skarels perror("ftp: socket"); 10226813Skarels code = -1; 10326813Skarels return (0); 10426813Skarels } 10525904Skarels continue; 10625904Skarels } 10710296Ssam perror("ftp: connect"); 10826048Sminshall code = -1; 10910296Ssam goto bad; 11010296Ssam } 11111627Ssam len = sizeof (myctladdr); 11238133Srick if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { 11311627Ssam perror("ftp: getsockname"); 11426048Sminshall code = -1; 11510296Ssam goto bad; 11610296Ssam } 11710296Ssam cin = fdopen(s, "r"); 11810296Ssam cout = fdopen(s, "w"); 11911219Ssam if (cin == NULL || cout == NULL) { 12010296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 12110296Ssam if (cin) 12226496Sminshall (void) fclose(cin); 12310296Ssam if (cout) 12426496Sminshall (void) fclose(cout); 12526048Sminshall code = -1; 12610296Ssam goto bad; 12710296Ssam } 12810296Ssam if (verbose) 12926067Sminshall printf("Connected to %s.\n", hostname); 13027687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 13126048Sminshall if (cin) 13226496Sminshall (void) fclose(cin); 13326048Sminshall if (cout) 13426496Sminshall (void) fclose(cout); 13526048Sminshall code = -1; 13626048Sminshall goto bad; 13726048Sminshall } 13827687Sminshall #ifdef SO_OOBINLINE 13927687Sminshall { 14027687Sminshall int on = 1; 14126048Sminshall 14240193Sbostic if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) 14327687Sminshall < 0 && debug) { 14427687Sminshall perror("ftp: setsockopt"); 14527687Sminshall } 14627687Sminshall } 14738133Srick #endif /* SO_OOBINLINE */ 14826048Sminshall 14925904Skarels return (hostname); 15010296Ssam bad: 15126496Sminshall (void) close(s); 15225904Skarels return ((char *)0); 15310296Ssam } 15410296Ssam 15525904Skarels login(host) 15625904Skarels char *host; 15710296Ssam { 15826048Sminshall char tmp[80]; 15935659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 16026048Sminshall int n, aflag = 0; 16110296Ssam 16226048Sminshall user = pass = acct = 0; 16326048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 16426048Sminshall code = -1; 16526048Sminshall return(0); 16626048Sminshall } 16737458Skarels while (user == NULL) { 16826048Sminshall char *myname = getlogin(); 16926048Sminshall 17026048Sminshall if (myname == NULL) { 17126048Sminshall struct passwd *pp = getpwuid(getuid()); 17226048Sminshall 17326448Slepreau if (pp != NULL) 17426048Sminshall myname = pp->pw_name; 17526048Sminshall } 17637458Skarels if (myname) 17737458Skarels printf("Name (%s:%s): ", host, myname); 17837458Skarels else 17937458Skarels printf("Name (%s): ", host); 18026048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 18126048Sminshall tmp[strlen(tmp) - 1] = '\0'; 18226448Slepreau if (*tmp == '\0') 18326048Sminshall user = myname; 18426448Slepreau else 18526048Sminshall user = tmp; 18626048Sminshall } 18710296Ssam n = command("USER %s", user); 18826048Sminshall if (n == CONTINUE) { 18926448Slepreau if (pass == NULL) 19035659Sbostic pass = getpass("Password:"); 19110296Ssam n = command("PASS %s", pass); 19226048Sminshall } 19310296Ssam if (n == CONTINUE) { 19426048Sminshall aflag++; 19535659Sbostic acct = getpass("Account:"); 19610296Ssam n = command("ACCT %s", acct); 19710296Ssam } 19810296Ssam if (n != COMPLETE) { 19910296Ssam fprintf(stderr, "Login failed.\n"); 20010296Ssam return (0); 20110296Ssam } 20226448Slepreau if (!aflag && acct != NULL) 20326048Sminshall (void) command("ACCT %s", acct); 20426448Slepreau if (proxy) 20526048Sminshall return(1); 20626048Sminshall for (n = 0; n < macnum; ++n) { 20726048Sminshall if (!strcmp("init", macros[n].mac_name)) { 20826496Sminshall (void) strcpy(line, "$init"); 20926048Sminshall makeargv(); 21026048Sminshall domacro(margc, margv); 21126048Sminshall break; 21226048Sminshall } 21326048Sminshall } 21410296Ssam return (1); 21510296Ssam } 21610296Ssam 21740193Sbostic void 21826048Sminshall cmdabort() 21926048Sminshall { 22026048Sminshall extern jmp_buf ptabort; 22126048Sminshall 22226048Sminshall printf("\n"); 22326048Sminshall (void) fflush(stdout); 22426048Sminshall abrtflag++; 22526448Slepreau if (ptflag) 22626048Sminshall longjmp(ptabort,1); 22726048Sminshall } 22826048Sminshall 22938133Srick /*VARARGS*/ 23038133Srick command(va_alist) 23138133Srick va_dcl 23238133Srick { 23338133Srick va_list ap; 23410296Ssam char *fmt; 23538133Srick int r; 23640193Sbostic sig_t oldintr; 23740193Sbostic void cmdabort(); 23810296Ssam 23926048Sminshall abrtflag = 0; 24010296Ssam if (debug) { 24110296Ssam printf("---> "); 24238133Srick va_start(ap); 24338133Srick fmt = va_arg(ap, char *); 24438133Srick if (strncmp("PASS ", fmt, 5) == 0) 24538133Srick printf("PASS XXXX"); 24638133Srick else 24738133Srick vfprintf(stdout, fmt, ap); 24838133Srick va_end(ap); 24910296Ssam printf("\n"); 25010296Ssam (void) fflush(stdout); 25110296Ssam } 25211219Ssam if (cout == NULL) { 25311219Ssam perror ("No control connection for command"); 25426048Sminshall code = -1; 25511219Ssam return (0); 25611219Ssam } 25738133Srick oldintr = signal(SIGINT, cmdabort); 25838133Srick va_start(ap); 25938133Srick fmt = va_arg(ap, char *); 26038133Srick vfprintf(cout, fmt, ap); 26138133Srick va_end(ap); 26210296Ssam fprintf(cout, "\r\n"); 26310296Ssam (void) fflush(cout); 26426048Sminshall cpend = 1; 26526048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 26626448Slepreau if (abrtflag && oldintr != SIG_IGN) 26726048Sminshall (*oldintr)(); 26826048Sminshall (void) signal(SIGINT, oldintr); 26926048Sminshall return(r); 27010296Ssam } 27110296Ssam 27237229Skarels char reply_string[BUFSIZ]; /* last line of previous reply */ 27336935Skarels 27410296Ssam #include <ctype.h> 27510296Ssam 27610296Ssam getreply(expecteof) 27710296Ssam int expecteof; 27810296Ssam { 27911219Ssam register int c, n; 28026048Sminshall register int dig; 28136935Skarels register char *cp; 28238133Srick int originalcode = 0, continuation = 0; 28340193Sbostic sig_t oldintr; 28426048Sminshall int pflag = 0; 28526048Sminshall char *pt = pasv; 28640193Sbostic void cmdabort(); 28710296Ssam 28838133Srick oldintr = signal(SIGINT, cmdabort); 28910296Ssam for (;;) { 29010296Ssam dig = n = code = 0; 29137229Skarels cp = reply_string; 29210296Ssam while ((c = getc(cin)) != '\n') { 29327687Sminshall if (c == IAC) { /* handle telnet commands */ 29427687Sminshall switch (c = getc(cin)) { 29527687Sminshall case WILL: 29627687Sminshall case WONT: 29727687Sminshall c = getc(cin); 29838133Srick fprintf(cout, "%c%c%c", IAC, DONT, c); 29927687Sminshall (void) fflush(cout); 30027687Sminshall break; 30127687Sminshall case DO: 30227687Sminshall case DONT: 30327687Sminshall c = getc(cin); 30438133Srick fprintf(cout, "%c%c%c", IAC, WONT, c); 30527687Sminshall (void) fflush(cout); 30627687Sminshall break; 30727687Sminshall default: 30827687Sminshall break; 30927687Sminshall } 31027687Sminshall continue; 31127687Sminshall } 31210296Ssam dig++; 31310296Ssam if (c == EOF) { 31426048Sminshall if (expecteof) { 31526048Sminshall (void) signal(SIGINT,oldintr); 31626048Sminshall code = 221; 31710296Ssam return (0); 31826048Sminshall } 31910296Ssam lostpeer(); 32026048Sminshall if (verbose) { 32126048Sminshall printf("421 Service not available, remote server has closed connection\n"); 32226048Sminshall (void) fflush(stdout); 32326048Sminshall } 32433772Scsvsj code = 421; 32533772Scsvsj return(4); 32610296Ssam } 32726048Sminshall if (c != '\r' && (verbose > 0 || 32826048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 32926448Slepreau if (proxflag && 33026448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 33126048Sminshall printf("%s:",hostname); 33226496Sminshall (void) putchar(c); 33326048Sminshall } 33410296Ssam if (dig < 4 && isdigit(c)) 33510296Ssam code = code * 10 + (c - '0'); 33626448Slepreau if (!pflag && code == 227) 33726048Sminshall pflag = 1; 33826448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 33926048Sminshall pflag = 2; 34026048Sminshall if (pflag == 2) { 34126448Slepreau if (c != '\r' && c != ')') 34226048Sminshall *pt++ = c; 34326048Sminshall else { 34426048Sminshall *pt = '\0'; 34526048Sminshall pflag = 3; 34626048Sminshall } 34726048Sminshall } 34826048Sminshall if (dig == 4 && c == '-') { 34926448Slepreau if (continuation) 35026048Sminshall code = 0; 35110296Ssam continuation++; 35226048Sminshall } 35310296Ssam if (n == 0) 35410296Ssam n = c; 35537229Skarels if (cp < &reply_string[sizeof(reply_string) - 1]) 35637229Skarels *cp++ = c; 35710296Ssam } 35826048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 35926496Sminshall (void) putchar(c); 36011346Ssam (void) fflush (stdout); 36111346Ssam } 36210296Ssam if (continuation && code != originalcode) { 36310296Ssam if (originalcode == 0) 36410296Ssam originalcode = code; 36510296Ssam continue; 36610296Ssam } 36736935Skarels *cp = '\0'; 36826448Slepreau if (n != '1') 36926048Sminshall cpend = 0; 37026048Sminshall (void) signal(SIGINT,oldintr); 37126448Slepreau if (code == 421 || originalcode == 421) 37226048Sminshall lostpeer(); 37326448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 37426048Sminshall (*oldintr)(); 37525907Smckusick return (n - '0'); 37610296Ssam } 37710296Ssam } 37810296Ssam 37926048Sminshall empty(mask, sec) 38027687Sminshall struct fd_set *mask; 38126048Sminshall int sec; 38226048Sminshall { 38326048Sminshall struct timeval t; 38426048Sminshall 38526048Sminshall t.tv_sec = (long) sec; 38626048Sminshall t.tv_usec = 0; 38727687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 38826048Sminshall } 38926048Sminshall 39010296Ssam jmp_buf sendabort; 39110296Ssam 39240193Sbostic void 39310296Ssam abortsend() 39410296Ssam { 39510296Ssam 39626048Sminshall mflag = 0; 39726048Sminshall abrtflag = 0; 39838133Srick printf("\nsend aborted\nwaiting for remote to finish abort\n"); 39926048Sminshall (void) fflush(stdout); 40010296Ssam longjmp(sendabort, 1); 40110296Ssam } 40210296Ssam 40336940Skarels #define HASHBYTES 1024 40436940Skarels 40537225Skarels sendrequest(cmd, local, remote, printnames) 40610296Ssam char *cmd, *local, *remote; 40737225Skarels int printnames; 40810296Ssam { 40940193Sbostic struct stat st; 41040193Sbostic struct timeval start, stop; 41140193Sbostic register int c, d; 41235659Sbostic FILE *fin, *dout = 0, *popen(); 41338133Srick int (*closefunc)(), pclose(), fclose(); 41440193Sbostic sig_t oldintr, oldintp; 41536940Skarels long bytes = 0, hashbytes = HASHBYTES; 41640193Sbostic char *lmode, buf[BUFSIZ], *bufp; 41740193Sbostic void abortsend(); 41810296Ssam 41937225Skarels if (verbose && printnames) { 42037225Skarels if (local && *local != '-') 42137225Skarels printf("local: %s ", local); 42237225Skarels if (remote) 42337225Skarels printf("remote: %s\n", remote); 42437225Skarels } 42526048Sminshall if (proxy) { 42626048Sminshall proxtrans(cmd, local, remote); 42726048Sminshall return; 42826048Sminshall } 42938033Skarels if (curtype != type) 43038033Skarels changetype(type, 0); 43110296Ssam closefunc = NULL; 43226048Sminshall oldintr = NULL; 43326048Sminshall oldintp = NULL; 43440193Sbostic lmode = "w"; 43526048Sminshall if (setjmp(sendabort)) { 43626048Sminshall while (cpend) { 43726048Sminshall (void) getreply(0); 43826048Sminshall } 43926048Sminshall if (data >= 0) { 44026048Sminshall (void) close(data); 44126048Sminshall data = -1; 44226048Sminshall } 44326448Slepreau if (oldintr) 44426048Sminshall (void) signal(SIGINT,oldintr); 44526448Slepreau if (oldintp) 44626048Sminshall (void) signal(SIGPIPE,oldintp); 44726048Sminshall code = -1; 44826048Sminshall return; 44926048Sminshall } 45010296Ssam oldintr = signal(SIGINT, abortsend); 45110296Ssam if (strcmp(local, "-") == 0) 45210296Ssam fin = stdin; 45310296Ssam else if (*local == '|') { 45426048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 45535659Sbostic fin = popen(local + 1, "r"); 45610296Ssam if (fin == NULL) { 45726048Sminshall perror(local + 1); 45826048Sminshall (void) signal(SIGINT, oldintr); 45926048Sminshall (void) signal(SIGPIPE, oldintp); 46026048Sminshall code = -1; 46126048Sminshall return; 46210296Ssam } 46335659Sbostic closefunc = pclose; 46410296Ssam } else { 46510296Ssam fin = fopen(local, "r"); 46610296Ssam if (fin == NULL) { 46738202Srick fprintf(stderr, "local: %s: %s\n", local, 46838202Srick strerror(errno)); 46926048Sminshall (void) signal(SIGINT, oldintr); 47026048Sminshall code = -1; 47126048Sminshall return; 47210296Ssam } 47310296Ssam closefunc = fclose; 47410296Ssam if (fstat(fileno(fin), &st) < 0 || 47510296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 47626496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 47726048Sminshall (void) signal(SIGINT, oldintr); 47836935Skarels fclose(fin); 47926048Sminshall code = -1; 48026048Sminshall return; 48110296Ssam } 48210296Ssam } 48326048Sminshall if (initconn()) { 48426048Sminshall (void) signal(SIGINT, oldintr); 48526448Slepreau if (oldintp) 48626048Sminshall (void) signal(SIGPIPE, oldintp); 48726048Sminshall code = -1; 48836935Skarels if (closefunc != NULL) 48936935Skarels (*closefunc)(fin); 49026048Sminshall return; 49126048Sminshall } 49226448Slepreau if (setjmp(sendabort)) 49326048Sminshall goto abort; 49436935Skarels 49537225Skarels if (restart_point && 49637225Skarels (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 49737225Skarels if (fseek(fin, (long) restart_point, 0) < 0) { 49838202Srick fprintf(stderr, "local: %s: %s\n", local, 49938202Srick strerror(errno)); 50037225Skarels restart_point = 0; 50137225Skarels if (closefunc != NULL) 50237225Skarels (*closefunc)(fin); 50337225Skarels return; 50437225Skarels } 50537225Skarels if (command("REST %ld", (long) restart_point) 50637225Skarels != CONTINUE) { 50737225Skarels restart_point = 0; 50837225Skarels if (closefunc != NULL) 50937225Skarels (*closefunc)(fin); 51037225Skarels return; 51137225Skarels } 51237225Skarels restart_point = 0; 51340193Sbostic lmode = "r+w"; 51437225Skarels } 51510296Ssam if (remote) { 51626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 51726048Sminshall (void) signal(SIGINT, oldintr); 51826448Slepreau if (oldintp) 51926048Sminshall (void) signal(SIGPIPE, oldintp); 52036935Skarels if (closefunc != NULL) 52136935Skarels (*closefunc)(fin); 52226048Sminshall return; 52326048Sminshall } 52410296Ssam } else 52526048Sminshall if (command("%s", cmd) != PRELIM) { 52626048Sminshall (void) signal(SIGINT, oldintr); 52726448Slepreau if (oldintp) 52826048Sminshall (void) signal(SIGPIPE, oldintp); 52936935Skarels if (closefunc != NULL) 53036935Skarels (*closefunc)(fin); 53126048Sminshall return; 53226048Sminshall } 53340193Sbostic dout = dataconn(lmode); 53426448Slepreau if (dout == NULL) 53526048Sminshall goto abort; 53626496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 53736935Skarels oldintp = signal(SIGPIPE, SIG_IGN); 53842278Skarels switch (curtype) { 53911219Ssam 54011219Ssam case TYPE_I: 54111219Ssam case TYPE_L: 54211346Ssam errno = d = 0; 54336942Skarels while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { 54411219Ssam bytes += c; 54536942Skarels for (bufp = buf; c > 0; c -= d, bufp += d) 54636942Skarels if ((d = write(fileno(dout), bufp, c)) <= 0) 54736942Skarels break; 54811651Ssam if (hash) { 54936940Skarels while (bytes >= hashbytes) { 55036940Skarels (void) putchar('#'); 55136940Skarels hashbytes += HASHBYTES; 55236940Skarels } 55326496Sminshall (void) fflush(stdout); 55411651Ssam } 55511219Ssam } 55613213Ssam if (hash && bytes > 0) { 55736940Skarels if (bytes < HASHBYTES) 55836940Skarels (void) putchar('#'); 55926496Sminshall (void) putchar('\n'); 56026496Sminshall (void) fflush(stdout); 56111651Ssam } 56211219Ssam if (c < 0) 56338202Srick fprintf(stderr, "local: %s: %s\n", local, 56438202Srick strerror(errno)); 56536942Skarels if (d <= 0) { 56636942Skarels if (d == 0) 56736942Skarels fprintf(stderr, "netout: write returned 0?\n"); 56836942Skarels else if (errno != EPIPE) 56936935Skarels perror("netout"); 57036935Skarels bytes = -1; 57136935Skarels } 57211219Ssam break; 57311219Ssam 57411219Ssam case TYPE_A: 57511219Ssam while ((c = getc(fin)) != EOF) { 57611219Ssam if (c == '\n') { 57711651Ssam while (hash && (bytes >= hashbytes)) { 57826496Sminshall (void) putchar('#'); 57926496Sminshall (void) fflush(stdout); 58036940Skarels hashbytes += HASHBYTES; 58111651Ssam } 58211219Ssam if (ferror(dout)) 58311219Ssam break; 58426496Sminshall (void) putc('\r', dout); 58511219Ssam bytes++; 58611219Ssam } 58726496Sminshall (void) putc(c, dout); 58811219Ssam bytes++; 58926048Sminshall /* if (c == '\r') { */ 59026496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 59126048Sminshall /* bytes++; */ 59226048Sminshall /* } */ 59311219Ssam } 59411651Ssam if (hash) { 59513213Ssam if (bytes < hashbytes) 59626496Sminshall (void) putchar('#'); 59726496Sminshall (void) putchar('\n'); 59826496Sminshall (void) fflush(stdout); 59911651Ssam } 60011219Ssam if (ferror(fin)) 60138202Srick fprintf(stderr, "local: %s: %s\n", local, 60238202Srick strerror(errno)); 60336935Skarels if (ferror(dout)) { 60436935Skarels if (errno != EPIPE) 60536935Skarels perror("netout"); 60636935Skarels bytes = -1; 60736935Skarels } 60811219Ssam break; 60910296Ssam } 61026496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 61110296Ssam if (closefunc != NULL) 61226048Sminshall (*closefunc)(fin); 61310296Ssam (void) fclose(dout); 61426048Sminshall (void) getreply(0); 61526048Sminshall (void) signal(SIGINT, oldintr); 61636935Skarels if (oldintp) 61736935Skarels (void) signal(SIGPIPE, oldintp); 61835699Sbostic if (bytes > 0) 61937225Skarels ptransfer("sent", bytes, &start, &stop); 62010296Ssam return; 62126048Sminshall abort: 62226496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 62326048Sminshall (void) signal(SIGINT, oldintr); 62426448Slepreau if (oldintp) 62526048Sminshall (void) signal(SIGPIPE, oldintp); 62626048Sminshall if (!cpend) { 62726048Sminshall code = -1; 62826048Sminshall return; 62926048Sminshall } 63026048Sminshall if (data >= 0) { 63126048Sminshall (void) close(data); 63226048Sminshall data = -1; 63326048Sminshall } 63426448Slepreau if (dout) 63526048Sminshall (void) fclose(dout); 63626048Sminshall (void) getreply(0); 63726048Sminshall code = -1; 63810296Ssam if (closefunc != NULL && fin != NULL) 63926048Sminshall (*closefunc)(fin); 64035699Sbostic if (bytes > 0) 64137225Skarels ptransfer("sent", bytes, &start, &stop); 64210296Ssam } 64310296Ssam 64410296Ssam jmp_buf recvabort; 64510296Ssam 64640193Sbostic void 64710296Ssam abortrecv() 64810296Ssam { 64910296Ssam 65026048Sminshall mflag = 0; 65126048Sminshall abrtflag = 0; 65238133Srick printf("\nreceive aborted\nwaiting for remote to finish abort\n"); 65326048Sminshall (void) fflush(stdout); 65410296Ssam longjmp(recvabort, 1); 65510296Ssam } 65610296Ssam 65740193Sbostic recvrequest(cmd, local, remote, lmode, printnames) 65840193Sbostic char *cmd, *local, *remote, *lmode; 65910296Ssam { 66035659Sbostic FILE *fout, *din = 0, *popen(); 66138133Srick int (*closefunc)(), pclose(), fclose(); 66240193Sbostic sig_t oldintr, oldintp; 66338133Srick int is_retr, tcrflag, bare_lfs = 0; 66438133Srick char *gunique(); 66538133Srick static int bufsize; 66636944Skarels static char *buf; 66736940Skarels long bytes = 0, hashbytes = HASHBYTES; 66811346Ssam register int c, d; 66910296Ssam struct timeval start, stop; 67036940Skarels struct stat st; 67140193Sbostic off_t lseek(); 67240193Sbostic void abortrecv(); 67340193Sbostic char *malloc(); 67410296Ssam 67536935Skarels is_retr = strcmp(cmd, "RETR") == 0; 67637225Skarels if (is_retr && verbose && printnames) { 67737225Skarels if (local && *local != '-') 67837225Skarels printf("local: %s ", local); 67937225Skarels if (remote) 68037225Skarels printf("remote: %s\n", remote); 68137225Skarels } 68236935Skarels if (proxy && is_retr) { 68326048Sminshall proxtrans(cmd, local, remote); 68426048Sminshall return; 68526048Sminshall } 68610296Ssam closefunc = NULL; 68726048Sminshall oldintr = NULL; 68826048Sminshall oldintp = NULL; 68936935Skarels tcrflag = !crflag && is_retr; 69026048Sminshall if (setjmp(recvabort)) { 69126048Sminshall while (cpend) { 69226048Sminshall (void) getreply(0); 69326048Sminshall } 69426048Sminshall if (data >= 0) { 69526048Sminshall (void) close(data); 69626048Sminshall data = -1; 69726048Sminshall } 69826448Slepreau if (oldintr) 69926048Sminshall (void) signal(SIGINT, oldintr); 70026048Sminshall code = -1; 70126048Sminshall return; 70226048Sminshall } 70310296Ssam oldintr = signal(SIGINT, abortrecv); 70426048Sminshall if (strcmp(local, "-") && *local != '|') { 70510296Ssam if (access(local, 2) < 0) { 70626048Sminshall char *dir = rindex(local, '/'); 70710296Ssam 70826048Sminshall if (errno != ENOENT && errno != EACCES) { 70938202Srick fprintf(stderr, "local: %s: %s\n", local, 71038202Srick strerror(errno)); 71126048Sminshall (void) signal(SIGINT, oldintr); 71226048Sminshall code = -1; 71326048Sminshall return; 71410296Ssam } 71526048Sminshall if (dir != NULL) 71626048Sminshall *dir = 0; 71726048Sminshall d = access(dir ? local : ".", 2); 71826048Sminshall if (dir != NULL) 71926048Sminshall *dir = '/'; 72026048Sminshall if (d < 0) { 72138202Srick fprintf(stderr, "local: %s: %s\n", local, 72238202Srick strerror(errno)); 72326048Sminshall (void) signal(SIGINT, oldintr); 72426048Sminshall code = -1; 72526048Sminshall return; 72626048Sminshall } 72726048Sminshall if (!runique && errno == EACCES && 72836935Skarels chmod(local, 0600) < 0) { 72938202Srick fprintf(stderr, "local: %s: %s\n", local, 73038202Srick strerror(errno)); 73126048Sminshall (void) signal(SIGINT, oldintr); 73238202Srick (void) signal(SIGINT, oldintr); 73326048Sminshall code = -1; 73426048Sminshall return; 73526048Sminshall } 73626048Sminshall if (runique && errno == EACCES && 73726048Sminshall (local = gunique(local)) == NULL) { 73826048Sminshall (void) signal(SIGINT, oldintr); 73926048Sminshall code = -1; 74026048Sminshall return; 74126048Sminshall } 74210296Ssam } 74326048Sminshall else if (runique && (local = gunique(local)) == NULL) { 74426048Sminshall (void) signal(SIGINT, oldintr); 74526048Sminshall code = -1; 74626048Sminshall return; 74726048Sminshall } 74826048Sminshall } 74938033Skarels if (!is_retr) { 75038033Skarels if (curtype != TYPE_A) 75138033Skarels changetype(TYPE_A, 0); 75238033Skarels } else if (curtype != type) 75338033Skarels changetype(type, 0); 75426048Sminshall if (initconn()) { 75526048Sminshall (void) signal(SIGINT, oldintr); 75626048Sminshall code = -1; 75726048Sminshall return; 75826048Sminshall } 75926448Slepreau if (setjmp(recvabort)) 76026048Sminshall goto abort; 76138033Skarels if (is_retr && restart_point && 76238033Skarels command("REST %ld", (long) restart_point) != CONTINUE) 76338033Skarels return; 76410296Ssam if (remote) { 76526048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 76626048Sminshall (void) signal(SIGINT, oldintr); 76726048Sminshall return; 76826048Sminshall } 76926048Sminshall } else { 77026048Sminshall if (command("%s", cmd) != PRELIM) { 77126048Sminshall (void) signal(SIGINT, oldintr); 77226048Sminshall return; 77326048Sminshall } 77426048Sminshall } 77526048Sminshall din = dataconn("r"); 77626048Sminshall if (din == NULL) 77726048Sminshall goto abort; 77826448Slepreau if (strcmp(local, "-") == 0) 77910296Ssam fout = stdout; 78010296Ssam else if (*local == '|') { 78126048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 78235659Sbostic fout = popen(local + 1, "w"); 78326048Sminshall if (fout == NULL) { 78426048Sminshall perror(local+1); 78526048Sminshall goto abort; 78626048Sminshall } 78735659Sbostic closefunc = pclose; 78836940Skarels } else { 78940193Sbostic fout = fopen(local, lmode); 79026048Sminshall if (fout == NULL) { 79138202Srick fprintf(stderr, "local: %s: %s\n", local, 79238202Srick strerror(errno)); 79326048Sminshall goto abort; 79426048Sminshall } 79510296Ssam closefunc = fclose; 79610296Ssam } 79736940Skarels if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 79836940Skarels st.st_blksize = BUFSIZ; 79936940Skarels if (st.st_blksize > bufsize) { 80036940Skarels if (buf) 80136940Skarels (void) free(buf); 80238133Srick buf = malloc((unsigned)st.st_blksize); 80336940Skarels if (buf == NULL) { 80436940Skarels perror("malloc"); 80536944Skarels bufsize = 0; 80636940Skarels goto abort; 80736940Skarels } 80836940Skarels bufsize = st.st_blksize; 80936940Skarels } 81026496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 81138033Skarels switch (curtype) { 81211219Ssam 81311219Ssam case TYPE_I: 81411219Ssam case TYPE_L: 81537225Skarels if (restart_point && 81637225Skarels lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 81738202Srick fprintf(stderr, "local: %s: %s\n", local, 81838202Srick strerror(errno)); 81937225Skarels if (closefunc != NULL) 82037225Skarels (*closefunc)(fout); 82137225Skarels return; 82237225Skarels } 82311346Ssam errno = d = 0; 82436940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) { 82536944Skarels if ((d = write(fileno(fout), buf, c)) != c) 82611219Ssam break; 82711219Ssam bytes += c; 82811651Ssam if (hash) { 82936940Skarels while (bytes >= hashbytes) { 83036940Skarels (void) putchar('#'); 83136940Skarels hashbytes += HASHBYTES; 83236940Skarels } 83326496Sminshall (void) fflush(stdout); 83411651Ssam } 83511219Ssam } 83613213Ssam if (hash && bytes > 0) { 83736940Skarels if (bytes < HASHBYTES) 83836940Skarels (void) putchar('#'); 83926496Sminshall (void) putchar('\n'); 84026496Sminshall (void) fflush(stdout); 84111651Ssam } 84236935Skarels if (c < 0) { 84336935Skarels if (errno != EPIPE) 84436935Skarels perror("netin"); 84536935Skarels bytes = -1; 84636935Skarels } 84736942Skarels if (d < c) { 84836942Skarels if (d < 0) 84938202Srick fprintf(stderr, "local: %s: %s\n", local, 85038202Srick strerror(errno)); 85136942Skarels else 85236942Skarels fprintf(stderr, "%s: short write\n", local); 85336942Skarels } 85411219Ssam break; 85511219Ssam 85611219Ssam case TYPE_A: 85737225Skarels if (restart_point) { 85840193Sbostic register int i, n, ch; 85937225Skarels 86037225Skarels if (fseek(fout, 0L, L_SET) < 0) 86137225Skarels goto done; 86237225Skarels n = restart_point; 86340193Sbostic for (i = 0; i++ < n;) { 86440193Sbostic if ((ch = getc(fout)) == EOF) 86537225Skarels goto done; 86640193Sbostic if (ch == '\n') 86737225Skarels i++; 86837225Skarels } 86937225Skarels if (fseek(fout, 0L, L_INCR) < 0) { 87037225Skarels done: 87138202Srick fprintf(stderr, "local: %s: %s\n", local, 87238202Srick strerror(errno)); 87337225Skarels if (closefunc != NULL) 87437225Skarels (*closefunc)(fout); 87537225Skarels return; 87637225Skarels } 87737225Skarels } 87811219Ssam while ((c = getc(din)) != EOF) { 87938133Srick if (c == '\n') 88038133Srick bare_lfs++; 88127749Sminshall while (c == '\r') { 88211651Ssam while (hash && (bytes >= hashbytes)) { 88326496Sminshall (void) putchar('#'); 88426496Sminshall (void) fflush(stdout); 88536940Skarels hashbytes += HASHBYTES; 88611651Ssam } 88710296Ssam bytes++; 88826048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 88936940Skarels if (ferror(fout)) 89036940Skarels goto break2; 89136940Skarels (void) putc('\r', fout); 89236942Skarels if (c == '\0') { 89336942Skarels bytes++; 89436940Skarels goto contin2; 89536942Skarels } 89636942Skarels if (c == EOF) 89736942Skarels goto contin2; 89811219Ssam } 89911219Ssam } 90036940Skarels (void) putc(c, fout); 90111219Ssam bytes++; 90236940Skarels contin2: ; 90310296Ssam } 90436940Skarels break2: 90538133Srick if (bare_lfs) { 90638133Srick printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); 90738133Srick printf("File may not have transferred correctly.\n"); 90838133Srick } 90911651Ssam if (hash) { 91013213Ssam if (bytes < hashbytes) 91126496Sminshall (void) putchar('#'); 91226496Sminshall (void) putchar('\n'); 91326496Sminshall (void) fflush(stdout); 91411651Ssam } 91536944Skarels if (ferror(din)) { 91636935Skarels if (errno != EPIPE) 91736944Skarels perror("netin"); 91836935Skarels bytes = -1; 91936935Skarels } 92036940Skarels if (ferror(fout)) 92138202Srick fprintf(stderr, "local: %s: %s\n", local, 92238202Srick strerror(errno)); 92311219Ssam break; 92410296Ssam } 92526448Slepreau if (closefunc != NULL) 92626048Sminshall (*closefunc)(fout); 92726496Sminshall (void) signal(SIGINT, oldintr); 92826448Slepreau if (oldintp) 92926048Sminshall (void) signal(SIGPIPE, oldintp); 93026496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 93110296Ssam (void) fclose(din); 93226048Sminshall (void) getreply(0); 93336935Skarels if (bytes > 0 && is_retr) 93437225Skarels ptransfer("received", bytes, &start, &stop); 93526048Sminshall return; 93626048Sminshall abort: 93726048Sminshall 93827687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 93926048Sminshall 94026496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 94126448Slepreau if (oldintp) 94226048Sminshall (void) signal(SIGPIPE, oldintr); 94338133Srick (void) signal(SIGINT, SIG_IGN); 94426048Sminshall if (!cpend) { 94526048Sminshall code = -1; 94638133Srick (void) signal(SIGINT, oldintr); 94726048Sminshall return; 94826048Sminshall } 94926048Sminshall 95038133Srick abort_remote(din); 95126048Sminshall code = -1; 95226048Sminshall if (data >= 0) { 95326048Sminshall (void) close(data); 95426048Sminshall data = -1; 95526048Sminshall } 95626448Slepreau if (closefunc != NULL && fout != NULL) 95726048Sminshall (*closefunc)(fout); 95826448Slepreau if (din) 95926048Sminshall (void) fclose(din); 96035699Sbostic if (bytes > 0) 96137225Skarels ptransfer("received", bytes, &start, &stop); 96238133Srick (void) signal(SIGINT, oldintr); 96310296Ssam } 96410296Ssam 96510296Ssam /* 96640193Sbostic * Need to start a listen on the data channel before we send the command, 96740193Sbostic * otherwise the server's connect may fail. 96810296Ssam */ 96910296Ssam initconn() 97010296Ssam { 97110296Ssam register char *p, *a; 97226048Sminshall int result, len, tmpno = 0; 97326993Skarels int on = 1; 97410296Ssam 97511651Ssam noport: 97610296Ssam data_addr = myctladdr; 97711651Ssam if (sendport) 97811651Ssam data_addr.sin_port = 0; /* let system pick one */ 97911651Ssam if (data != -1) 98038133Srick (void) close(data); 98118287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 98210296Ssam if (data < 0) { 98310296Ssam perror("ftp: socket"); 98426448Slepreau if (tmpno) 98526048Sminshall sendport = 1; 98610296Ssam return (1); 98710296Ssam } 98812397Ssam if (!sendport) 98927687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 99033224Sbostic perror("ftp: setsockopt (reuse address)"); 99112397Ssam goto bad; 99212397Ssam } 99326496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 99410296Ssam perror("ftp: bind"); 99510296Ssam goto bad; 99610296Ssam } 99710296Ssam if (options & SO_DEBUG && 99827687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 99910296Ssam perror("ftp: setsockopt (ignored)"); 100011627Ssam len = sizeof (data_addr); 100138133Srick if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 100211627Ssam perror("ftp: getsockname"); 100310296Ssam goto bad; 100410296Ssam } 100526448Slepreau if (listen(data, 1) < 0) 100610296Ssam perror("ftp: listen"); 100711651Ssam if (sendport) { 100811651Ssam a = (char *)&data_addr.sin_addr; 100911651Ssam p = (char *)&data_addr.sin_port; 101010296Ssam #define UC(b) (((int)b)&0xff) 101111651Ssam result = 101211651Ssam command("PORT %d,%d,%d,%d,%d,%d", 101311651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 101411651Ssam UC(p[0]), UC(p[1])); 101511651Ssam if (result == ERROR && sendport == -1) { 101611651Ssam sendport = 0; 101726048Sminshall tmpno = 1; 101811651Ssam goto noport; 101911651Ssam } 102011651Ssam return (result != COMPLETE); 102111651Ssam } 102226448Slepreau if (tmpno) 102326048Sminshall sendport = 1; 102411651Ssam return (0); 102510296Ssam bad: 102610296Ssam (void) close(data), data = -1; 102726448Slepreau if (tmpno) 102826048Sminshall sendport = 1; 102910296Ssam return (1); 103010296Ssam } 103110296Ssam 103210296Ssam FILE * 103340193Sbostic dataconn(lmode) 103440193Sbostic char *lmode; 103510296Ssam { 103610296Ssam struct sockaddr_in from; 103710296Ssam int s, fromlen = sizeof (from); 103810296Ssam 103926496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 104010296Ssam if (s < 0) { 104110296Ssam perror("ftp: accept"); 104210296Ssam (void) close(data), data = -1; 104310296Ssam return (NULL); 104410296Ssam } 104510296Ssam (void) close(data); 104610296Ssam data = s; 104740193Sbostic return (fdopen(data, lmode)); 104810296Ssam } 104910296Ssam 105037225Skarels ptransfer(direction, bytes, t0, t1) 105137225Skarels char *direction; 105211651Ssam long bytes; 105310296Ssam struct timeval *t0, *t1; 105410296Ssam { 105510296Ssam struct timeval td; 105616437Sleres float s, bs; 105710296Ssam 105835699Sbostic if (verbose) { 105935699Sbostic tvsub(&td, t1, t0); 106035699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 106110296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 106235699Sbostic bs = bytes / nz(s); 106335699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 106435699Sbostic bytes, direction, s, bs / 1024.); 106535699Sbostic } 106610296Ssam } 106710296Ssam 106826496Sminshall /*tvadd(tsum, t0) 106910296Ssam struct timeval *tsum, *t0; 107010296Ssam { 107110296Ssam 107210296Ssam tsum->tv_sec += t0->tv_sec; 107310296Ssam tsum->tv_usec += t0->tv_usec; 107410296Ssam if (tsum->tv_usec > 1000000) 107510296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 107626496Sminshall } */ 107710296Ssam 107810296Ssam tvsub(tdiff, t1, t0) 107910296Ssam struct timeval *tdiff, *t1, *t0; 108010296Ssam { 108110296Ssam 108210296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 108310296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 108410296Ssam if (tdiff->tv_usec < 0) 108510296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 108610296Ssam } 108726048Sminshall 108840193Sbostic void 108926048Sminshall psabort() 109026048Sminshall { 109126048Sminshall extern int abrtflag; 109226048Sminshall 109326048Sminshall abrtflag++; 109426048Sminshall } 109526048Sminshall 109626048Sminshall pswitch(flag) 109726048Sminshall int flag; 109826048Sminshall { 109926048Sminshall extern int proxy, abrtflag; 110040193Sbostic sig_t oldintr; 110126048Sminshall static struct comvars { 110226048Sminshall int connect; 110328469Skarels char name[MAXHOSTNAMELEN]; 110426048Sminshall struct sockaddr_in mctl; 110526048Sminshall struct sockaddr_in hctl; 110626048Sminshall FILE *in; 110726048Sminshall FILE *out; 110826048Sminshall int tpe; 110938033Skarels int curtpe; 111026048Sminshall int cpnd; 111126048Sminshall int sunqe; 111226048Sminshall int runqe; 111326048Sminshall int mcse; 111426048Sminshall int ntflg; 111526048Sminshall char nti[17]; 111626048Sminshall char nto[17]; 111726048Sminshall int mapflg; 111826048Sminshall char mi[MAXPATHLEN]; 111926048Sminshall char mo[MAXPATHLEN]; 112038033Skarels } proxstruct, tmpstruct; 112126048Sminshall struct comvars *ip, *op; 112226048Sminshall 112326048Sminshall abrtflag = 0; 112426048Sminshall oldintr = signal(SIGINT, psabort); 112526048Sminshall if (flag) { 112626448Slepreau if (proxy) 112726048Sminshall return; 112826048Sminshall ip = &tmpstruct; 112926048Sminshall op = &proxstruct; 113026048Sminshall proxy++; 113138033Skarels } else { 113226448Slepreau if (!proxy) 113326048Sminshall return; 113426048Sminshall ip = &proxstruct; 113526048Sminshall op = &tmpstruct; 113626048Sminshall proxy = 0; 113726048Sminshall } 113826048Sminshall ip->connect = connected; 113926048Sminshall connected = op->connect; 114028469Skarels if (hostname) { 114128469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 114228469Skarels ip->name[strlen(ip->name)] = '\0'; 114328469Skarels } else 114428469Skarels ip->name[0] = 0; 114526048Sminshall hostname = op->name; 114626048Sminshall ip->hctl = hisctladdr; 114726048Sminshall hisctladdr = op->hctl; 114826048Sminshall ip->mctl = myctladdr; 114926048Sminshall myctladdr = op->mctl; 115026048Sminshall ip->in = cin; 115126048Sminshall cin = op->in; 115226048Sminshall ip->out = cout; 115326048Sminshall cout = op->out; 115426048Sminshall ip->tpe = type; 115526048Sminshall type = op->tpe; 115638033Skarels ip->curtpe = curtype; 115738033Skarels curtype = op->curtpe; 115826048Sminshall ip->cpnd = cpend; 115926048Sminshall cpend = op->cpnd; 116026048Sminshall ip->sunqe = sunique; 116126048Sminshall sunique = op->sunqe; 116226048Sminshall ip->runqe = runique; 116326048Sminshall runique = op->runqe; 116426048Sminshall ip->mcse = mcase; 116526048Sminshall mcase = op->mcse; 116626048Sminshall ip->ntflg = ntflag; 116726048Sminshall ntflag = op->ntflg; 116826496Sminshall (void) strncpy(ip->nti, ntin, 16); 116926048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 117026496Sminshall (void) strcpy(ntin, op->nti); 117126496Sminshall (void) strncpy(ip->nto, ntout, 16); 117226048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 117326496Sminshall (void) strcpy(ntout, op->nto); 117426048Sminshall ip->mapflg = mapflag; 117526048Sminshall mapflag = op->mapflg; 117626496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 117726048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 117826496Sminshall (void) strcpy(mapin, op->mi); 117926496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 118026048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 118126496Sminshall (void) strcpy(mapout, op->mo); 118226048Sminshall (void) signal(SIGINT, oldintr); 118326048Sminshall if (abrtflag) { 118426048Sminshall abrtflag = 0; 118526048Sminshall (*oldintr)(); 118626448Slepreau } 118726048Sminshall } 118826048Sminshall 118926048Sminshall jmp_buf ptabort; 119026048Sminshall int ptabflg; 119126048Sminshall 119240193Sbostic void 119326048Sminshall abortpt() 119426048Sminshall { 119526048Sminshall printf("\n"); 119626496Sminshall (void) fflush(stdout); 119726048Sminshall ptabflg++; 119826048Sminshall mflag = 0; 119926048Sminshall abrtflag = 0; 120026048Sminshall longjmp(ptabort, 1); 120126048Sminshall } 120226048Sminshall 120326048Sminshall proxtrans(cmd, local, remote) 120426048Sminshall char *cmd, *local, *remote; 120526048Sminshall { 120640193Sbostic sig_t oldintr; 120738133Srick int secndflag = 0, prox_type, nfnd; 120826048Sminshall extern jmp_buf ptabort; 120926048Sminshall char *cmd2; 121026496Sminshall struct fd_set mask; 121140193Sbostic void abortpt(); 121226048Sminshall 121326448Slepreau if (strcmp(cmd, "RETR")) 121426048Sminshall cmd2 = "RETR"; 121526448Slepreau else 121626048Sminshall cmd2 = runique ? "STOU" : "STOR"; 121738033Skarels if ((prox_type = type) == 0) { 121838033Skarels if (unix_server && unix_proxy) 121938033Skarels prox_type = TYPE_I; 122038033Skarels else 122138033Skarels prox_type = TYPE_A; 122238033Skarels } 122338033Skarels if (curtype != prox_type) 122438033Skarels changetype(prox_type, 1); 122526048Sminshall if (command("PASV") != COMPLETE) { 122638033Skarels printf("proxy server does not support third party transfers.\n"); 122726048Sminshall return; 122826048Sminshall } 122926048Sminshall pswitch(0); 123026048Sminshall if (!connected) { 123126048Sminshall printf("No primary connection\n"); 123226048Sminshall pswitch(1); 123326048Sminshall code = -1; 123426048Sminshall return; 123526048Sminshall } 123638033Skarels if (curtype != prox_type) 123738033Skarels changetype(prox_type, 1); 123826048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 123926048Sminshall pswitch(1); 124026048Sminshall return; 124126048Sminshall } 124226448Slepreau if (setjmp(ptabort)) 124326048Sminshall goto abort; 124426048Sminshall oldintr = signal(SIGINT, abortpt); 124526048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 124626048Sminshall (void) signal(SIGINT, oldintr); 124726048Sminshall pswitch(1); 124826048Sminshall return; 124926048Sminshall } 125026048Sminshall sleep(2); 125126048Sminshall pswitch(1); 125226048Sminshall secndflag++; 125326448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 125426048Sminshall goto abort; 125526048Sminshall ptflag++; 125626048Sminshall (void) getreply(0); 125726048Sminshall pswitch(0); 125826048Sminshall (void) getreply(0); 125926048Sminshall (void) signal(SIGINT, oldintr); 126026048Sminshall pswitch(1); 126126048Sminshall ptflag = 0; 126226048Sminshall printf("local: %s remote: %s\n", local, remote); 126326048Sminshall return; 126426048Sminshall abort: 126526048Sminshall (void) signal(SIGINT, SIG_IGN); 126626048Sminshall ptflag = 0; 126726448Slepreau if (strcmp(cmd, "RETR") && !proxy) 126826048Sminshall pswitch(1); 126926448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 127026048Sminshall pswitch(0); 127126048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 127226048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 127326048Sminshall pswitch(0); 127438133Srick if (cpend) 127538133Srick abort_remote((FILE *) NULL); 127626048Sminshall } 127726048Sminshall pswitch(1); 127826448Slepreau if (ptabflg) 127926048Sminshall code = -1; 128026048Sminshall (void) signal(SIGINT, oldintr); 128126048Sminshall return; 128226048Sminshall } 128338133Srick if (cpend) 128438133Srick abort_remote((FILE *) NULL); 128526048Sminshall pswitch(!proxy); 128626048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 128726048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 128826048Sminshall pswitch(0); 128938133Srick if (cpend) 129038133Srick abort_remote((FILE *) NULL); 129126048Sminshall pswitch(1); 129226448Slepreau if (ptabflg) 129326048Sminshall code = -1; 129426048Sminshall (void) signal(SIGINT, oldintr); 129526048Sminshall return; 129626048Sminshall } 129726048Sminshall } 129838133Srick if (cpend) 129938133Srick abort_remote((FILE *) NULL); 130026048Sminshall pswitch(!proxy); 130126048Sminshall if (cpend) { 130227687Sminshall FD_ZERO(&mask); 130326496Sminshall FD_SET(fileno(cin), &mask); 130438133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 130527687Sminshall if (nfnd < 0) { 130627687Sminshall perror("abort"); 130727687Sminshall } 130826448Slepreau if (ptabflg) 130926048Sminshall code = -1; 131026048Sminshall lostpeer(); 131126048Sminshall } 131226048Sminshall (void) getreply(0); 131326048Sminshall (void) getreply(0); 131426048Sminshall } 131526448Slepreau if (proxy) 131626048Sminshall pswitch(0); 131726048Sminshall pswitch(1); 131826448Slepreau if (ptabflg) 131926048Sminshall code = -1; 132026048Sminshall (void) signal(SIGINT, oldintr); 132126048Sminshall } 132226048Sminshall 132326048Sminshall reset() 132426048Sminshall { 132526496Sminshall struct fd_set mask; 132626496Sminshall int nfnd = 1; 132726048Sminshall 132827687Sminshall FD_ZERO(&mask); 132930946Scsvsj while (nfnd > 0) { 133026496Sminshall FD_SET(fileno(cin), &mask); 133127687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 133226048Sminshall perror("reset"); 133326048Sminshall code = -1; 133426048Sminshall lostpeer(); 133526048Sminshall } 133627687Sminshall else if (nfnd) { 133726048Sminshall (void) getreply(0); 133826496Sminshall } 133926048Sminshall } 134026048Sminshall } 134126048Sminshall 134226048Sminshall char * 134326048Sminshall gunique(local) 134426048Sminshall char *local; 134526048Sminshall { 134626048Sminshall static char new[MAXPATHLEN]; 134726048Sminshall char *cp = rindex(local, '/'); 134826048Sminshall int d, count=0; 134926048Sminshall char ext = '1'; 135026048Sminshall 135126448Slepreau if (cp) 135226048Sminshall *cp = '\0'; 135326048Sminshall d = access(cp ? local : ".", 2); 135426448Slepreau if (cp) 135526048Sminshall *cp = '/'; 135626048Sminshall if (d < 0) { 135738202Srick fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); 135826048Sminshall return((char *) 0); 135926048Sminshall } 136026048Sminshall (void) strcpy(new, local); 136126048Sminshall cp = new + strlen(new); 136226048Sminshall *cp++ = '.'; 136326048Sminshall while (!d) { 136426048Sminshall if (++count == 100) { 136526048Sminshall printf("runique: can't find unique file name.\n"); 136626048Sminshall return((char *) 0); 136726048Sminshall } 136826048Sminshall *cp++ = ext; 136926048Sminshall *cp = '\0'; 137026448Slepreau if (ext == '9') 137126048Sminshall ext = '0'; 137226448Slepreau else 137326048Sminshall ext++; 137426448Slepreau if ((d = access(new, 0)) < 0) 137526048Sminshall break; 137626448Slepreau if (ext != '0') 137726048Sminshall cp--; 137826448Slepreau else if (*(cp - 2) == '.') 137926048Sminshall *(cp - 1) = '1'; 138026048Sminshall else { 138126048Sminshall *(cp - 2) = *(cp - 2) + 1; 138226048Sminshall cp--; 138326048Sminshall } 138426048Sminshall } 138526048Sminshall return(new); 138626048Sminshall } 138738133Srick 138838133Srick abort_remote(din) 138938133Srick FILE *din; 139038133Srick { 139138133Srick char buf[BUFSIZ]; 139238133Srick int nfnd; 139338133Srick struct fd_set mask; 139438133Srick 139538133Srick /* 139638133Srick * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 139738133Srick * after urgent byte rather than before as is protocol now 139838133Srick */ 139938133Srick sprintf(buf, "%c%c%c", IAC, IP, IAC); 140038133Srick if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 140138133Srick perror("abort"); 140238133Srick fprintf(cout,"%cABOR\r\n", DM); 140338133Srick (void) fflush(cout); 140438133Srick FD_ZERO(&mask); 140538133Srick FD_SET(fileno(cin), &mask); 140638133Srick if (din) { 140738133Srick FD_SET(fileno(din), &mask); 140838133Srick } 140938133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 141038133Srick if (nfnd < 0) { 141138133Srick perror("abort"); 141238133Srick } 141338133Srick if (ptabflg) 141438133Srick code = -1; 141538133Srick lostpeer(); 141638133Srick } 141738133Srick if (din && FD_ISSET(fileno(din), &mask)) { 141838133Srick while (read(fileno(din), buf, BUFSIZ) > 0) 141938133Srick /* LOOP */; 142038133Srick } 142138133Srick if (getreply(0) == ERROR && code == 552) { 142238133Srick /* 552 needed for nic style abort */ 142338133Srick (void) getreply(0); 142438133Srick } 142538133Srick (void) getreply(0); 142638133Srick } 1427