121739Sdist /* 236942Skarels * Copyright (c) 1985, 1989 Regents of the University of California. 333737Sbostic * All rights reserved. 433737Sbostic * 533737Sbostic * Redistribution and use in source and binary forms are permitted 634901Sbostic * provided that the above copyright notice and this paragraph are 734901Sbostic * duplicated in all such forms and that any documentation, 834901Sbostic * advertising materials, and other materials related to such 934901Sbostic * distribution and use acknowledge that the software was developed 1034901Sbostic * by the University of California, Berkeley. The name of the 1134901Sbostic * University may not be used to endorse or promote products derived 1234901Sbostic * from this software without specific prior written permission. 1334901Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434901Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536935Skarels * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621739Sdist */ 1721739Sdist 1810296Ssam #ifndef lint 19*38202Srick static char sccsid[] = "@(#)ftp.c 5.31 (Berkeley) 05/30/89"; 2033737Sbostic #endif /* not lint */ 2110296Ssam 2236940Skarels #include <sys/param.h> 2310296Ssam #include <sys/stat.h> 2410296Ssam #include <sys/ioctl.h> 2510296Ssam #include <sys/socket.h> 2613614Ssam #include <sys/time.h> 2736935Skarels #include <sys/file.h> 2810296Ssam 2910296Ssam #include <netinet/in.h> 3012397Ssam #include <arpa/ftp.h> 3126048Sminshall #include <arpa/telnet.h> 3210296Ssam 3310296Ssam #include <stdio.h> 3410296Ssam #include <signal.h> 3510296Ssam #include <errno.h> 3610296Ssam #include <netdb.h> 3726048Sminshall #include <fcntl.h> 3826048Sminshall #include <pwd.h> 3938133Srick #include <varargs.h> 4010296Ssam 4136940Skarels #include "ftp_var.h" 4236940Skarels 4310296Ssam struct sockaddr_in hisctladdr; 4410296Ssam struct sockaddr_in data_addr; 4510296Ssam int data = -1; 4626048Sminshall int abrtflag = 0; 4726048Sminshall int ptflag = 0; 4810296Ssam int connected; 4910296Ssam struct sockaddr_in myctladdr; 5026496Sminshall uid_t getuid(); 5138133Srick sig_t lostpeer(); 5237225Skarels off_t restart_point = 0; 5310296Ssam 54*38202Srick extern char *strerror(); 55*38202Srick extern int errno; 56*38202Srick 5710296Ssam FILE *cin, *cout; 5810296Ssam FILE *dataconn(); 5910296Ssam 6025904Skarels char * 6110296Ssam hookup(host, port) 6210296Ssam char *host; 6310296Ssam int port; 6410296Ssam { 6525904Skarels register struct hostent *hp = 0; 6627687Sminshall int s,len; 6725904Skarels static char hostnamebuf[80]; 6810296Ssam 6910296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 7025904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 7125904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 7225904Skarels hisctladdr.sin_family = AF_INET; 7336940Skarels (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); 7436940Skarels } else { 7525100Sbloom hp = gethostbyname(host); 7625904Skarels if (hp == NULL) { 7735792Sbostic fprintf(stderr, "ftp: %s: ", host); 7835792Sbostic herror((char *)NULL); 7926048Sminshall code = -1; 8026048Sminshall return((char *) 0); 8125904Skarels } 8225904Skarels hisctladdr.sin_family = hp->h_addrtype; 8325904Skarels bcopy(hp->h_addr_list[0], 8425904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 8536940Skarels (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); 8610296Ssam } 8725904Skarels hostname = hostnamebuf; 8825904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 8910296Ssam if (s < 0) { 9010296Ssam perror("ftp: socket"); 9126048Sminshall code = -1; 9210296Ssam return (0); 9310296Ssam } 9410296Ssam hisctladdr.sin_port = port; 9538133Srick while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { 9625904Skarels if (hp && hp->h_addr_list[1]) { 9725904Skarels int oerrno = errno; 9838133Srick extern char *inet_ntoa(); 9925904Skarels 10025904Skarels fprintf(stderr, "ftp: connect to address %s: ", 10125904Skarels inet_ntoa(hisctladdr.sin_addr)); 10225904Skarels errno = oerrno; 10326496Sminshall perror((char *) 0); 10425904Skarels hp->h_addr_list++; 10525904Skarels bcopy(hp->h_addr_list[0], 10626048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 10726496Sminshall fprintf(stdout, "Trying %s...\n", 10825904Skarels inet_ntoa(hisctladdr.sin_addr)); 10926813Skarels (void) close(s); 11026813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 11126813Skarels if (s < 0) { 11226813Skarels perror("ftp: socket"); 11326813Skarels code = -1; 11426813Skarels return (0); 11526813Skarels } 11625904Skarels continue; 11725904Skarels } 11810296Ssam perror("ftp: connect"); 11926048Sminshall code = -1; 12010296Ssam goto bad; 12110296Ssam } 12211627Ssam len = sizeof (myctladdr); 12338133Srick if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { 12411627Ssam perror("ftp: getsockname"); 12526048Sminshall code = -1; 12610296Ssam goto bad; 12710296Ssam } 12810296Ssam cin = fdopen(s, "r"); 12910296Ssam cout = fdopen(s, "w"); 13011219Ssam if (cin == NULL || cout == NULL) { 13110296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 13210296Ssam if (cin) 13326496Sminshall (void) fclose(cin); 13410296Ssam if (cout) 13526496Sminshall (void) fclose(cout); 13626048Sminshall code = -1; 13710296Ssam goto bad; 13810296Ssam } 13910296Ssam if (verbose) 14026067Sminshall printf("Connected to %s.\n", hostname); 14127687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 14226048Sminshall if (cin) 14326496Sminshall (void) fclose(cin); 14426048Sminshall if (cout) 14526496Sminshall (void) fclose(cout); 14626048Sminshall code = -1; 14726048Sminshall goto bad; 14826048Sminshall } 14927687Sminshall #ifdef SO_OOBINLINE 15027687Sminshall { 15127687Sminshall int on = 1; 15226048Sminshall 15327687Sminshall if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 15427687Sminshall < 0 && debug) { 15527687Sminshall perror("ftp: setsockopt"); 15627687Sminshall } 15727687Sminshall } 15838133Srick #endif /* SO_OOBINLINE */ 15926048Sminshall 16025904Skarels return (hostname); 16110296Ssam bad: 16226496Sminshall (void) close(s); 16325904Skarels return ((char *)0); 16410296Ssam } 16510296Ssam 16625904Skarels login(host) 16725904Skarels char *host; 16810296Ssam { 16926048Sminshall char tmp[80]; 17035659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 17126048Sminshall int n, aflag = 0; 17210296Ssam 17326048Sminshall user = pass = acct = 0; 17426048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 17526048Sminshall code = -1; 17626048Sminshall return(0); 17726048Sminshall } 17837458Skarels while (user == NULL) { 17926048Sminshall char *myname = getlogin(); 18026048Sminshall 18126048Sminshall if (myname == NULL) { 18226048Sminshall struct passwd *pp = getpwuid(getuid()); 18326048Sminshall 18426448Slepreau if (pp != NULL) 18526048Sminshall myname = pp->pw_name; 18626048Sminshall } 18737458Skarels if (myname) 18837458Skarels printf("Name (%s:%s): ", host, myname); 18937458Skarels else 19037458Skarels printf("Name (%s): ", host); 19126048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 19226048Sminshall tmp[strlen(tmp) - 1] = '\0'; 19326448Slepreau if (*tmp == '\0') 19426048Sminshall user = myname; 19526448Slepreau else 19626048Sminshall user = tmp; 19726048Sminshall } 19810296Ssam n = command("USER %s", user); 19926048Sminshall if (n == CONTINUE) { 20026448Slepreau if (pass == NULL) 20135659Sbostic pass = getpass("Password:"); 20210296Ssam n = command("PASS %s", pass); 20326048Sminshall } 20410296Ssam if (n == CONTINUE) { 20526048Sminshall aflag++; 20635659Sbostic acct = getpass("Account:"); 20710296Ssam n = command("ACCT %s", acct); 20810296Ssam } 20910296Ssam if (n != COMPLETE) { 21010296Ssam fprintf(stderr, "Login failed.\n"); 21110296Ssam return (0); 21210296Ssam } 21326448Slepreau if (!aflag && acct != NULL) 21426048Sminshall (void) command("ACCT %s", acct); 21526448Slepreau if (proxy) 21626048Sminshall return(1); 21726048Sminshall for (n = 0; n < macnum; ++n) { 21826048Sminshall if (!strcmp("init", macros[n].mac_name)) { 21926496Sminshall (void) strcpy(line, "$init"); 22026048Sminshall makeargv(); 22126048Sminshall domacro(margc, margv); 22226048Sminshall break; 22326048Sminshall } 22426048Sminshall } 22510296Ssam return (1); 22610296Ssam } 22710296Ssam 22838133Srick sig_t 22926048Sminshall cmdabort() 23026048Sminshall { 23126048Sminshall extern jmp_buf ptabort; 23226048Sminshall 23326048Sminshall printf("\n"); 23426048Sminshall (void) fflush(stdout); 23526048Sminshall abrtflag++; 23626448Slepreau if (ptflag) 23726048Sminshall longjmp(ptabort,1); 23826048Sminshall } 23926048Sminshall 24038133Srick /*VARARGS*/ 24138133Srick command(va_alist) 24238133Srick va_dcl 24338133Srick { 24438133Srick va_list ap; 24510296Ssam char *fmt; 24638133Srick int r; 24738133Srick sig_t (*oldintr)(), cmdabort(); 24810296Ssam 24926048Sminshall abrtflag = 0; 25010296Ssam if (debug) { 25110296Ssam printf("---> "); 25238133Srick va_start(ap); 25338133Srick fmt = va_arg(ap, char *); 25438133Srick if (strncmp("PASS ", fmt, 5) == 0) 25538133Srick printf("PASS XXXX"); 25638133Srick else 25738133Srick vfprintf(stdout, fmt, ap); 25838133Srick va_end(ap); 25910296Ssam printf("\n"); 26010296Ssam (void) fflush(stdout); 26110296Ssam } 26211219Ssam if (cout == NULL) { 26311219Ssam perror ("No control connection for command"); 26426048Sminshall code = -1; 26511219Ssam return (0); 26611219Ssam } 26738133Srick oldintr = signal(SIGINT, cmdabort); 26838133Srick va_start(ap); 26938133Srick fmt = va_arg(ap, char *); 27038133Srick vfprintf(cout, fmt, ap); 27138133Srick va_end(ap); 27210296Ssam fprintf(cout, "\r\n"); 27310296Ssam (void) fflush(cout); 27426048Sminshall cpend = 1; 27526048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 27626448Slepreau if (abrtflag && oldintr != SIG_IGN) 27726048Sminshall (*oldintr)(); 27826048Sminshall (void) signal(SIGINT, oldintr); 27926048Sminshall return(r); 28010296Ssam } 28110296Ssam 28237229Skarels char reply_string[BUFSIZ]; /* last line of previous reply */ 28336935Skarels 28410296Ssam #include <ctype.h> 28510296Ssam 28610296Ssam getreply(expecteof) 28710296Ssam int expecteof; 28810296Ssam { 28911219Ssam register int c, n; 29026048Sminshall register int dig; 29136935Skarels register char *cp; 29238133Srick int originalcode = 0, continuation = 0; 29338133Srick sig_t (*oldintr)(), cmdabort(); 29426048Sminshall int pflag = 0; 29526048Sminshall char *pt = pasv; 29610296Ssam 29738133Srick oldintr = signal(SIGINT, cmdabort); 29810296Ssam for (;;) { 29910296Ssam dig = n = code = 0; 30037229Skarels cp = reply_string; 30110296Ssam while ((c = getc(cin)) != '\n') { 30227687Sminshall if (c == IAC) { /* handle telnet commands */ 30327687Sminshall switch (c = getc(cin)) { 30427687Sminshall case WILL: 30527687Sminshall case WONT: 30627687Sminshall c = getc(cin); 30738133Srick fprintf(cout, "%c%c%c", IAC, DONT, c); 30827687Sminshall (void) fflush(cout); 30927687Sminshall break; 31027687Sminshall case DO: 31127687Sminshall case DONT: 31227687Sminshall c = getc(cin); 31338133Srick fprintf(cout, "%c%c%c", IAC, WONT, c); 31427687Sminshall (void) fflush(cout); 31527687Sminshall break; 31627687Sminshall default: 31727687Sminshall break; 31827687Sminshall } 31927687Sminshall continue; 32027687Sminshall } 32110296Ssam dig++; 32210296Ssam if (c == EOF) { 32326048Sminshall if (expecteof) { 32426048Sminshall (void) signal(SIGINT,oldintr); 32526048Sminshall code = 221; 32610296Ssam return (0); 32726048Sminshall } 32810296Ssam lostpeer(); 32926048Sminshall if (verbose) { 33026048Sminshall printf("421 Service not available, remote server has closed connection\n"); 33126048Sminshall (void) fflush(stdout); 33226048Sminshall } 33333772Scsvsj code = 421; 33433772Scsvsj return(4); 33510296Ssam } 33626048Sminshall if (c != '\r' && (verbose > 0 || 33726048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 33826448Slepreau if (proxflag && 33926448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 34026048Sminshall printf("%s:",hostname); 34126496Sminshall (void) putchar(c); 34226048Sminshall } 34310296Ssam if (dig < 4 && isdigit(c)) 34410296Ssam code = code * 10 + (c - '0'); 34526448Slepreau if (!pflag && code == 227) 34626048Sminshall pflag = 1; 34726448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 34826048Sminshall pflag = 2; 34926048Sminshall if (pflag == 2) { 35026448Slepreau if (c != '\r' && c != ')') 35126048Sminshall *pt++ = c; 35226048Sminshall else { 35326048Sminshall *pt = '\0'; 35426048Sminshall pflag = 3; 35526048Sminshall } 35626048Sminshall } 35726048Sminshall if (dig == 4 && c == '-') { 35826448Slepreau if (continuation) 35926048Sminshall code = 0; 36010296Ssam continuation++; 36126048Sminshall } 36210296Ssam if (n == 0) 36310296Ssam n = c; 36437229Skarels if (cp < &reply_string[sizeof(reply_string) - 1]) 36537229Skarels *cp++ = c; 36610296Ssam } 36726048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 36826496Sminshall (void) putchar(c); 36911346Ssam (void) fflush (stdout); 37011346Ssam } 37110296Ssam if (continuation && code != originalcode) { 37210296Ssam if (originalcode == 0) 37310296Ssam originalcode = code; 37410296Ssam continue; 37510296Ssam } 37636935Skarels *cp = '\0'; 37726448Slepreau if (n != '1') 37826048Sminshall cpend = 0; 37926048Sminshall (void) signal(SIGINT,oldintr); 38026448Slepreau if (code == 421 || originalcode == 421) 38126048Sminshall lostpeer(); 38226448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 38326048Sminshall (*oldintr)(); 38425907Smckusick return (n - '0'); 38510296Ssam } 38610296Ssam } 38710296Ssam 38826048Sminshall empty(mask, sec) 38927687Sminshall struct fd_set *mask; 39026048Sminshall int sec; 39126048Sminshall { 39226048Sminshall struct timeval t; 39326048Sminshall 39426048Sminshall t.tv_sec = (long) sec; 39526048Sminshall t.tv_usec = 0; 39627687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 39726048Sminshall } 39826048Sminshall 39910296Ssam jmp_buf sendabort; 40010296Ssam 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 { 41735659Sbostic FILE *fin, *dout = 0, *popen(); 41838133Srick int (*closefunc)(), pclose(), fclose(); 41938133Srick sig_t (*oldintr)(), (*oldintp)(); 42026048Sminshall int abortsend(); 42136942Skarels char buf[BUFSIZ], *bufp; 42236940Skarels long bytes = 0, hashbytes = HASHBYTES; 42311346Ssam register int c, d; 42410296Ssam struct stat st; 42510296Ssam struct timeval start, stop; 42636935Skarels char *mode; 42710296Ssam 42837225Skarels if (verbose && printnames) { 42937225Skarels if (local && *local != '-') 43037225Skarels printf("local: %s ", local); 43137225Skarels if (remote) 43237225Skarels printf("remote: %s\n", remote); 43337225Skarels } 43426048Sminshall if (proxy) { 43526048Sminshall proxtrans(cmd, local, remote); 43626048Sminshall return; 43726048Sminshall } 43838033Skarels if (curtype != type) 43938033Skarels changetype(type, 0); 44010296Ssam closefunc = NULL; 44126048Sminshall oldintr = NULL; 44226048Sminshall oldintp = NULL; 44336935Skarels mode = "w"; 44426048Sminshall if (setjmp(sendabort)) { 44526048Sminshall while (cpend) { 44626048Sminshall (void) getreply(0); 44726048Sminshall } 44826048Sminshall if (data >= 0) { 44926048Sminshall (void) close(data); 45026048Sminshall data = -1; 45126048Sminshall } 45226448Slepreau if (oldintr) 45326048Sminshall (void) signal(SIGINT,oldintr); 45426448Slepreau if (oldintp) 45526048Sminshall (void) signal(SIGPIPE,oldintp); 45626048Sminshall code = -1; 45726048Sminshall return; 45826048Sminshall } 45910296Ssam oldintr = signal(SIGINT, abortsend); 46010296Ssam if (strcmp(local, "-") == 0) 46110296Ssam fin = stdin; 46210296Ssam else if (*local == '|') { 46326048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 46435659Sbostic fin = popen(local + 1, "r"); 46510296Ssam if (fin == NULL) { 46626048Sminshall perror(local + 1); 46726048Sminshall (void) signal(SIGINT, oldintr); 46826048Sminshall (void) signal(SIGPIPE, oldintp); 46926048Sminshall code = -1; 47026048Sminshall return; 47110296Ssam } 47235659Sbostic closefunc = pclose; 47310296Ssam } else { 47410296Ssam fin = fopen(local, "r"); 47510296Ssam if (fin == NULL) { 476*38202Srick fprintf(stderr, "local: %s: %s\n", local, 477*38202Srick strerror(errno)); 47826048Sminshall (void) signal(SIGINT, oldintr); 47926048Sminshall code = -1; 48026048Sminshall return; 48110296Ssam } 48210296Ssam closefunc = fclose; 48310296Ssam if (fstat(fileno(fin), &st) < 0 || 48410296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 48526496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 48626048Sminshall (void) signal(SIGINT, oldintr); 48736935Skarels fclose(fin); 48826048Sminshall code = -1; 48926048Sminshall return; 49010296Ssam } 49110296Ssam } 49226048Sminshall if (initconn()) { 49326048Sminshall (void) signal(SIGINT, oldintr); 49426448Slepreau if (oldintp) 49526048Sminshall (void) signal(SIGPIPE, oldintp); 49626048Sminshall code = -1; 49736935Skarels if (closefunc != NULL) 49836935Skarels (*closefunc)(fin); 49926048Sminshall return; 50026048Sminshall } 50126448Slepreau if (setjmp(sendabort)) 50226048Sminshall goto abort; 50336935Skarels 50437225Skarels if (restart_point && 50537225Skarels (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 50637225Skarels if (fseek(fin, (long) restart_point, 0) < 0) { 507*38202Srick fprintf(stderr, "local: %s: %s\n", local, 508*38202Srick strerror(errno)); 50937225Skarels restart_point = 0; 51037225Skarels if (closefunc != NULL) 51137225Skarels (*closefunc)(fin); 51237225Skarels return; 51337225Skarels } 51437225Skarels if (command("REST %ld", (long) restart_point) 51537225Skarels != CONTINUE) { 51637225Skarels restart_point = 0; 51737225Skarels if (closefunc != NULL) 51837225Skarels (*closefunc)(fin); 51937225Skarels return; 52037225Skarels } 52137225Skarels restart_point = 0; 52237225Skarels mode = "r+w"; 52337225Skarels } 52410296Ssam if (remote) { 52526048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 52626048Sminshall (void) signal(SIGINT, oldintr); 52726448Slepreau if (oldintp) 52826048Sminshall (void) signal(SIGPIPE, oldintp); 52936935Skarels if (closefunc != NULL) 53036935Skarels (*closefunc)(fin); 53126048Sminshall return; 53226048Sminshall } 53310296Ssam } else 53426048Sminshall if (command("%s", cmd) != PRELIM) { 53526048Sminshall (void) signal(SIGINT, oldintr); 53626448Slepreau if (oldintp) 53726048Sminshall (void) signal(SIGPIPE, oldintp); 53836935Skarels if (closefunc != NULL) 53936935Skarels (*closefunc)(fin); 54026048Sminshall return; 54126048Sminshall } 54236935Skarels dout = dataconn(mode); 54326448Slepreau if (dout == NULL) 54426048Sminshall goto abort; 54526496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 54636935Skarels oldintp = signal(SIGPIPE, SIG_IGN); 54711219Ssam switch (type) { 54811219Ssam 54911219Ssam case TYPE_I: 55011219Ssam case TYPE_L: 55111346Ssam errno = d = 0; 55236942Skarels while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { 55311219Ssam bytes += c; 55436942Skarels for (bufp = buf; c > 0; c -= d, bufp += d) 55536942Skarels if ((d = write(fileno(dout), bufp, c)) <= 0) 55636942Skarels break; 55711651Ssam if (hash) { 55836940Skarels while (bytes >= hashbytes) { 55936940Skarels (void) putchar('#'); 56036940Skarels hashbytes += HASHBYTES; 56136940Skarels } 56226496Sminshall (void) fflush(stdout); 56311651Ssam } 56411219Ssam } 56513213Ssam if (hash && bytes > 0) { 56636940Skarels if (bytes < HASHBYTES) 56736940Skarels (void) putchar('#'); 56826496Sminshall (void) putchar('\n'); 56926496Sminshall (void) fflush(stdout); 57011651Ssam } 57111219Ssam if (c < 0) 572*38202Srick fprintf(stderr, "local: %s: %s\n", local, 573*38202Srick strerror(errno)); 57436942Skarels if (d <= 0) { 57536942Skarels if (d == 0) 57636942Skarels fprintf(stderr, "netout: write returned 0?\n"); 57736942Skarels else if (errno != EPIPE) 57836935Skarels perror("netout"); 57936935Skarels bytes = -1; 58036935Skarels } 58111219Ssam break; 58211219Ssam 58311219Ssam case TYPE_A: 58411219Ssam while ((c = getc(fin)) != EOF) { 58511219Ssam if (c == '\n') { 58611651Ssam while (hash && (bytes >= hashbytes)) { 58726496Sminshall (void) putchar('#'); 58826496Sminshall (void) fflush(stdout); 58936940Skarels hashbytes += HASHBYTES; 59011651Ssam } 59111219Ssam if (ferror(dout)) 59211219Ssam break; 59326496Sminshall (void) putc('\r', dout); 59411219Ssam bytes++; 59511219Ssam } 59626496Sminshall (void) putc(c, dout); 59711219Ssam bytes++; 59826048Sminshall /* if (c == '\r') { */ 59926496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 60026048Sminshall /* bytes++; */ 60126048Sminshall /* } */ 60211219Ssam } 60311651Ssam if (hash) { 60413213Ssam if (bytes < hashbytes) 60526496Sminshall (void) putchar('#'); 60626496Sminshall (void) putchar('\n'); 60726496Sminshall (void) fflush(stdout); 60811651Ssam } 60911219Ssam if (ferror(fin)) 610*38202Srick fprintf(stderr, "local: %s: %s\n", local, 611*38202Srick strerror(errno)); 61236935Skarels if (ferror(dout)) { 61336935Skarels if (errno != EPIPE) 61436935Skarels perror("netout"); 61536935Skarels bytes = -1; 61636935Skarels } 61711219Ssam break; 61810296Ssam } 61926496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 62010296Ssam if (closefunc != NULL) 62126048Sminshall (*closefunc)(fin); 62210296Ssam (void) fclose(dout); 62326048Sminshall (void) getreply(0); 62426048Sminshall (void) signal(SIGINT, oldintr); 62536935Skarels if (oldintp) 62636935Skarels (void) signal(SIGPIPE, oldintp); 62735699Sbostic if (bytes > 0) 62837225Skarels ptransfer("sent", bytes, &start, &stop); 62910296Ssam return; 63026048Sminshall abort: 63126496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 63226048Sminshall (void) signal(SIGINT, oldintr); 63326448Slepreau if (oldintp) 63426048Sminshall (void) signal(SIGPIPE, oldintp); 63526048Sminshall if (!cpend) { 63626048Sminshall code = -1; 63726048Sminshall return; 63826048Sminshall } 63926048Sminshall if (data >= 0) { 64026048Sminshall (void) close(data); 64126048Sminshall data = -1; 64226048Sminshall } 64326448Slepreau if (dout) 64426048Sminshall (void) fclose(dout); 64526048Sminshall (void) getreply(0); 64626048Sminshall code = -1; 64710296Ssam if (closefunc != NULL && fin != NULL) 64826048Sminshall (*closefunc)(fin); 64935699Sbostic if (bytes > 0) 65037225Skarels ptransfer("sent", bytes, &start, &stop); 65110296Ssam } 65210296Ssam 65310296Ssam jmp_buf recvabort; 65410296Ssam 65538133Srick sig_t 65610296Ssam abortrecv() 65710296Ssam { 65810296Ssam 65926048Sminshall mflag = 0; 66026048Sminshall abrtflag = 0; 66138133Srick printf("\nreceive aborted\nwaiting for remote to finish abort\n"); 66226048Sminshall (void) fflush(stdout); 66310296Ssam longjmp(recvabort, 1); 66410296Ssam } 66510296Ssam 66637225Skarels recvrequest(cmd, local, remote, mode, printnames) 66711651Ssam char *cmd, *local, *remote, *mode; 66810296Ssam { 66935659Sbostic FILE *fout, *din = 0, *popen(); 67038133Srick int (*closefunc)(), pclose(), fclose(); 67138133Srick sig_t (*oldintr)(), (*oldintp)(), abortrecv(); 67238133Srick int is_retr, tcrflag, bare_lfs = 0; 67338133Srick char *gunique(); 67438133Srick static int bufsize; 67536944Skarels static char *buf; 67636940Skarels long bytes = 0, hashbytes = HASHBYTES; 67711346Ssam register int c, d; 67810296Ssam struct timeval start, stop; 67936940Skarels struct stat st; 68036940Skarels extern char *malloc(); 68110296Ssam 68236935Skarels is_retr = strcmp(cmd, "RETR") == 0; 68337225Skarels if (is_retr && verbose && printnames) { 68437225Skarels if (local && *local != '-') 68537225Skarels printf("local: %s ", local); 68637225Skarels if (remote) 68737225Skarels printf("remote: %s\n", remote); 68837225Skarels } 68936935Skarels if (proxy && is_retr) { 69026048Sminshall proxtrans(cmd, local, remote); 69126048Sminshall return; 69226048Sminshall } 69310296Ssam closefunc = NULL; 69426048Sminshall oldintr = NULL; 69526048Sminshall oldintp = NULL; 69636935Skarels tcrflag = !crflag && is_retr; 69726048Sminshall if (setjmp(recvabort)) { 69826048Sminshall while (cpend) { 69926048Sminshall (void) getreply(0); 70026048Sminshall } 70126048Sminshall if (data >= 0) { 70226048Sminshall (void) close(data); 70326048Sminshall data = -1; 70426048Sminshall } 70526448Slepreau if (oldintr) 70626048Sminshall (void) signal(SIGINT, oldintr); 70726048Sminshall code = -1; 70826048Sminshall return; 70926048Sminshall } 71010296Ssam oldintr = signal(SIGINT, abortrecv); 71126048Sminshall if (strcmp(local, "-") && *local != '|') { 71210296Ssam if (access(local, 2) < 0) { 71326048Sminshall char *dir = rindex(local, '/'); 71410296Ssam 71526048Sminshall if (errno != ENOENT && errno != EACCES) { 716*38202Srick fprintf(stderr, "local: %s: %s\n", local, 717*38202Srick strerror(errno)); 71826048Sminshall (void) signal(SIGINT, oldintr); 71926048Sminshall code = -1; 72026048Sminshall return; 72110296Ssam } 72226048Sminshall if (dir != NULL) 72326048Sminshall *dir = 0; 72426048Sminshall d = access(dir ? local : ".", 2); 72526048Sminshall if (dir != NULL) 72626048Sminshall *dir = '/'; 72726048Sminshall if (d < 0) { 728*38202Srick fprintf(stderr, "local: %s: %s\n", local, 729*38202Srick strerror(errno)); 73026048Sminshall (void) signal(SIGINT, oldintr); 73126048Sminshall code = -1; 73226048Sminshall return; 73326048Sminshall } 73426048Sminshall if (!runique && errno == EACCES && 73536935Skarels chmod(local, 0600) < 0) { 736*38202Srick fprintf(stderr, "local: %s: %s\n", local, 737*38202Srick strerror(errno)); 73826048Sminshall (void) signal(SIGINT, oldintr); 739*38202Srick (void) signal(SIGINT, oldintr); 74026048Sminshall code = -1; 74126048Sminshall return; 74226048Sminshall } 74326048Sminshall if (runique && errno == EACCES && 74426048Sminshall (local = gunique(local)) == NULL) { 74526048Sminshall (void) signal(SIGINT, oldintr); 74626048Sminshall code = -1; 74726048Sminshall return; 74826048Sminshall } 74910296Ssam } 75026048Sminshall else if (runique && (local = gunique(local)) == NULL) { 75126048Sminshall (void) signal(SIGINT, oldintr); 75226048Sminshall code = -1; 75326048Sminshall return; 75426048Sminshall } 75526048Sminshall } 75638033Skarels if (!is_retr) { 75738033Skarels if (curtype != TYPE_A) 75838033Skarels changetype(TYPE_A, 0); 75938033Skarels } else if (curtype != type) 76038033Skarels changetype(type, 0); 76126048Sminshall if (initconn()) { 76226048Sminshall (void) signal(SIGINT, oldintr); 76326048Sminshall code = -1; 76426048Sminshall return; 76526048Sminshall } 76626448Slepreau if (setjmp(recvabort)) 76726048Sminshall goto abort; 76838033Skarels if (is_retr && restart_point && 76938033Skarels command("REST %ld", (long) restart_point) != CONTINUE) 77038033Skarels return; 77110296Ssam if (remote) { 77226048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 77326048Sminshall (void) signal(SIGINT, oldintr); 77426048Sminshall return; 77526048Sminshall } 77626048Sminshall } else { 77726048Sminshall if (command("%s", cmd) != PRELIM) { 77826048Sminshall (void) signal(SIGINT, oldintr); 77926048Sminshall return; 78026048Sminshall } 78126048Sminshall } 78226048Sminshall din = dataconn("r"); 78326048Sminshall if (din == NULL) 78426048Sminshall goto abort; 78526448Slepreau if (strcmp(local, "-") == 0) 78610296Ssam fout = stdout; 78710296Ssam else if (*local == '|') { 78826048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 78935659Sbostic fout = popen(local + 1, "w"); 79026048Sminshall if (fout == NULL) { 79126048Sminshall perror(local+1); 79226048Sminshall goto abort; 79326048Sminshall } 79435659Sbostic closefunc = pclose; 79536940Skarels } else { 79611651Ssam fout = fopen(local, mode); 79726048Sminshall if (fout == NULL) { 798*38202Srick fprintf(stderr, "local: %s: %s\n", local, 799*38202Srick strerror(errno)); 80026048Sminshall goto abort; 80126048Sminshall } 80210296Ssam closefunc = fclose; 80310296Ssam } 80436940Skarels if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 80536940Skarels st.st_blksize = BUFSIZ; 80636940Skarels if (st.st_blksize > bufsize) { 80736940Skarels if (buf) 80836940Skarels (void) free(buf); 80938133Srick buf = malloc((unsigned)st.st_blksize); 81036940Skarels if (buf == NULL) { 81136940Skarels perror("malloc"); 81236944Skarels bufsize = 0; 81336940Skarels goto abort; 81436940Skarels } 81536940Skarels bufsize = st.st_blksize; 81636940Skarels } 81726496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 81838033Skarels switch (curtype) { 81911219Ssam 82011219Ssam case TYPE_I: 82111219Ssam case TYPE_L: 82237225Skarels if (restart_point && 82337225Skarels lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 824*38202Srick fprintf(stderr, "local: %s: %s\n", local, 825*38202Srick strerror(errno)); 82637225Skarels if (closefunc != NULL) 82737225Skarels (*closefunc)(fout); 82837225Skarels return; 82937225Skarels } 83011346Ssam errno = d = 0; 83136940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) { 83236944Skarels if ((d = write(fileno(fout), buf, c)) != c) 83311219Ssam break; 83411219Ssam bytes += c; 83511651Ssam if (hash) { 83636940Skarels while (bytes >= hashbytes) { 83736940Skarels (void) putchar('#'); 83836940Skarels hashbytes += HASHBYTES; 83936940Skarels } 84026496Sminshall (void) fflush(stdout); 84111651Ssam } 84211219Ssam } 84313213Ssam if (hash && bytes > 0) { 84436940Skarels if (bytes < HASHBYTES) 84536940Skarels (void) putchar('#'); 84626496Sminshall (void) putchar('\n'); 84726496Sminshall (void) fflush(stdout); 84811651Ssam } 84936935Skarels if (c < 0) { 85036935Skarels if (errno != EPIPE) 85136935Skarels perror("netin"); 85236935Skarels bytes = -1; 85336935Skarels } 85436942Skarels if (d < c) { 85536942Skarels if (d < 0) 856*38202Srick fprintf(stderr, "local: %s: %s\n", local, 857*38202Srick strerror(errno)); 85836942Skarels else 85936942Skarels fprintf(stderr, "%s: short write\n", local); 86036942Skarels } 86111219Ssam break; 86211219Ssam 86311219Ssam case TYPE_A: 86437225Skarels if (restart_point) { 86537225Skarels register int i, n, c; 86637225Skarels 86737225Skarels if (fseek(fout, 0L, L_SET) < 0) 86837225Skarels goto done; 86937225Skarels n = restart_point; 87037225Skarels i = 0; 87137225Skarels while (i++ < n) { 87237225Skarels if ((c=getc(fout)) == EOF) 87337225Skarels goto done; 87437225Skarels if (c == '\n') 87537225Skarels i++; 87637225Skarels } 87737225Skarels if (fseek(fout, 0L, L_INCR) < 0) { 87837225Skarels done: 879*38202Srick fprintf(stderr, "local: %s: %s\n", local, 880*38202Srick strerror(errno)); 88137225Skarels if (closefunc != NULL) 88237225Skarels (*closefunc)(fout); 88337225Skarels return; 88437225Skarels } 88537225Skarels } 88611219Ssam while ((c = getc(din)) != EOF) { 88738133Srick if (c == '\n') 88838133Srick bare_lfs++; 88927749Sminshall while (c == '\r') { 89011651Ssam while (hash && (bytes >= hashbytes)) { 89126496Sminshall (void) putchar('#'); 89226496Sminshall (void) fflush(stdout); 89336940Skarels hashbytes += HASHBYTES; 89411651Ssam } 89510296Ssam bytes++; 89626048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 89736940Skarels if (ferror(fout)) 89836940Skarels goto break2; 89936940Skarels (void) putc('\r', fout); 90036942Skarels if (c == '\0') { 90136942Skarels bytes++; 90236940Skarels goto contin2; 90336942Skarels } 90436942Skarels if (c == EOF) 90536942Skarels goto contin2; 90611219Ssam } 90711219Ssam } 90836940Skarels (void) putc(c, fout); 90911219Ssam bytes++; 91036940Skarels contin2: ; 91110296Ssam } 91236940Skarels break2: 91338133Srick if (bare_lfs) { 91438133Srick printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); 91538133Srick printf("File may not have transferred correctly.\n"); 91638133Srick } 91711651Ssam if (hash) { 91813213Ssam if (bytes < hashbytes) 91926496Sminshall (void) putchar('#'); 92026496Sminshall (void) putchar('\n'); 92126496Sminshall (void) fflush(stdout); 92211651Ssam } 92336944Skarels if (ferror(din)) { 92436935Skarels if (errno != EPIPE) 92536944Skarels perror("netin"); 92636935Skarels bytes = -1; 92736935Skarels } 92836940Skarels if (ferror(fout)) 929*38202Srick fprintf(stderr, "local: %s: %s\n", local, 930*38202Srick strerror(errno)); 93111219Ssam break; 93210296Ssam } 93326448Slepreau if (closefunc != NULL) 93426048Sminshall (*closefunc)(fout); 93526496Sminshall (void) signal(SIGINT, oldintr); 93626448Slepreau if (oldintp) 93726048Sminshall (void) signal(SIGPIPE, oldintp); 93826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 93910296Ssam (void) fclose(din); 94026048Sminshall (void) getreply(0); 94136935Skarels if (bytes > 0 && is_retr) 94237225Skarels ptransfer("received", bytes, &start, &stop); 94326048Sminshall return; 94426048Sminshall abort: 94526048Sminshall 94627687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 94726048Sminshall 94826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 94926448Slepreau if (oldintp) 95026048Sminshall (void) signal(SIGPIPE, oldintr); 95138133Srick (void) signal(SIGINT, SIG_IGN); 95226048Sminshall if (!cpend) { 95326048Sminshall code = -1; 95438133Srick (void) signal(SIGINT, oldintr); 95526048Sminshall return; 95626048Sminshall } 95726048Sminshall 95838133Srick abort_remote(din); 95926048Sminshall code = -1; 96026048Sminshall if (data >= 0) { 96126048Sminshall (void) close(data); 96226048Sminshall data = -1; 96326048Sminshall } 96426448Slepreau if (closefunc != NULL && fout != NULL) 96526048Sminshall (*closefunc)(fout); 96626448Slepreau if (din) 96726048Sminshall (void) fclose(din); 96835699Sbostic if (bytes > 0) 96937225Skarels ptransfer("received", bytes, &start, &stop); 97038133Srick (void) signal(SIGINT, oldintr); 97110296Ssam } 97210296Ssam 97310296Ssam /* 97410296Ssam * Need to start a listen on the data channel 97510296Ssam * before we send the command, otherwise the 97610296Ssam * server's connect may fail. 97710296Ssam */ 97838133Srick int sendport; 97911651Ssam 98010296Ssam initconn() 98110296Ssam { 98210296Ssam register char *p, *a; 98326048Sminshall int result, len, tmpno = 0; 98426993Skarels int on = 1; 98510296Ssam 98611651Ssam noport: 98710296Ssam data_addr = myctladdr; 98811651Ssam if (sendport) 98911651Ssam data_addr.sin_port = 0; /* let system pick one */ 99011651Ssam if (data != -1) 99138133Srick (void) close(data); 99218287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 99310296Ssam if (data < 0) { 99410296Ssam perror("ftp: socket"); 99526448Slepreau if (tmpno) 99626048Sminshall sendport = 1; 99710296Ssam return (1); 99810296Ssam } 99912397Ssam if (!sendport) 100027687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 100133224Sbostic perror("ftp: setsockopt (reuse address)"); 100212397Ssam goto bad; 100312397Ssam } 100426496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 100510296Ssam perror("ftp: bind"); 100610296Ssam goto bad; 100710296Ssam } 100810296Ssam if (options & SO_DEBUG && 100927687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 101010296Ssam perror("ftp: setsockopt (ignored)"); 101111627Ssam len = sizeof (data_addr); 101238133Srick if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 101311627Ssam perror("ftp: getsockname"); 101410296Ssam goto bad; 101510296Ssam } 101626448Slepreau if (listen(data, 1) < 0) 101710296Ssam perror("ftp: listen"); 101811651Ssam if (sendport) { 101911651Ssam a = (char *)&data_addr.sin_addr; 102011651Ssam p = (char *)&data_addr.sin_port; 102110296Ssam #define UC(b) (((int)b)&0xff) 102211651Ssam result = 102311651Ssam command("PORT %d,%d,%d,%d,%d,%d", 102411651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 102511651Ssam UC(p[0]), UC(p[1])); 102611651Ssam if (result == ERROR && sendport == -1) { 102711651Ssam sendport = 0; 102826048Sminshall tmpno = 1; 102911651Ssam goto noport; 103011651Ssam } 103111651Ssam return (result != COMPLETE); 103211651Ssam } 103326448Slepreau if (tmpno) 103426048Sminshall sendport = 1; 103511651Ssam return (0); 103610296Ssam bad: 103710296Ssam (void) close(data), data = -1; 103826448Slepreau if (tmpno) 103926048Sminshall sendport = 1; 104010296Ssam return (1); 104110296Ssam } 104210296Ssam 104310296Ssam FILE * 104410296Ssam dataconn(mode) 104510296Ssam char *mode; 104610296Ssam { 104710296Ssam struct sockaddr_in from; 104810296Ssam int s, fromlen = sizeof (from); 104910296Ssam 105026496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 105110296Ssam if (s < 0) { 105210296Ssam perror("ftp: accept"); 105310296Ssam (void) close(data), data = -1; 105410296Ssam return (NULL); 105510296Ssam } 105610296Ssam (void) close(data); 105710296Ssam data = s; 105810296Ssam return (fdopen(data, mode)); 105910296Ssam } 106010296Ssam 106137225Skarels ptransfer(direction, bytes, t0, t1) 106237225Skarels char *direction; 106311651Ssam long bytes; 106410296Ssam struct timeval *t0, *t1; 106510296Ssam { 106610296Ssam struct timeval td; 106716437Sleres float s, bs; 106810296Ssam 106935699Sbostic if (verbose) { 107035699Sbostic tvsub(&td, t1, t0); 107135699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 107210296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 107335699Sbostic bs = bytes / nz(s); 107435699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 107535699Sbostic bytes, direction, s, bs / 1024.); 107635699Sbostic } 107710296Ssam } 107810296Ssam 107926496Sminshall /*tvadd(tsum, t0) 108010296Ssam struct timeval *tsum, *t0; 108110296Ssam { 108210296Ssam 108310296Ssam tsum->tv_sec += t0->tv_sec; 108410296Ssam tsum->tv_usec += t0->tv_usec; 108510296Ssam if (tsum->tv_usec > 1000000) 108610296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 108726496Sminshall } */ 108810296Ssam 108910296Ssam tvsub(tdiff, t1, t0) 109010296Ssam struct timeval *tdiff, *t1, *t0; 109110296Ssam { 109210296Ssam 109310296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 109410296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 109510296Ssam if (tdiff->tv_usec < 0) 109610296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 109710296Ssam } 109826048Sminshall 109938133Srick sig_t 110026048Sminshall psabort() 110126048Sminshall { 110226048Sminshall extern int abrtflag; 110326048Sminshall 110426048Sminshall abrtflag++; 110526048Sminshall } 110626048Sminshall 110726048Sminshall pswitch(flag) 110826048Sminshall int flag; 110926048Sminshall { 111026048Sminshall extern int proxy, abrtflag; 111138133Srick sig_t (*oldintr)(); 111226048Sminshall static struct comvars { 111326048Sminshall int connect; 111428469Skarels char name[MAXHOSTNAMELEN]; 111526048Sminshall struct sockaddr_in mctl; 111626048Sminshall struct sockaddr_in hctl; 111726048Sminshall FILE *in; 111826048Sminshall FILE *out; 111926048Sminshall int tpe; 112038033Skarels int curtpe; 112126048Sminshall int cpnd; 112226048Sminshall int sunqe; 112326048Sminshall int runqe; 112426048Sminshall int mcse; 112526048Sminshall int ntflg; 112626048Sminshall char nti[17]; 112726048Sminshall char nto[17]; 112826048Sminshall int mapflg; 112926048Sminshall char mi[MAXPATHLEN]; 113026048Sminshall char mo[MAXPATHLEN]; 113138033Skarels } proxstruct, tmpstruct; 113226048Sminshall struct comvars *ip, *op; 113326048Sminshall 113426048Sminshall abrtflag = 0; 113526048Sminshall oldintr = signal(SIGINT, psabort); 113626048Sminshall if (flag) { 113726448Slepreau if (proxy) 113826048Sminshall return; 113926048Sminshall ip = &tmpstruct; 114026048Sminshall op = &proxstruct; 114126048Sminshall proxy++; 114238033Skarels } else { 114326448Slepreau if (!proxy) 114426048Sminshall return; 114526048Sminshall ip = &proxstruct; 114626048Sminshall op = &tmpstruct; 114726048Sminshall proxy = 0; 114826048Sminshall } 114926048Sminshall ip->connect = connected; 115026048Sminshall connected = op->connect; 115128469Skarels if (hostname) { 115228469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 115328469Skarels ip->name[strlen(ip->name)] = '\0'; 115428469Skarels } else 115528469Skarels ip->name[0] = 0; 115626048Sminshall hostname = op->name; 115726048Sminshall ip->hctl = hisctladdr; 115826048Sminshall hisctladdr = op->hctl; 115926048Sminshall ip->mctl = myctladdr; 116026048Sminshall myctladdr = op->mctl; 116126048Sminshall ip->in = cin; 116226048Sminshall cin = op->in; 116326048Sminshall ip->out = cout; 116426048Sminshall cout = op->out; 116526048Sminshall ip->tpe = type; 116626048Sminshall type = op->tpe; 116738033Skarels ip->curtpe = curtype; 116838033Skarels curtype = op->curtpe; 116926048Sminshall ip->cpnd = cpend; 117026048Sminshall cpend = op->cpnd; 117126048Sminshall ip->sunqe = sunique; 117226048Sminshall sunique = op->sunqe; 117326048Sminshall ip->runqe = runique; 117426048Sminshall runique = op->runqe; 117526048Sminshall ip->mcse = mcase; 117626048Sminshall mcase = op->mcse; 117726048Sminshall ip->ntflg = ntflag; 117826048Sminshall ntflag = op->ntflg; 117926496Sminshall (void) strncpy(ip->nti, ntin, 16); 118026048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 118126496Sminshall (void) strcpy(ntin, op->nti); 118226496Sminshall (void) strncpy(ip->nto, ntout, 16); 118326048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 118426496Sminshall (void) strcpy(ntout, op->nto); 118526048Sminshall ip->mapflg = mapflag; 118626048Sminshall mapflag = op->mapflg; 118726496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 118826048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 118926496Sminshall (void) strcpy(mapin, op->mi); 119026496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 119126048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 119226496Sminshall (void) strcpy(mapout, op->mo); 119326048Sminshall (void) signal(SIGINT, oldintr); 119426048Sminshall if (abrtflag) { 119526048Sminshall abrtflag = 0; 119626048Sminshall (*oldintr)(); 119726448Slepreau } 119826048Sminshall } 119926048Sminshall 120026048Sminshall jmp_buf ptabort; 120126048Sminshall int ptabflg; 120226048Sminshall 120338133Srick sig_t 120426048Sminshall abortpt() 120526048Sminshall { 120626048Sminshall printf("\n"); 120726496Sminshall (void) fflush(stdout); 120826048Sminshall ptabflg++; 120926048Sminshall mflag = 0; 121026048Sminshall abrtflag = 0; 121126048Sminshall longjmp(ptabort, 1); 121226048Sminshall } 121326048Sminshall 121426048Sminshall proxtrans(cmd, local, remote) 121526048Sminshall char *cmd, *local, *remote; 121626048Sminshall { 121738133Srick sig_t (*oldintr)(), abortpt(); 121838133Srick int secndflag = 0, prox_type, nfnd; 121926048Sminshall extern jmp_buf ptabort; 122026048Sminshall char *cmd2; 122126496Sminshall struct fd_set mask; 122226048Sminshall 122326448Slepreau if (strcmp(cmd, "RETR")) 122426048Sminshall cmd2 = "RETR"; 122526448Slepreau else 122626048Sminshall cmd2 = runique ? "STOU" : "STOR"; 122738033Skarels if ((prox_type = type) == 0) { 122838033Skarels if (unix_server && unix_proxy) 122938033Skarels prox_type = TYPE_I; 123038033Skarels else 123138033Skarels prox_type = TYPE_A; 123238033Skarels } 123338033Skarels if (curtype != prox_type) 123438033Skarels changetype(prox_type, 1); 123526048Sminshall if (command("PASV") != COMPLETE) { 123638033Skarels printf("proxy server does not support third party transfers.\n"); 123726048Sminshall return; 123826048Sminshall } 123926048Sminshall pswitch(0); 124026048Sminshall if (!connected) { 124126048Sminshall printf("No primary connection\n"); 124226048Sminshall pswitch(1); 124326048Sminshall code = -1; 124426048Sminshall return; 124526048Sminshall } 124638033Skarels if (curtype != prox_type) 124738033Skarels changetype(prox_type, 1); 124826048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 124926048Sminshall pswitch(1); 125026048Sminshall return; 125126048Sminshall } 125226448Slepreau if (setjmp(ptabort)) 125326048Sminshall goto abort; 125426048Sminshall oldintr = signal(SIGINT, abortpt); 125526048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 125626048Sminshall (void) signal(SIGINT, oldintr); 125726048Sminshall pswitch(1); 125826048Sminshall return; 125926048Sminshall } 126026048Sminshall sleep(2); 126126048Sminshall pswitch(1); 126226048Sminshall secndflag++; 126326448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 126426048Sminshall goto abort; 126526048Sminshall ptflag++; 126626048Sminshall (void) getreply(0); 126726048Sminshall pswitch(0); 126826048Sminshall (void) getreply(0); 126926048Sminshall (void) signal(SIGINT, oldintr); 127026048Sminshall pswitch(1); 127126048Sminshall ptflag = 0; 127226048Sminshall printf("local: %s remote: %s\n", local, remote); 127326048Sminshall return; 127426048Sminshall abort: 127526048Sminshall (void) signal(SIGINT, SIG_IGN); 127626048Sminshall ptflag = 0; 127726448Slepreau if (strcmp(cmd, "RETR") && !proxy) 127826048Sminshall pswitch(1); 127926448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 128026048Sminshall pswitch(0); 128126048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 128226048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 128326048Sminshall pswitch(0); 128438133Srick if (cpend) 128538133Srick abort_remote((FILE *) NULL); 128626048Sminshall } 128726048Sminshall pswitch(1); 128826448Slepreau if (ptabflg) 128926048Sminshall code = -1; 129026048Sminshall (void) signal(SIGINT, oldintr); 129126048Sminshall return; 129226048Sminshall } 129338133Srick if (cpend) 129438133Srick abort_remote((FILE *) NULL); 129526048Sminshall pswitch(!proxy); 129626048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 129726048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 129826048Sminshall pswitch(0); 129938133Srick if (cpend) 130038133Srick abort_remote((FILE *) NULL); 130126048Sminshall pswitch(1); 130226448Slepreau if (ptabflg) 130326048Sminshall code = -1; 130426048Sminshall (void) signal(SIGINT, oldintr); 130526048Sminshall return; 130626048Sminshall } 130726048Sminshall } 130838133Srick if (cpend) 130938133Srick abort_remote((FILE *) NULL); 131026048Sminshall pswitch(!proxy); 131126048Sminshall if (cpend) { 131227687Sminshall FD_ZERO(&mask); 131326496Sminshall FD_SET(fileno(cin), &mask); 131438133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 131527687Sminshall if (nfnd < 0) { 131627687Sminshall perror("abort"); 131727687Sminshall } 131826448Slepreau if (ptabflg) 131926048Sminshall code = -1; 132026048Sminshall lostpeer(); 132126048Sminshall } 132226048Sminshall (void) getreply(0); 132326048Sminshall (void) getreply(0); 132426048Sminshall } 132526448Slepreau if (proxy) 132626048Sminshall pswitch(0); 132726048Sminshall pswitch(1); 132826448Slepreau if (ptabflg) 132926048Sminshall code = -1; 133026048Sminshall (void) signal(SIGINT, oldintr); 133126048Sminshall } 133226048Sminshall 133326048Sminshall reset() 133426048Sminshall { 133526496Sminshall struct fd_set mask; 133626496Sminshall int nfnd = 1; 133726048Sminshall 133827687Sminshall FD_ZERO(&mask); 133930946Scsvsj while (nfnd > 0) { 134026496Sminshall FD_SET(fileno(cin), &mask); 134127687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 134226048Sminshall perror("reset"); 134326048Sminshall code = -1; 134426048Sminshall lostpeer(); 134526048Sminshall } 134627687Sminshall else if (nfnd) { 134726048Sminshall (void) getreply(0); 134826496Sminshall } 134926048Sminshall } 135026048Sminshall } 135126048Sminshall 135226048Sminshall char * 135326048Sminshall gunique(local) 135426048Sminshall char *local; 135526048Sminshall { 135626048Sminshall static char new[MAXPATHLEN]; 135726048Sminshall char *cp = rindex(local, '/'); 135826048Sminshall int d, count=0; 135926048Sminshall char ext = '1'; 136026048Sminshall 136126448Slepreau if (cp) 136226048Sminshall *cp = '\0'; 136326048Sminshall d = access(cp ? local : ".", 2); 136426448Slepreau if (cp) 136526048Sminshall *cp = '/'; 136626048Sminshall if (d < 0) { 1367*38202Srick fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); 136826048Sminshall return((char *) 0); 136926048Sminshall } 137026048Sminshall (void) strcpy(new, local); 137126048Sminshall cp = new + strlen(new); 137226048Sminshall *cp++ = '.'; 137326048Sminshall while (!d) { 137426048Sminshall if (++count == 100) { 137526048Sminshall printf("runique: can't find unique file name.\n"); 137626048Sminshall return((char *) 0); 137726048Sminshall } 137826048Sminshall *cp++ = ext; 137926048Sminshall *cp = '\0'; 138026448Slepreau if (ext == '9') 138126048Sminshall ext = '0'; 138226448Slepreau else 138326048Sminshall ext++; 138426448Slepreau if ((d = access(new, 0)) < 0) 138526048Sminshall break; 138626448Slepreau if (ext != '0') 138726048Sminshall cp--; 138826448Slepreau else if (*(cp - 2) == '.') 138926048Sminshall *(cp - 1) = '1'; 139026048Sminshall else { 139126048Sminshall *(cp - 2) = *(cp - 2) + 1; 139226048Sminshall cp--; 139326048Sminshall } 139426048Sminshall } 139526048Sminshall return(new); 139626048Sminshall } 139738133Srick 139838133Srick abort_remote(din) 139938133Srick FILE *din; 140038133Srick { 140138133Srick char buf[BUFSIZ]; 140238133Srick int nfnd; 140338133Srick struct fd_set mask; 140438133Srick 140538133Srick /* 140638133Srick * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 140738133Srick * after urgent byte rather than before as is protocol now 140838133Srick */ 140938133Srick sprintf(buf, "%c%c%c", IAC, IP, IAC); 141038133Srick if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 141138133Srick perror("abort"); 141238133Srick fprintf(cout,"%cABOR\r\n", DM); 141338133Srick (void) fflush(cout); 141438133Srick FD_ZERO(&mask); 141538133Srick FD_SET(fileno(cin), &mask); 141638133Srick if (din) { 141738133Srick FD_SET(fileno(din), &mask); 141838133Srick } 141938133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 142038133Srick if (nfnd < 0) { 142138133Srick perror("abort"); 142238133Srick } 142338133Srick if (ptabflg) 142438133Srick code = -1; 142538133Srick lostpeer(); 142638133Srick } 142738133Srick if (din && FD_ISSET(fileno(din), &mask)) { 142838133Srick while (read(fileno(din), buf, BUFSIZ) > 0) 142938133Srick /* LOOP */; 143038133Srick } 143138133Srick if (getreply(0) == ERROR && code == 552) { 143238133Srick /* 552 needed for nic style abort */ 143338133Srick (void) getreply(0); 143438133Srick } 143538133Srick (void) getreply(0); 143638133Srick } 1437