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*38033Skarels static char sccsid[] = "@(#)ftp.c 5.29 (Berkeley) 05/17/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> 3910296Ssam 4036940Skarels #include "ftp_var.h" 4136940Skarels 4210296Ssam struct sockaddr_in hisctladdr; 4310296Ssam struct sockaddr_in data_addr; 4410296Ssam int data = -1; 4526048Sminshall int abrtflag = 0; 4626048Sminshall int ptflag = 0; 4710296Ssam int connected; 4810296Ssam struct sockaddr_in myctladdr; 4926496Sminshall uid_t getuid(); 5037225Skarels off_t restart_point = 0; 5110296Ssam 5210296Ssam FILE *cin, *cout; 5310296Ssam FILE *dataconn(); 5410296Ssam 5525904Skarels char * 5610296Ssam hookup(host, port) 5710296Ssam char *host; 5810296Ssam int port; 5910296Ssam { 6025904Skarels register struct hostent *hp = 0; 6127687Sminshall int s,len; 6225904Skarels static char hostnamebuf[80]; 6310296Ssam 6410296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 6525904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 6625904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 6725904Skarels hisctladdr.sin_family = AF_INET; 6836940Skarels (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); 6936940Skarels } else { 7025100Sbloom hp = gethostbyname(host); 7125904Skarels if (hp == NULL) { 7235792Sbostic fprintf(stderr, "ftp: %s: ", host); 7335792Sbostic herror((char *)NULL); 7426048Sminshall code = -1; 7526048Sminshall return((char *) 0); 7625904Skarels } 7725904Skarels hisctladdr.sin_family = hp->h_addrtype; 7825904Skarels bcopy(hp->h_addr_list[0], 7925904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 8036940Skarels (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); 8110296Ssam } 8225904Skarels hostname = hostnamebuf; 8325904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 8410296Ssam if (s < 0) { 8510296Ssam perror("ftp: socket"); 8626048Sminshall code = -1; 8710296Ssam return (0); 8810296Ssam } 8910296Ssam hisctladdr.sin_port = port; 9026496Sminshall while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 9125904Skarels if (hp && hp->h_addr_list[1]) { 9225904Skarels int oerrno = errno; 9325904Skarels 9425904Skarels fprintf(stderr, "ftp: connect to address %s: ", 9525904Skarels inet_ntoa(hisctladdr.sin_addr)); 9625904Skarels errno = oerrno; 9726496Sminshall perror((char *) 0); 9825904Skarels hp->h_addr_list++; 9925904Skarels bcopy(hp->h_addr_list[0], 10026048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 10126496Sminshall fprintf(stdout, "Trying %s...\n", 10225904Skarels inet_ntoa(hisctladdr.sin_addr)); 10326813Skarels (void) close(s); 10426813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 10526813Skarels if (s < 0) { 10626813Skarels perror("ftp: socket"); 10726813Skarels code = -1; 10826813Skarels return (0); 10926813Skarels } 11025904Skarels continue; 11125904Skarels } 11210296Ssam perror("ftp: connect"); 11326048Sminshall code = -1; 11410296Ssam goto bad; 11510296Ssam } 11611627Ssam len = sizeof (myctladdr); 11711627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 11811627Ssam perror("ftp: getsockname"); 11926048Sminshall code = -1; 12010296Ssam goto bad; 12110296Ssam } 12210296Ssam cin = fdopen(s, "r"); 12310296Ssam cout = fdopen(s, "w"); 12411219Ssam if (cin == NULL || cout == NULL) { 12510296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 12610296Ssam if (cin) 12726496Sminshall (void) fclose(cin); 12810296Ssam if (cout) 12926496Sminshall (void) fclose(cout); 13026048Sminshall code = -1; 13110296Ssam goto bad; 13210296Ssam } 13310296Ssam if (verbose) 13426067Sminshall printf("Connected to %s.\n", hostname); 13527687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 13626048Sminshall if (cin) 13726496Sminshall (void) fclose(cin); 13826048Sminshall if (cout) 13926496Sminshall (void) fclose(cout); 14026048Sminshall code = -1; 14126048Sminshall goto bad; 14226048Sminshall } 14327687Sminshall #ifdef SO_OOBINLINE 14427687Sminshall { 14527687Sminshall int on = 1; 14626048Sminshall 14727687Sminshall if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 14827687Sminshall < 0 && debug) { 14927687Sminshall perror("ftp: setsockopt"); 15027687Sminshall } 15127687Sminshall } 15227687Sminshall #endif SO_OOBINLINE 15326048Sminshall 15425904Skarels return (hostname); 15510296Ssam bad: 15626496Sminshall (void) close(s); 15725904Skarels return ((char *)0); 15810296Ssam } 15910296Ssam 16025904Skarels login(host) 16125904Skarels char *host; 16210296Ssam { 16326048Sminshall char tmp[80]; 16435659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 16526048Sminshall int n, aflag = 0; 16610296Ssam 16726048Sminshall user = pass = acct = 0; 16826048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 16926048Sminshall code = -1; 17026048Sminshall return(0); 17126048Sminshall } 17237458Skarels while (user == NULL) { 17326048Sminshall char *myname = getlogin(); 17426048Sminshall 17526048Sminshall if (myname == NULL) { 17626048Sminshall struct passwd *pp = getpwuid(getuid()); 17726048Sminshall 17826448Slepreau if (pp != NULL) 17926048Sminshall myname = pp->pw_name; 18026048Sminshall } 18137458Skarels if (myname) 18237458Skarels printf("Name (%s:%s): ", host, myname); 18337458Skarels else 18437458Skarels printf("Name (%s): ", host); 18526048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 18626048Sminshall tmp[strlen(tmp) - 1] = '\0'; 18726448Slepreau if (*tmp == '\0') 18826048Sminshall user = myname; 18926448Slepreau else 19026048Sminshall user = tmp; 19126048Sminshall } 19210296Ssam n = command("USER %s", user); 19326048Sminshall if (n == CONTINUE) { 19426448Slepreau if (pass == NULL) 19535659Sbostic pass = getpass("Password:"); 19610296Ssam n = command("PASS %s", pass); 19726048Sminshall } 19810296Ssam if (n == CONTINUE) { 19926048Sminshall aflag++; 20035659Sbostic acct = getpass("Account:"); 20110296Ssam n = command("ACCT %s", acct); 20210296Ssam } 20310296Ssam if (n != COMPLETE) { 20410296Ssam fprintf(stderr, "Login failed.\n"); 20510296Ssam return (0); 20610296Ssam } 20726448Slepreau if (!aflag && acct != NULL) 20826048Sminshall (void) command("ACCT %s", acct); 20926448Slepreau if (proxy) 21026048Sminshall return(1); 21126048Sminshall for (n = 0; n < macnum; ++n) { 21226048Sminshall if (!strcmp("init", macros[n].mac_name)) { 21326496Sminshall (void) strcpy(line, "$init"); 21426048Sminshall makeargv(); 21526048Sminshall domacro(margc, margv); 21626048Sminshall break; 21726048Sminshall } 21826048Sminshall } 21910296Ssam return (1); 22010296Ssam } 22110296Ssam 22226048Sminshall cmdabort() 22326048Sminshall { 22426048Sminshall extern jmp_buf ptabort; 22526048Sminshall 22626048Sminshall printf("\n"); 22726048Sminshall (void) fflush(stdout); 22826048Sminshall abrtflag++; 22926448Slepreau if (ptflag) 23026048Sminshall longjmp(ptabort,1); 23126048Sminshall } 23226048Sminshall 23326496Sminshall /*VARARGS1*/ 23410296Ssam command(fmt, args) 23510296Ssam char *fmt; 23610296Ssam { 23726048Sminshall int r, (*oldintr)(), cmdabort(); 238*38033Skarels char *xxx = "XXX"; 23910296Ssam 24026048Sminshall abrtflag = 0; 24110296Ssam if (debug) { 24210296Ssam printf("---> "); 243*38033Skarels if (strncmp(fmt, "PASS", 4) == 0) 244*38033Skarels _doprnt(fmt, (int *)&xxx, stdout); 245*38033Skarels else 246*38033Skarels _doprnt(fmt, &args, stdout); 24710296Ssam printf("\n"); 24810296Ssam (void) fflush(stdout); 24910296Ssam } 25011219Ssam if (cout == NULL) { 25111219Ssam perror ("No control connection for command"); 25226048Sminshall code = -1; 25311219Ssam return (0); 25411219Ssam } 25526048Sminshall oldintr = signal(SIGINT,cmdabort); 25610296Ssam _doprnt(fmt, &args, cout); 25710296Ssam fprintf(cout, "\r\n"); 25810296Ssam (void) fflush(cout); 25926048Sminshall cpend = 1; 26026048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 26126448Slepreau if (abrtflag && oldintr != SIG_IGN) 26226048Sminshall (*oldintr)(); 26326048Sminshall (void) signal(SIGINT, oldintr); 26426048Sminshall return(r); 26510296Ssam } 26610296Ssam 26737229Skarels char reply_string[BUFSIZ]; /* last line of previous reply */ 26836935Skarels 26910296Ssam #include <ctype.h> 27010296Ssam 27110296Ssam getreply(expecteof) 27210296Ssam int expecteof; 27310296Ssam { 27411219Ssam register int c, n; 27526048Sminshall register int dig; 27636935Skarels register char *cp; 27726048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 27826048Sminshall int pflag = 0; 27926048Sminshall char *pt = pasv; 28010296Ssam 28126048Sminshall oldintr = signal(SIGINT,cmdabort); 28210296Ssam for (;;) { 28310296Ssam dig = n = code = 0; 28437229Skarels cp = reply_string; 28510296Ssam while ((c = getc(cin)) != '\n') { 28627687Sminshall if (c == IAC) { /* handle telnet commands */ 28727687Sminshall switch (c = getc(cin)) { 28827687Sminshall case WILL: 28927687Sminshall case WONT: 29027687Sminshall c = getc(cin); 29136940Skarels fprintf(cout, "%c%c%c",IAC,DONT,c); 29227687Sminshall (void) fflush(cout); 29327687Sminshall break; 29427687Sminshall case DO: 29527687Sminshall case DONT: 29627687Sminshall c = getc(cin); 29736940Skarels fprintf(cout, "%c%c%c",IAC,WONT,c); 29827687Sminshall (void) fflush(cout); 29927687Sminshall break; 30027687Sminshall default: 30127687Sminshall break; 30227687Sminshall } 30327687Sminshall continue; 30427687Sminshall } 30510296Ssam dig++; 30610296Ssam if (c == EOF) { 30726048Sminshall if (expecteof) { 30826048Sminshall (void) signal(SIGINT,oldintr); 30926048Sminshall code = 221; 31010296Ssam return (0); 31126048Sminshall } 31210296Ssam lostpeer(); 31326048Sminshall if (verbose) { 31426048Sminshall printf("421 Service not available, remote server has closed connection\n"); 31526048Sminshall (void) fflush(stdout); 31626048Sminshall } 31733772Scsvsj code = 421; 31833772Scsvsj return(4); 31910296Ssam } 32026048Sminshall if (c != '\r' && (verbose > 0 || 32126048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 32226448Slepreau if (proxflag && 32326448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 32426048Sminshall printf("%s:",hostname); 32526496Sminshall (void) putchar(c); 32626048Sminshall } 32710296Ssam if (dig < 4 && isdigit(c)) 32810296Ssam code = code * 10 + (c - '0'); 32926448Slepreau if (!pflag && code == 227) 33026048Sminshall pflag = 1; 33126448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 33226048Sminshall pflag = 2; 33326048Sminshall if (pflag == 2) { 33426448Slepreau if (c != '\r' && c != ')') 33526048Sminshall *pt++ = c; 33626048Sminshall else { 33726048Sminshall *pt = '\0'; 33826048Sminshall pflag = 3; 33926048Sminshall } 34026048Sminshall } 34126048Sminshall if (dig == 4 && c == '-') { 34226448Slepreau if (continuation) 34326048Sminshall code = 0; 34410296Ssam continuation++; 34526048Sminshall } 34610296Ssam if (n == 0) 34710296Ssam n = c; 34837229Skarels if (cp < &reply_string[sizeof(reply_string) - 1]) 34937229Skarels *cp++ = c; 35010296Ssam } 35126048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 35226496Sminshall (void) putchar(c); 35311346Ssam (void) fflush (stdout); 35411346Ssam } 35510296Ssam if (continuation && code != originalcode) { 35610296Ssam if (originalcode == 0) 35710296Ssam originalcode = code; 35810296Ssam continue; 35910296Ssam } 36036935Skarels *cp = '\0'; 36126448Slepreau if (n != '1') 36226048Sminshall cpend = 0; 36326048Sminshall (void) signal(SIGINT,oldintr); 36426448Slepreau if (code == 421 || originalcode == 421) 36526048Sminshall lostpeer(); 36626448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 36726048Sminshall (*oldintr)(); 36825907Smckusick return (n - '0'); 36910296Ssam } 37010296Ssam } 37110296Ssam 37226048Sminshall empty(mask, sec) 37327687Sminshall struct fd_set *mask; 37426048Sminshall int sec; 37526048Sminshall { 37626048Sminshall struct timeval t; 37726048Sminshall 37826048Sminshall t.tv_sec = (long) sec; 37926048Sminshall t.tv_usec = 0; 38027687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 38126048Sminshall } 38226048Sminshall 38310296Ssam jmp_buf sendabort; 38410296Ssam 38510296Ssam abortsend() 38610296Ssam { 38710296Ssam 38826048Sminshall mflag = 0; 38926048Sminshall abrtflag = 0; 39026048Sminshall printf("\nsend aborted\n"); 39126048Sminshall (void) fflush(stdout); 39210296Ssam longjmp(sendabort, 1); 39310296Ssam } 39410296Ssam 39536940Skarels #define HASHBYTES 1024 39636940Skarels 39737225Skarels sendrequest(cmd, local, remote, printnames) 39810296Ssam char *cmd, *local, *remote; 39937225Skarels int printnames; 40010296Ssam { 40135659Sbostic FILE *fin, *dout = 0, *popen(); 40235659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 40326048Sminshall int abortsend(); 40436942Skarels char buf[BUFSIZ], *bufp; 40536940Skarels long bytes = 0, hashbytes = HASHBYTES; 40611346Ssam register int c, d; 40710296Ssam struct stat st; 40810296Ssam struct timeval start, stop; 40936935Skarels char *mode; 41010296Ssam 41137225Skarels if (verbose && printnames) { 41237225Skarels if (local && *local != '-') 41337225Skarels printf("local: %s ", local); 41437225Skarels if (remote) 41537225Skarels printf("remote: %s\n", remote); 41637225Skarels } 41726048Sminshall if (proxy) { 41826048Sminshall proxtrans(cmd, local, remote); 41926048Sminshall return; 42026048Sminshall } 421*38033Skarels if (curtype != type) 422*38033Skarels changetype(type, 0); 42310296Ssam closefunc = NULL; 42426048Sminshall oldintr = NULL; 42526048Sminshall oldintp = NULL; 42636935Skarels mode = "w"; 42726048Sminshall if (setjmp(sendabort)) { 42826048Sminshall while (cpend) { 42926048Sminshall (void) getreply(0); 43026048Sminshall } 43126048Sminshall if (data >= 0) { 43226048Sminshall (void) close(data); 43326048Sminshall data = -1; 43426048Sminshall } 43526448Slepreau if (oldintr) 43626048Sminshall (void) signal(SIGINT,oldintr); 43726448Slepreau if (oldintp) 43826048Sminshall (void) signal(SIGPIPE,oldintp); 43926048Sminshall code = -1; 44026048Sminshall return; 44126048Sminshall } 44210296Ssam oldintr = signal(SIGINT, abortsend); 44310296Ssam if (strcmp(local, "-") == 0) 44410296Ssam fin = stdin; 44510296Ssam else if (*local == '|') { 44626048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 44735659Sbostic fin = popen(local + 1, "r"); 44810296Ssam if (fin == NULL) { 44926048Sminshall perror(local + 1); 45026048Sminshall (void) signal(SIGINT, oldintr); 45126048Sminshall (void) signal(SIGPIPE, oldintp); 45226048Sminshall code = -1; 45326048Sminshall return; 45410296Ssam } 45535659Sbostic closefunc = pclose; 45610296Ssam } else { 45710296Ssam fin = fopen(local, "r"); 45810296Ssam if (fin == NULL) { 45910296Ssam perror(local); 46026048Sminshall (void) signal(SIGINT, oldintr); 46126048Sminshall code = -1; 46226048Sminshall return; 46310296Ssam } 46410296Ssam closefunc = fclose; 46510296Ssam if (fstat(fileno(fin), &st) < 0 || 46610296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 46726496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 46826048Sminshall (void) signal(SIGINT, oldintr); 46936935Skarels fclose(fin); 47026048Sminshall code = -1; 47126048Sminshall return; 47210296Ssam } 47310296Ssam } 47426048Sminshall if (initconn()) { 47526048Sminshall (void) signal(SIGINT, oldintr); 47626448Slepreau if (oldintp) 47726048Sminshall (void) signal(SIGPIPE, oldintp); 47826048Sminshall code = -1; 47936935Skarels if (closefunc != NULL) 48036935Skarels (*closefunc)(fin); 48126048Sminshall return; 48226048Sminshall } 48326448Slepreau if (setjmp(sendabort)) 48426048Sminshall goto abort; 48536935Skarels 48637225Skarels if (restart_point && 48737225Skarels (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 48837225Skarels if (fseek(fin, (long) restart_point, 0) < 0) { 48937225Skarels perror(local); 49037225Skarels restart_point = 0; 49137225Skarels if (closefunc != NULL) 49237225Skarels (*closefunc)(fin); 49337225Skarels return; 49437225Skarels } 49537225Skarels if (command("REST %ld", (long) restart_point) 49637225Skarels != CONTINUE) { 49737225Skarels restart_point = 0; 49837225Skarels if (closefunc != NULL) 49937225Skarels (*closefunc)(fin); 50037225Skarels return; 50137225Skarels } 50237225Skarels restart_point = 0; 50337225Skarels mode = "r+w"; 50437225Skarels } 50510296Ssam if (remote) { 50626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 50726048Sminshall (void) signal(SIGINT, oldintr); 50826448Slepreau if (oldintp) 50926048Sminshall (void) signal(SIGPIPE, oldintp); 51036935Skarels if (closefunc != NULL) 51136935Skarels (*closefunc)(fin); 51226048Sminshall return; 51326048Sminshall } 51410296Ssam } else 51526048Sminshall if (command("%s", cmd) != PRELIM) { 51626048Sminshall (void) signal(SIGINT, oldintr); 51726448Slepreau if (oldintp) 51826048Sminshall (void) signal(SIGPIPE, oldintp); 51936935Skarels if (closefunc != NULL) 52036935Skarels (*closefunc)(fin); 52126048Sminshall return; 52226048Sminshall } 52336935Skarels dout = dataconn(mode); 52426448Slepreau if (dout == NULL) 52526048Sminshall goto abort; 52626496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 52736935Skarels oldintp = signal(SIGPIPE, SIG_IGN); 52811219Ssam switch (type) { 52911219Ssam 53011219Ssam case TYPE_I: 53111219Ssam case TYPE_L: 53211346Ssam errno = d = 0; 53336942Skarels while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { 53411219Ssam bytes += c; 53536942Skarels for (bufp = buf; c > 0; c -= d, bufp += d) 53636942Skarels if ((d = write(fileno(dout), bufp, c)) <= 0) 53736942Skarels break; 53811651Ssam if (hash) { 53936940Skarels while (bytes >= hashbytes) { 54036940Skarels (void) putchar('#'); 54136940Skarels hashbytes += HASHBYTES; 54236940Skarels } 54326496Sminshall (void) fflush(stdout); 54411651Ssam } 54511219Ssam } 54613213Ssam if (hash && bytes > 0) { 54736940Skarels if (bytes < HASHBYTES) 54836940Skarels (void) putchar('#'); 54926496Sminshall (void) putchar('\n'); 55026496Sminshall (void) fflush(stdout); 55111651Ssam } 55211219Ssam if (c < 0) 55311219Ssam perror(local); 55436942Skarels if (d <= 0) { 55536942Skarels if (d == 0) 55636942Skarels fprintf(stderr, "netout: write returned 0?\n"); 55736942Skarels else if (errno != EPIPE) 55836935Skarels perror("netout"); 55936935Skarels bytes = -1; 56036935Skarels } 56111219Ssam break; 56211219Ssam 56311219Ssam case TYPE_A: 56411219Ssam while ((c = getc(fin)) != EOF) { 56511219Ssam if (c == '\n') { 56611651Ssam while (hash && (bytes >= hashbytes)) { 56726496Sminshall (void) putchar('#'); 56826496Sminshall (void) fflush(stdout); 56936940Skarels hashbytes += HASHBYTES; 57011651Ssam } 57111219Ssam if (ferror(dout)) 57211219Ssam break; 57326496Sminshall (void) putc('\r', dout); 57411219Ssam bytes++; 57511219Ssam } 57626496Sminshall (void) putc(c, dout); 57711219Ssam bytes++; 57826048Sminshall /* if (c == '\r') { */ 57926496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 58026048Sminshall /* bytes++; */ 58126048Sminshall /* } */ 58211219Ssam } 58311651Ssam if (hash) { 58413213Ssam if (bytes < hashbytes) 58526496Sminshall (void) putchar('#'); 58626496Sminshall (void) putchar('\n'); 58726496Sminshall (void) fflush(stdout); 58811651Ssam } 58911219Ssam if (ferror(fin)) 59011219Ssam perror(local); 59136935Skarels if (ferror(dout)) { 59236935Skarels if (errno != EPIPE) 59336935Skarels perror("netout"); 59436935Skarels bytes = -1; 59536935Skarels } 59611219Ssam break; 59710296Ssam } 59826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 59910296Ssam if (closefunc != NULL) 60026048Sminshall (*closefunc)(fin); 60110296Ssam (void) fclose(dout); 60226048Sminshall (void) getreply(0); 60326048Sminshall (void) signal(SIGINT, oldintr); 60436935Skarels if (oldintp) 60536935Skarels (void) signal(SIGPIPE, oldintp); 60635699Sbostic if (bytes > 0) 60737225Skarels ptransfer("sent", bytes, &start, &stop); 60810296Ssam return; 60926048Sminshall abort: 61026496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 61126048Sminshall (void) signal(SIGINT, oldintr); 61226448Slepreau if (oldintp) 61326048Sminshall (void) signal(SIGPIPE, oldintp); 61426048Sminshall if (!cpend) { 61526048Sminshall code = -1; 61626048Sminshall return; 61726048Sminshall } 61826048Sminshall if (data >= 0) { 61926048Sminshall (void) close(data); 62026048Sminshall data = -1; 62126048Sminshall } 62226448Slepreau if (dout) 62326048Sminshall (void) fclose(dout); 62426048Sminshall (void) getreply(0); 62526048Sminshall code = -1; 62610296Ssam if (closefunc != NULL && fin != NULL) 62726048Sminshall (*closefunc)(fin); 62835699Sbostic if (bytes > 0) 62937225Skarels ptransfer("sent", bytes, &start, &stop); 63010296Ssam } 63110296Ssam 63210296Ssam jmp_buf recvabort; 63310296Ssam 63410296Ssam abortrecv() 63510296Ssam { 63610296Ssam 63726048Sminshall mflag = 0; 63826048Sminshall abrtflag = 0; 63926048Sminshall printf("\n"); 64026048Sminshall (void) fflush(stdout); 64110296Ssam longjmp(recvabort, 1); 64210296Ssam } 64310296Ssam 64437225Skarels recvrequest(cmd, local, remote, mode, printnames) 64511651Ssam char *cmd, *local, *remote, *mode; 64610296Ssam { 64735659Sbostic FILE *fout, *din = 0, *popen(); 64835659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 649*38033Skarels int abortrecv(), is_retr, tcrflag, nfnd; 65036944Skarels char *bufp, *gunique(), msg; 65136944Skarels static char *buf; 65236940Skarels static int bufsize; 65336940Skarels long bytes = 0, hashbytes = HASHBYTES; 65426496Sminshall struct fd_set mask; 65511346Ssam register int c, d; 65610296Ssam struct timeval start, stop; 65736940Skarels struct stat st; 65836940Skarels extern char *malloc(); 65910296Ssam 66036935Skarels is_retr = strcmp(cmd, "RETR") == 0; 66137225Skarels if (is_retr && verbose && printnames) { 66237225Skarels if (local && *local != '-') 66337225Skarels printf("local: %s ", local); 66437225Skarels if (remote) 66537225Skarels printf("remote: %s\n", remote); 66637225Skarels } 66736935Skarels if (proxy && is_retr) { 66826048Sminshall proxtrans(cmd, local, remote); 66926048Sminshall return; 67026048Sminshall } 67110296Ssam closefunc = NULL; 67226048Sminshall oldintr = NULL; 67326048Sminshall oldintp = NULL; 67436935Skarels tcrflag = !crflag && is_retr; 67526048Sminshall if (setjmp(recvabort)) { 67626048Sminshall while (cpend) { 67726048Sminshall (void) getreply(0); 67826048Sminshall } 67926048Sminshall if (data >= 0) { 68026048Sminshall (void) close(data); 68126048Sminshall data = -1; 68226048Sminshall } 68326448Slepreau if (oldintr) 68426048Sminshall (void) signal(SIGINT, oldintr); 68526048Sminshall code = -1; 68626048Sminshall return; 68726048Sminshall } 68810296Ssam oldintr = signal(SIGINT, abortrecv); 68926048Sminshall if (strcmp(local, "-") && *local != '|') { 69010296Ssam if (access(local, 2) < 0) { 69126048Sminshall char *dir = rindex(local, '/'); 69210296Ssam 69326048Sminshall if (errno != ENOENT && errno != EACCES) { 69410296Ssam perror(local); 69526048Sminshall (void) signal(SIGINT, oldintr); 69626048Sminshall code = -1; 69726048Sminshall return; 69810296Ssam } 69926048Sminshall if (dir != NULL) 70026048Sminshall *dir = 0; 70126048Sminshall d = access(dir ? local : ".", 2); 70226048Sminshall if (dir != NULL) 70326048Sminshall *dir = '/'; 70426048Sminshall if (d < 0) { 70526048Sminshall perror(local); 70626048Sminshall (void) signal(SIGINT, oldintr); 70726048Sminshall code = -1; 70826048Sminshall return; 70926048Sminshall } 71026048Sminshall if (!runique && errno == EACCES && 71136935Skarels chmod(local, 0600) < 0) { 71226048Sminshall perror(local); 71326048Sminshall (void) signal(SIGINT, oldintr); 71426048Sminshall code = -1; 71526048Sminshall return; 71626048Sminshall } 71726048Sminshall if (runique && errno == EACCES && 71826048Sminshall (local = gunique(local)) == NULL) { 71926048Sminshall (void) signal(SIGINT, oldintr); 72026048Sminshall code = -1; 72126048Sminshall return; 72226048Sminshall } 72310296Ssam } 72426048Sminshall else if (runique && (local = gunique(local)) == NULL) { 72526048Sminshall (void) signal(SIGINT, oldintr); 72626048Sminshall code = -1; 72726048Sminshall return; 72826048Sminshall } 72926048Sminshall } 730*38033Skarels if (!is_retr) { 731*38033Skarels if (curtype != TYPE_A) 732*38033Skarels changetype(TYPE_A, 0); 733*38033Skarels } else if (curtype != type) 734*38033Skarels changetype(type, 0); 73526048Sminshall if (initconn()) { 73626048Sminshall (void) signal(SIGINT, oldintr); 73726048Sminshall code = -1; 73826048Sminshall return; 73926048Sminshall } 74026448Slepreau if (setjmp(recvabort)) 74126048Sminshall goto abort; 742*38033Skarels if (is_retr && restart_point && 743*38033Skarels command("REST %ld", (long) restart_point) != CONTINUE) 744*38033Skarels return; 74510296Ssam if (remote) { 74626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 74726048Sminshall (void) signal(SIGINT, oldintr); 74826048Sminshall return; 74926048Sminshall } 75026048Sminshall } else { 75126048Sminshall if (command("%s", cmd) != PRELIM) { 75226048Sminshall (void) signal(SIGINT, oldintr); 75326048Sminshall return; 75426048Sminshall } 75526048Sminshall } 75626048Sminshall din = dataconn("r"); 75726048Sminshall if (din == NULL) 75826048Sminshall goto abort; 75926448Slepreau if (strcmp(local, "-") == 0) 76010296Ssam fout = stdout; 76110296Ssam else if (*local == '|') { 76226048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 76335659Sbostic fout = popen(local + 1, "w"); 76426048Sminshall if (fout == NULL) { 76526048Sminshall perror(local+1); 76626048Sminshall goto abort; 76726048Sminshall } 76835659Sbostic closefunc = pclose; 76936940Skarels } else { 77011651Ssam fout = fopen(local, mode); 77126048Sminshall if (fout == NULL) { 77226048Sminshall perror(local); 77326048Sminshall goto abort; 77426048Sminshall } 77510296Ssam closefunc = fclose; 77610296Ssam } 77736940Skarels if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 77836940Skarels st.st_blksize = BUFSIZ; 77936940Skarels if (st.st_blksize > bufsize) { 78036940Skarels if (buf) 78136940Skarels (void) free(buf); 78236940Skarels buf = malloc(st.st_blksize); 78336940Skarels if (buf == NULL) { 78436940Skarels perror("malloc"); 78536944Skarels bufsize = 0; 78636940Skarels goto abort; 78736940Skarels } 78836940Skarels bufsize = st.st_blksize; 78936940Skarels } 79026496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 791*38033Skarels switch (curtype) { 79211219Ssam 79311219Ssam case TYPE_I: 79411219Ssam case TYPE_L: 79537225Skarels if (restart_point && 79637225Skarels lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 79737225Skarels perror(local); 79837225Skarels if (closefunc != NULL) 79937225Skarels (*closefunc)(fout); 80037225Skarels return; 80137225Skarels } 80211346Ssam errno = d = 0; 80336940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) { 80436944Skarels if ((d = write(fileno(fout), buf, c)) != c) 80511219Ssam break; 80611219Ssam bytes += c; 80711651Ssam if (hash) { 80836940Skarels while (bytes >= hashbytes) { 80936940Skarels (void) putchar('#'); 81036940Skarels hashbytes += HASHBYTES; 81136940Skarels } 81226496Sminshall (void) fflush(stdout); 81311651Ssam } 81411219Ssam } 81513213Ssam if (hash && bytes > 0) { 81636940Skarels if (bytes < HASHBYTES) 81736940Skarels (void) putchar('#'); 81826496Sminshall (void) putchar('\n'); 81926496Sminshall (void) fflush(stdout); 82011651Ssam } 82136935Skarels if (c < 0) { 82236935Skarels if (errno != EPIPE) 82336935Skarels perror("netin"); 82436935Skarels bytes = -1; 82536935Skarels } 82636942Skarels if (d < c) { 82736942Skarels if (d < 0) 82836942Skarels perror(local); 82936942Skarels else 83036942Skarels fprintf(stderr, "%s: short write\n", local); 83136942Skarels } 83211219Ssam break; 83311219Ssam 83411219Ssam case TYPE_A: 83537225Skarels if (restart_point) { 83637225Skarels register int i, n, c; 83737225Skarels 83837225Skarels if (fseek(fout, 0L, L_SET) < 0) 83937225Skarels goto done; 84037225Skarels n = restart_point; 84137225Skarels i = 0; 84237225Skarels while (i++ < n) { 84337225Skarels if ((c=getc(fout)) == EOF) 84437225Skarels goto done; 84537225Skarels if (c == '\n') 84637225Skarels i++; 84737225Skarels } 84837225Skarels if (fseek(fout, 0L, L_INCR) < 0) { 84937225Skarels done: 85037225Skarels perror(local); 85137225Skarels if (closefunc != NULL) 85237225Skarels (*closefunc)(fout); 85337225Skarels return; 85437225Skarels } 85537225Skarels } 85611219Ssam while ((c = getc(din)) != EOF) { 85727749Sminshall while (c == '\r') { 85811651Ssam while (hash && (bytes >= hashbytes)) { 85926496Sminshall (void) putchar('#'); 86026496Sminshall (void) fflush(stdout); 86136940Skarels hashbytes += HASHBYTES; 86211651Ssam } 86310296Ssam bytes++; 86426048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 86536940Skarels if (ferror(fout)) 86636940Skarels goto break2; 86736940Skarels (void) putc('\r', fout); 86836942Skarels if (c == '\0') { 86936942Skarels bytes++; 87036940Skarels goto contin2; 87136942Skarels } 87236942Skarels if (c == EOF) 87336942Skarels goto contin2; 87411219Ssam } 87511219Ssam } 87636940Skarels (void) putc(c, fout); 87711219Ssam bytes++; 87836940Skarels contin2: ; 87910296Ssam } 88036940Skarels break2: 88111651Ssam if (hash) { 88213213Ssam if (bytes < hashbytes) 88326496Sminshall (void) putchar('#'); 88426496Sminshall (void) putchar('\n'); 88526496Sminshall (void) fflush(stdout); 88611651Ssam } 88736944Skarels if (ferror(din)) { 88836935Skarels if (errno != EPIPE) 88936944Skarels perror("netin"); 89036935Skarels bytes = -1; 89136935Skarels } 89236940Skarels if (ferror(fout)) 89336944Skarels perror(local); 89411219Ssam break; 89510296Ssam } 89626448Slepreau if (closefunc != NULL) 89726048Sminshall (*closefunc)(fout); 89826496Sminshall (void) signal(SIGINT, oldintr); 89926448Slepreau if (oldintp) 90026048Sminshall (void) signal(SIGPIPE, oldintp); 90126496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 90210296Ssam (void) fclose(din); 90326048Sminshall (void) getreply(0); 90436935Skarels if (bytes > 0 && is_retr) 90537225Skarels ptransfer("received", bytes, &start, &stop); 90626048Sminshall return; 90726048Sminshall abort: 90826048Sminshall 90927687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 91026048Sminshall 91126496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 91226448Slepreau if (oldintp) 91326048Sminshall (void) signal(SIGPIPE, oldintr); 91426048Sminshall (void) signal(SIGINT,SIG_IGN); 91526048Sminshall if (!cpend) { 91626048Sminshall code = -1; 91726048Sminshall (void) signal(SIGINT,oldintr); 91826048Sminshall return; 91926048Sminshall } 92026048Sminshall 92127687Sminshall fprintf(cout,"%c%c",IAC,IP); 92227687Sminshall (void) fflush(cout); 92327687Sminshall msg = IAC; 92427687Sminshall /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 92527687Sminshall /* after urgent byte rather than before as now is protocol */ 92627687Sminshall if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 92727687Sminshall perror("abort"); 92826048Sminshall } 92927687Sminshall fprintf(cout,"%cABOR\r\n",DM); 93026048Sminshall (void) fflush(cout); 93127687Sminshall FD_ZERO(&mask); 93226496Sminshall FD_SET(fileno(cin), &mask); 93326496Sminshall if (din) { 93426496Sminshall FD_SET(fileno(din), &mask); 93526496Sminshall } 93627687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 93727687Sminshall if (nfnd < 0) { 93827687Sminshall perror("abort"); 93927687Sminshall } 94026048Sminshall code = -1; 94126048Sminshall lostpeer(); 94226048Sminshall } 94326496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 94436940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) 94526448Slepreau ; 94626496Sminshall } 94727687Sminshall if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 94826048Sminshall if (data >= 0) { 94926496Sminshall (void) close(data); 95026048Sminshall data = -1; 95126048Sminshall } 95225907Smckusick (void) getreply(0); 95325907Smckusick } 95426048Sminshall (void) getreply(0); 95526048Sminshall code = -1; 95626048Sminshall if (data >= 0) { 95726048Sminshall (void) close(data); 95826048Sminshall data = -1; 95926048Sminshall } 96026448Slepreau if (closefunc != NULL && fout != NULL) 96126048Sminshall (*closefunc)(fout); 96226448Slepreau if (din) 96326048Sminshall (void) fclose(din); 96435699Sbostic if (bytes > 0) 96537225Skarels ptransfer("received", bytes, &start, &stop); 96626048Sminshall (void) signal(SIGINT,oldintr); 96710296Ssam } 96810296Ssam 96910296Ssam /* 97010296Ssam * Need to start a listen on the data channel 97110296Ssam * before we send the command, otherwise the 97210296Ssam * server's connect may fail. 97310296Ssam */ 97433224Sbostic int sendport = -1; 97511651Ssam 97610296Ssam initconn() 97710296Ssam { 97810296Ssam register char *p, *a; 97926048Sminshall int result, len, tmpno = 0; 98026993Skarels int on = 1; 98110296Ssam 98211651Ssam noport: 98310296Ssam data_addr = myctladdr; 98411651Ssam if (sendport) 98511651Ssam data_addr.sin_port = 0; /* let system pick one */ 98611651Ssam if (data != -1) 98711651Ssam (void) close (data); 98818287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 98910296Ssam if (data < 0) { 99010296Ssam perror("ftp: socket"); 99126448Slepreau if (tmpno) 99226048Sminshall sendport = 1; 99310296Ssam return (1); 99410296Ssam } 99512397Ssam if (!sendport) 99627687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 99733224Sbostic perror("ftp: setsockopt (reuse address)"); 99812397Ssam goto bad; 99912397Ssam } 100026496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 100110296Ssam perror("ftp: bind"); 100210296Ssam goto bad; 100310296Ssam } 100410296Ssam if (options & SO_DEBUG && 100527687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 100610296Ssam perror("ftp: setsockopt (ignored)"); 100711627Ssam len = sizeof (data_addr); 100811627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 100911627Ssam perror("ftp: getsockname"); 101010296Ssam goto bad; 101110296Ssam } 101226448Slepreau if (listen(data, 1) < 0) 101310296Ssam perror("ftp: listen"); 101411651Ssam if (sendport) { 101511651Ssam a = (char *)&data_addr.sin_addr; 101611651Ssam p = (char *)&data_addr.sin_port; 101710296Ssam #define UC(b) (((int)b)&0xff) 101811651Ssam result = 101911651Ssam command("PORT %d,%d,%d,%d,%d,%d", 102011651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 102111651Ssam UC(p[0]), UC(p[1])); 102211651Ssam if (result == ERROR && sendport == -1) { 102311651Ssam sendport = 0; 102426048Sminshall tmpno = 1; 102511651Ssam goto noport; 102611651Ssam } 102711651Ssam return (result != COMPLETE); 102811651Ssam } 102926448Slepreau if (tmpno) 103026048Sminshall sendport = 1; 103111651Ssam return (0); 103210296Ssam bad: 103310296Ssam (void) close(data), data = -1; 103426448Slepreau if (tmpno) 103526048Sminshall sendport = 1; 103610296Ssam return (1); 103710296Ssam } 103810296Ssam 103910296Ssam FILE * 104010296Ssam dataconn(mode) 104110296Ssam char *mode; 104210296Ssam { 104310296Ssam struct sockaddr_in from; 104410296Ssam int s, fromlen = sizeof (from); 104510296Ssam 104626496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 104710296Ssam if (s < 0) { 104810296Ssam perror("ftp: accept"); 104910296Ssam (void) close(data), data = -1; 105010296Ssam return (NULL); 105110296Ssam } 105210296Ssam (void) close(data); 105310296Ssam data = s; 105410296Ssam return (fdopen(data, mode)); 105510296Ssam } 105610296Ssam 105737225Skarels ptransfer(direction, bytes, t0, t1) 105837225Skarels char *direction; 105911651Ssam long bytes; 106010296Ssam struct timeval *t0, *t1; 106110296Ssam { 106210296Ssam struct timeval td; 106316437Sleres float s, bs; 106410296Ssam 106535699Sbostic if (verbose) { 106635699Sbostic tvsub(&td, t1, t0); 106735699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 106810296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 106935699Sbostic bs = bytes / nz(s); 107035699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 107135699Sbostic bytes, direction, s, bs / 1024.); 107235699Sbostic } 107310296Ssam } 107410296Ssam 107526496Sminshall /*tvadd(tsum, t0) 107610296Ssam struct timeval *tsum, *t0; 107710296Ssam { 107810296Ssam 107910296Ssam tsum->tv_sec += t0->tv_sec; 108010296Ssam tsum->tv_usec += t0->tv_usec; 108110296Ssam if (tsum->tv_usec > 1000000) 108210296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 108326496Sminshall } */ 108410296Ssam 108510296Ssam tvsub(tdiff, t1, t0) 108610296Ssam struct timeval *tdiff, *t1, *t0; 108710296Ssam { 108810296Ssam 108910296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 109010296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 109110296Ssam if (tdiff->tv_usec < 0) 109210296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 109310296Ssam } 109426048Sminshall 109526048Sminshall psabort() 109626048Sminshall { 109726048Sminshall extern int abrtflag; 109826048Sminshall 109926048Sminshall abrtflag++; 110026048Sminshall } 110126048Sminshall 110226048Sminshall pswitch(flag) 110326048Sminshall int flag; 110426048Sminshall { 110526048Sminshall extern int proxy, abrtflag; 110626048Sminshall int (*oldintr)(); 110726048Sminshall static struct comvars { 110826048Sminshall int connect; 110928469Skarels char name[MAXHOSTNAMELEN]; 111026048Sminshall struct sockaddr_in mctl; 111126048Sminshall struct sockaddr_in hctl; 111226048Sminshall FILE *in; 111326048Sminshall FILE *out; 111426048Sminshall int tpe; 1115*38033Skarels int curtpe; 111626048Sminshall int cpnd; 111726048Sminshall int sunqe; 111826048Sminshall int runqe; 111926048Sminshall int mcse; 112026048Sminshall int ntflg; 112126048Sminshall char nti[17]; 112226048Sminshall char nto[17]; 112326048Sminshall int mapflg; 112426048Sminshall char mi[MAXPATHLEN]; 112526048Sminshall char mo[MAXPATHLEN]; 1126*38033Skarels } proxstruct, tmpstruct; 112726048Sminshall struct comvars *ip, *op; 112826048Sminshall 112926048Sminshall abrtflag = 0; 113026048Sminshall oldintr = signal(SIGINT, psabort); 113126048Sminshall if (flag) { 113226448Slepreau if (proxy) 113326048Sminshall return; 113426048Sminshall ip = &tmpstruct; 113526048Sminshall op = &proxstruct; 113626048Sminshall proxy++; 1137*38033Skarels } else { 113826448Slepreau if (!proxy) 113926048Sminshall return; 114026048Sminshall ip = &proxstruct; 114126048Sminshall op = &tmpstruct; 114226048Sminshall proxy = 0; 114326048Sminshall } 114426048Sminshall ip->connect = connected; 114526048Sminshall connected = op->connect; 114628469Skarels if (hostname) { 114728469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 114828469Skarels ip->name[strlen(ip->name)] = '\0'; 114928469Skarels } else 115028469Skarels ip->name[0] = 0; 115126048Sminshall hostname = op->name; 115226048Sminshall ip->hctl = hisctladdr; 115326048Sminshall hisctladdr = op->hctl; 115426048Sminshall ip->mctl = myctladdr; 115526048Sminshall myctladdr = op->mctl; 115626048Sminshall ip->in = cin; 115726048Sminshall cin = op->in; 115826048Sminshall ip->out = cout; 115926048Sminshall cout = op->out; 116026048Sminshall ip->tpe = type; 116126048Sminshall type = op->tpe; 1162*38033Skarels ip->curtpe = curtype; 1163*38033Skarels curtype = op->curtpe; 116426048Sminshall ip->cpnd = cpend; 116526048Sminshall cpend = op->cpnd; 116626048Sminshall ip->sunqe = sunique; 116726048Sminshall sunique = op->sunqe; 116826048Sminshall ip->runqe = runique; 116926048Sminshall runique = op->runqe; 117026048Sminshall ip->mcse = mcase; 117126048Sminshall mcase = op->mcse; 117226048Sminshall ip->ntflg = ntflag; 117326048Sminshall ntflag = op->ntflg; 117426496Sminshall (void) strncpy(ip->nti, ntin, 16); 117526048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 117626496Sminshall (void) strcpy(ntin, op->nti); 117726496Sminshall (void) strncpy(ip->nto, ntout, 16); 117826048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 117926496Sminshall (void) strcpy(ntout, op->nto); 118026048Sminshall ip->mapflg = mapflag; 118126048Sminshall mapflag = op->mapflg; 118226496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 118326048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 118426496Sminshall (void) strcpy(mapin, op->mi); 118526496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 118626048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 118726496Sminshall (void) strcpy(mapout, op->mo); 118826048Sminshall (void) signal(SIGINT, oldintr); 118926048Sminshall if (abrtflag) { 119026048Sminshall abrtflag = 0; 119126048Sminshall (*oldintr)(); 119226448Slepreau } 119326048Sminshall } 119426048Sminshall 119526048Sminshall jmp_buf ptabort; 119626048Sminshall int ptabflg; 119726048Sminshall 119826048Sminshall abortpt() 119926048Sminshall { 120026048Sminshall printf("\n"); 120126496Sminshall (void) fflush(stdout); 120226048Sminshall ptabflg++; 120326048Sminshall mflag = 0; 120426048Sminshall abrtflag = 0; 120526048Sminshall longjmp(ptabort, 1); 120626048Sminshall } 120726048Sminshall 120826048Sminshall proxtrans(cmd, local, remote) 120926048Sminshall char *cmd, *local, *remote; 121026048Sminshall { 1211*38033Skarels int (*oldintr)(), abortpt(), prox_type, secndflag = 0, nfnd; 121226048Sminshall extern jmp_buf ptabort; 121326048Sminshall char *cmd2; 121426496Sminshall struct fd_set mask; 121526048Sminshall 121626448Slepreau if (strcmp(cmd, "RETR")) 121726048Sminshall cmd2 = "RETR"; 121826448Slepreau else 121926048Sminshall cmd2 = runique ? "STOU" : "STOR"; 1220*38033Skarels if ((prox_type = type) == 0) { 1221*38033Skarels if (unix_server && unix_proxy) 1222*38033Skarels prox_type = TYPE_I; 1223*38033Skarels else 1224*38033Skarels prox_type = TYPE_A; 1225*38033Skarels } 1226*38033Skarels if (curtype != prox_type) 1227*38033Skarels changetype(prox_type, 1); 122826048Sminshall if (command("PASV") != COMPLETE) { 1229*38033Skarels printf("proxy server does not support third party transfers.\n"); 123026048Sminshall return; 123126048Sminshall } 123226048Sminshall pswitch(0); 123326048Sminshall if (!connected) { 123426048Sminshall printf("No primary connection\n"); 123526048Sminshall pswitch(1); 123626048Sminshall code = -1; 123726048Sminshall return; 123826048Sminshall } 1239*38033Skarels if (curtype != prox_type) 1240*38033Skarels changetype(prox_type, 1); 124126048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 124226048Sminshall pswitch(1); 124326048Sminshall return; 124426048Sminshall } 124526448Slepreau if (setjmp(ptabort)) 124626048Sminshall goto abort; 124726048Sminshall oldintr = signal(SIGINT, abortpt); 124826048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 124926048Sminshall (void) signal(SIGINT, oldintr); 125026048Sminshall pswitch(1); 125126048Sminshall return; 125226048Sminshall } 125326048Sminshall sleep(2); 125426048Sminshall pswitch(1); 125526048Sminshall secndflag++; 125626448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 125726048Sminshall goto abort; 125826048Sminshall ptflag++; 125926048Sminshall (void) getreply(0); 126026048Sminshall pswitch(0); 126126048Sminshall (void) getreply(0); 126226048Sminshall (void) signal(SIGINT, oldintr); 126326048Sminshall pswitch(1); 126426048Sminshall ptflag = 0; 126526048Sminshall printf("local: %s remote: %s\n", local, remote); 126626048Sminshall return; 126726048Sminshall abort: 126826048Sminshall (void) signal(SIGINT, SIG_IGN); 126926048Sminshall ptflag = 0; 127026448Slepreau if (strcmp(cmd, "RETR") && !proxy) 127126048Sminshall pswitch(1); 127226448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 127326048Sminshall pswitch(0); 127426048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 127526048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 127626048Sminshall pswitch(0); 127727687Sminshall if (cpend) { 127826048Sminshall char msg[2]; 127926048Sminshall 128026048Sminshall fprintf(cout,"%c%c",IAC,IP); 128126048Sminshall (void) fflush(cout); 128226048Sminshall *msg = IAC; 128326048Sminshall *(msg+1) = DM; 128426448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 128526048Sminshall perror("abort"); 128626048Sminshall fprintf(cout,"ABOR\r\n"); 128726048Sminshall (void) fflush(cout); 128827687Sminshall FD_ZERO(&mask); 128926496Sminshall FD_SET(fileno(cin), &mask); 129027687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 129127687Sminshall if (nfnd < 0) { 129227687Sminshall perror("abort"); 129327687Sminshall } 129426448Slepreau if (ptabflg) 129526048Sminshall code = -1; 129626048Sminshall lostpeer(); 129726048Sminshall } 129826048Sminshall (void) getreply(0); 129926048Sminshall (void) getreply(0); 130026048Sminshall } 130126048Sminshall } 130226048Sminshall pswitch(1); 130326448Slepreau if (ptabflg) 130426048Sminshall code = -1; 130526048Sminshall (void) signal(SIGINT, oldintr); 130626048Sminshall return; 130726048Sminshall } 130827687Sminshall if (cpend) { 130926048Sminshall char msg[2]; 131026048Sminshall 131126048Sminshall fprintf(cout,"%c%c",IAC,IP); 131226048Sminshall (void) fflush(cout); 131326048Sminshall *msg = IAC; 131426048Sminshall *(msg+1) = DM; 131526448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 131626048Sminshall perror("abort"); 131726048Sminshall fprintf(cout,"ABOR\r\n"); 131826048Sminshall (void) fflush(cout); 131927687Sminshall FD_ZERO(&mask); 132026496Sminshall FD_SET(fileno(cin), &mask); 132127687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 132227687Sminshall if (nfnd < 0) { 132327687Sminshall perror("abort"); 132427687Sminshall } 132526448Slepreau if (ptabflg) 132626048Sminshall code = -1; 132726048Sminshall lostpeer(); 132826048Sminshall } 132926048Sminshall (void) getreply(0); 133026048Sminshall (void) getreply(0); 133126048Sminshall } 133226048Sminshall pswitch(!proxy); 133326048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 133426048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 133526048Sminshall pswitch(0); 133627687Sminshall if (cpend) { 133726048Sminshall char msg[2]; 133826048Sminshall 133926048Sminshall fprintf(cout,"%c%c",IAC,IP); 134026048Sminshall (void) fflush(cout); 134126048Sminshall *msg = IAC; 134226048Sminshall *(msg+1) = DM; 134326448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 134426048Sminshall perror("abort"); 134526048Sminshall fprintf(cout,"ABOR\r\n"); 134626048Sminshall (void) fflush(cout); 134727687Sminshall FD_ZERO(&mask); 134826496Sminshall FD_SET(fileno(cin), &mask); 134927687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 135027687Sminshall if (nfnd < 0) { 135127687Sminshall perror("abort"); 135227687Sminshall } 135326448Slepreau if (ptabflg) 135426048Sminshall code = -1; 135526048Sminshall lostpeer(); 135626048Sminshall } 135726048Sminshall (void) getreply(0); 135826048Sminshall (void) getreply(0); 135926048Sminshall } 136026048Sminshall pswitch(1); 136126448Slepreau if (ptabflg) 136226048Sminshall code = -1; 136326048Sminshall (void) signal(SIGINT, oldintr); 136426048Sminshall return; 136526048Sminshall } 136626048Sminshall } 136727687Sminshall if (cpend) { 136826048Sminshall char msg[2]; 136926048Sminshall 137026048Sminshall fprintf(cout,"%c%c",IAC,IP); 137126048Sminshall (void) fflush(cout); 137226048Sminshall *msg = IAC; 137326048Sminshall *(msg+1) = DM; 137426448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 137526048Sminshall perror("abort"); 137626048Sminshall fprintf(cout,"ABOR\r\n"); 137726048Sminshall (void) fflush(cout); 137827687Sminshall FD_ZERO(&mask); 137926496Sminshall FD_SET(fileno(cin), &mask); 138027687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 138127687Sminshall if (nfnd < 0) { 138227687Sminshall perror("abort"); 138327687Sminshall } 138426448Slepreau if (ptabflg) 138526048Sminshall code = -1; 138626048Sminshall lostpeer(); 138726048Sminshall } 138826048Sminshall (void) getreply(0); 138926048Sminshall (void) getreply(0); 139026048Sminshall } 139126048Sminshall pswitch(!proxy); 139226048Sminshall if (cpend) { 139327687Sminshall FD_ZERO(&mask); 139426496Sminshall FD_SET(fileno(cin), &mask); 139527687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 139627687Sminshall if (nfnd < 0) { 139727687Sminshall perror("abort"); 139827687Sminshall } 139926448Slepreau if (ptabflg) 140026048Sminshall code = -1; 140126048Sminshall lostpeer(); 140226048Sminshall } 140326048Sminshall (void) getreply(0); 140426048Sminshall (void) getreply(0); 140526048Sminshall } 140626448Slepreau if (proxy) 140726048Sminshall pswitch(0); 140826048Sminshall pswitch(1); 140926448Slepreau if (ptabflg) 141026048Sminshall code = -1; 141126048Sminshall (void) signal(SIGINT, oldintr); 141226048Sminshall } 141326048Sminshall 141426048Sminshall reset() 141526048Sminshall { 141626496Sminshall struct fd_set mask; 141726496Sminshall int nfnd = 1; 141826048Sminshall 141927687Sminshall FD_ZERO(&mask); 142030946Scsvsj while (nfnd > 0) { 142126496Sminshall FD_SET(fileno(cin), &mask); 142227687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 142326048Sminshall perror("reset"); 142426048Sminshall code = -1; 142526048Sminshall lostpeer(); 142626048Sminshall } 142727687Sminshall else if (nfnd) { 142826048Sminshall (void) getreply(0); 142926496Sminshall } 143026048Sminshall } 143126048Sminshall } 143226048Sminshall 143326048Sminshall char * 143426048Sminshall gunique(local) 143526048Sminshall char *local; 143626048Sminshall { 143726048Sminshall static char new[MAXPATHLEN]; 143826048Sminshall char *cp = rindex(local, '/'); 143926048Sminshall int d, count=0; 144026048Sminshall char ext = '1'; 144126048Sminshall 144226448Slepreau if (cp) 144326048Sminshall *cp = '\0'; 144426048Sminshall d = access(cp ? local : ".", 2); 144526448Slepreau if (cp) 144626048Sminshall *cp = '/'; 144726048Sminshall if (d < 0) { 144826048Sminshall perror(local); 144926048Sminshall return((char *) 0); 145026048Sminshall } 145126048Sminshall (void) strcpy(new, local); 145226048Sminshall cp = new + strlen(new); 145326048Sminshall *cp++ = '.'; 145426048Sminshall while (!d) { 145526048Sminshall if (++count == 100) { 145626048Sminshall printf("runique: can't find unique file name.\n"); 145726048Sminshall return((char *) 0); 145826048Sminshall } 145926048Sminshall *cp++ = ext; 146026048Sminshall *cp = '\0'; 146126448Slepreau if (ext == '9') 146226048Sminshall ext = '0'; 146326448Slepreau else 146426048Sminshall ext++; 146526448Slepreau if ((d = access(new, 0)) < 0) 146626048Sminshall break; 146726448Slepreau if (ext != '0') 146826048Sminshall cp--; 146926448Slepreau else if (*(cp - 2) == '.') 147026048Sminshall *(cp - 1) = '1'; 147126048Sminshall else { 147226048Sminshall *(cp - 2) = *(cp - 2) + 1; 147326048Sminshall cp--; 147426048Sminshall } 147526048Sminshall } 147626048Sminshall return(new); 147726048Sminshall } 1478