121739Sdist /* 226048Sminshall * Copyright (c) 1985 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 15*36935Skarels * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621739Sdist */ 1721739Sdist 1810296Ssam #ifndef lint 19*36935Skarels static char sccsid[] = "@(#)ftp.c 5.23 (Berkeley) 02/28/89"; 2033737Sbostic #endif /* not lint */ 2110296Ssam 2226048Sminshall #include "ftp_var.h" 2326048Sminshall 2410296Ssam #include <sys/stat.h> 2510296Ssam #include <sys/ioctl.h> 2610296Ssam #include <sys/socket.h> 2713614Ssam #include <sys/time.h> 2828469Skarels #include <sys/param.h> 29*36935Skarels #include <sys/file.h> 3010296Ssam 3110296Ssam #include <netinet/in.h> 3212397Ssam #include <arpa/ftp.h> 3326048Sminshall #include <arpa/telnet.h> 3410296Ssam 3510296Ssam #include <stdio.h> 3610296Ssam #include <signal.h> 3710296Ssam #include <errno.h> 3810296Ssam #include <netdb.h> 3926048Sminshall #include <fcntl.h> 4026048Sminshall #include <pwd.h> 4110296Ssam 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(); 50*36935Skarels 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; 6825904Skarels (void) strcpy(hostnamebuf, host); 6926048Sminshall } 7026048Sminshall else { 7125100Sbloom hp = gethostbyname(host); 7225904Skarels if (hp == NULL) { 7335792Sbostic fprintf(stderr, "ftp: %s: ", host); 7435792Sbostic herror((char *)NULL); 7526048Sminshall code = -1; 7626048Sminshall return((char *) 0); 7725904Skarels } 7825904Skarels hisctladdr.sin_family = hp->h_addrtype; 7925904Skarels bcopy(hp->h_addr_list[0], 8025904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 8125904Skarels (void) strcpy(hostnamebuf, hp->h_name); 8210296Ssam } 8325904Skarels hostname = hostnamebuf; 8425904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 8510296Ssam if (s < 0) { 8610296Ssam perror("ftp: socket"); 8726048Sminshall code = -1; 8810296Ssam return (0); 8910296Ssam } 9010296Ssam hisctladdr.sin_port = port; 9126496Sminshall while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 9225904Skarels if (hp && hp->h_addr_list[1]) { 9325904Skarels int oerrno = errno; 9425904Skarels 9525904Skarels fprintf(stderr, "ftp: connect to address %s: ", 9625904Skarels inet_ntoa(hisctladdr.sin_addr)); 9725904Skarels errno = oerrno; 9826496Sminshall perror((char *) 0); 9925904Skarels hp->h_addr_list++; 10025904Skarels bcopy(hp->h_addr_list[0], 10126048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 10226496Sminshall fprintf(stdout, "Trying %s...\n", 10325904Skarels inet_ntoa(hisctladdr.sin_addr)); 10426813Skarels (void) close(s); 10526813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 10626813Skarels if (s < 0) { 10726813Skarels perror("ftp: socket"); 10826813Skarels code = -1; 10926813Skarels return (0); 11026813Skarels } 11125904Skarels continue; 11225904Skarels } 11310296Ssam perror("ftp: connect"); 11426048Sminshall code = -1; 11510296Ssam goto bad; 11610296Ssam } 11711627Ssam len = sizeof (myctladdr); 11811627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 11911627Ssam perror("ftp: getsockname"); 12026048Sminshall code = -1; 12110296Ssam goto bad; 12210296Ssam } 12310296Ssam cin = fdopen(s, "r"); 12410296Ssam cout = fdopen(s, "w"); 12511219Ssam if (cin == NULL || cout == NULL) { 12610296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 12710296Ssam if (cin) 12826496Sminshall (void) fclose(cin); 12910296Ssam if (cout) 13026496Sminshall (void) fclose(cout); 13126048Sminshall code = -1; 13210296Ssam goto bad; 13310296Ssam } 13410296Ssam if (verbose) 13526067Sminshall printf("Connected to %s.\n", hostname); 13627687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 13726048Sminshall if (cin) 13826496Sminshall (void) fclose(cin); 13926048Sminshall if (cout) 14026496Sminshall (void) fclose(cout); 14126048Sminshall code = -1; 14226048Sminshall goto bad; 14326048Sminshall } 14427687Sminshall #ifdef SO_OOBINLINE 14527687Sminshall { 14627687Sminshall int on = 1; 14726048Sminshall 14827687Sminshall if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 14927687Sminshall < 0 && debug) { 15027687Sminshall perror("ftp: setsockopt"); 15127687Sminshall } 15227687Sminshall } 15327687Sminshall #endif SO_OOBINLINE 15426048Sminshall 15525904Skarels return (hostname); 15610296Ssam bad: 15726496Sminshall (void) close(s); 15825904Skarels return ((char *)0); 15910296Ssam } 16010296Ssam 16125904Skarels login(host) 16225904Skarels char *host; 16310296Ssam { 16426048Sminshall char tmp[80]; 16535659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 16626048Sminshall int n, aflag = 0; 16710296Ssam 16826048Sminshall user = pass = acct = 0; 16926048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 17026048Sminshall disconnect(); 17126048Sminshall code = -1; 17226048Sminshall return(0); 17326048Sminshall } 17426048Sminshall if (user == NULL) { 17526048Sminshall char *myname = getlogin(); 17626048Sminshall 17726048Sminshall if (myname == NULL) { 17826048Sminshall struct passwd *pp = getpwuid(getuid()); 17926048Sminshall 18026448Slepreau if (pp != NULL) 18126048Sminshall myname = pp->pw_name; 18226048Sminshall } 18326048Sminshall printf("Name (%s:%s): ", host, myname); 18426048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 18526048Sminshall tmp[strlen(tmp) - 1] = '\0'; 18626448Slepreau if (*tmp == '\0') 18726048Sminshall user = myname; 18826448Slepreau else 18926048Sminshall user = tmp; 19026048Sminshall } 19110296Ssam n = command("USER %s", user); 19226048Sminshall if (n == CONTINUE) { 19326448Slepreau if (pass == NULL) 19435659Sbostic pass = getpass("Password:"); 19510296Ssam n = command("PASS %s", pass); 19626048Sminshall } 19710296Ssam if (n == CONTINUE) { 19826048Sminshall aflag++; 19935659Sbostic acct = getpass("Account:"); 20010296Ssam n = command("ACCT %s", acct); 20110296Ssam } 20210296Ssam if (n != COMPLETE) { 20310296Ssam fprintf(stderr, "Login failed.\n"); 20410296Ssam return (0); 20510296Ssam } 20626448Slepreau if (!aflag && acct != NULL) 20726048Sminshall (void) command("ACCT %s", acct); 20826448Slepreau if (proxy) 20926048Sminshall return(1); 21026048Sminshall for (n = 0; n < macnum; ++n) { 21126048Sminshall if (!strcmp("init", macros[n].mac_name)) { 21226496Sminshall (void) strcpy(line, "$init"); 21326048Sminshall makeargv(); 21426048Sminshall domacro(margc, margv); 21526048Sminshall break; 21626048Sminshall } 21726048Sminshall } 21810296Ssam return (1); 21910296Ssam } 22010296Ssam 22126048Sminshall cmdabort() 22226048Sminshall { 22326048Sminshall extern jmp_buf ptabort; 22426048Sminshall 22526048Sminshall printf("\n"); 22626048Sminshall (void) fflush(stdout); 22726048Sminshall abrtflag++; 22826448Slepreau if (ptflag) 22926048Sminshall longjmp(ptabort,1); 23026048Sminshall } 23126048Sminshall 23226496Sminshall /*VARARGS1*/ 23310296Ssam command(fmt, args) 23410296Ssam char *fmt; 23510296Ssam { 23626048Sminshall int r, (*oldintr)(), cmdabort(); 23710296Ssam 23826048Sminshall abrtflag = 0; 23910296Ssam if (debug) { 24010296Ssam printf("---> "); 24110296Ssam _doprnt(fmt, &args, stdout); 24210296Ssam printf("\n"); 24310296Ssam (void) fflush(stdout); 24410296Ssam } 24511219Ssam if (cout == NULL) { 24611219Ssam perror ("No control connection for command"); 24726048Sminshall code = -1; 24811219Ssam return (0); 24911219Ssam } 25026048Sminshall oldintr = signal(SIGINT,cmdabort); 25110296Ssam _doprnt(fmt, &args, cout); 25210296Ssam fprintf(cout, "\r\n"); 25310296Ssam (void) fflush(cout); 25426048Sminshall cpend = 1; 25526048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 25626448Slepreau if (abrtflag && oldintr != SIG_IGN) 25726048Sminshall (*oldintr)(); 25826048Sminshall (void) signal(SIGINT, oldintr); 25926048Sminshall return(r); 26010296Ssam } 26110296Ssam 262*36935Skarels char reply_string[BUFSIZ]; 263*36935Skarels 26410296Ssam #include <ctype.h> 26510296Ssam 26610296Ssam getreply(expecteof) 26710296Ssam int expecteof; 26810296Ssam { 26911219Ssam register int c, n; 27026048Sminshall register int dig; 271*36935Skarels register char *cp; 27226048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 27326048Sminshall int pflag = 0; 27426048Sminshall char *pt = pasv; 27510296Ssam 276*36935Skarels cp = reply_string; 27726048Sminshall oldintr = signal(SIGINT,cmdabort); 27810296Ssam for (;;) { 27910296Ssam dig = n = code = 0; 28010296Ssam while ((c = getc(cin)) != '\n') { 28127687Sminshall if (c == IAC) { /* handle telnet commands */ 28227687Sminshall switch (c = getc(cin)) { 28327687Sminshall case WILL: 28427687Sminshall case WONT: 28527687Sminshall c = getc(cin); 28627687Sminshall fprintf(cout, "%c%c%c",IAC,WONT,c); 28727687Sminshall (void) fflush(cout); 28827687Sminshall break; 28927687Sminshall case DO: 29027687Sminshall case DONT: 29127687Sminshall c = getc(cin); 29227687Sminshall fprintf(cout, "%c%c%c",IAC,DONT,c); 29327687Sminshall (void) fflush(cout); 29427687Sminshall break; 29527687Sminshall default: 29627687Sminshall break; 29727687Sminshall } 29827687Sminshall continue; 29927687Sminshall } 30010296Ssam dig++; 30110296Ssam if (c == EOF) { 30226048Sminshall if (expecteof) { 30326048Sminshall (void) signal(SIGINT,oldintr); 30426048Sminshall code = 221; 30510296Ssam return (0); 30626048Sminshall } 30710296Ssam lostpeer(); 30826048Sminshall if (verbose) { 30926048Sminshall printf("421 Service not available, remote server has closed connection\n"); 31026048Sminshall (void) fflush(stdout); 31126048Sminshall } 31233772Scsvsj code = 421; 31333772Scsvsj return(4); 31410296Ssam } 31526048Sminshall if (c != '\r' && (verbose > 0 || 31626048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 31726448Slepreau if (proxflag && 31826448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 31926048Sminshall printf("%s:",hostname); 32026496Sminshall (void) putchar(c); 32126048Sminshall } 32210296Ssam if (dig < 4 && isdigit(c)) 32310296Ssam code = code * 10 + (c - '0'); 32426448Slepreau if (!pflag && code == 227) 32526048Sminshall pflag = 1; 32626448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 32726048Sminshall pflag = 2; 32826048Sminshall if (pflag == 2) { 32926448Slepreau if (c != '\r' && c != ')') 33026048Sminshall *pt++ = c; 33126048Sminshall else { 33226048Sminshall *pt = '\0'; 33326048Sminshall pflag = 3; 33426048Sminshall } 33526048Sminshall } 33626048Sminshall if (dig == 4 && c == '-') { 33726448Slepreau if (continuation) 33826048Sminshall code = 0; 33910296Ssam continuation++; 34026048Sminshall } 34110296Ssam if (n == 0) 34210296Ssam n = c; 343*36935Skarels *cp++ = c; 34410296Ssam } 34526048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 34626496Sminshall (void) putchar(c); 34711346Ssam (void) fflush (stdout); 34811346Ssam } 34910296Ssam if (continuation && code != originalcode) { 35010296Ssam if (originalcode == 0) 35110296Ssam originalcode = code; 35210296Ssam continue; 35310296Ssam } 354*36935Skarels *cp = '\0'; 35526448Slepreau if (n != '1') 35626048Sminshall cpend = 0; 35726048Sminshall (void) signal(SIGINT,oldintr); 35826448Slepreau if (code == 421 || originalcode == 421) 35926048Sminshall lostpeer(); 36026448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 36126048Sminshall (*oldintr)(); 36225907Smckusick return (n - '0'); 36310296Ssam } 36410296Ssam } 36510296Ssam 36626048Sminshall empty(mask, sec) 36727687Sminshall struct fd_set *mask; 36826048Sminshall int sec; 36926048Sminshall { 37026048Sminshall struct timeval t; 37126048Sminshall 37226048Sminshall t.tv_sec = (long) sec; 37326048Sminshall t.tv_usec = 0; 37427687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 37526048Sminshall } 37626048Sminshall 37710296Ssam jmp_buf sendabort; 37810296Ssam 37910296Ssam abortsend() 38010296Ssam { 38110296Ssam 38226048Sminshall mflag = 0; 38326048Sminshall abrtflag = 0; 38426048Sminshall printf("\nsend aborted\n"); 38526048Sminshall (void) fflush(stdout); 38610296Ssam longjmp(sendabort, 1); 38710296Ssam } 38810296Ssam 38910296Ssam sendrequest(cmd, local, remote) 39010296Ssam char *cmd, *local, *remote; 39110296Ssam { 39235659Sbostic FILE *fin, *dout = 0, *popen(); 39335659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 39426048Sminshall int abortsend(); 39511219Ssam char buf[BUFSIZ]; 39611651Ssam long bytes = 0, hashbytes = sizeof (buf); 39711346Ssam register int c, d; 39810296Ssam struct stat st; 39910296Ssam struct timeval start, stop; 400*36935Skarels char *mode; 40110296Ssam 40226048Sminshall if (proxy) { 40326048Sminshall proxtrans(cmd, local, remote); 40426048Sminshall return; 40526048Sminshall } 40610296Ssam closefunc = NULL; 40726048Sminshall oldintr = NULL; 40826048Sminshall oldintp = NULL; 409*36935Skarels mode = "w"; 41026048Sminshall if (setjmp(sendabort)) { 41126048Sminshall while (cpend) { 41226048Sminshall (void) getreply(0); 41326048Sminshall } 41426048Sminshall if (data >= 0) { 41526048Sminshall (void) close(data); 41626048Sminshall data = -1; 41726048Sminshall } 41826448Slepreau if (oldintr) 41926048Sminshall (void) signal(SIGINT,oldintr); 42026448Slepreau if (oldintp) 42126048Sminshall (void) signal(SIGPIPE,oldintp); 42226048Sminshall code = -1; 42326048Sminshall return; 42426048Sminshall } 42510296Ssam oldintr = signal(SIGINT, abortsend); 42610296Ssam if (strcmp(local, "-") == 0) 42710296Ssam fin = stdin; 42810296Ssam else if (*local == '|') { 42926048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 43035659Sbostic fin = popen(local + 1, "r"); 43110296Ssam if (fin == NULL) { 43226048Sminshall perror(local + 1); 43326048Sminshall (void) signal(SIGINT, oldintr); 43426048Sminshall (void) signal(SIGPIPE, oldintp); 43526048Sminshall code = -1; 43626048Sminshall return; 43710296Ssam } 43835659Sbostic closefunc = pclose; 43910296Ssam } else { 44010296Ssam fin = fopen(local, "r"); 44110296Ssam if (fin == NULL) { 44210296Ssam perror(local); 44326048Sminshall (void) signal(SIGINT, oldintr); 44426048Sminshall code = -1; 44526048Sminshall return; 44610296Ssam } 44710296Ssam closefunc = fclose; 44810296Ssam if (fstat(fileno(fin), &st) < 0 || 44910296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 45026496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 45126048Sminshall (void) signal(SIGINT, oldintr); 452*36935Skarels fclose(fin); 45326048Sminshall code = -1; 45426048Sminshall return; 45510296Ssam } 45610296Ssam } 45726048Sminshall if (initconn()) { 45826048Sminshall (void) signal(SIGINT, oldintr); 45926448Slepreau if (oldintp) 46026048Sminshall (void) signal(SIGPIPE, oldintp); 46126048Sminshall code = -1; 462*36935Skarels if (closefunc != NULL) 463*36935Skarels (*closefunc)(fin); 46426048Sminshall return; 46526048Sminshall } 46626448Slepreau if (setjmp(sendabort)) 46726048Sminshall goto abort; 468*36935Skarels 469*36935Skarels if (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0) { 470*36935Skarels if (restart_point) { 471*36935Skarels if (fseek(fin, (long) restart_point, 0) < 0) { 472*36935Skarels perror(local); 473*36935Skarels restart_point = 0; 474*36935Skarels if (closefunc != NULL) 475*36935Skarels (*closefunc)(fin); 476*36935Skarels return; 477*36935Skarels } 478*36935Skarels if (command("REST %ld", (long) restart_point) 479*36935Skarels != CONTINUE) { 480*36935Skarels restart_point = 0; 481*36935Skarels if (closefunc != NULL) 482*36935Skarels (*closefunc)(fin); 483*36935Skarels return; 484*36935Skarels } 485*36935Skarels restart_point = 0; 486*36935Skarels mode = "r+w"; 487*36935Skarels } 488*36935Skarels } 48910296Ssam if (remote) { 49026048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 49126048Sminshall (void) signal(SIGINT, oldintr); 49226448Slepreau if (oldintp) 49326048Sminshall (void) signal(SIGPIPE, oldintp); 494*36935Skarels if (closefunc != NULL) 495*36935Skarels (*closefunc)(fin); 49626048Sminshall return; 49726048Sminshall } 49810296Ssam } else 49926048Sminshall if (command("%s", cmd) != PRELIM) { 50026048Sminshall (void) signal(SIGINT, oldintr); 50126448Slepreau if (oldintp) 50226048Sminshall (void) signal(SIGPIPE, oldintp); 503*36935Skarels if (closefunc != NULL) 504*36935Skarels (*closefunc)(fin); 50526048Sminshall return; 50626048Sminshall } 507*36935Skarels dout = dataconn(mode); 50826448Slepreau if (dout == NULL) 50926048Sminshall goto abort; 51026496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 511*36935Skarels oldintp = signal(SIGPIPE, SIG_IGN); 51211219Ssam switch (type) { 51311219Ssam 51411219Ssam case TYPE_I: 51511219Ssam case TYPE_L: 51611346Ssam errno = d = 0; 51711219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 518*36935Skarels if ((d = write(fileno (dout), buf, c)) != c) 51911219Ssam break; 52011219Ssam bytes += c; 52111651Ssam if (hash) { 52226496Sminshall (void) putchar('#'); 52326496Sminshall (void) fflush(stdout); 52411651Ssam } 52511219Ssam } 52613213Ssam if (hash && bytes > 0) { 52726496Sminshall (void) putchar('\n'); 52826496Sminshall (void) fflush(stdout); 52911651Ssam } 53011219Ssam if (c < 0) 53111219Ssam perror(local); 532*36935Skarels if (d < 0) { 533*36935Skarels if (errno != EPIPE) 534*36935Skarels perror("netout"); 535*36935Skarels bytes = -1; 536*36935Skarels } 53711219Ssam break; 53811219Ssam 53911219Ssam case TYPE_A: 54011219Ssam while ((c = getc(fin)) != EOF) { 54111219Ssam if (c == '\n') { 54211651Ssam while (hash && (bytes >= hashbytes)) { 54326496Sminshall (void) putchar('#'); 54426496Sminshall (void) fflush(stdout); 54511651Ssam hashbytes += sizeof (buf); 54611651Ssam } 54711219Ssam if (ferror(dout)) 54811219Ssam break; 54926496Sminshall (void) putc('\r', dout); 55011219Ssam bytes++; 55111219Ssam } 55226496Sminshall (void) putc(c, dout); 55311219Ssam bytes++; 55426048Sminshall /* if (c == '\r') { */ 55526496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 55626048Sminshall /* bytes++; */ 55726048Sminshall /* } */ 55811219Ssam } 55911651Ssam if (hash) { 56013213Ssam if (bytes < hashbytes) 56126496Sminshall (void) putchar('#'); 56226496Sminshall (void) putchar('\n'); 56326496Sminshall (void) fflush(stdout); 56411651Ssam } 56511219Ssam if (ferror(fin)) 56611219Ssam perror(local); 567*36935Skarels if (ferror(dout)) { 568*36935Skarels if (errno != EPIPE) 569*36935Skarels perror("netout"); 570*36935Skarels bytes = -1; 571*36935Skarels } 57211219Ssam break; 57310296Ssam } 57426496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 57510296Ssam if (closefunc != NULL) 57626048Sminshall (*closefunc)(fin); 57710296Ssam (void) fclose(dout); 57826048Sminshall (void) getreply(0); 57926048Sminshall (void) signal(SIGINT, oldintr); 580*36935Skarels if (oldintp) 581*36935Skarels (void) signal(SIGPIPE, oldintp); 58235699Sbostic if (bytes > 0) 58326048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 58410296Ssam return; 58526048Sminshall abort: 58626496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 58726048Sminshall (void) signal(SIGINT, oldintr); 58826448Slepreau if (oldintp) 58926048Sminshall (void) signal(SIGPIPE, oldintp); 59026048Sminshall if (!cpend) { 59126048Sminshall code = -1; 59226048Sminshall return; 59326048Sminshall } 59426048Sminshall if (data >= 0) { 59526048Sminshall (void) close(data); 59626048Sminshall data = -1; 59726048Sminshall } 59826448Slepreau if (dout) 59926048Sminshall (void) fclose(dout); 60026048Sminshall (void) getreply(0); 60126048Sminshall code = -1; 60210296Ssam if (closefunc != NULL && fin != NULL) 60326048Sminshall (*closefunc)(fin); 60435699Sbostic if (bytes > 0) 60526048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 60610296Ssam } 60710296Ssam 60810296Ssam jmp_buf recvabort; 60910296Ssam 61010296Ssam abortrecv() 61110296Ssam { 61210296Ssam 61326048Sminshall mflag = 0; 61426048Sminshall abrtflag = 0; 61526048Sminshall printf("\n"); 61626048Sminshall (void) fflush(stdout); 61710296Ssam longjmp(recvabort, 1); 61810296Ssam } 61910296Ssam 62011651Ssam recvrequest(cmd, local, remote, mode) 62111651Ssam char *cmd, *local, *remote, *mode; 62210296Ssam { 62335659Sbostic FILE *fout, *din = 0, *popen(); 62435659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 625*36935Skarels int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd; 62627687Sminshall char buf[BUFSIZ], *gunique(), msg; 62726496Sminshall long bytes = 0, hashbytes = sizeof (buf); 62826496Sminshall struct fd_set mask; 62911346Ssam register int c, d; 63010296Ssam struct timeval start, stop; 63110296Ssam 632*36935Skarels is_retr = strcmp(cmd, "RETR") == 0; 633*36935Skarels if (proxy && is_retr) { 63426048Sminshall proxtrans(cmd, local, remote); 63526048Sminshall return; 63626048Sminshall } 63710296Ssam closefunc = NULL; 63826048Sminshall oldintr = NULL; 63926048Sminshall oldintp = NULL; 640*36935Skarels tcrflag = !crflag && is_retr; 64126048Sminshall if (setjmp(recvabort)) { 64226048Sminshall while (cpend) { 64326048Sminshall (void) getreply(0); 64426048Sminshall } 64526048Sminshall if (data >= 0) { 64626048Sminshall (void) close(data); 64726048Sminshall data = -1; 64826048Sminshall } 64926448Slepreau if (oldintr) 65026048Sminshall (void) signal(SIGINT, oldintr); 65126048Sminshall code = -1; 65226048Sminshall return; 65326048Sminshall } 65410296Ssam oldintr = signal(SIGINT, abortrecv); 65526048Sminshall if (strcmp(local, "-") && *local != '|') { 65610296Ssam if (access(local, 2) < 0) { 65726048Sminshall char *dir = rindex(local, '/'); 65810296Ssam 65926048Sminshall if (errno != ENOENT && errno != EACCES) { 66010296Ssam perror(local); 66126048Sminshall (void) signal(SIGINT, oldintr); 66226048Sminshall code = -1; 66326048Sminshall return; 66410296Ssam } 66526048Sminshall if (dir != NULL) 66626048Sminshall *dir = 0; 66726048Sminshall d = access(dir ? local : ".", 2); 66826048Sminshall if (dir != NULL) 66926048Sminshall *dir = '/'; 67026048Sminshall if (d < 0) { 67126048Sminshall perror(local); 67226048Sminshall (void) signal(SIGINT, oldintr); 67326048Sminshall code = -1; 67426048Sminshall return; 67526048Sminshall } 67626048Sminshall if (!runique && errno == EACCES && 677*36935Skarels chmod(local, 0600) < 0) { 67826048Sminshall perror(local); 67926048Sminshall (void) signal(SIGINT, oldintr); 68026048Sminshall code = -1; 68126048Sminshall return; 68226048Sminshall } 68326048Sminshall if (runique && errno == EACCES && 68426048Sminshall (local = gunique(local)) == NULL) { 68526048Sminshall (void) signal(SIGINT, oldintr); 68626048Sminshall code = -1; 68726048Sminshall return; 68826048Sminshall } 68910296Ssam } 69026048Sminshall else if (runique && (local = gunique(local)) == NULL) { 69126048Sminshall (void) signal(SIGINT, oldintr); 69226048Sminshall code = -1; 69326048Sminshall return; 69426048Sminshall } 69526048Sminshall } 69626048Sminshall if (initconn()) { 69726048Sminshall (void) signal(SIGINT, oldintr); 69826048Sminshall code = -1; 69926048Sminshall return; 70026048Sminshall } 70126448Slepreau if (setjmp(recvabort)) 70226048Sminshall goto abort; 703*36935Skarels if (!is_retr) { 704*36935Skarels if (type != TYPE_A) { 705*36935Skarels oldtype = type; 706*36935Skarels oldverbose = verbose; 707*36935Skarels if (!debug) 708*36935Skarels verbose = 0; 709*36935Skarels setascii(); 710*36935Skarels verbose = oldverbose; 711*36935Skarels } 712*36935Skarels } else if (restart_point) { 713*36935Skarels if (command("REST %ld", (long) restart_point) != CONTINUE) 714*36935Skarels return; 71526048Sminshall } 71610296Ssam if (remote) { 71726048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 71826048Sminshall (void) signal(SIGINT, oldintr); 71926048Sminshall if (oldtype) { 72026448Slepreau if (!debug) 72126048Sminshall verbose = 0; 72226048Sminshall switch (oldtype) { 72326048Sminshall case TYPE_I: 72426048Sminshall setbinary(); 72526048Sminshall break; 72626048Sminshall case TYPE_E: 72726048Sminshall setebcdic(); 72826048Sminshall break; 72926048Sminshall case TYPE_L: 73026048Sminshall settenex(); 73126048Sminshall break; 732*36935Skarels } 73326048Sminshall verbose = oldverbose; 73426048Sminshall } 73526048Sminshall return; 73626048Sminshall } 73726048Sminshall } else { 73826048Sminshall if (command("%s", cmd) != PRELIM) { 73926048Sminshall (void) signal(SIGINT, oldintr); 74026048Sminshall if (oldtype) { 74126448Slepreau if (!debug) 74226048Sminshall verbose = 0; 74326048Sminshall switch (oldtype) { 74426048Sminshall case TYPE_I: 74526048Sminshall setbinary(); 74626048Sminshall break; 74726048Sminshall case TYPE_E: 74826048Sminshall setebcdic(); 74926048Sminshall break; 75026048Sminshall case TYPE_L: 75126048Sminshall settenex(); 75226048Sminshall break; 753*36935Skarels } 75426048Sminshall verbose = oldverbose; 75526048Sminshall } 75626048Sminshall return; 75726048Sminshall } 75826048Sminshall } 75926048Sminshall din = dataconn("r"); 76026048Sminshall if (din == NULL) 76126048Sminshall goto abort; 76226448Slepreau if (strcmp(local, "-") == 0) 76310296Ssam fout = stdout; 76410296Ssam else if (*local == '|') { 76526048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 76635659Sbostic fout = popen(local + 1, "w"); 76726048Sminshall if (fout == NULL) { 76826048Sminshall perror(local+1); 76926048Sminshall goto abort; 77026048Sminshall } 77135659Sbostic closefunc = pclose; 77226048Sminshall } 77326048Sminshall else { 77411651Ssam fout = fopen(local, mode); 77526048Sminshall if (fout == NULL) { 77626048Sminshall perror(local); 77726048Sminshall goto abort; 77826048Sminshall } 77910296Ssam closefunc = fclose; 78010296Ssam } 78126496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 78211219Ssam switch (type) { 78311219Ssam 78411219Ssam case TYPE_I: 78511219Ssam case TYPE_L: 786*36935Skarels if (restart_point && 787*36935Skarels lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 788*36935Skarels perror(local); 789*36935Skarels if (closefunc != NULL) 790*36935Skarels (*closefunc)(fout); 791*36935Skarels return; 792*36935Skarels } 79311346Ssam errno = d = 0; 79411219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 795*36935Skarels if ((d = write(fileno(fout), buf, c)) != c) 79611219Ssam break; 79711219Ssam bytes += c; 79811651Ssam if (hash) { 79926496Sminshall (void) putchar('#'); 80026496Sminshall (void) fflush(stdout); 80111651Ssam } 80211219Ssam } 80313213Ssam if (hash && bytes > 0) { 80426496Sminshall (void) putchar('\n'); 80526496Sminshall (void) fflush(stdout); 80611651Ssam } 807*36935Skarels if (c < 0) { 808*36935Skarels if (errno != EPIPE) 809*36935Skarels perror("netin"); 810*36935Skarels bytes = -1; 811*36935Skarels } 81211346Ssam if (d < 0) 81310296Ssam perror(local); 81411219Ssam break; 81511219Ssam 81611219Ssam case TYPE_A: 817*36935Skarels if (restart_point) { 818*36935Skarels register int i, n, c; 819*36935Skarels if (fseek(fout, 0L, L_SET) < 0) 820*36935Skarels goto done; 821*36935Skarels n = restart_point; 822*36935Skarels i = 0; 823*36935Skarels while(i++ < n) { 824*36935Skarels if ((c=getc(fout)) == EOF) 825*36935Skarels goto done; 826*36935Skarels if (c == '\n') 827*36935Skarels i++; 828*36935Skarels } 829*36935Skarels if (fseek(fout, 0L, L_INCR) < 0) { 830*36935Skarels done: 831*36935Skarels perror(local); 832*36935Skarels if (closefunc != NULL) 833*36935Skarels (*closefunc)(fout); 834*36935Skarels return; 835*36935Skarels } 836*36935Skarels } 83711219Ssam while ((c = getc(din)) != EOF) { 83827749Sminshall while (c == '\r') { 83911651Ssam while (hash && (bytes >= hashbytes)) { 84026496Sminshall (void) putchar('#'); 84126496Sminshall (void) fflush(stdout); 84211651Ssam hashbytes += sizeof (buf); 84311651Ssam } 84410296Ssam bytes++; 84526048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 84611219Ssam if (ferror (fout)) 84711219Ssam break; 84826496Sminshall (void) putc ('\r', fout); 84911219Ssam } 85011219Ssam } 85126496Sminshall (void) putc (c, fout); 85211219Ssam bytes++; 85310296Ssam } 85411651Ssam if (hash) { 85513213Ssam if (bytes < hashbytes) 85626496Sminshall (void) putchar('#'); 85726496Sminshall (void) putchar('\n'); 85826496Sminshall (void) fflush(stdout); 85911651Ssam } 860*36935Skarels if (ferror (din)){ 861*36935Skarels if (errno != EPIPE) 862*36935Skarels perror ("netin"); 863*36935Skarels bytes = -1; 864*36935Skarels } 86511219Ssam if (ferror (fout)) 86611219Ssam perror (local); 86711219Ssam break; 86810296Ssam } 86926448Slepreau if (closefunc != NULL) 87026048Sminshall (*closefunc)(fout); 87126496Sminshall (void) signal(SIGINT, oldintr); 87226448Slepreau if (oldintp) 87326048Sminshall (void) signal(SIGPIPE, oldintp); 87426496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 87510296Ssam (void) fclose(din); 87626048Sminshall (void) getreply(0); 877*36935Skarels if (bytes > 0 && is_retr) 87826048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 87926048Sminshall if (oldtype) { 88026448Slepreau if (!debug) 88126048Sminshall verbose = 0; 88226048Sminshall switch (oldtype) { 88326048Sminshall case TYPE_I: 88426048Sminshall setbinary(); 88526048Sminshall break; 88626048Sminshall case TYPE_E: 88726048Sminshall setebcdic(); 88826048Sminshall break; 88926048Sminshall case TYPE_L: 89026048Sminshall settenex(); 89126048Sminshall break; 89226048Sminshall } 89326048Sminshall verbose = oldverbose; 89426048Sminshall } 89526048Sminshall return; 89626048Sminshall abort: 89726048Sminshall 89827687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 89926048Sminshall 90026496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 90126448Slepreau if (oldintp) 90226048Sminshall (void) signal(SIGPIPE, oldintr); 90326048Sminshall (void) signal(SIGINT,SIG_IGN); 90426048Sminshall if (oldtype) { 90526448Slepreau if (!debug) 90626048Sminshall verbose = 0; 90726048Sminshall switch (oldtype) { 90826048Sminshall case TYPE_I: 90926048Sminshall setbinary(); 91026048Sminshall break; 91126048Sminshall case TYPE_E: 91226048Sminshall setebcdic(); 91326048Sminshall break; 91426048Sminshall case TYPE_L: 91526048Sminshall settenex(); 91626048Sminshall break; 91726048Sminshall } 91826048Sminshall verbose = oldverbose; 91926048Sminshall } 92026048Sminshall if (!cpend) { 92126048Sminshall code = -1; 92226048Sminshall (void) signal(SIGINT,oldintr); 92326048Sminshall return; 92426048Sminshall } 92526048Sminshall 92627687Sminshall fprintf(cout,"%c%c",IAC,IP); 92727687Sminshall (void) fflush(cout); 92827687Sminshall msg = IAC; 92927687Sminshall /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 93027687Sminshall /* after urgent byte rather than before as now is protocol */ 93127687Sminshall if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 93227687Sminshall perror("abort"); 93326048Sminshall } 93427687Sminshall fprintf(cout,"%cABOR\r\n",DM); 93526048Sminshall (void) fflush(cout); 93627687Sminshall FD_ZERO(&mask); 93726496Sminshall FD_SET(fileno(cin), &mask); 93826496Sminshall if (din) { 93926496Sminshall FD_SET(fileno(din), &mask); 94026496Sminshall } 94127687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 94227687Sminshall if (nfnd < 0) { 94327687Sminshall perror("abort"); 94427687Sminshall } 94526048Sminshall code = -1; 94626048Sminshall lostpeer(); 94726048Sminshall } 94826496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 94926448Slepreau while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 95026448Slepreau ; 95126496Sminshall } 95227687Sminshall if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 95326048Sminshall if (data >= 0) { 95426496Sminshall (void) close(data); 95526048Sminshall data = -1; 95626048Sminshall } 95725907Smckusick (void) getreply(0); 95825907Smckusick } 95926048Sminshall (void) getreply(0); 96026048Sminshall code = -1; 96126048Sminshall if (data >= 0) { 96226048Sminshall (void) close(data); 96326048Sminshall data = -1; 96426048Sminshall } 96526448Slepreau if (closefunc != NULL && fout != NULL) 96626048Sminshall (*closefunc)(fout); 96726448Slepreau if (din) 96826048Sminshall (void) fclose(din); 96935699Sbostic if (bytes > 0) 97026048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 97126048Sminshall (void) signal(SIGINT,oldintr); 97210296Ssam } 97310296Ssam 97410296Ssam /* 97510296Ssam * Need to start a listen on the data channel 97610296Ssam * before we send the command, otherwise the 97710296Ssam * server's connect may fail. 97810296Ssam */ 97933224Sbostic int sendport = -1; 98011651Ssam 98110296Ssam initconn() 98210296Ssam { 98310296Ssam register char *p, *a; 98426048Sminshall int result, len, tmpno = 0; 98526993Skarels int on = 1; 98610296Ssam 98711651Ssam noport: 98810296Ssam data_addr = myctladdr; 98911651Ssam if (sendport) 99011651Ssam data_addr.sin_port = 0; /* let system pick one */ 99111651Ssam if (data != -1) 99211651Ssam (void) close (data); 99318287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 99410296Ssam if (data < 0) { 99510296Ssam perror("ftp: socket"); 99626448Slepreau if (tmpno) 99726048Sminshall sendport = 1; 99810296Ssam return (1); 99910296Ssam } 100012397Ssam if (!sendport) 100127687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 100233224Sbostic perror("ftp: setsockopt (reuse address)"); 100312397Ssam goto bad; 100412397Ssam } 100526496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 100610296Ssam perror("ftp: bind"); 100710296Ssam goto bad; 100810296Ssam } 100910296Ssam if (options & SO_DEBUG && 101027687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 101110296Ssam perror("ftp: setsockopt (ignored)"); 101211627Ssam len = sizeof (data_addr); 101311627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 101411627Ssam perror("ftp: getsockname"); 101510296Ssam goto bad; 101610296Ssam } 101726448Slepreau if (listen(data, 1) < 0) 101810296Ssam perror("ftp: listen"); 101911651Ssam if (sendport) { 102011651Ssam a = (char *)&data_addr.sin_addr; 102111651Ssam p = (char *)&data_addr.sin_port; 102210296Ssam #define UC(b) (((int)b)&0xff) 102311651Ssam result = 102411651Ssam command("PORT %d,%d,%d,%d,%d,%d", 102511651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 102611651Ssam UC(p[0]), UC(p[1])); 102711651Ssam if (result == ERROR && sendport == -1) { 102811651Ssam sendport = 0; 102926048Sminshall tmpno = 1; 103011651Ssam goto noport; 103111651Ssam } 103211651Ssam return (result != COMPLETE); 103311651Ssam } 103426448Slepreau if (tmpno) 103526048Sminshall sendport = 1; 103611651Ssam return (0); 103710296Ssam bad: 103810296Ssam (void) close(data), data = -1; 103926448Slepreau if (tmpno) 104026048Sminshall sendport = 1; 104110296Ssam return (1); 104210296Ssam } 104310296Ssam 104410296Ssam FILE * 104510296Ssam dataconn(mode) 104610296Ssam char *mode; 104710296Ssam { 104810296Ssam struct sockaddr_in from; 104910296Ssam int s, fromlen = sizeof (from); 105010296Ssam 105126496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 105210296Ssam if (s < 0) { 105310296Ssam perror("ftp: accept"); 105410296Ssam (void) close(data), data = -1; 105510296Ssam return (NULL); 105610296Ssam } 105710296Ssam (void) close(data); 105810296Ssam data = s; 105910296Ssam return (fdopen(data, mode)); 106010296Ssam } 106110296Ssam 106226048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 106326048Sminshall char *direction, *local, *remote; 106411651Ssam long bytes; 106510296Ssam struct timeval *t0, *t1; 106610296Ssam { 106710296Ssam struct timeval td; 106816437Sleres float s, bs; 106910296Ssam 107035699Sbostic if (verbose) { 107135699Sbostic tvsub(&td, t1, t0); 107235699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 107310296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 107435699Sbostic bs = bytes / nz(s); 107535699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 107635699Sbostic bytes, direction, s, bs / 1024.); 107735699Sbostic } else { 107835699Sbostic if (local && *local != '-') 107935699Sbostic printf("local: %s ", local); 108035699Sbostic if (remote) 108135699Sbostic printf("remote: %s\n", remote); 108235699Sbostic } 108310296Ssam } 108410296Ssam 108526496Sminshall /*tvadd(tsum, t0) 108610296Ssam struct timeval *tsum, *t0; 108710296Ssam { 108810296Ssam 108910296Ssam tsum->tv_sec += t0->tv_sec; 109010296Ssam tsum->tv_usec += t0->tv_usec; 109110296Ssam if (tsum->tv_usec > 1000000) 109210296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 109326496Sminshall } */ 109410296Ssam 109510296Ssam tvsub(tdiff, t1, t0) 109610296Ssam struct timeval *tdiff, *t1, *t0; 109710296Ssam { 109810296Ssam 109910296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 110010296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 110110296Ssam if (tdiff->tv_usec < 0) 110210296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 110310296Ssam } 110426048Sminshall 110526048Sminshall psabort() 110626048Sminshall { 110726048Sminshall extern int abrtflag; 110826048Sminshall 110926048Sminshall abrtflag++; 111026048Sminshall } 111126048Sminshall 111226048Sminshall pswitch(flag) 111326048Sminshall int flag; 111426048Sminshall { 111526048Sminshall extern int proxy, abrtflag; 111626048Sminshall int (*oldintr)(); 111726048Sminshall static struct comvars { 111826048Sminshall int connect; 111928469Skarels char name[MAXHOSTNAMELEN]; 112026048Sminshall struct sockaddr_in mctl; 112126048Sminshall struct sockaddr_in hctl; 112226048Sminshall FILE *in; 112326048Sminshall FILE *out; 112426048Sminshall int tpe; 112526048Sminshall int cpnd; 112626048Sminshall int sunqe; 112726048Sminshall int runqe; 112826048Sminshall int mcse; 112926048Sminshall int ntflg; 113026048Sminshall char nti[17]; 113126048Sminshall char nto[17]; 113226048Sminshall int mapflg; 113326048Sminshall char mi[MAXPATHLEN]; 113426048Sminshall char mo[MAXPATHLEN]; 113526048Sminshall } proxstruct, tmpstruct; 113626048Sminshall struct comvars *ip, *op; 113726048Sminshall 113826048Sminshall abrtflag = 0; 113926048Sminshall oldintr = signal(SIGINT, psabort); 114026048Sminshall if (flag) { 114126448Slepreau if (proxy) 114226048Sminshall return; 114326048Sminshall ip = &tmpstruct; 114426048Sminshall op = &proxstruct; 114526048Sminshall proxy++; 114626048Sminshall } 114726048Sminshall else { 114826448Slepreau if (!proxy) 114926048Sminshall return; 115026048Sminshall ip = &proxstruct; 115126048Sminshall op = &tmpstruct; 115226048Sminshall proxy = 0; 115326048Sminshall } 115426048Sminshall ip->connect = connected; 115526048Sminshall connected = op->connect; 115628469Skarels if (hostname) { 115728469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 115828469Skarels ip->name[strlen(ip->name)] = '\0'; 115928469Skarels } else 116028469Skarels ip->name[0] = 0; 116126048Sminshall hostname = op->name; 116226048Sminshall ip->hctl = hisctladdr; 116326048Sminshall hisctladdr = op->hctl; 116426048Sminshall ip->mctl = myctladdr; 116526048Sminshall myctladdr = op->mctl; 116626048Sminshall ip->in = cin; 116726048Sminshall cin = op->in; 116826048Sminshall ip->out = cout; 116926048Sminshall cout = op->out; 117026048Sminshall ip->tpe = type; 117126048Sminshall type = op->tpe; 117226448Slepreau if (!type) 117326048Sminshall type = 1; 117426048Sminshall ip->cpnd = cpend; 117526048Sminshall cpend = op->cpnd; 117626048Sminshall ip->sunqe = sunique; 117726048Sminshall sunique = op->sunqe; 117826048Sminshall ip->runqe = runique; 117926048Sminshall runique = op->runqe; 118026048Sminshall ip->mcse = mcase; 118126048Sminshall mcase = op->mcse; 118226048Sminshall ip->ntflg = ntflag; 118326048Sminshall ntflag = op->ntflg; 118426496Sminshall (void) strncpy(ip->nti, ntin, 16); 118526048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 118626496Sminshall (void) strcpy(ntin, op->nti); 118726496Sminshall (void) strncpy(ip->nto, ntout, 16); 118826048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 118926496Sminshall (void) strcpy(ntout, op->nto); 119026048Sminshall ip->mapflg = mapflag; 119126048Sminshall mapflag = op->mapflg; 119226496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 119326048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 119426496Sminshall (void) strcpy(mapin, op->mi); 119526496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 119626048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 119726496Sminshall (void) strcpy(mapout, op->mo); 119826048Sminshall (void) signal(SIGINT, oldintr); 119926048Sminshall if (abrtflag) { 120026048Sminshall abrtflag = 0; 120126048Sminshall (*oldintr)(); 120226448Slepreau } 120326048Sminshall } 120426048Sminshall 120526048Sminshall jmp_buf ptabort; 120626048Sminshall int ptabflg; 120726048Sminshall 120826048Sminshall abortpt() 120926048Sminshall { 121026048Sminshall printf("\n"); 121126496Sminshall (void) fflush(stdout); 121226048Sminshall ptabflg++; 121326048Sminshall mflag = 0; 121426048Sminshall abrtflag = 0; 121526048Sminshall longjmp(ptabort, 1); 121626048Sminshall } 121726048Sminshall 121826048Sminshall proxtrans(cmd, local, remote) 121926048Sminshall char *cmd, *local, *remote; 122026048Sminshall { 122127687Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 122226048Sminshall extern jmp_buf ptabort; 122326048Sminshall char *cmd2; 122426496Sminshall struct fd_set mask; 122526048Sminshall 122626448Slepreau if (strcmp(cmd, "RETR")) 122726048Sminshall cmd2 = "RETR"; 122826448Slepreau else 122926048Sminshall cmd2 = runique ? "STOU" : "STOR"; 123026048Sminshall if (command("PASV") != COMPLETE) { 123126048Sminshall printf("proxy server does not support third part transfers.\n"); 123226048Sminshall return; 123326048Sminshall } 123426048Sminshall tmptype = type; 123526048Sminshall pswitch(0); 123626048Sminshall if (!connected) { 123726048Sminshall printf("No primary connection\n"); 123826048Sminshall pswitch(1); 123926048Sminshall code = -1; 124026048Sminshall return; 124126048Sminshall } 124226048Sminshall if (type != tmptype) { 124326048Sminshall oldtype = type; 124426048Sminshall switch (tmptype) { 124526048Sminshall case TYPE_A: 124626048Sminshall setascii(); 124726048Sminshall break; 124826048Sminshall case TYPE_I: 124926048Sminshall setbinary(); 125026048Sminshall break; 125126048Sminshall case TYPE_E: 125226048Sminshall setebcdic(); 125326048Sminshall break; 125426048Sminshall case TYPE_L: 125526048Sminshall settenex(); 125626048Sminshall break; 125726048Sminshall } 125826048Sminshall } 125926048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 126026048Sminshall switch (oldtype) { 126126048Sminshall case 0: 126226048Sminshall break; 126326048Sminshall case TYPE_A: 126426048Sminshall setascii(); 126526048Sminshall break; 126626048Sminshall case TYPE_I: 126726048Sminshall setbinary(); 126826048Sminshall break; 126926048Sminshall case TYPE_E: 127026048Sminshall setebcdic(); 127126048Sminshall break; 127226048Sminshall case TYPE_L: 127326048Sminshall settenex(); 127426048Sminshall break; 127526048Sminshall } 127626048Sminshall pswitch(1); 127726048Sminshall return; 127826048Sminshall } 127926448Slepreau if (setjmp(ptabort)) 128026048Sminshall goto abort; 128126048Sminshall oldintr = signal(SIGINT, abortpt); 128226048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 128326048Sminshall (void) signal(SIGINT, oldintr); 128426048Sminshall switch (oldtype) { 128526048Sminshall case 0: 128626048Sminshall break; 128726048Sminshall case TYPE_A: 128826048Sminshall setascii(); 128926048Sminshall break; 129026048Sminshall case TYPE_I: 129126048Sminshall setbinary(); 129226048Sminshall break; 129326048Sminshall case TYPE_E: 129426048Sminshall setebcdic(); 129526048Sminshall break; 129626048Sminshall case TYPE_L: 129726048Sminshall settenex(); 129826048Sminshall break; 129926048Sminshall } 130026048Sminshall pswitch(1); 130126048Sminshall return; 130226048Sminshall } 130326048Sminshall sleep(2); 130426048Sminshall pswitch(1); 130526048Sminshall secndflag++; 130626448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 130726048Sminshall goto abort; 130826048Sminshall ptflag++; 130926048Sminshall (void) getreply(0); 131026048Sminshall pswitch(0); 131126048Sminshall (void) getreply(0); 131226048Sminshall (void) signal(SIGINT, oldintr); 131326048Sminshall switch (oldtype) { 131426048Sminshall case 0: 131526048Sminshall break; 131626048Sminshall case TYPE_A: 131726048Sminshall setascii(); 131826048Sminshall break; 131926048Sminshall case TYPE_I: 132026048Sminshall setbinary(); 132126048Sminshall break; 132226048Sminshall case TYPE_E: 132326048Sminshall setebcdic(); 132426048Sminshall break; 132526048Sminshall case TYPE_L: 132626048Sminshall settenex(); 132726048Sminshall break; 132826048Sminshall } 132926048Sminshall pswitch(1); 133026048Sminshall ptflag = 0; 133126048Sminshall printf("local: %s remote: %s\n", local, remote); 133226048Sminshall return; 133326048Sminshall abort: 133426048Sminshall (void) signal(SIGINT, SIG_IGN); 133526048Sminshall ptflag = 0; 133626448Slepreau if (strcmp(cmd, "RETR") && !proxy) 133726048Sminshall pswitch(1); 133826448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 133926048Sminshall pswitch(0); 134026048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 134126048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 134226048Sminshall pswitch(0); 134326048Sminshall switch (oldtype) { 134426048Sminshall case 0: 134526048Sminshall break; 134626048Sminshall case TYPE_A: 134726048Sminshall setascii(); 134826048Sminshall break; 134926048Sminshall case TYPE_I: 135026048Sminshall setbinary(); 135126048Sminshall break; 135226048Sminshall case TYPE_E: 135326048Sminshall setebcdic(); 135426048Sminshall break; 135526048Sminshall case TYPE_L: 135626048Sminshall settenex(); 135726048Sminshall break; 135826048Sminshall } 135927687Sminshall if (cpend) { 136026048Sminshall char msg[2]; 136126048Sminshall 136226048Sminshall fprintf(cout,"%c%c",IAC,IP); 136326048Sminshall (void) fflush(cout); 136426048Sminshall *msg = IAC; 136526048Sminshall *(msg+1) = DM; 136626448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 136726048Sminshall perror("abort"); 136826048Sminshall fprintf(cout,"ABOR\r\n"); 136926048Sminshall (void) fflush(cout); 137027687Sminshall FD_ZERO(&mask); 137126496Sminshall FD_SET(fileno(cin), &mask); 137227687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 137327687Sminshall if (nfnd < 0) { 137427687Sminshall perror("abort"); 137527687Sminshall } 137626448Slepreau if (ptabflg) 137726048Sminshall code = -1; 137826048Sminshall lostpeer(); 137926048Sminshall } 138026048Sminshall (void) getreply(0); 138126048Sminshall (void) getreply(0); 138226048Sminshall } 138326048Sminshall } 138426048Sminshall pswitch(1); 138526448Slepreau if (ptabflg) 138626048Sminshall code = -1; 138726048Sminshall (void) signal(SIGINT, oldintr); 138826048Sminshall return; 138926048Sminshall } 139027687Sminshall if (cpend) { 139126048Sminshall char msg[2]; 139226048Sminshall 139326048Sminshall fprintf(cout,"%c%c",IAC,IP); 139426048Sminshall (void) fflush(cout); 139526048Sminshall *msg = IAC; 139626048Sminshall *(msg+1) = DM; 139726448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 139826048Sminshall perror("abort"); 139926048Sminshall fprintf(cout,"ABOR\r\n"); 140026048Sminshall (void) fflush(cout); 140127687Sminshall FD_ZERO(&mask); 140226496Sminshall FD_SET(fileno(cin), &mask); 140327687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 140427687Sminshall if (nfnd < 0) { 140527687Sminshall perror("abort"); 140627687Sminshall } 140726448Slepreau if (ptabflg) 140826048Sminshall code = -1; 140926048Sminshall lostpeer(); 141026048Sminshall } 141126048Sminshall (void) getreply(0); 141226048Sminshall (void) getreply(0); 141326048Sminshall } 141426048Sminshall pswitch(!proxy); 141526048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 141626048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 141726048Sminshall pswitch(0); 141826048Sminshall switch (oldtype) { 141926048Sminshall case 0: 142026048Sminshall break; 142126048Sminshall case TYPE_A: 142226048Sminshall setascii(); 142326048Sminshall break; 142426048Sminshall case TYPE_I: 142526048Sminshall setbinary(); 142626048Sminshall break; 142726048Sminshall case TYPE_E: 142826048Sminshall setebcdic(); 142926048Sminshall break; 143026048Sminshall case TYPE_L: 143126048Sminshall settenex(); 143226048Sminshall break; 143326048Sminshall } 143427687Sminshall if (cpend) { 143526048Sminshall char msg[2]; 143626048Sminshall 143726048Sminshall fprintf(cout,"%c%c",IAC,IP); 143826048Sminshall (void) fflush(cout); 143926048Sminshall *msg = IAC; 144026048Sminshall *(msg+1) = DM; 144126448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 144226048Sminshall perror("abort"); 144326048Sminshall fprintf(cout,"ABOR\r\n"); 144426048Sminshall (void) fflush(cout); 144527687Sminshall FD_ZERO(&mask); 144626496Sminshall FD_SET(fileno(cin), &mask); 144727687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 144827687Sminshall if (nfnd < 0) { 144927687Sminshall perror("abort"); 145027687Sminshall } 145126448Slepreau if (ptabflg) 145226048Sminshall code = -1; 145326048Sminshall lostpeer(); 145426048Sminshall } 145526048Sminshall (void) getreply(0); 145626048Sminshall (void) getreply(0); 145726048Sminshall } 145826048Sminshall pswitch(1); 145926448Slepreau if (ptabflg) 146026048Sminshall code = -1; 146126048Sminshall (void) signal(SIGINT, oldintr); 146226048Sminshall return; 146326048Sminshall } 146426048Sminshall } 146527687Sminshall if (cpend) { 146626048Sminshall char msg[2]; 146726048Sminshall 146826048Sminshall fprintf(cout,"%c%c",IAC,IP); 146926048Sminshall (void) fflush(cout); 147026048Sminshall *msg = IAC; 147126048Sminshall *(msg+1) = DM; 147226448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 147326048Sminshall perror("abort"); 147426048Sminshall fprintf(cout,"ABOR\r\n"); 147526048Sminshall (void) fflush(cout); 147627687Sminshall FD_ZERO(&mask); 147726496Sminshall FD_SET(fileno(cin), &mask); 147827687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 147927687Sminshall if (nfnd < 0) { 148027687Sminshall perror("abort"); 148127687Sminshall } 148226448Slepreau if (ptabflg) 148326048Sminshall code = -1; 148426048Sminshall lostpeer(); 148526048Sminshall } 148626048Sminshall (void) getreply(0); 148726048Sminshall (void) getreply(0); 148826048Sminshall } 148926048Sminshall pswitch(!proxy); 149026048Sminshall if (cpend) { 149127687Sminshall FD_ZERO(&mask); 149226496Sminshall FD_SET(fileno(cin), &mask); 149327687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 149427687Sminshall if (nfnd < 0) { 149527687Sminshall perror("abort"); 149627687Sminshall } 149726448Slepreau if (ptabflg) 149826048Sminshall code = -1; 149926048Sminshall lostpeer(); 150026048Sminshall } 150126048Sminshall (void) getreply(0); 150226048Sminshall (void) getreply(0); 150326048Sminshall } 150426448Slepreau if (proxy) 150526048Sminshall pswitch(0); 150626048Sminshall switch (oldtype) { 150726048Sminshall case 0: 150826048Sminshall break; 150926048Sminshall case TYPE_A: 151026048Sminshall setascii(); 151126048Sminshall break; 151226048Sminshall case TYPE_I: 151326048Sminshall setbinary(); 151426048Sminshall break; 151526048Sminshall case TYPE_E: 151626048Sminshall setebcdic(); 151726048Sminshall break; 151826048Sminshall case TYPE_L: 151926048Sminshall settenex(); 152026048Sminshall break; 152126048Sminshall } 152226048Sminshall pswitch(1); 152326448Slepreau if (ptabflg) 152426048Sminshall code = -1; 152526048Sminshall (void) signal(SIGINT, oldintr); 152626048Sminshall } 152726048Sminshall 152826048Sminshall reset() 152926048Sminshall { 153026496Sminshall struct fd_set mask; 153126496Sminshall int nfnd = 1; 153226048Sminshall 153327687Sminshall FD_ZERO(&mask); 153430946Scsvsj while (nfnd > 0) { 153526496Sminshall FD_SET(fileno(cin), &mask); 153627687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 153726048Sminshall perror("reset"); 153826048Sminshall code = -1; 153926048Sminshall lostpeer(); 154026048Sminshall } 154127687Sminshall else if (nfnd) { 154226048Sminshall (void) getreply(0); 154326496Sminshall } 154426048Sminshall } 154526048Sminshall } 154626048Sminshall 154726048Sminshall char * 154826048Sminshall gunique(local) 154926048Sminshall char *local; 155026048Sminshall { 155126048Sminshall static char new[MAXPATHLEN]; 155226048Sminshall char *cp = rindex(local, '/'); 155326048Sminshall int d, count=0; 155426048Sminshall char ext = '1'; 155526048Sminshall 155626448Slepreau if (cp) 155726048Sminshall *cp = '\0'; 155826048Sminshall d = access(cp ? local : ".", 2); 155926448Slepreau if (cp) 156026048Sminshall *cp = '/'; 156126048Sminshall if (d < 0) { 156226048Sminshall perror(local); 156326048Sminshall return((char *) 0); 156426048Sminshall } 156526048Sminshall (void) strcpy(new, local); 156626048Sminshall cp = new + strlen(new); 156726048Sminshall *cp++ = '.'; 156826048Sminshall while (!d) { 156926048Sminshall if (++count == 100) { 157026048Sminshall printf("runique: can't find unique file name.\n"); 157126048Sminshall return((char *) 0); 157226048Sminshall } 157326048Sminshall *cp++ = ext; 157426048Sminshall *cp = '\0'; 157526448Slepreau if (ext == '9') 157626048Sminshall ext = '0'; 157726448Slepreau else 157826048Sminshall ext++; 157926448Slepreau if ((d = access(new, 0)) < 0) 158026048Sminshall break; 158126448Slepreau if (ext != '0') 158226048Sminshall cp--; 158326448Slepreau else if (*(cp - 2) == '.') 158426048Sminshall *(cp - 1) = '1'; 158526048Sminshall else { 158626048Sminshall *(cp - 2) = *(cp - 2) + 1; 158726048Sminshall cp--; 158826048Sminshall } 158926048Sminshall } 159026048Sminshall return(new); 159126048Sminshall } 1592