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 1536935Skarels * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621739Sdist */ 1721739Sdist 1810296Ssam #ifndef lint 19*36940Skarels static char sccsid[] = "@(#)ftp.c 5.24 (Berkeley) 03/01/89"; 2033737Sbostic #endif /* not lint */ 2110296Ssam 22*36940Skarels #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 40*36940Skarels #include "ftp_var.h" 41*36940Skarels 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(); 5036935Skarels 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; 68*36940Skarels (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); 69*36940Skarels } 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); 80*36940Skarels (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 } 17226048Sminshall if (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 } 18126048Sminshall printf("Name (%s:%s): ", host, myname); 18226048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 18326048Sminshall tmp[strlen(tmp) - 1] = '\0'; 18426448Slepreau if (*tmp == '\0') 18526048Sminshall user = myname; 18626448Slepreau else 18726048Sminshall user = tmp; 18826048Sminshall } 18910296Ssam n = command("USER %s", user); 19026048Sminshall if (n == CONTINUE) { 19126448Slepreau if (pass == NULL) 19235659Sbostic pass = getpass("Password:"); 19310296Ssam n = command("PASS %s", pass); 19426048Sminshall } 19510296Ssam if (n == CONTINUE) { 19626048Sminshall aflag++; 19735659Sbostic acct = getpass("Account:"); 19810296Ssam n = command("ACCT %s", acct); 19910296Ssam } 20010296Ssam if (n != COMPLETE) { 20110296Ssam fprintf(stderr, "Login failed.\n"); 20210296Ssam return (0); 20310296Ssam } 20426448Slepreau if (!aflag && acct != NULL) 20526048Sminshall (void) command("ACCT %s", acct); 20626448Slepreau if (proxy) 20726048Sminshall return(1); 20826048Sminshall for (n = 0; n < macnum; ++n) { 20926048Sminshall if (!strcmp("init", macros[n].mac_name)) { 21026496Sminshall (void) strcpy(line, "$init"); 21126048Sminshall makeargv(); 21226048Sminshall domacro(margc, margv); 21326048Sminshall break; 21426048Sminshall } 21526048Sminshall } 21610296Ssam return (1); 21710296Ssam } 21810296Ssam 21926048Sminshall cmdabort() 22026048Sminshall { 22126048Sminshall extern jmp_buf ptabort; 22226048Sminshall 22326048Sminshall printf("\n"); 22426048Sminshall (void) fflush(stdout); 22526048Sminshall abrtflag++; 22626448Slepreau if (ptflag) 22726048Sminshall longjmp(ptabort,1); 22826048Sminshall } 22926048Sminshall 23026496Sminshall /*VARARGS1*/ 23110296Ssam command(fmt, args) 23210296Ssam char *fmt; 23310296Ssam { 23426048Sminshall int r, (*oldintr)(), cmdabort(); 23510296Ssam 23626048Sminshall abrtflag = 0; 23710296Ssam if (debug) { 23810296Ssam printf("---> "); 23910296Ssam _doprnt(fmt, &args, stdout); 24010296Ssam printf("\n"); 24110296Ssam (void) fflush(stdout); 24210296Ssam } 24311219Ssam if (cout == NULL) { 24411219Ssam perror ("No control connection for command"); 24526048Sminshall code = -1; 24611219Ssam return (0); 24711219Ssam } 24826048Sminshall oldintr = signal(SIGINT,cmdabort); 24910296Ssam _doprnt(fmt, &args, cout); 25010296Ssam fprintf(cout, "\r\n"); 25110296Ssam (void) fflush(cout); 25226048Sminshall cpend = 1; 25326048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 25426448Slepreau if (abrtflag && oldintr != SIG_IGN) 25526048Sminshall (*oldintr)(); 25626048Sminshall (void) signal(SIGINT, oldintr); 25726048Sminshall return(r); 25810296Ssam } 25910296Ssam 26036935Skarels char reply_string[BUFSIZ]; 26136935Skarels 26210296Ssam #include <ctype.h> 26310296Ssam 26410296Ssam getreply(expecteof) 26510296Ssam int expecteof; 26610296Ssam { 26711219Ssam register int c, n; 26826048Sminshall register int dig; 26936935Skarels register char *cp; 27026048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 27126048Sminshall int pflag = 0; 27226048Sminshall char *pt = pasv; 27310296Ssam 27436935Skarels cp = reply_string; 27526048Sminshall oldintr = signal(SIGINT,cmdabort); 27610296Ssam for (;;) { 27710296Ssam dig = n = code = 0; 27810296Ssam while ((c = getc(cin)) != '\n') { 27927687Sminshall if (c == IAC) { /* handle telnet commands */ 28027687Sminshall switch (c = getc(cin)) { 28127687Sminshall case WILL: 28227687Sminshall case WONT: 28327687Sminshall c = getc(cin); 284*36940Skarels fprintf(cout, "%c%c%c",IAC,DONT,c); 28527687Sminshall (void) fflush(cout); 28627687Sminshall break; 28727687Sminshall case DO: 28827687Sminshall case DONT: 28927687Sminshall c = getc(cin); 290*36940Skarels fprintf(cout, "%c%c%c",IAC,WONT,c); 29127687Sminshall (void) fflush(cout); 29227687Sminshall break; 29327687Sminshall default: 29427687Sminshall break; 29527687Sminshall } 29627687Sminshall continue; 29727687Sminshall } 29810296Ssam dig++; 29910296Ssam if (c == EOF) { 30026048Sminshall if (expecteof) { 30126048Sminshall (void) signal(SIGINT,oldintr); 30226048Sminshall code = 221; 30310296Ssam return (0); 30426048Sminshall } 30510296Ssam lostpeer(); 30626048Sminshall if (verbose) { 30726048Sminshall printf("421 Service not available, remote server has closed connection\n"); 30826048Sminshall (void) fflush(stdout); 30926048Sminshall } 31033772Scsvsj code = 421; 31133772Scsvsj return(4); 31210296Ssam } 31326048Sminshall if (c != '\r' && (verbose > 0 || 31426048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 31526448Slepreau if (proxflag && 31626448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 31726048Sminshall printf("%s:",hostname); 31826496Sminshall (void) putchar(c); 31926048Sminshall } 32010296Ssam if (dig < 4 && isdigit(c)) 32110296Ssam code = code * 10 + (c - '0'); 32226448Slepreau if (!pflag && code == 227) 32326048Sminshall pflag = 1; 32426448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 32526048Sminshall pflag = 2; 32626048Sminshall if (pflag == 2) { 32726448Slepreau if (c != '\r' && c != ')') 32826048Sminshall *pt++ = c; 32926048Sminshall else { 33026048Sminshall *pt = '\0'; 33126048Sminshall pflag = 3; 33226048Sminshall } 33326048Sminshall } 33426048Sminshall if (dig == 4 && c == '-') { 33526448Slepreau if (continuation) 33626048Sminshall code = 0; 33710296Ssam continuation++; 33826048Sminshall } 33910296Ssam if (n == 0) 34010296Ssam n = c; 34136935Skarels *cp++ = c; 34210296Ssam } 34326048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 34426496Sminshall (void) putchar(c); 34511346Ssam (void) fflush (stdout); 34611346Ssam } 34710296Ssam if (continuation && code != originalcode) { 34810296Ssam if (originalcode == 0) 34910296Ssam originalcode = code; 35010296Ssam continue; 35110296Ssam } 35236935Skarels *cp = '\0'; 35326448Slepreau if (n != '1') 35426048Sminshall cpend = 0; 35526048Sminshall (void) signal(SIGINT,oldintr); 35626448Slepreau if (code == 421 || originalcode == 421) 35726048Sminshall lostpeer(); 35826448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 35926048Sminshall (*oldintr)(); 36025907Smckusick return (n - '0'); 36110296Ssam } 36210296Ssam } 36310296Ssam 36426048Sminshall empty(mask, sec) 36527687Sminshall struct fd_set *mask; 36626048Sminshall int sec; 36726048Sminshall { 36826048Sminshall struct timeval t; 36926048Sminshall 37026048Sminshall t.tv_sec = (long) sec; 37126048Sminshall t.tv_usec = 0; 37227687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 37326048Sminshall } 37426048Sminshall 37510296Ssam jmp_buf sendabort; 37610296Ssam 37710296Ssam abortsend() 37810296Ssam { 37910296Ssam 38026048Sminshall mflag = 0; 38126048Sminshall abrtflag = 0; 38226048Sminshall printf("\nsend aborted\n"); 38326048Sminshall (void) fflush(stdout); 38410296Ssam longjmp(sendabort, 1); 38510296Ssam } 38610296Ssam 387*36940Skarels #define HASHBYTES 1024 388*36940Skarels 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]; 396*36940Skarels long bytes = 0, hashbytes = HASHBYTES; 39711346Ssam register int c, d; 39810296Ssam struct stat st; 39910296Ssam struct timeval start, stop; 40036935Skarels char *mode; 40110296Ssam 40226048Sminshall if (proxy) { 40326048Sminshall proxtrans(cmd, local, remote); 40426048Sminshall return; 40526048Sminshall } 40610296Ssam closefunc = NULL; 40726048Sminshall oldintr = NULL; 40826048Sminshall oldintp = NULL; 40936935Skarels 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); 45236935Skarels 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; 46236935Skarels if (closefunc != NULL) 46336935Skarels (*closefunc)(fin); 46426048Sminshall return; 46526048Sminshall } 46626448Slepreau if (setjmp(sendabort)) 46726048Sminshall goto abort; 46836935Skarels 46936935Skarels if (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0) { 47036935Skarels if (restart_point) { 47136935Skarels if (fseek(fin, (long) restart_point, 0) < 0) { 47236935Skarels perror(local); 47336935Skarels restart_point = 0; 47436935Skarels if (closefunc != NULL) 47536935Skarels (*closefunc)(fin); 47636935Skarels return; 47736935Skarels } 47836935Skarels if (command("REST %ld", (long) restart_point) 47936935Skarels != CONTINUE) { 48036935Skarels restart_point = 0; 48136935Skarels if (closefunc != NULL) 48236935Skarels (*closefunc)(fin); 48336935Skarels return; 48436935Skarels } 48536935Skarels restart_point = 0; 48636935Skarels mode = "r+w"; 48736935Skarels } 48836935Skarels } 48910296Ssam if (remote) { 49026048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 49126048Sminshall (void) signal(SIGINT, oldintr); 49226448Slepreau if (oldintp) 49326048Sminshall (void) signal(SIGPIPE, oldintp); 49436935Skarels if (closefunc != NULL) 49536935Skarels (*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); 50336935Skarels if (closefunc != NULL) 50436935Skarels (*closefunc)(fin); 50526048Sminshall return; 50626048Sminshall } 50736935Skarels dout = dataconn(mode); 50826448Slepreau if (dout == NULL) 50926048Sminshall goto abort; 51026496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 51136935Skarels 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) { 51836935Skarels if ((d = write(fileno (dout), buf, c)) != c) 51911219Ssam break; 52011219Ssam bytes += c; 52111651Ssam if (hash) { 522*36940Skarels while (bytes >= hashbytes) { 523*36940Skarels (void) putchar('#'); 524*36940Skarels hashbytes += HASHBYTES; 525*36940Skarels } 52626496Sminshall (void) fflush(stdout); 52711651Ssam } 52811219Ssam } 52913213Ssam if (hash && bytes > 0) { 530*36940Skarels if (bytes < HASHBYTES) 531*36940Skarels (void) putchar('#'); 53226496Sminshall (void) putchar('\n'); 53326496Sminshall (void) fflush(stdout); 53411651Ssam } 53511219Ssam if (c < 0) 53611219Ssam perror(local); 53736935Skarels if (d < 0) { 53836935Skarels if (errno != EPIPE) 53936935Skarels perror("netout"); 54036935Skarels bytes = -1; 54136935Skarels } 54211219Ssam break; 54311219Ssam 54411219Ssam case TYPE_A: 54511219Ssam while ((c = getc(fin)) != EOF) { 54611219Ssam if (c == '\n') { 54711651Ssam while (hash && (bytes >= hashbytes)) { 54826496Sminshall (void) putchar('#'); 54926496Sminshall (void) fflush(stdout); 550*36940Skarels hashbytes += HASHBYTES; 55111651Ssam } 55211219Ssam if (ferror(dout)) 55311219Ssam break; 55426496Sminshall (void) putc('\r', dout); 55511219Ssam bytes++; 55611219Ssam } 55726496Sminshall (void) putc(c, dout); 55811219Ssam bytes++; 55926048Sminshall /* if (c == '\r') { */ 56026496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 56126048Sminshall /* bytes++; */ 56226048Sminshall /* } */ 56311219Ssam } 56411651Ssam if (hash) { 56513213Ssam if (bytes < hashbytes) 56626496Sminshall (void) putchar('#'); 56726496Sminshall (void) putchar('\n'); 56826496Sminshall (void) fflush(stdout); 56911651Ssam } 57011219Ssam if (ferror(fin)) 57111219Ssam perror(local); 57236935Skarels if (ferror(dout)) { 57336935Skarels if (errno != EPIPE) 57436935Skarels perror("netout"); 57536935Skarels bytes = -1; 57636935Skarels } 57711219Ssam break; 57810296Ssam } 57926496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 58010296Ssam if (closefunc != NULL) 58126048Sminshall (*closefunc)(fin); 58210296Ssam (void) fclose(dout); 58326048Sminshall (void) getreply(0); 58426048Sminshall (void) signal(SIGINT, oldintr); 58536935Skarels if (oldintp) 58636935Skarels (void) signal(SIGPIPE, oldintp); 58735699Sbostic if (bytes > 0) 58826048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 58910296Ssam return; 59026048Sminshall abort: 59126496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 59226048Sminshall (void) signal(SIGINT, oldintr); 59326448Slepreau if (oldintp) 59426048Sminshall (void) signal(SIGPIPE, oldintp); 59526048Sminshall if (!cpend) { 59626048Sminshall code = -1; 59726048Sminshall return; 59826048Sminshall } 59926048Sminshall if (data >= 0) { 60026048Sminshall (void) close(data); 60126048Sminshall data = -1; 60226048Sminshall } 60326448Slepreau if (dout) 60426048Sminshall (void) fclose(dout); 60526048Sminshall (void) getreply(0); 60626048Sminshall code = -1; 60710296Ssam if (closefunc != NULL && fin != NULL) 60826048Sminshall (*closefunc)(fin); 60935699Sbostic if (bytes > 0) 61026048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 61110296Ssam } 61210296Ssam 61310296Ssam jmp_buf recvabort; 61410296Ssam 61510296Ssam abortrecv() 61610296Ssam { 61710296Ssam 61826048Sminshall mflag = 0; 61926048Sminshall abrtflag = 0; 62026048Sminshall printf("\n"); 62126048Sminshall (void) fflush(stdout); 62210296Ssam longjmp(recvabort, 1); 62310296Ssam } 62410296Ssam 62511651Ssam recvrequest(cmd, local, remote, mode) 62611651Ssam char *cmd, *local, *remote, *mode; 62710296Ssam { 62835659Sbostic FILE *fout, *din = 0, *popen(); 62935659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 63036935Skarels int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd; 631*36940Skarels char *buf, *gunique(), msg; 632*36940Skarels static int bufsize; 633*36940Skarels long bytes = 0, hashbytes = HASHBYTES; 63426496Sminshall struct fd_set mask; 63511346Ssam register int c, d; 63610296Ssam struct timeval start, stop; 637*36940Skarels struct stat st; 638*36940Skarels extern char *malloc(); 63910296Ssam 64036935Skarels is_retr = strcmp(cmd, "RETR") == 0; 64136935Skarels if (proxy && is_retr) { 64226048Sminshall proxtrans(cmd, local, remote); 64326048Sminshall return; 64426048Sminshall } 64510296Ssam closefunc = NULL; 64626048Sminshall oldintr = NULL; 64726048Sminshall oldintp = NULL; 64836935Skarels tcrflag = !crflag && is_retr; 64926048Sminshall if (setjmp(recvabort)) { 65026048Sminshall while (cpend) { 65126048Sminshall (void) getreply(0); 65226048Sminshall } 65326048Sminshall if (data >= 0) { 65426048Sminshall (void) close(data); 65526048Sminshall data = -1; 65626048Sminshall } 65726448Slepreau if (oldintr) 65826048Sminshall (void) signal(SIGINT, oldintr); 65926048Sminshall code = -1; 66026048Sminshall return; 66126048Sminshall } 66210296Ssam oldintr = signal(SIGINT, abortrecv); 66326048Sminshall if (strcmp(local, "-") && *local != '|') { 66410296Ssam if (access(local, 2) < 0) { 66526048Sminshall char *dir = rindex(local, '/'); 66610296Ssam 66726048Sminshall if (errno != ENOENT && errno != EACCES) { 66810296Ssam perror(local); 66926048Sminshall (void) signal(SIGINT, oldintr); 67026048Sminshall code = -1; 67126048Sminshall return; 67210296Ssam } 67326048Sminshall if (dir != NULL) 67426048Sminshall *dir = 0; 67526048Sminshall d = access(dir ? local : ".", 2); 67626048Sminshall if (dir != NULL) 67726048Sminshall *dir = '/'; 67826048Sminshall if (d < 0) { 67926048Sminshall perror(local); 68026048Sminshall (void) signal(SIGINT, oldintr); 68126048Sminshall code = -1; 68226048Sminshall return; 68326048Sminshall } 68426048Sminshall if (!runique && errno == EACCES && 68536935Skarels chmod(local, 0600) < 0) { 68626048Sminshall perror(local); 68726048Sminshall (void) signal(SIGINT, oldintr); 68826048Sminshall code = -1; 68926048Sminshall return; 69026048Sminshall } 69126048Sminshall if (runique && errno == EACCES && 69226048Sminshall (local = gunique(local)) == NULL) { 69326048Sminshall (void) signal(SIGINT, oldintr); 69426048Sminshall code = -1; 69526048Sminshall return; 69626048Sminshall } 69710296Ssam } 69826048Sminshall else if (runique && (local = gunique(local)) == NULL) { 69926048Sminshall (void) signal(SIGINT, oldintr); 70026048Sminshall code = -1; 70126048Sminshall return; 70226048Sminshall } 70326048Sminshall } 70426048Sminshall if (initconn()) { 70526048Sminshall (void) signal(SIGINT, oldintr); 70626048Sminshall code = -1; 70726048Sminshall return; 70826048Sminshall } 70926448Slepreau if (setjmp(recvabort)) 71026048Sminshall goto abort; 71136935Skarels if (!is_retr) { 71236935Skarels if (type != TYPE_A) { 71336935Skarels oldtype = type; 71436935Skarels oldverbose = verbose; 71536935Skarels if (!debug) 71636935Skarels verbose = 0; 71736935Skarels setascii(); 71836935Skarels verbose = oldverbose; 71936935Skarels } 72036935Skarels } else if (restart_point) { 72136935Skarels if (command("REST %ld", (long) restart_point) != CONTINUE) 72236935Skarels return; 72326048Sminshall } 72410296Ssam if (remote) { 72526048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 72626048Sminshall (void) signal(SIGINT, oldintr); 72726048Sminshall if (oldtype) { 72826448Slepreau if (!debug) 72926048Sminshall verbose = 0; 73026048Sminshall switch (oldtype) { 73126048Sminshall case TYPE_I: 73226048Sminshall setbinary(); 73326048Sminshall break; 73426048Sminshall case TYPE_E: 73526048Sminshall setebcdic(); 73626048Sminshall break; 73726048Sminshall case TYPE_L: 73826048Sminshall settenex(); 73926048Sminshall break; 74036935Skarels } 74126048Sminshall verbose = oldverbose; 74226048Sminshall } 74326048Sminshall return; 74426048Sminshall } 74526048Sminshall } else { 74626048Sminshall if (command("%s", cmd) != PRELIM) { 74726048Sminshall (void) signal(SIGINT, oldintr); 74826048Sminshall if (oldtype) { 74926448Slepreau if (!debug) 75026048Sminshall verbose = 0; 75126048Sminshall switch (oldtype) { 75226048Sminshall case TYPE_I: 75326048Sminshall setbinary(); 75426048Sminshall break; 75526048Sminshall case TYPE_E: 75626048Sminshall setebcdic(); 75726048Sminshall break; 75826048Sminshall case TYPE_L: 75926048Sminshall settenex(); 76026048Sminshall break; 76136935Skarels } 76226048Sminshall verbose = oldverbose; 76326048Sminshall } 76426048Sminshall return; 76526048Sminshall } 76626048Sminshall } 76726048Sminshall din = dataconn("r"); 76826048Sminshall if (din == NULL) 76926048Sminshall goto abort; 77026448Slepreau if (strcmp(local, "-") == 0) 77110296Ssam fout = stdout; 77210296Ssam else if (*local == '|') { 77326048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 77435659Sbostic fout = popen(local + 1, "w"); 77526048Sminshall if (fout == NULL) { 77626048Sminshall perror(local+1); 77726048Sminshall goto abort; 77826048Sminshall } 77935659Sbostic closefunc = pclose; 780*36940Skarels } else { 78111651Ssam fout = fopen(local, mode); 78226048Sminshall if (fout == NULL) { 78326048Sminshall perror(local); 78426048Sminshall goto abort; 78526048Sminshall } 78610296Ssam closefunc = fclose; 78710296Ssam } 788*36940Skarels if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 789*36940Skarels st.st_blksize = BUFSIZ; 790*36940Skarels if (st.st_blksize > bufsize) { 791*36940Skarels if (buf) 792*36940Skarels (void) free(buf); 793*36940Skarels buf = malloc(st.st_blksize); 794*36940Skarels if (buf == NULL) { 795*36940Skarels perror("malloc"); 796*36940Skarels goto abort; 797*36940Skarels } 798*36940Skarels bufsize = st.st_blksize; 799*36940Skarels } 80026496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 80111219Ssam switch (type) { 80211219Ssam 80311219Ssam case TYPE_I: 80411219Ssam case TYPE_L: 80536935Skarels if (restart_point && 80636935Skarels lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 80736935Skarels perror(local); 80836935Skarels if (closefunc != NULL) 80936935Skarels (*closefunc)(fout); 81036935Skarels return; 81136935Skarels } 81211346Ssam errno = d = 0; 813*36940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) { 81436935Skarels if ((d = write(fileno(fout), buf, c)) != c) 81511219Ssam break; 81611219Ssam bytes += c; 81711651Ssam if (hash) { 818*36940Skarels while (bytes >= hashbytes) { 819*36940Skarels (void) putchar('#'); 820*36940Skarels hashbytes += HASHBYTES; 821*36940Skarels } 82226496Sminshall (void) fflush(stdout); 82311651Ssam } 82411219Ssam } 82513213Ssam if (hash && bytes > 0) { 826*36940Skarels if (bytes < HASHBYTES) 827*36940Skarels (void) putchar('#'); 82826496Sminshall (void) putchar('\n'); 82926496Sminshall (void) fflush(stdout); 83011651Ssam } 83136935Skarels if (c < 0) { 83236935Skarels if (errno != EPIPE) 83336935Skarels perror("netin"); 83436935Skarels bytes = -1; 83536935Skarels } 83611346Ssam if (d < 0) 83710296Ssam perror(local); 83811219Ssam break; 83911219Ssam 84011219Ssam case TYPE_A: 84136935Skarels if (restart_point) { 84236935Skarels register int i, n, c; 843*36940Skarels 84436935Skarels if (fseek(fout, 0L, L_SET) < 0) 84536935Skarels goto done; 84636935Skarels n = restart_point; 84736935Skarels i = 0; 848*36940Skarels while (i++ < n) { 84936935Skarels if ((c=getc(fout)) == EOF) 85036935Skarels goto done; 85136935Skarels if (c == '\n') 85236935Skarels i++; 85336935Skarels } 85436935Skarels if (fseek(fout, 0L, L_INCR) < 0) { 85536935Skarels done: 85636935Skarels perror(local); 85736935Skarels if (closefunc != NULL) 85836935Skarels (*closefunc)(fout); 85936935Skarels return; 86036935Skarels } 86136935Skarels } 86211219Ssam while ((c = getc(din)) != EOF) { 86327749Sminshall while (c == '\r') { 86411651Ssam while (hash && (bytes >= hashbytes)) { 86526496Sminshall (void) putchar('#'); 86626496Sminshall (void) fflush(stdout); 867*36940Skarels hashbytes += HASHBYTES; 86811651Ssam } 86910296Ssam bytes++; 87026048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 871*36940Skarels if (ferror(fout)) 872*36940Skarels goto break2; 873*36940Skarels (void) putc('\r', fout); 874*36940Skarels if (c == '\0' || c == EOF) 875*36940Skarels goto contin2; 87611219Ssam } 87711219Ssam } 878*36940Skarels (void) putc(c, fout); 87911219Ssam bytes++; 880*36940Skarels contin2: ; 88110296Ssam } 882*36940Skarels break2: 88311651Ssam if (hash) { 88413213Ssam if (bytes < hashbytes) 88526496Sminshall (void) putchar('#'); 88626496Sminshall (void) putchar('\n'); 88726496Sminshall (void) fflush(stdout); 88811651Ssam } 889*36940Skarels if (ferror(din)){ 89036935Skarels if (errno != EPIPE) 89136935Skarels perror ("netin"); 89236935Skarels bytes = -1; 89336935Skarels } 894*36940Skarels if (ferror(fout)) 89511219Ssam perror (local); 89611219Ssam break; 89710296Ssam } 89826448Slepreau if (closefunc != NULL) 89926048Sminshall (*closefunc)(fout); 90026496Sminshall (void) signal(SIGINT, oldintr); 90126448Slepreau if (oldintp) 90226048Sminshall (void) signal(SIGPIPE, oldintp); 90326496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 90410296Ssam (void) fclose(din); 90526048Sminshall (void) getreply(0); 90636935Skarels if (bytes > 0 && is_retr) 90726048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 90826048Sminshall if (oldtype) { 90926448Slepreau if (!debug) 91026048Sminshall verbose = 0; 91126048Sminshall switch (oldtype) { 91226048Sminshall case TYPE_I: 91326048Sminshall setbinary(); 91426048Sminshall break; 91526048Sminshall case TYPE_E: 91626048Sminshall setebcdic(); 91726048Sminshall break; 91826048Sminshall case TYPE_L: 91926048Sminshall settenex(); 92026048Sminshall break; 92126048Sminshall } 92226048Sminshall verbose = oldverbose; 92326048Sminshall } 92426048Sminshall return; 92526048Sminshall abort: 92626048Sminshall 92727687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 92826048Sminshall 92926496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 93026448Slepreau if (oldintp) 93126048Sminshall (void) signal(SIGPIPE, oldintr); 93226048Sminshall (void) signal(SIGINT,SIG_IGN); 93326048Sminshall if (oldtype) { 93426448Slepreau if (!debug) 93526048Sminshall verbose = 0; 93626048Sminshall switch (oldtype) { 93726048Sminshall case TYPE_I: 93826048Sminshall setbinary(); 93926048Sminshall break; 94026048Sminshall case TYPE_E: 94126048Sminshall setebcdic(); 94226048Sminshall break; 94326048Sminshall case TYPE_L: 94426048Sminshall settenex(); 94526048Sminshall break; 94626048Sminshall } 94726048Sminshall verbose = oldverbose; 94826048Sminshall } 94926048Sminshall if (!cpend) { 95026048Sminshall code = -1; 95126048Sminshall (void) signal(SIGINT,oldintr); 95226048Sminshall return; 95326048Sminshall } 95426048Sminshall 95527687Sminshall fprintf(cout,"%c%c",IAC,IP); 95627687Sminshall (void) fflush(cout); 95727687Sminshall msg = IAC; 95827687Sminshall /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 95927687Sminshall /* after urgent byte rather than before as now is protocol */ 96027687Sminshall if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 96127687Sminshall perror("abort"); 96226048Sminshall } 96327687Sminshall fprintf(cout,"%cABOR\r\n",DM); 96426048Sminshall (void) fflush(cout); 96527687Sminshall FD_ZERO(&mask); 96626496Sminshall FD_SET(fileno(cin), &mask); 96726496Sminshall if (din) { 96826496Sminshall FD_SET(fileno(din), &mask); 96926496Sminshall } 97027687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 97127687Sminshall if (nfnd < 0) { 97227687Sminshall perror("abort"); 97327687Sminshall } 97426048Sminshall code = -1; 97526048Sminshall lostpeer(); 97626048Sminshall } 97726496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 978*36940Skarels while ((c = read(fileno(din), buf, bufsize)) > 0) 97926448Slepreau ; 98026496Sminshall } 98127687Sminshall if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 98226048Sminshall if (data >= 0) { 98326496Sminshall (void) close(data); 98426048Sminshall data = -1; 98526048Sminshall } 98625907Smckusick (void) getreply(0); 98725907Smckusick } 98826048Sminshall (void) getreply(0); 98926048Sminshall code = -1; 99026048Sminshall if (data >= 0) { 99126048Sminshall (void) close(data); 99226048Sminshall data = -1; 99326048Sminshall } 99426448Slepreau if (closefunc != NULL && fout != NULL) 99526048Sminshall (*closefunc)(fout); 99626448Slepreau if (din) 99726048Sminshall (void) fclose(din); 99835699Sbostic if (bytes > 0) 99926048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 100026048Sminshall (void) signal(SIGINT,oldintr); 100110296Ssam } 100210296Ssam 100310296Ssam /* 100410296Ssam * Need to start a listen on the data channel 100510296Ssam * before we send the command, otherwise the 100610296Ssam * server's connect may fail. 100710296Ssam */ 100833224Sbostic int sendport = -1; 100911651Ssam 101010296Ssam initconn() 101110296Ssam { 101210296Ssam register char *p, *a; 101326048Sminshall int result, len, tmpno = 0; 101426993Skarels int on = 1; 101510296Ssam 101611651Ssam noport: 101710296Ssam data_addr = myctladdr; 101811651Ssam if (sendport) 101911651Ssam data_addr.sin_port = 0; /* let system pick one */ 102011651Ssam if (data != -1) 102111651Ssam (void) close (data); 102218287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 102310296Ssam if (data < 0) { 102410296Ssam perror("ftp: socket"); 102526448Slepreau if (tmpno) 102626048Sminshall sendport = 1; 102710296Ssam return (1); 102810296Ssam } 102912397Ssam if (!sendport) 103027687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 103133224Sbostic perror("ftp: setsockopt (reuse address)"); 103212397Ssam goto bad; 103312397Ssam } 103426496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 103510296Ssam perror("ftp: bind"); 103610296Ssam goto bad; 103710296Ssam } 103810296Ssam if (options & SO_DEBUG && 103927687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 104010296Ssam perror("ftp: setsockopt (ignored)"); 104111627Ssam len = sizeof (data_addr); 104211627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 104311627Ssam perror("ftp: getsockname"); 104410296Ssam goto bad; 104510296Ssam } 104626448Slepreau if (listen(data, 1) < 0) 104710296Ssam perror("ftp: listen"); 104811651Ssam if (sendport) { 104911651Ssam a = (char *)&data_addr.sin_addr; 105011651Ssam p = (char *)&data_addr.sin_port; 105110296Ssam #define UC(b) (((int)b)&0xff) 105211651Ssam result = 105311651Ssam command("PORT %d,%d,%d,%d,%d,%d", 105411651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 105511651Ssam UC(p[0]), UC(p[1])); 105611651Ssam if (result == ERROR && sendport == -1) { 105711651Ssam sendport = 0; 105826048Sminshall tmpno = 1; 105911651Ssam goto noport; 106011651Ssam } 106111651Ssam return (result != COMPLETE); 106211651Ssam } 106326448Slepreau if (tmpno) 106426048Sminshall sendport = 1; 106511651Ssam return (0); 106610296Ssam bad: 106710296Ssam (void) close(data), data = -1; 106826448Slepreau if (tmpno) 106926048Sminshall sendport = 1; 107010296Ssam return (1); 107110296Ssam } 107210296Ssam 107310296Ssam FILE * 107410296Ssam dataconn(mode) 107510296Ssam char *mode; 107610296Ssam { 107710296Ssam struct sockaddr_in from; 107810296Ssam int s, fromlen = sizeof (from); 107910296Ssam 108026496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 108110296Ssam if (s < 0) { 108210296Ssam perror("ftp: accept"); 108310296Ssam (void) close(data), data = -1; 108410296Ssam return (NULL); 108510296Ssam } 108610296Ssam (void) close(data); 108710296Ssam data = s; 108810296Ssam return (fdopen(data, mode)); 108910296Ssam } 109010296Ssam 109126048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 109226048Sminshall char *direction, *local, *remote; 109311651Ssam long bytes; 109410296Ssam struct timeval *t0, *t1; 109510296Ssam { 109610296Ssam struct timeval td; 109716437Sleres float s, bs; 109810296Ssam 109935699Sbostic if (verbose) { 110035699Sbostic tvsub(&td, t1, t0); 110135699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 110210296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 110335699Sbostic bs = bytes / nz(s); 110435699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 110535699Sbostic bytes, direction, s, bs / 1024.); 110635699Sbostic } else { 110735699Sbostic if (local && *local != '-') 110835699Sbostic printf("local: %s ", local); 110935699Sbostic if (remote) 111035699Sbostic printf("remote: %s\n", remote); 111135699Sbostic } 111210296Ssam } 111310296Ssam 111426496Sminshall /*tvadd(tsum, t0) 111510296Ssam struct timeval *tsum, *t0; 111610296Ssam { 111710296Ssam 111810296Ssam tsum->tv_sec += t0->tv_sec; 111910296Ssam tsum->tv_usec += t0->tv_usec; 112010296Ssam if (tsum->tv_usec > 1000000) 112110296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 112226496Sminshall } */ 112310296Ssam 112410296Ssam tvsub(tdiff, t1, t0) 112510296Ssam struct timeval *tdiff, *t1, *t0; 112610296Ssam { 112710296Ssam 112810296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 112910296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 113010296Ssam if (tdiff->tv_usec < 0) 113110296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 113210296Ssam } 113326048Sminshall 113426048Sminshall psabort() 113526048Sminshall { 113626048Sminshall extern int abrtflag; 113726048Sminshall 113826048Sminshall abrtflag++; 113926048Sminshall } 114026048Sminshall 114126048Sminshall pswitch(flag) 114226048Sminshall int flag; 114326048Sminshall { 114426048Sminshall extern int proxy, abrtflag; 114526048Sminshall int (*oldintr)(); 114626048Sminshall static struct comvars { 114726048Sminshall int connect; 114828469Skarels char name[MAXHOSTNAMELEN]; 114926048Sminshall struct sockaddr_in mctl; 115026048Sminshall struct sockaddr_in hctl; 115126048Sminshall FILE *in; 115226048Sminshall FILE *out; 115326048Sminshall int tpe; 115426048Sminshall int cpnd; 115526048Sminshall int sunqe; 115626048Sminshall int runqe; 115726048Sminshall int mcse; 115826048Sminshall int ntflg; 115926048Sminshall char nti[17]; 116026048Sminshall char nto[17]; 116126048Sminshall int mapflg; 116226048Sminshall char mi[MAXPATHLEN]; 116326048Sminshall char mo[MAXPATHLEN]; 116426048Sminshall } proxstruct, tmpstruct; 116526048Sminshall struct comvars *ip, *op; 116626048Sminshall 116726048Sminshall abrtflag = 0; 116826048Sminshall oldintr = signal(SIGINT, psabort); 116926048Sminshall if (flag) { 117026448Slepreau if (proxy) 117126048Sminshall return; 117226048Sminshall ip = &tmpstruct; 117326048Sminshall op = &proxstruct; 117426048Sminshall proxy++; 117526048Sminshall } 117626048Sminshall else { 117726448Slepreau if (!proxy) 117826048Sminshall return; 117926048Sminshall ip = &proxstruct; 118026048Sminshall op = &tmpstruct; 118126048Sminshall proxy = 0; 118226048Sminshall } 118326048Sminshall ip->connect = connected; 118426048Sminshall connected = op->connect; 118528469Skarels if (hostname) { 118628469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 118728469Skarels ip->name[strlen(ip->name)] = '\0'; 118828469Skarels } else 118928469Skarels ip->name[0] = 0; 119026048Sminshall hostname = op->name; 119126048Sminshall ip->hctl = hisctladdr; 119226048Sminshall hisctladdr = op->hctl; 119326048Sminshall ip->mctl = myctladdr; 119426048Sminshall myctladdr = op->mctl; 119526048Sminshall ip->in = cin; 119626048Sminshall cin = op->in; 119726048Sminshall ip->out = cout; 119826048Sminshall cout = op->out; 119926048Sminshall ip->tpe = type; 120026048Sminshall type = op->tpe; 120126448Slepreau if (!type) 120226048Sminshall type = 1; 120326048Sminshall ip->cpnd = cpend; 120426048Sminshall cpend = op->cpnd; 120526048Sminshall ip->sunqe = sunique; 120626048Sminshall sunique = op->sunqe; 120726048Sminshall ip->runqe = runique; 120826048Sminshall runique = op->runqe; 120926048Sminshall ip->mcse = mcase; 121026048Sminshall mcase = op->mcse; 121126048Sminshall ip->ntflg = ntflag; 121226048Sminshall ntflag = op->ntflg; 121326496Sminshall (void) strncpy(ip->nti, ntin, 16); 121426048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 121526496Sminshall (void) strcpy(ntin, op->nti); 121626496Sminshall (void) strncpy(ip->nto, ntout, 16); 121726048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 121826496Sminshall (void) strcpy(ntout, op->nto); 121926048Sminshall ip->mapflg = mapflag; 122026048Sminshall mapflag = op->mapflg; 122126496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 122226048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 122326496Sminshall (void) strcpy(mapin, op->mi); 122426496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 122526048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 122626496Sminshall (void) strcpy(mapout, op->mo); 122726048Sminshall (void) signal(SIGINT, oldintr); 122826048Sminshall if (abrtflag) { 122926048Sminshall abrtflag = 0; 123026048Sminshall (*oldintr)(); 123126448Slepreau } 123226048Sminshall } 123326048Sminshall 123426048Sminshall jmp_buf ptabort; 123526048Sminshall int ptabflg; 123626048Sminshall 123726048Sminshall abortpt() 123826048Sminshall { 123926048Sminshall printf("\n"); 124026496Sminshall (void) fflush(stdout); 124126048Sminshall ptabflg++; 124226048Sminshall mflag = 0; 124326048Sminshall abrtflag = 0; 124426048Sminshall longjmp(ptabort, 1); 124526048Sminshall } 124626048Sminshall 124726048Sminshall proxtrans(cmd, local, remote) 124826048Sminshall char *cmd, *local, *remote; 124926048Sminshall { 125027687Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 125126048Sminshall extern jmp_buf ptabort; 125226048Sminshall char *cmd2; 125326496Sminshall struct fd_set mask; 125426048Sminshall 125526448Slepreau if (strcmp(cmd, "RETR")) 125626048Sminshall cmd2 = "RETR"; 125726448Slepreau else 125826048Sminshall cmd2 = runique ? "STOU" : "STOR"; 125926048Sminshall if (command("PASV") != COMPLETE) { 126026048Sminshall printf("proxy server does not support third part transfers.\n"); 126126048Sminshall return; 126226048Sminshall } 126326048Sminshall tmptype = type; 126426048Sminshall pswitch(0); 126526048Sminshall if (!connected) { 126626048Sminshall printf("No primary connection\n"); 126726048Sminshall pswitch(1); 126826048Sminshall code = -1; 126926048Sminshall return; 127026048Sminshall } 127126048Sminshall if (type != tmptype) { 127226048Sminshall oldtype = type; 127326048Sminshall switch (tmptype) { 127426048Sminshall case TYPE_A: 127526048Sminshall setascii(); 127626048Sminshall break; 127726048Sminshall case TYPE_I: 127826048Sminshall setbinary(); 127926048Sminshall break; 128026048Sminshall case TYPE_E: 128126048Sminshall setebcdic(); 128226048Sminshall break; 128326048Sminshall case TYPE_L: 128426048Sminshall settenex(); 128526048Sminshall break; 128626048Sminshall } 128726048Sminshall } 128826048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 128926048Sminshall switch (oldtype) { 129026048Sminshall case 0: 129126048Sminshall break; 129226048Sminshall case TYPE_A: 129326048Sminshall setascii(); 129426048Sminshall break; 129526048Sminshall case TYPE_I: 129626048Sminshall setbinary(); 129726048Sminshall break; 129826048Sminshall case TYPE_E: 129926048Sminshall setebcdic(); 130026048Sminshall break; 130126048Sminshall case TYPE_L: 130226048Sminshall settenex(); 130326048Sminshall break; 130426048Sminshall } 130526048Sminshall pswitch(1); 130626048Sminshall return; 130726048Sminshall } 130826448Slepreau if (setjmp(ptabort)) 130926048Sminshall goto abort; 131026048Sminshall oldintr = signal(SIGINT, abortpt); 131126048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 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 return; 133126048Sminshall } 133226048Sminshall sleep(2); 133326048Sminshall pswitch(1); 133426048Sminshall secndflag++; 133526448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 133626048Sminshall goto abort; 133726048Sminshall ptflag++; 133826048Sminshall (void) getreply(0); 133926048Sminshall pswitch(0); 134026048Sminshall (void) getreply(0); 134126048Sminshall (void) signal(SIGINT, oldintr); 134226048Sminshall switch (oldtype) { 134326048Sminshall case 0: 134426048Sminshall break; 134526048Sminshall case TYPE_A: 134626048Sminshall setascii(); 134726048Sminshall break; 134826048Sminshall case TYPE_I: 134926048Sminshall setbinary(); 135026048Sminshall break; 135126048Sminshall case TYPE_E: 135226048Sminshall setebcdic(); 135326048Sminshall break; 135426048Sminshall case TYPE_L: 135526048Sminshall settenex(); 135626048Sminshall break; 135726048Sminshall } 135826048Sminshall pswitch(1); 135926048Sminshall ptflag = 0; 136026048Sminshall printf("local: %s remote: %s\n", local, remote); 136126048Sminshall return; 136226048Sminshall abort: 136326048Sminshall (void) signal(SIGINT, SIG_IGN); 136426048Sminshall ptflag = 0; 136526448Slepreau if (strcmp(cmd, "RETR") && !proxy) 136626048Sminshall pswitch(1); 136726448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 136826048Sminshall pswitch(0); 136926048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 137026048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 137126048Sminshall pswitch(0); 137226048Sminshall switch (oldtype) { 137326048Sminshall case 0: 137426048Sminshall break; 137526048Sminshall case TYPE_A: 137626048Sminshall setascii(); 137726048Sminshall break; 137826048Sminshall case TYPE_I: 137926048Sminshall setbinary(); 138026048Sminshall break; 138126048Sminshall case TYPE_E: 138226048Sminshall setebcdic(); 138326048Sminshall break; 138426048Sminshall case TYPE_L: 138526048Sminshall settenex(); 138626048Sminshall break; 138726048Sminshall } 138827687Sminshall if (cpend) { 138926048Sminshall char msg[2]; 139026048Sminshall 139126048Sminshall fprintf(cout,"%c%c",IAC,IP); 139226048Sminshall (void) fflush(cout); 139326048Sminshall *msg = IAC; 139426048Sminshall *(msg+1) = DM; 139526448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 139626048Sminshall perror("abort"); 139726048Sminshall fprintf(cout,"ABOR\r\n"); 139826048Sminshall (void) fflush(cout); 139927687Sminshall FD_ZERO(&mask); 140026496Sminshall FD_SET(fileno(cin), &mask); 140127687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 140227687Sminshall if (nfnd < 0) { 140327687Sminshall perror("abort"); 140427687Sminshall } 140526448Slepreau if (ptabflg) 140626048Sminshall code = -1; 140726048Sminshall lostpeer(); 140826048Sminshall } 140926048Sminshall (void) getreply(0); 141026048Sminshall (void) getreply(0); 141126048Sminshall } 141226048Sminshall } 141326048Sminshall pswitch(1); 141426448Slepreau if (ptabflg) 141526048Sminshall code = -1; 141626048Sminshall (void) signal(SIGINT, oldintr); 141726048Sminshall return; 141826048Sminshall } 141927687Sminshall if (cpend) { 142026048Sminshall char msg[2]; 142126048Sminshall 142226048Sminshall fprintf(cout,"%c%c",IAC,IP); 142326048Sminshall (void) fflush(cout); 142426048Sminshall *msg = IAC; 142526048Sminshall *(msg+1) = DM; 142626448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 142726048Sminshall perror("abort"); 142826048Sminshall fprintf(cout,"ABOR\r\n"); 142926048Sminshall (void) fflush(cout); 143027687Sminshall FD_ZERO(&mask); 143126496Sminshall FD_SET(fileno(cin), &mask); 143227687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 143327687Sminshall if (nfnd < 0) { 143427687Sminshall perror("abort"); 143527687Sminshall } 143626448Slepreau if (ptabflg) 143726048Sminshall code = -1; 143826048Sminshall lostpeer(); 143926048Sminshall } 144026048Sminshall (void) getreply(0); 144126048Sminshall (void) getreply(0); 144226048Sminshall } 144326048Sminshall pswitch(!proxy); 144426048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 144526048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 144626048Sminshall pswitch(0); 144726048Sminshall switch (oldtype) { 144826048Sminshall case 0: 144926048Sminshall break; 145026048Sminshall case TYPE_A: 145126048Sminshall setascii(); 145226048Sminshall break; 145326048Sminshall case TYPE_I: 145426048Sminshall setbinary(); 145526048Sminshall break; 145626048Sminshall case TYPE_E: 145726048Sminshall setebcdic(); 145826048Sminshall break; 145926048Sminshall case TYPE_L: 146026048Sminshall settenex(); 146126048Sminshall break; 146226048Sminshall } 146327687Sminshall if (cpend) { 146426048Sminshall char msg[2]; 146526048Sminshall 146626048Sminshall fprintf(cout,"%c%c",IAC,IP); 146726048Sminshall (void) fflush(cout); 146826048Sminshall *msg = IAC; 146926048Sminshall *(msg+1) = DM; 147026448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 147126048Sminshall perror("abort"); 147226048Sminshall fprintf(cout,"ABOR\r\n"); 147326048Sminshall (void) fflush(cout); 147427687Sminshall FD_ZERO(&mask); 147526496Sminshall FD_SET(fileno(cin), &mask); 147627687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 147727687Sminshall if (nfnd < 0) { 147827687Sminshall perror("abort"); 147927687Sminshall } 148026448Slepreau if (ptabflg) 148126048Sminshall code = -1; 148226048Sminshall lostpeer(); 148326048Sminshall } 148426048Sminshall (void) getreply(0); 148526048Sminshall (void) getreply(0); 148626048Sminshall } 148726048Sminshall pswitch(1); 148826448Slepreau if (ptabflg) 148926048Sminshall code = -1; 149026048Sminshall (void) signal(SIGINT, oldintr); 149126048Sminshall return; 149226048Sminshall } 149326048Sminshall } 149427687Sminshall if (cpend) { 149526048Sminshall char msg[2]; 149626048Sminshall 149726048Sminshall fprintf(cout,"%c%c",IAC,IP); 149826048Sminshall (void) fflush(cout); 149926048Sminshall *msg = IAC; 150026048Sminshall *(msg+1) = DM; 150126448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 150226048Sminshall perror("abort"); 150326048Sminshall fprintf(cout,"ABOR\r\n"); 150426048Sminshall (void) fflush(cout); 150527687Sminshall FD_ZERO(&mask); 150626496Sminshall FD_SET(fileno(cin), &mask); 150727687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 150827687Sminshall if (nfnd < 0) { 150927687Sminshall perror("abort"); 151027687Sminshall } 151126448Slepreau if (ptabflg) 151226048Sminshall code = -1; 151326048Sminshall lostpeer(); 151426048Sminshall } 151526048Sminshall (void) getreply(0); 151626048Sminshall (void) getreply(0); 151726048Sminshall } 151826048Sminshall pswitch(!proxy); 151926048Sminshall if (cpend) { 152027687Sminshall FD_ZERO(&mask); 152126496Sminshall FD_SET(fileno(cin), &mask); 152227687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 152327687Sminshall if (nfnd < 0) { 152427687Sminshall perror("abort"); 152527687Sminshall } 152626448Slepreau if (ptabflg) 152726048Sminshall code = -1; 152826048Sminshall lostpeer(); 152926048Sminshall } 153026048Sminshall (void) getreply(0); 153126048Sminshall (void) getreply(0); 153226048Sminshall } 153326448Slepreau if (proxy) 153426048Sminshall pswitch(0); 153526048Sminshall switch (oldtype) { 153626048Sminshall case 0: 153726048Sminshall break; 153826048Sminshall case TYPE_A: 153926048Sminshall setascii(); 154026048Sminshall break; 154126048Sminshall case TYPE_I: 154226048Sminshall setbinary(); 154326048Sminshall break; 154426048Sminshall case TYPE_E: 154526048Sminshall setebcdic(); 154626048Sminshall break; 154726048Sminshall case TYPE_L: 154826048Sminshall settenex(); 154926048Sminshall break; 155026048Sminshall } 155126048Sminshall pswitch(1); 155226448Slepreau if (ptabflg) 155326048Sminshall code = -1; 155426048Sminshall (void) signal(SIGINT, oldintr); 155526048Sminshall } 155626048Sminshall 155726048Sminshall reset() 155826048Sminshall { 155926496Sminshall struct fd_set mask; 156026496Sminshall int nfnd = 1; 156126048Sminshall 156227687Sminshall FD_ZERO(&mask); 156330946Scsvsj while (nfnd > 0) { 156426496Sminshall FD_SET(fileno(cin), &mask); 156527687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 156626048Sminshall perror("reset"); 156726048Sminshall code = -1; 156826048Sminshall lostpeer(); 156926048Sminshall } 157027687Sminshall else if (nfnd) { 157126048Sminshall (void) getreply(0); 157226496Sminshall } 157326048Sminshall } 157426048Sminshall } 157526048Sminshall 157626048Sminshall char * 157726048Sminshall gunique(local) 157826048Sminshall char *local; 157926048Sminshall { 158026048Sminshall static char new[MAXPATHLEN]; 158126048Sminshall char *cp = rindex(local, '/'); 158226048Sminshall int d, count=0; 158326048Sminshall char ext = '1'; 158426048Sminshall 158526448Slepreau if (cp) 158626048Sminshall *cp = '\0'; 158726048Sminshall d = access(cp ? local : ".", 2); 158826448Slepreau if (cp) 158926048Sminshall *cp = '/'; 159026048Sminshall if (d < 0) { 159126048Sminshall perror(local); 159226048Sminshall return((char *) 0); 159326048Sminshall } 159426048Sminshall (void) strcpy(new, local); 159526048Sminshall cp = new + strlen(new); 159626048Sminshall *cp++ = '.'; 159726048Sminshall while (!d) { 159826048Sminshall if (++count == 100) { 159926048Sminshall printf("runique: can't find unique file name.\n"); 160026048Sminshall return((char *) 0); 160126048Sminshall } 160226048Sminshall *cp++ = ext; 160326048Sminshall *cp = '\0'; 160426448Slepreau if (ext == '9') 160526048Sminshall ext = '0'; 160626448Slepreau else 160726048Sminshall ext++; 160826448Slepreau if ((d = access(new, 0)) < 0) 160926048Sminshall break; 161026448Slepreau if (ext != '0') 161126048Sminshall cp--; 161226448Slepreau else if (*(cp - 2) == '.') 161326048Sminshall *(cp - 1) = '1'; 161426048Sminshall else { 161526048Sminshall *(cp - 2) = *(cp - 2) + 1; 161626048Sminshall cp--; 161726048Sminshall } 161826048Sminshall } 161926048Sminshall return(new); 162026048Sminshall } 1621