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*38133Srick static char sccsid[] = "@(#)ftp.c 5.30 (Berkeley) 05/26/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> 39*38133Srick #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(); 51*38133Srick sig_t lostpeer(); 5237225Skarels off_t restart_point = 0; 5310296Ssam 5410296Ssam FILE *cin, *cout; 5510296Ssam FILE *dataconn(); 5610296Ssam 5725904Skarels char * 5810296Ssam hookup(host, port) 5910296Ssam char *host; 6010296Ssam int port; 6110296Ssam { 6225904Skarels register struct hostent *hp = 0; 6327687Sminshall int s,len; 6425904Skarels static char hostnamebuf[80]; 6510296Ssam 6610296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 6725904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 6825904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 6925904Skarels hisctladdr.sin_family = AF_INET; 7036940Skarels (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); 7136940Skarels } else { 7225100Sbloom hp = gethostbyname(host); 7325904Skarels if (hp == NULL) { 7435792Sbostic fprintf(stderr, "ftp: %s: ", host); 7535792Sbostic herror((char *)NULL); 7626048Sminshall code = -1; 7726048Sminshall return((char *) 0); 7825904Skarels } 7925904Skarels hisctladdr.sin_family = hp->h_addrtype; 8025904Skarels bcopy(hp->h_addr_list[0], 8125904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 8236940Skarels (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); 8310296Ssam } 8425904Skarels hostname = hostnamebuf; 8525904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 8610296Ssam if (s < 0) { 8710296Ssam perror("ftp: socket"); 8826048Sminshall code = -1; 8910296Ssam return (0); 9010296Ssam } 9110296Ssam hisctladdr.sin_port = port; 92*38133Srick while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { 9325904Skarels if (hp && hp->h_addr_list[1]) { 9425904Skarels int oerrno = errno; 95*38133Srick extern char *inet_ntoa(); 9625904Skarels 9725904Skarels fprintf(stderr, "ftp: connect to address %s: ", 9825904Skarels inet_ntoa(hisctladdr.sin_addr)); 9925904Skarels errno = oerrno; 10026496Sminshall perror((char *) 0); 10125904Skarels hp->h_addr_list++; 10225904Skarels bcopy(hp->h_addr_list[0], 10326048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 10426496Sminshall fprintf(stdout, "Trying %s...\n", 10525904Skarels inet_ntoa(hisctladdr.sin_addr)); 10626813Skarels (void) close(s); 10726813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 10826813Skarels if (s < 0) { 10926813Skarels perror("ftp: socket"); 11026813Skarels code = -1; 11126813Skarels return (0); 11226813Skarels } 11325904Skarels continue; 11425904Skarels } 11510296Ssam perror("ftp: connect"); 11626048Sminshall code = -1; 11710296Ssam goto bad; 11810296Ssam } 11911627Ssam len = sizeof (myctladdr); 120*38133Srick if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { 12111627Ssam perror("ftp: getsockname"); 12226048Sminshall code = -1; 12310296Ssam goto bad; 12410296Ssam } 12510296Ssam cin = fdopen(s, "r"); 12610296Ssam cout = fdopen(s, "w"); 12711219Ssam if (cin == NULL || cout == NULL) { 12810296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 12910296Ssam if (cin) 13026496Sminshall (void) fclose(cin); 13110296Ssam if (cout) 13226496Sminshall (void) fclose(cout); 13326048Sminshall code = -1; 13410296Ssam goto bad; 13510296Ssam } 13610296Ssam if (verbose) 13726067Sminshall printf("Connected to %s.\n", hostname); 13827687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 13926048Sminshall if (cin) 14026496Sminshall (void) fclose(cin); 14126048Sminshall if (cout) 14226496Sminshall (void) fclose(cout); 14326048Sminshall code = -1; 14426048Sminshall goto bad; 14526048Sminshall } 14627687Sminshall #ifdef SO_OOBINLINE 14727687Sminshall { 14827687Sminshall int on = 1; 14926048Sminshall 15027687Sminshall if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 15127687Sminshall < 0 && debug) { 15227687Sminshall perror("ftp: setsockopt"); 15327687Sminshall } 15427687Sminshall } 155*38133Srick #endif /* SO_OOBINLINE */ 15626048Sminshall 15725904Skarels return (hostname); 15810296Ssam bad: 15926496Sminshall (void) close(s); 16025904Skarels return ((char *)0); 16110296Ssam } 16210296Ssam 16325904Skarels login(host) 16425904Skarels char *host; 16510296Ssam { 16626048Sminshall char tmp[80]; 16735659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 16826048Sminshall int n, aflag = 0; 16910296Ssam 17026048Sminshall user = pass = acct = 0; 17126048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 17226048Sminshall code = -1; 17326048Sminshall return(0); 17426048Sminshall } 17537458Skarels while (user == NULL) { 17626048Sminshall char *myname = getlogin(); 17726048Sminshall 17826048Sminshall if (myname == NULL) { 17926048Sminshall struct passwd *pp = getpwuid(getuid()); 18026048Sminshall 18126448Slepreau if (pp != NULL) 18226048Sminshall myname = pp->pw_name; 18326048Sminshall } 18437458Skarels if (myname) 18537458Skarels printf("Name (%s:%s): ", host, myname); 18637458Skarels else 18737458Skarels printf("Name (%s): ", host); 18826048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 18926048Sminshall tmp[strlen(tmp) - 1] = '\0'; 19026448Slepreau if (*tmp == '\0') 19126048Sminshall user = myname; 19226448Slepreau else 19326048Sminshall user = tmp; 19426048Sminshall } 19510296Ssam n = command("USER %s", user); 19626048Sminshall if (n == CONTINUE) { 19726448Slepreau if (pass == NULL) 19835659Sbostic pass = getpass("Password:"); 19910296Ssam n = command("PASS %s", pass); 20026048Sminshall } 20110296Ssam if (n == CONTINUE) { 20226048Sminshall aflag++; 20335659Sbostic acct = getpass("Account:"); 20410296Ssam n = command("ACCT %s", acct); 20510296Ssam } 20610296Ssam if (n != COMPLETE) { 20710296Ssam fprintf(stderr, "Login failed.\n"); 20810296Ssam return (0); 20910296Ssam } 21026448Slepreau if (!aflag && acct != NULL) 21126048Sminshall (void) command("ACCT %s", acct); 21226448Slepreau if (proxy) 21326048Sminshall return(1); 21426048Sminshall for (n = 0; n < macnum; ++n) { 21526048Sminshall if (!strcmp("init", macros[n].mac_name)) { 21626496Sminshall (void) strcpy(line, "$init"); 21726048Sminshall makeargv(); 21826048Sminshall domacro(margc, margv); 21926048Sminshall break; 22026048Sminshall } 22126048Sminshall } 22210296Ssam return (1); 22310296Ssam } 22410296Ssam 225*38133Srick sig_t 22626048Sminshall cmdabort() 22726048Sminshall { 22826048Sminshall extern jmp_buf ptabort; 22926048Sminshall 23026048Sminshall printf("\n"); 23126048Sminshall (void) fflush(stdout); 23226048Sminshall abrtflag++; 23326448Slepreau if (ptflag) 23426048Sminshall longjmp(ptabort,1); 23526048Sminshall } 23626048Sminshall 237*38133Srick /*VARARGS*/ 238*38133Srick command(va_alist) 239*38133Srick va_dcl 240*38133Srick { 241*38133Srick va_list ap; 24210296Ssam char *fmt; 243*38133Srick int r; 244*38133Srick sig_t (*oldintr)(), cmdabort(); 24510296Ssam 24626048Sminshall abrtflag = 0; 24710296Ssam if (debug) { 24810296Ssam printf("---> "); 249*38133Srick va_start(ap); 250*38133Srick fmt = va_arg(ap, char *); 251*38133Srick if (strncmp("PASS ", fmt, 5) == 0) 252*38133Srick printf("PASS XXXX"); 253*38133Srick else 254*38133Srick vfprintf(stdout, fmt, ap); 255*38133Srick va_end(ap); 25610296Ssam printf("\n"); 25710296Ssam (void) fflush(stdout); 25810296Ssam } 25911219Ssam if (cout == NULL) { 26011219Ssam perror ("No control connection for command"); 26126048Sminshall code = -1; 26211219Ssam return (0); 26311219Ssam } 264*38133Srick oldintr = signal(SIGINT, cmdabort); 265*38133Srick va_start(ap); 266*38133Srick fmt = va_arg(ap, char *); 267*38133Srick vfprintf(cout, fmt, ap); 268*38133Srick va_end(ap); 26910296Ssam fprintf(cout, "\r\n"); 27010296Ssam (void) fflush(cout); 27126048Sminshall cpend = 1; 27226048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 27326448Slepreau if (abrtflag && oldintr != SIG_IGN) 27426048Sminshall (*oldintr)(); 27526048Sminshall (void) signal(SIGINT, oldintr); 27626048Sminshall return(r); 27710296Ssam } 27810296Ssam 27937229Skarels char reply_string[BUFSIZ]; /* last line of previous reply */ 28036935Skarels 28110296Ssam #include <ctype.h> 28210296Ssam 28310296Ssam getreply(expecteof) 28410296Ssam int expecteof; 28510296Ssam { 28611219Ssam register int c, n; 28726048Sminshall register int dig; 28836935Skarels register char *cp; 289*38133Srick int originalcode = 0, continuation = 0; 290*38133Srick sig_t (*oldintr)(), cmdabort(); 29126048Sminshall int pflag = 0; 29226048Sminshall char *pt = pasv; 29310296Ssam 294*38133Srick oldintr = signal(SIGINT, cmdabort); 29510296Ssam for (;;) { 29610296Ssam dig = n = code = 0; 29737229Skarels cp = reply_string; 29810296Ssam while ((c = getc(cin)) != '\n') { 29927687Sminshall if (c == IAC) { /* handle telnet commands */ 30027687Sminshall switch (c = getc(cin)) { 30127687Sminshall case WILL: 30227687Sminshall case WONT: 30327687Sminshall c = getc(cin); 304*38133Srick fprintf(cout, "%c%c%c", IAC, DONT, c); 30527687Sminshall (void) fflush(cout); 30627687Sminshall break; 30727687Sminshall case DO: 30827687Sminshall case DONT: 30927687Sminshall c = getc(cin); 310*38133Srick fprintf(cout, "%c%c%c", IAC, WONT, c); 31127687Sminshall (void) fflush(cout); 31227687Sminshall break; 31327687Sminshall default: 31427687Sminshall break; 31527687Sminshall } 31627687Sminshall continue; 31727687Sminshall } 31810296Ssam dig++; 31910296Ssam if (c == EOF) { 32026048Sminshall if (expecteof) { 32126048Sminshall (void) signal(SIGINT,oldintr); 32226048Sminshall code = 221; 32310296Ssam return (0); 32426048Sminshall } 32510296Ssam lostpeer(); 32626048Sminshall if (verbose) { 32726048Sminshall printf("421 Service not available, remote server has closed connection\n"); 32826048Sminshall (void) fflush(stdout); 32926048Sminshall } 33033772Scsvsj code = 421; 33133772Scsvsj return(4); 33210296Ssam } 33326048Sminshall if (c != '\r' && (verbose > 0 || 33426048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 33526448Slepreau if (proxflag && 33626448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 33726048Sminshall printf("%s:",hostname); 33826496Sminshall (void) putchar(c); 33926048Sminshall } 34010296Ssam if (dig < 4 && isdigit(c)) 34110296Ssam code = code * 10 + (c - '0'); 34226448Slepreau if (!pflag && code == 227) 34326048Sminshall pflag = 1; 34426448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 34526048Sminshall pflag = 2; 34626048Sminshall if (pflag == 2) { 34726448Slepreau if (c != '\r' && c != ')') 34826048Sminshall *pt++ = c; 34926048Sminshall else { 35026048Sminshall *pt = '\0'; 35126048Sminshall pflag = 3; 35226048Sminshall } 35326048Sminshall } 35426048Sminshall if (dig == 4 && c == '-') { 35526448Slepreau if (continuation) 35626048Sminshall code = 0; 35710296Ssam continuation++; 35826048Sminshall } 35910296Ssam if (n == 0) 36010296Ssam n = c; 36137229Skarels if (cp < &reply_string[sizeof(reply_string) - 1]) 36237229Skarels *cp++ = c; 36310296Ssam } 36426048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 36526496Sminshall (void) putchar(c); 36611346Ssam (void) fflush (stdout); 36711346Ssam } 36810296Ssam if (continuation && code != originalcode) { 36910296Ssam if (originalcode == 0) 37010296Ssam originalcode = code; 37110296Ssam continue; 37210296Ssam } 37336935Skarels *cp = '\0'; 37426448Slepreau if (n != '1') 37526048Sminshall cpend = 0; 37626048Sminshall (void) signal(SIGINT,oldintr); 37726448Slepreau if (code == 421 || originalcode == 421) 37826048Sminshall lostpeer(); 37926448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 38026048Sminshall (*oldintr)(); 38125907Smckusick return (n - '0'); 38210296Ssam } 38310296Ssam } 38410296Ssam 38526048Sminshall empty(mask, sec) 38627687Sminshall struct fd_set *mask; 38726048Sminshall int sec; 38826048Sminshall { 38926048Sminshall struct timeval t; 39026048Sminshall 39126048Sminshall t.tv_sec = (long) sec; 39226048Sminshall t.tv_usec = 0; 39327687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 39426048Sminshall } 39526048Sminshall 39610296Ssam jmp_buf sendabort; 39710296Ssam 39810296Ssam abortsend() 39910296Ssam { 40010296Ssam 40126048Sminshall mflag = 0; 40226048Sminshall abrtflag = 0; 403*38133Srick printf("\nsend aborted\nwaiting for remote to finish abort\n"); 40426048Sminshall (void) fflush(stdout); 40510296Ssam longjmp(sendabort, 1); 40610296Ssam } 40710296Ssam 40836940Skarels #define HASHBYTES 1024 40936940Skarels 41037225Skarels sendrequest(cmd, local, remote, printnames) 41110296Ssam char *cmd, *local, *remote; 41237225Skarels int printnames; 41310296Ssam { 41435659Sbostic FILE *fin, *dout = 0, *popen(); 415*38133Srick int (*closefunc)(), pclose(), fclose(); 416*38133Srick sig_t (*oldintr)(), (*oldintp)(); 41726048Sminshall int abortsend(); 41836942Skarels char buf[BUFSIZ], *bufp; 41936940Skarels long bytes = 0, hashbytes = HASHBYTES; 42011346Ssam register int c, d; 42110296Ssam struct stat st; 42210296Ssam struct timeval start, stop; 42336935Skarels char *mode; 42410296Ssam 42537225Skarels if (verbose && printnames) { 42637225Skarels if (local && *local != '-') 42737225Skarels printf("local: %s ", local); 42837225Skarels if (remote) 42937225Skarels printf("remote: %s\n", remote); 43037225Skarels } 43126048Sminshall if (proxy) { 43226048Sminshall proxtrans(cmd, local, remote); 43326048Sminshall return; 43426048Sminshall } 43538033Skarels if (curtype != type) 43638033Skarels changetype(type, 0); 43710296Ssam closefunc = NULL; 43826048Sminshall oldintr = NULL; 43926048Sminshall oldintp = NULL; 44036935Skarels mode = "w"; 44126048Sminshall if (setjmp(sendabort)) { 44226048Sminshall while (cpend) { 44326048Sminshall (void) getreply(0); 44426048Sminshall } 44526048Sminshall if (data >= 0) { 44626048Sminshall (void) close(data); 44726048Sminshall data = -1; 44826048Sminshall } 44926448Slepreau if (oldintr) 45026048Sminshall (void) signal(SIGINT,oldintr); 45126448Slepreau if (oldintp) 45226048Sminshall (void) signal(SIGPIPE,oldintp); 45326048Sminshall code = -1; 45426048Sminshall return; 45526048Sminshall } 45610296Ssam oldintr = signal(SIGINT, abortsend); 45710296Ssam if (strcmp(local, "-") == 0) 45810296Ssam fin = stdin; 45910296Ssam else if (*local == '|') { 46026048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 46135659Sbostic fin = popen(local + 1, "r"); 46210296Ssam if (fin == NULL) { 46326048Sminshall perror(local + 1); 46426048Sminshall (void) signal(SIGINT, oldintr); 46526048Sminshall (void) signal(SIGPIPE, oldintp); 46626048Sminshall code = -1; 46726048Sminshall return; 46810296Ssam } 46935659Sbostic closefunc = pclose; 47010296Ssam } else { 47110296Ssam fin = fopen(local, "r"); 47210296Ssam if (fin == NULL) { 47310296Ssam perror(local); 47426048Sminshall (void) signal(SIGINT, oldintr); 47526048Sminshall code = -1; 47626048Sminshall return; 47710296Ssam } 47810296Ssam closefunc = fclose; 47910296Ssam if (fstat(fileno(fin), &st) < 0 || 48010296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 48126496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 48226048Sminshall (void) signal(SIGINT, oldintr); 48336935Skarels fclose(fin); 48426048Sminshall code = -1; 48526048Sminshall return; 48610296Ssam } 48710296Ssam } 48826048Sminshall if (initconn()) { 48926048Sminshall (void) signal(SIGINT, oldintr); 49026448Slepreau if (oldintp) 49126048Sminshall (void) signal(SIGPIPE, oldintp); 49226048Sminshall code = -1; 49336935Skarels if (closefunc != NULL) 49436935Skarels (*closefunc)(fin); 49526048Sminshall return; 49626048Sminshall } 49726448Slepreau if (setjmp(sendabort)) 49826048Sminshall goto abort; 49936935Skarels 50037225Skarels if (restart_point && 50137225Skarels (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 50237225Skarels if (fseek(fin, (long) restart_point, 0) < 0) { 50337225Skarels perror(local); 50437225Skarels restart_point = 0; 50537225Skarels if (closefunc != NULL) 50637225Skarels (*closefunc)(fin); 50737225Skarels return; 50837225Skarels } 50937225Skarels if (command("REST %ld", (long) restart_point) 51037225Skarels != CONTINUE) { 51137225Skarels restart_point = 0; 51237225Skarels if (closefunc != NULL) 51337225Skarels (*closefunc)(fin); 51437225Skarels return; 51537225Skarels } 51637225Skarels restart_point = 0; 51737225Skarels mode = "r+w"; 51837225Skarels } 51910296Ssam if (remote) { 52026048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 52126048Sminshall (void) signal(SIGINT, oldintr); 52226448Slepreau if (oldintp) 52326048Sminshall (void) signal(SIGPIPE, oldintp); 52436935Skarels if (closefunc != NULL) 52536935Skarels (*closefunc)(fin); 52626048Sminshall return; 52726048Sminshall } 52810296Ssam } else 52926048Sminshall if (command("%s", cmd) != PRELIM) { 53026048Sminshall (void) signal(SIGINT, oldintr); 53126448Slepreau if (oldintp) 53226048Sminshall (void) signal(SIGPIPE, oldintp); 53336935Skarels if (closefunc != NULL) 53436935Skarels (*closefunc)(fin); 53526048Sminshall return; 53626048Sminshall } 53736935Skarels dout = dataconn(mode); 53826448Slepreau if (dout == NULL) 53926048Sminshall goto abort; 54026496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 54136935Skarels oldintp = signal(SIGPIPE, SIG_IGN); 54211219Ssam switch (type) { 54311219Ssam 54411219Ssam case TYPE_I: 54511219Ssam case TYPE_L: 54611346Ssam errno = d = 0; 54736942Skarels while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { 54811219Ssam bytes += c; 54936942Skarels for (bufp = buf; c > 0; c -= d, bufp += d) 55036942Skarels if ((d = write(fileno(dout), bufp, c)) <= 0) 55136942Skarels break; 55211651Ssam if (hash) { 55336940Skarels while (bytes >= hashbytes) { 55436940Skarels (void) putchar('#'); 55536940Skarels hashbytes += HASHBYTES; 55636940Skarels } 55726496Sminshall (void) fflush(stdout); 55811651Ssam } 55911219Ssam } 56013213Ssam if (hash && bytes > 0) { 56136940Skarels if (bytes < HASHBYTES) 56236940Skarels (void) putchar('#'); 56326496Sminshall (void) putchar('\n'); 56426496Sminshall (void) fflush(stdout); 56511651Ssam } 56611219Ssam if (c < 0) 56711219Ssam perror(local); 56836942Skarels if (d <= 0) { 56936942Skarels if (d == 0) 57036942Skarels fprintf(stderr, "netout: write returned 0?\n"); 57136942Skarels else if (errno != EPIPE) 57236935Skarels perror("netout"); 57336935Skarels bytes = -1; 57436935Skarels } 57511219Ssam break; 57611219Ssam 57711219Ssam case TYPE_A: 57811219Ssam while ((c = getc(fin)) != EOF) { 57911219Ssam if (c == '\n') { 58011651Ssam while (hash && (bytes >= hashbytes)) { 58126496Sminshall (void) putchar('#'); 58226496Sminshall (void) fflush(stdout); 58336940Skarels hashbytes += HASHBYTES; 58411651Ssam } 58511219Ssam if (ferror(dout)) 58611219Ssam break; 58726496Sminshall (void) putc('\r', dout); 58811219Ssam bytes++; 58911219Ssam } 59026496Sminshall (void) putc(c, dout); 59111219Ssam bytes++; 59226048Sminshall /* if (c == '\r') { */ 59326496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 59426048Sminshall /* bytes++; */ 59526048Sminshall /* } */ 59611219Ssam } 59711651Ssam if (hash) { 59813213Ssam if (bytes < hashbytes) 59926496Sminshall (void) putchar('#'); 60026496Sminshall (void) putchar('\n'); 60126496Sminshall (void) fflush(stdout); 60211651Ssam } 60311219Ssam if (ferror(fin)) 60411219Ssam perror(local); 60536935Skarels if (ferror(dout)) { 60636935Skarels if (errno != EPIPE) 60736935Skarels perror("netout"); 60836935Skarels bytes = -1; 60936935Skarels } 61011219Ssam break; 61110296Ssam } 61226496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 61310296Ssam if (closefunc != NULL) 61426048Sminshall (*closefunc)(fin); 61510296Ssam (void) fclose(dout); 61626048Sminshall (void) getreply(0); 61726048Sminshall (void) signal(SIGINT, oldintr); 61836935Skarels if (oldintp) 61936935Skarels (void) signal(SIGPIPE, oldintp); 62035699Sbostic if (bytes > 0) 62137225Skarels ptransfer("sent", bytes, &start, &stop); 62210296Ssam return; 62326048Sminshall abort: 62426496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 62526048Sminshall (void) signal(SIGINT, oldintr); 62626448Slepreau if (oldintp) 62726048Sminshall (void) signal(SIGPIPE, oldintp); 62826048Sminshall if (!cpend) { 62926048Sminshall code = -1; 63026048Sminshall return; 63126048Sminshall } 63226048Sminshall if (data >= 0) { 63326048Sminshall (void) close(data); 63426048Sminshall data = -1; 63526048Sminshall } 63626448Slepreau if (dout) 63726048Sminshall (void) fclose(dout); 63826048Sminshall (void) getreply(0); 63926048Sminshall code = -1; 64010296Ssam if (closefunc != NULL && fin != NULL) 64126048Sminshall (*closefunc)(fin); 64235699Sbostic if (bytes > 0) 64337225Skarels ptransfer("sent", bytes, &start, &stop); 64410296Ssam } 64510296Ssam 64610296Ssam jmp_buf recvabort; 64710296Ssam 648*38133Srick sig_t 64910296Ssam abortrecv() 65010296Ssam { 65110296Ssam 65226048Sminshall mflag = 0; 65326048Sminshall abrtflag = 0; 654*38133Srick printf("\nreceive aborted\nwaiting for remote to finish abort\n"); 65526048Sminshall (void) fflush(stdout); 65610296Ssam longjmp(recvabort, 1); 65710296Ssam } 65810296Ssam 65937225Skarels recvrequest(cmd, local, remote, mode, printnames) 66011651Ssam char *cmd, *local, *remote, *mode; 66110296Ssam { 66235659Sbostic FILE *fout, *din = 0, *popen(); 663*38133Srick int (*closefunc)(), pclose(), fclose(); 664*38133Srick sig_t (*oldintr)(), (*oldintp)(), abortrecv(); 665*38133Srick int is_retr, tcrflag, bare_lfs = 0; 666*38133Srick char *gunique(); 667*38133Srick static int bufsize; 66836944Skarels static char *buf; 66936940Skarels long bytes = 0, hashbytes = HASHBYTES; 67011346Ssam register int c, d; 67110296Ssam struct timeval start, stop; 67236940Skarels struct stat st; 67336940Skarels extern 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) { 70910296Ssam perror(local); 71026048Sminshall (void) signal(SIGINT, oldintr); 71126048Sminshall code = -1; 71226048Sminshall return; 71310296Ssam } 71426048Sminshall if (dir != NULL) 71526048Sminshall *dir = 0; 71626048Sminshall d = access(dir ? local : ".", 2); 71726048Sminshall if (dir != NULL) 71826048Sminshall *dir = '/'; 71926048Sminshall if (d < 0) { 72026048Sminshall perror(local); 72126048Sminshall (void) signal(SIGINT, oldintr); 72226048Sminshall code = -1; 72326048Sminshall return; 72426048Sminshall } 72526048Sminshall if (!runique && errno == EACCES && 72636935Skarels chmod(local, 0600) < 0) { 72726048Sminshall perror(local); 72826048Sminshall (void) signal(SIGINT, oldintr); 72926048Sminshall code = -1; 73026048Sminshall return; 73126048Sminshall } 73226048Sminshall if (runique && errno == EACCES && 73326048Sminshall (local = gunique(local)) == NULL) { 73426048Sminshall (void) signal(SIGINT, oldintr); 73526048Sminshall code = -1; 73626048Sminshall return; 73726048Sminshall } 73810296Ssam } 73926048Sminshall else if (runique && (local = gunique(local)) == NULL) { 74026048Sminshall (void) signal(SIGINT, oldintr); 74126048Sminshall code = -1; 74226048Sminshall return; 74326048Sminshall } 74426048Sminshall } 74538033Skarels if (!is_retr) { 74638033Skarels if (curtype != TYPE_A) 74738033Skarels changetype(TYPE_A, 0); 74838033Skarels } else if (curtype != type) 74938033Skarels changetype(type, 0); 75026048Sminshall if (initconn()) { 75126048Sminshall (void) signal(SIGINT, oldintr); 75226048Sminshall code = -1; 75326048Sminshall return; 75426048Sminshall } 75526448Slepreau if (setjmp(recvabort)) 75626048Sminshall goto abort; 75738033Skarels if (is_retr && restart_point && 75838033Skarels command("REST %ld", (long) restart_point) != CONTINUE) 75938033Skarels return; 76010296Ssam if (remote) { 76126048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 76226048Sminshall (void) signal(SIGINT, oldintr); 76326048Sminshall return; 76426048Sminshall } 76526048Sminshall } else { 76626048Sminshall if (command("%s", cmd) != PRELIM) { 76726048Sminshall (void) signal(SIGINT, oldintr); 76826048Sminshall return; 76926048Sminshall } 77026048Sminshall } 77126048Sminshall din = dataconn("r"); 77226048Sminshall if (din == NULL) 77326048Sminshall goto abort; 77426448Slepreau if (strcmp(local, "-") == 0) 77510296Ssam fout = stdout; 77610296Ssam else if (*local == '|') { 77726048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 77835659Sbostic fout = popen(local + 1, "w"); 77926048Sminshall if (fout == NULL) { 78026048Sminshall perror(local+1); 78126048Sminshall goto abort; 78226048Sminshall } 78335659Sbostic closefunc = pclose; 78436940Skarels } else { 78511651Ssam fout = fopen(local, mode); 78626048Sminshall if (fout == NULL) { 78726048Sminshall perror(local); 78826048Sminshall goto abort; 78926048Sminshall } 79010296Ssam closefunc = fclose; 79110296Ssam } 79236940Skarels if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 79336940Skarels st.st_blksize = BUFSIZ; 79436940Skarels if (st.st_blksize > bufsize) { 79536940Skarels if (buf) 79636940Skarels (void) free(buf); 797*38133Srick buf = malloc((unsigned)st.st_blksize); 79836940Skarels if (buf == NULL) { 79936940Skarels perror("malloc"); 80036944Skarels bufsize = 0; 80136940Skarels goto abort; 80236940Skarels } 80336940Skarels bufsize = st.st_blksize; 80436940Skarels } 80526496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 80638033Skarels switch (curtype) { 80711219Ssam 80811219Ssam case TYPE_I: 80911219Ssam case TYPE_L: 81037225Skarels if (restart_point && 81137225Skarels lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 81237225Skarels perror(local); 81337225Skarels if (closefunc != NULL) 81437225Skarels (*closefunc)(fout); 81537225Skarels return; 81637225Skarels } 81711346Ssam errno = d = 0; 81836940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) { 81936944Skarels if ((d = write(fileno(fout), buf, c)) != c) 82011219Ssam break; 82111219Ssam bytes += c; 82211651Ssam if (hash) { 82336940Skarels while (bytes >= hashbytes) { 82436940Skarels (void) putchar('#'); 82536940Skarels hashbytes += HASHBYTES; 82636940Skarels } 82726496Sminshall (void) fflush(stdout); 82811651Ssam } 82911219Ssam } 83013213Ssam if (hash && bytes > 0) { 83136940Skarels if (bytes < HASHBYTES) 83236940Skarels (void) putchar('#'); 83326496Sminshall (void) putchar('\n'); 83426496Sminshall (void) fflush(stdout); 83511651Ssam } 83636935Skarels if (c < 0) { 83736935Skarels if (errno != EPIPE) 83836935Skarels perror("netin"); 83936935Skarels bytes = -1; 84036935Skarels } 84136942Skarels if (d < c) { 84236942Skarels if (d < 0) 84336942Skarels perror(local); 84436942Skarels else 84536942Skarels fprintf(stderr, "%s: short write\n", local); 84636942Skarels } 84711219Ssam break; 84811219Ssam 84911219Ssam case TYPE_A: 85037225Skarels if (restart_point) { 85137225Skarels register int i, n, c; 85237225Skarels 85337225Skarels if (fseek(fout, 0L, L_SET) < 0) 85437225Skarels goto done; 85537225Skarels n = restart_point; 85637225Skarels i = 0; 85737225Skarels while (i++ < n) { 85837225Skarels if ((c=getc(fout)) == EOF) 85937225Skarels goto done; 86037225Skarels if (c == '\n') 86137225Skarels i++; 86237225Skarels } 86337225Skarels if (fseek(fout, 0L, L_INCR) < 0) { 86437225Skarels done: 86537225Skarels perror(local); 86637225Skarels if (closefunc != NULL) 86737225Skarels (*closefunc)(fout); 86837225Skarels return; 86937225Skarels } 87037225Skarels } 87111219Ssam while ((c = getc(din)) != EOF) { 872*38133Srick if (c == '\n') 873*38133Srick bare_lfs++; 87427749Sminshall while (c == '\r') { 87511651Ssam while (hash && (bytes >= hashbytes)) { 87626496Sminshall (void) putchar('#'); 87726496Sminshall (void) fflush(stdout); 87836940Skarels hashbytes += HASHBYTES; 87911651Ssam } 88010296Ssam bytes++; 88126048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 88236940Skarels if (ferror(fout)) 88336940Skarels goto break2; 88436940Skarels (void) putc('\r', fout); 88536942Skarels if (c == '\0') { 88636942Skarels bytes++; 88736940Skarels goto contin2; 88836942Skarels } 88936942Skarels if (c == EOF) 89036942Skarels goto contin2; 89111219Ssam } 89211219Ssam } 89336940Skarels (void) putc(c, fout); 89411219Ssam bytes++; 89536940Skarels contin2: ; 89610296Ssam } 89736940Skarels break2: 898*38133Srick if (bare_lfs) { 899*38133Srick printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); 900*38133Srick printf("File may not have transferred correctly.\n"); 901*38133Srick } 90211651Ssam if (hash) { 90313213Ssam if (bytes < hashbytes) 90426496Sminshall (void) putchar('#'); 90526496Sminshall (void) putchar('\n'); 90626496Sminshall (void) fflush(stdout); 90711651Ssam } 90836944Skarels if (ferror(din)) { 90936935Skarels if (errno != EPIPE) 91036944Skarels perror("netin"); 91136935Skarels bytes = -1; 91236935Skarels } 91336940Skarels if (ferror(fout)) 91436944Skarels perror(local); 91511219Ssam break; 91610296Ssam } 91726448Slepreau if (closefunc != NULL) 91826048Sminshall (*closefunc)(fout); 91926496Sminshall (void) signal(SIGINT, oldintr); 92026448Slepreau if (oldintp) 92126048Sminshall (void) signal(SIGPIPE, oldintp); 92226496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 92310296Ssam (void) fclose(din); 92426048Sminshall (void) getreply(0); 92536935Skarels if (bytes > 0 && is_retr) 92637225Skarels ptransfer("received", bytes, &start, &stop); 92726048Sminshall return; 92826048Sminshall abort: 92926048Sminshall 93027687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 93126048Sminshall 93226496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 93326448Slepreau if (oldintp) 93426048Sminshall (void) signal(SIGPIPE, oldintr); 935*38133Srick (void) signal(SIGINT, SIG_IGN); 93626048Sminshall if (!cpend) { 93726048Sminshall code = -1; 938*38133Srick (void) signal(SIGINT, oldintr); 93926048Sminshall return; 94026048Sminshall } 94126048Sminshall 942*38133Srick abort_remote(din); 94326048Sminshall code = -1; 94426048Sminshall if (data >= 0) { 94526048Sminshall (void) close(data); 94626048Sminshall data = -1; 94726048Sminshall } 94826448Slepreau if (closefunc != NULL && fout != NULL) 94926048Sminshall (*closefunc)(fout); 95026448Slepreau if (din) 95126048Sminshall (void) fclose(din); 95235699Sbostic if (bytes > 0) 95337225Skarels ptransfer("received", bytes, &start, &stop); 954*38133Srick (void) signal(SIGINT, oldintr); 95510296Ssam } 95610296Ssam 95710296Ssam /* 95810296Ssam * Need to start a listen on the data channel 95910296Ssam * before we send the command, otherwise the 96010296Ssam * server's connect may fail. 96110296Ssam */ 962*38133Srick int sendport; 96311651Ssam 96410296Ssam initconn() 96510296Ssam { 96610296Ssam register char *p, *a; 96726048Sminshall int result, len, tmpno = 0; 96826993Skarels int on = 1; 96910296Ssam 97011651Ssam noport: 97110296Ssam data_addr = myctladdr; 97211651Ssam if (sendport) 97311651Ssam data_addr.sin_port = 0; /* let system pick one */ 97411651Ssam if (data != -1) 975*38133Srick (void) close(data); 97618287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 97710296Ssam if (data < 0) { 97810296Ssam perror("ftp: socket"); 97926448Slepreau if (tmpno) 98026048Sminshall sendport = 1; 98110296Ssam return (1); 98210296Ssam } 98312397Ssam if (!sendport) 98427687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 98533224Sbostic perror("ftp: setsockopt (reuse address)"); 98612397Ssam goto bad; 98712397Ssam } 98826496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 98910296Ssam perror("ftp: bind"); 99010296Ssam goto bad; 99110296Ssam } 99210296Ssam if (options & SO_DEBUG && 99327687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 99410296Ssam perror("ftp: setsockopt (ignored)"); 99511627Ssam len = sizeof (data_addr); 996*38133Srick if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 99711627Ssam perror("ftp: getsockname"); 99810296Ssam goto bad; 99910296Ssam } 100026448Slepreau if (listen(data, 1) < 0) 100110296Ssam perror("ftp: listen"); 100211651Ssam if (sendport) { 100311651Ssam a = (char *)&data_addr.sin_addr; 100411651Ssam p = (char *)&data_addr.sin_port; 100510296Ssam #define UC(b) (((int)b)&0xff) 100611651Ssam result = 100711651Ssam command("PORT %d,%d,%d,%d,%d,%d", 100811651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 100911651Ssam UC(p[0]), UC(p[1])); 101011651Ssam if (result == ERROR && sendport == -1) { 101111651Ssam sendport = 0; 101226048Sminshall tmpno = 1; 101311651Ssam goto noport; 101411651Ssam } 101511651Ssam return (result != COMPLETE); 101611651Ssam } 101726448Slepreau if (tmpno) 101826048Sminshall sendport = 1; 101911651Ssam return (0); 102010296Ssam bad: 102110296Ssam (void) close(data), data = -1; 102226448Slepreau if (tmpno) 102326048Sminshall sendport = 1; 102410296Ssam return (1); 102510296Ssam } 102610296Ssam 102710296Ssam FILE * 102810296Ssam dataconn(mode) 102910296Ssam char *mode; 103010296Ssam { 103110296Ssam struct sockaddr_in from; 103210296Ssam int s, fromlen = sizeof (from); 103310296Ssam 103426496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 103510296Ssam if (s < 0) { 103610296Ssam perror("ftp: accept"); 103710296Ssam (void) close(data), data = -1; 103810296Ssam return (NULL); 103910296Ssam } 104010296Ssam (void) close(data); 104110296Ssam data = s; 104210296Ssam return (fdopen(data, mode)); 104310296Ssam } 104410296Ssam 104537225Skarels ptransfer(direction, bytes, t0, t1) 104637225Skarels char *direction; 104711651Ssam long bytes; 104810296Ssam struct timeval *t0, *t1; 104910296Ssam { 105010296Ssam struct timeval td; 105116437Sleres float s, bs; 105210296Ssam 105335699Sbostic if (verbose) { 105435699Sbostic tvsub(&td, t1, t0); 105535699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 105610296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 105735699Sbostic bs = bytes / nz(s); 105835699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 105935699Sbostic bytes, direction, s, bs / 1024.); 106035699Sbostic } 106110296Ssam } 106210296Ssam 106326496Sminshall /*tvadd(tsum, t0) 106410296Ssam struct timeval *tsum, *t0; 106510296Ssam { 106610296Ssam 106710296Ssam tsum->tv_sec += t0->tv_sec; 106810296Ssam tsum->tv_usec += t0->tv_usec; 106910296Ssam if (tsum->tv_usec > 1000000) 107010296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 107126496Sminshall } */ 107210296Ssam 107310296Ssam tvsub(tdiff, t1, t0) 107410296Ssam struct timeval *tdiff, *t1, *t0; 107510296Ssam { 107610296Ssam 107710296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 107810296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 107910296Ssam if (tdiff->tv_usec < 0) 108010296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 108110296Ssam } 108226048Sminshall 1083*38133Srick sig_t 108426048Sminshall psabort() 108526048Sminshall { 108626048Sminshall extern int abrtflag; 108726048Sminshall 108826048Sminshall abrtflag++; 108926048Sminshall } 109026048Sminshall 109126048Sminshall pswitch(flag) 109226048Sminshall int flag; 109326048Sminshall { 109426048Sminshall extern int proxy, abrtflag; 1095*38133Srick sig_t (*oldintr)(); 109626048Sminshall static struct comvars { 109726048Sminshall int connect; 109828469Skarels char name[MAXHOSTNAMELEN]; 109926048Sminshall struct sockaddr_in mctl; 110026048Sminshall struct sockaddr_in hctl; 110126048Sminshall FILE *in; 110226048Sminshall FILE *out; 110326048Sminshall int tpe; 110438033Skarels int curtpe; 110526048Sminshall int cpnd; 110626048Sminshall int sunqe; 110726048Sminshall int runqe; 110826048Sminshall int mcse; 110926048Sminshall int ntflg; 111026048Sminshall char nti[17]; 111126048Sminshall char nto[17]; 111226048Sminshall int mapflg; 111326048Sminshall char mi[MAXPATHLEN]; 111426048Sminshall char mo[MAXPATHLEN]; 111538033Skarels } proxstruct, tmpstruct; 111626048Sminshall struct comvars *ip, *op; 111726048Sminshall 111826048Sminshall abrtflag = 0; 111926048Sminshall oldintr = signal(SIGINT, psabort); 112026048Sminshall if (flag) { 112126448Slepreau if (proxy) 112226048Sminshall return; 112326048Sminshall ip = &tmpstruct; 112426048Sminshall op = &proxstruct; 112526048Sminshall proxy++; 112638033Skarels } else { 112726448Slepreau if (!proxy) 112826048Sminshall return; 112926048Sminshall ip = &proxstruct; 113026048Sminshall op = &tmpstruct; 113126048Sminshall proxy = 0; 113226048Sminshall } 113326048Sminshall ip->connect = connected; 113426048Sminshall connected = op->connect; 113528469Skarels if (hostname) { 113628469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 113728469Skarels ip->name[strlen(ip->name)] = '\0'; 113828469Skarels } else 113928469Skarels ip->name[0] = 0; 114026048Sminshall hostname = op->name; 114126048Sminshall ip->hctl = hisctladdr; 114226048Sminshall hisctladdr = op->hctl; 114326048Sminshall ip->mctl = myctladdr; 114426048Sminshall myctladdr = op->mctl; 114526048Sminshall ip->in = cin; 114626048Sminshall cin = op->in; 114726048Sminshall ip->out = cout; 114826048Sminshall cout = op->out; 114926048Sminshall ip->tpe = type; 115026048Sminshall type = op->tpe; 115138033Skarels ip->curtpe = curtype; 115238033Skarels curtype = op->curtpe; 115326048Sminshall ip->cpnd = cpend; 115426048Sminshall cpend = op->cpnd; 115526048Sminshall ip->sunqe = sunique; 115626048Sminshall sunique = op->sunqe; 115726048Sminshall ip->runqe = runique; 115826048Sminshall runique = op->runqe; 115926048Sminshall ip->mcse = mcase; 116026048Sminshall mcase = op->mcse; 116126048Sminshall ip->ntflg = ntflag; 116226048Sminshall ntflag = op->ntflg; 116326496Sminshall (void) strncpy(ip->nti, ntin, 16); 116426048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 116526496Sminshall (void) strcpy(ntin, op->nti); 116626496Sminshall (void) strncpy(ip->nto, ntout, 16); 116726048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 116826496Sminshall (void) strcpy(ntout, op->nto); 116926048Sminshall ip->mapflg = mapflag; 117026048Sminshall mapflag = op->mapflg; 117126496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 117226048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 117326496Sminshall (void) strcpy(mapin, op->mi); 117426496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 117526048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 117626496Sminshall (void) strcpy(mapout, op->mo); 117726048Sminshall (void) signal(SIGINT, oldintr); 117826048Sminshall if (abrtflag) { 117926048Sminshall abrtflag = 0; 118026048Sminshall (*oldintr)(); 118126448Slepreau } 118226048Sminshall } 118326048Sminshall 118426048Sminshall jmp_buf ptabort; 118526048Sminshall int ptabflg; 118626048Sminshall 1187*38133Srick sig_t 118826048Sminshall abortpt() 118926048Sminshall { 119026048Sminshall printf("\n"); 119126496Sminshall (void) fflush(stdout); 119226048Sminshall ptabflg++; 119326048Sminshall mflag = 0; 119426048Sminshall abrtflag = 0; 119526048Sminshall longjmp(ptabort, 1); 119626048Sminshall } 119726048Sminshall 119826048Sminshall proxtrans(cmd, local, remote) 119926048Sminshall char *cmd, *local, *remote; 120026048Sminshall { 1201*38133Srick sig_t (*oldintr)(), abortpt(); 1202*38133Srick int secndflag = 0, prox_type, nfnd; 120326048Sminshall extern jmp_buf ptabort; 120426048Sminshall char *cmd2; 120526496Sminshall struct fd_set mask; 120626048Sminshall 120726448Slepreau if (strcmp(cmd, "RETR")) 120826048Sminshall cmd2 = "RETR"; 120926448Slepreau else 121026048Sminshall cmd2 = runique ? "STOU" : "STOR"; 121138033Skarels if ((prox_type = type) == 0) { 121238033Skarels if (unix_server && unix_proxy) 121338033Skarels prox_type = TYPE_I; 121438033Skarels else 121538033Skarels prox_type = TYPE_A; 121638033Skarels } 121738033Skarels if (curtype != prox_type) 121838033Skarels changetype(prox_type, 1); 121926048Sminshall if (command("PASV") != COMPLETE) { 122038033Skarels printf("proxy server does not support third party transfers.\n"); 122126048Sminshall return; 122226048Sminshall } 122326048Sminshall pswitch(0); 122426048Sminshall if (!connected) { 122526048Sminshall printf("No primary connection\n"); 122626048Sminshall pswitch(1); 122726048Sminshall code = -1; 122826048Sminshall return; 122926048Sminshall } 123038033Skarels if (curtype != prox_type) 123138033Skarels changetype(prox_type, 1); 123226048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 123326048Sminshall pswitch(1); 123426048Sminshall return; 123526048Sminshall } 123626448Slepreau if (setjmp(ptabort)) 123726048Sminshall goto abort; 123826048Sminshall oldintr = signal(SIGINT, abortpt); 123926048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 124026048Sminshall (void) signal(SIGINT, oldintr); 124126048Sminshall pswitch(1); 124226048Sminshall return; 124326048Sminshall } 124426048Sminshall sleep(2); 124526048Sminshall pswitch(1); 124626048Sminshall secndflag++; 124726448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 124826048Sminshall goto abort; 124926048Sminshall ptflag++; 125026048Sminshall (void) getreply(0); 125126048Sminshall pswitch(0); 125226048Sminshall (void) getreply(0); 125326048Sminshall (void) signal(SIGINT, oldintr); 125426048Sminshall pswitch(1); 125526048Sminshall ptflag = 0; 125626048Sminshall printf("local: %s remote: %s\n", local, remote); 125726048Sminshall return; 125826048Sminshall abort: 125926048Sminshall (void) signal(SIGINT, SIG_IGN); 126026048Sminshall ptflag = 0; 126126448Slepreau if (strcmp(cmd, "RETR") && !proxy) 126226048Sminshall pswitch(1); 126326448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 126426048Sminshall pswitch(0); 126526048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 126626048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 126726048Sminshall pswitch(0); 1268*38133Srick if (cpend) 1269*38133Srick abort_remote((FILE *) NULL); 127026048Sminshall } 127126048Sminshall pswitch(1); 127226448Slepreau if (ptabflg) 127326048Sminshall code = -1; 127426048Sminshall (void) signal(SIGINT, oldintr); 127526048Sminshall return; 127626048Sminshall } 1277*38133Srick if (cpend) 1278*38133Srick abort_remote((FILE *) NULL); 127926048Sminshall pswitch(!proxy); 128026048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 128126048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 128226048Sminshall pswitch(0); 1283*38133Srick if (cpend) 1284*38133Srick abort_remote((FILE *) NULL); 128526048Sminshall pswitch(1); 128626448Slepreau if (ptabflg) 128726048Sminshall code = -1; 128826048Sminshall (void) signal(SIGINT, oldintr); 128926048Sminshall return; 129026048Sminshall } 129126048Sminshall } 1292*38133Srick if (cpend) 1293*38133Srick abort_remote((FILE *) NULL); 129426048Sminshall pswitch(!proxy); 129526048Sminshall if (cpend) { 129627687Sminshall FD_ZERO(&mask); 129726496Sminshall FD_SET(fileno(cin), &mask); 1298*38133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 129927687Sminshall if (nfnd < 0) { 130027687Sminshall perror("abort"); 130127687Sminshall } 130226448Slepreau if (ptabflg) 130326048Sminshall code = -1; 130426048Sminshall lostpeer(); 130526048Sminshall } 130626048Sminshall (void) getreply(0); 130726048Sminshall (void) getreply(0); 130826048Sminshall } 130926448Slepreau if (proxy) 131026048Sminshall pswitch(0); 131126048Sminshall pswitch(1); 131226448Slepreau if (ptabflg) 131326048Sminshall code = -1; 131426048Sminshall (void) signal(SIGINT, oldintr); 131526048Sminshall } 131626048Sminshall 131726048Sminshall reset() 131826048Sminshall { 131926496Sminshall struct fd_set mask; 132026496Sminshall int nfnd = 1; 132126048Sminshall 132227687Sminshall FD_ZERO(&mask); 132330946Scsvsj while (nfnd > 0) { 132426496Sminshall FD_SET(fileno(cin), &mask); 132527687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 132626048Sminshall perror("reset"); 132726048Sminshall code = -1; 132826048Sminshall lostpeer(); 132926048Sminshall } 133027687Sminshall else if (nfnd) { 133126048Sminshall (void) getreply(0); 133226496Sminshall } 133326048Sminshall } 133426048Sminshall } 133526048Sminshall 133626048Sminshall char * 133726048Sminshall gunique(local) 133826048Sminshall char *local; 133926048Sminshall { 134026048Sminshall static char new[MAXPATHLEN]; 134126048Sminshall char *cp = rindex(local, '/'); 134226048Sminshall int d, count=0; 134326048Sminshall char ext = '1'; 134426048Sminshall 134526448Slepreau if (cp) 134626048Sminshall *cp = '\0'; 134726048Sminshall d = access(cp ? local : ".", 2); 134826448Slepreau if (cp) 134926048Sminshall *cp = '/'; 135026048Sminshall if (d < 0) { 135126048Sminshall perror(local); 135226048Sminshall return((char *) 0); 135326048Sminshall } 135426048Sminshall (void) strcpy(new, local); 135526048Sminshall cp = new + strlen(new); 135626048Sminshall *cp++ = '.'; 135726048Sminshall while (!d) { 135826048Sminshall if (++count == 100) { 135926048Sminshall printf("runique: can't find unique file name.\n"); 136026048Sminshall return((char *) 0); 136126048Sminshall } 136226048Sminshall *cp++ = ext; 136326048Sminshall *cp = '\0'; 136426448Slepreau if (ext == '9') 136526048Sminshall ext = '0'; 136626448Slepreau else 136726048Sminshall ext++; 136826448Slepreau if ((d = access(new, 0)) < 0) 136926048Sminshall break; 137026448Slepreau if (ext != '0') 137126048Sminshall cp--; 137226448Slepreau else if (*(cp - 2) == '.') 137326048Sminshall *(cp - 1) = '1'; 137426048Sminshall else { 137526048Sminshall *(cp - 2) = *(cp - 2) + 1; 137626048Sminshall cp--; 137726048Sminshall } 137826048Sminshall } 137926048Sminshall return(new); 138026048Sminshall } 1381*38133Srick 1382*38133Srick abort_remote(din) 1383*38133Srick FILE *din; 1384*38133Srick { 1385*38133Srick char buf[BUFSIZ]; 1386*38133Srick int nfnd; 1387*38133Srick struct fd_set mask; 1388*38133Srick 1389*38133Srick /* 1390*38133Srick * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 1391*38133Srick * after urgent byte rather than before as is protocol now 1392*38133Srick */ 1393*38133Srick sprintf(buf, "%c%c%c", IAC, IP, IAC); 1394*38133Srick if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 1395*38133Srick perror("abort"); 1396*38133Srick fprintf(cout,"%cABOR\r\n", DM); 1397*38133Srick (void) fflush(cout); 1398*38133Srick FD_ZERO(&mask); 1399*38133Srick FD_SET(fileno(cin), &mask); 1400*38133Srick if (din) { 1401*38133Srick FD_SET(fileno(din), &mask); 1402*38133Srick } 1403*38133Srick if ((nfnd = empty(&mask, 10)) <= 0) { 1404*38133Srick if (nfnd < 0) { 1405*38133Srick perror("abort"); 1406*38133Srick } 1407*38133Srick if (ptabflg) 1408*38133Srick code = -1; 1409*38133Srick lostpeer(); 1410*38133Srick } 1411*38133Srick if (din && FD_ISSET(fileno(din), &mask)) { 1412*38133Srick while (read(fileno(din), buf, BUFSIZ) > 0) 1413*38133Srick /* LOOP */; 1414*38133Srick } 1415*38133Srick if (getreply(0) == ERROR && code == 552) { 1416*38133Srick /* 552 needed for nic style abort */ 1417*38133Srick (void) getreply(0); 1418*38133Srick } 1419*38133Srick (void) getreply(0); 1420*38133Srick } 1421