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 1534901Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621739Sdist */ 1721739Sdist 1810296Ssam #ifndef lint 19*35659Sbostic static char sccsid[] = "@(#)ftp.c 5.20 (Berkeley) 09/21/88"; 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> 2910296Ssam 3010296Ssam #include <netinet/in.h> 3112397Ssam #include <arpa/ftp.h> 3226048Sminshall #include <arpa/telnet.h> 3310296Ssam 3410296Ssam #include <stdio.h> 3510296Ssam #include <signal.h> 3610296Ssam #include <errno.h> 3710296Ssam #include <netdb.h> 3826048Sminshall #include <fcntl.h> 3926048Sminshall #include <pwd.h> 4010296Ssam 4110296Ssam struct sockaddr_in hisctladdr; 4210296Ssam struct sockaddr_in data_addr; 4310296Ssam int data = -1; 4426048Sminshall int abrtflag = 0; 4526048Sminshall int ptflag = 0; 4610296Ssam int connected; 4710296Ssam struct sockaddr_in myctladdr; 4826496Sminshall uid_t getuid(); 4910296Ssam 5010296Ssam FILE *cin, *cout; 5110296Ssam FILE *dataconn(); 5210296Ssam 5325904Skarels char * 5410296Ssam hookup(host, port) 5510296Ssam char *host; 5610296Ssam int port; 5710296Ssam { 5825904Skarels register struct hostent *hp = 0; 5927687Sminshall int s,len; 6025904Skarels static char hostnamebuf[80]; 6110296Ssam 6210296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 6325904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 6425904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 6525904Skarels hisctladdr.sin_family = AF_INET; 6625904Skarels (void) strcpy(hostnamebuf, host); 6726048Sminshall } 6826048Sminshall else { 6925100Sbloom hp = gethostbyname(host); 7025904Skarels if (hp == NULL) { 7125904Skarels printf("%s: unknown host\n", host); 7226048Sminshall code = -1; 7326048Sminshall return((char *) 0); 7425904Skarels } 7525904Skarels hisctladdr.sin_family = hp->h_addrtype; 7625904Skarels bcopy(hp->h_addr_list[0], 7725904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 7825904Skarels (void) strcpy(hostnamebuf, hp->h_name); 7910296Ssam } 8025904Skarels hostname = hostnamebuf; 8125904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 8210296Ssam if (s < 0) { 8310296Ssam perror("ftp: socket"); 8426048Sminshall code = -1; 8510296Ssam return (0); 8610296Ssam } 8710296Ssam hisctladdr.sin_port = port; 8826496Sminshall while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 8925904Skarels if (hp && hp->h_addr_list[1]) { 9025904Skarels int oerrno = errno; 9125904Skarels 9225904Skarels fprintf(stderr, "ftp: connect to address %s: ", 9325904Skarels inet_ntoa(hisctladdr.sin_addr)); 9425904Skarels errno = oerrno; 9526496Sminshall perror((char *) 0); 9625904Skarels hp->h_addr_list++; 9725904Skarels bcopy(hp->h_addr_list[0], 9826048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 9926496Sminshall fprintf(stdout, "Trying %s...\n", 10025904Skarels inet_ntoa(hisctladdr.sin_addr)); 10126813Skarels (void) close(s); 10226813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 10326813Skarels if (s < 0) { 10426813Skarels perror("ftp: socket"); 10526813Skarels code = -1; 10626813Skarels return (0); 10726813Skarels } 10825904Skarels continue; 10925904Skarels } 11010296Ssam perror("ftp: connect"); 11126048Sminshall code = -1; 11210296Ssam goto bad; 11310296Ssam } 11411627Ssam len = sizeof (myctladdr); 11511627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 11611627Ssam perror("ftp: getsockname"); 11726048Sminshall code = -1; 11810296Ssam goto bad; 11910296Ssam } 12010296Ssam cin = fdopen(s, "r"); 12110296Ssam cout = fdopen(s, "w"); 12211219Ssam if (cin == NULL || cout == NULL) { 12310296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 12410296Ssam if (cin) 12526496Sminshall (void) fclose(cin); 12610296Ssam if (cout) 12726496Sminshall (void) fclose(cout); 12826048Sminshall code = -1; 12910296Ssam goto bad; 13010296Ssam } 13110296Ssam if (verbose) 13226067Sminshall printf("Connected to %s.\n", hostname); 13327687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 13426048Sminshall if (cin) 13526496Sminshall (void) fclose(cin); 13626048Sminshall if (cout) 13726496Sminshall (void) fclose(cout); 13826048Sminshall code = -1; 13926048Sminshall goto bad; 14026048Sminshall } 14127687Sminshall #ifdef SO_OOBINLINE 14227687Sminshall { 14327687Sminshall int on = 1; 14426048Sminshall 14527687Sminshall if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 14627687Sminshall < 0 && debug) { 14727687Sminshall perror("ftp: setsockopt"); 14827687Sminshall } 14927687Sminshall } 15027687Sminshall #endif SO_OOBINLINE 15126048Sminshall 15225904Skarels return (hostname); 15310296Ssam bad: 15426496Sminshall (void) close(s); 15525904Skarels return ((char *)0); 15610296Ssam } 15710296Ssam 15825904Skarels login(host) 15925904Skarels char *host; 16010296Ssam { 16126048Sminshall char tmp[80]; 162*35659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 16326048Sminshall int n, aflag = 0; 16410296Ssam 16526048Sminshall user = pass = acct = 0; 16626048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 16726048Sminshall disconnect(); 16826048Sminshall code = -1; 16926048Sminshall return(0); 17026048Sminshall } 17126048Sminshall if (user == NULL) { 17226048Sminshall char *myname = getlogin(); 17326048Sminshall 17426048Sminshall if (myname == NULL) { 17526048Sminshall struct passwd *pp = getpwuid(getuid()); 17626048Sminshall 17726448Slepreau if (pp != NULL) 17826048Sminshall myname = pp->pw_name; 17926048Sminshall } 18026048Sminshall printf("Name (%s:%s): ", host, myname); 18126048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 18226048Sminshall tmp[strlen(tmp) - 1] = '\0'; 18326448Slepreau if (*tmp == '\0') 18426048Sminshall user = myname; 18526448Slepreau else 18626048Sminshall user = tmp; 18726048Sminshall } 18810296Ssam n = command("USER %s", user); 18926048Sminshall if (n == CONTINUE) { 19026448Slepreau if (pass == NULL) 191*35659Sbostic pass = getpass("Password:"); 19210296Ssam n = command("PASS %s", pass); 19326048Sminshall } 19410296Ssam if (n == CONTINUE) { 19526048Sminshall aflag++; 196*35659Sbostic acct = getpass("Account:"); 19710296Ssam n = command("ACCT %s", acct); 19810296Ssam } 19910296Ssam if (n != COMPLETE) { 20010296Ssam fprintf(stderr, "Login failed.\n"); 20110296Ssam return (0); 20210296Ssam } 20326448Slepreau if (!aflag && acct != NULL) 20426048Sminshall (void) command("ACCT %s", acct); 20526448Slepreau if (proxy) 20626048Sminshall return(1); 20726048Sminshall for (n = 0; n < macnum; ++n) { 20826048Sminshall if (!strcmp("init", macros[n].mac_name)) { 20926496Sminshall (void) strcpy(line, "$init"); 21026048Sminshall makeargv(); 21126048Sminshall domacro(margc, margv); 21226048Sminshall break; 21326048Sminshall } 21426048Sminshall } 21510296Ssam return (1); 21610296Ssam } 21710296Ssam 21826048Sminshall cmdabort() 21926048Sminshall { 22026048Sminshall extern jmp_buf ptabort; 22126048Sminshall 22226048Sminshall printf("\n"); 22326048Sminshall (void) fflush(stdout); 22426048Sminshall abrtflag++; 22526448Slepreau if (ptflag) 22626048Sminshall longjmp(ptabort,1); 22726048Sminshall } 22826048Sminshall 22926496Sminshall /*VARARGS1*/ 23010296Ssam command(fmt, args) 23110296Ssam char *fmt; 23210296Ssam { 23326048Sminshall int r, (*oldintr)(), cmdabort(); 23410296Ssam 23526048Sminshall abrtflag = 0; 23610296Ssam if (debug) { 23710296Ssam printf("---> "); 23810296Ssam _doprnt(fmt, &args, stdout); 23910296Ssam printf("\n"); 24010296Ssam (void) fflush(stdout); 24110296Ssam } 24211219Ssam if (cout == NULL) { 24311219Ssam perror ("No control connection for command"); 24426048Sminshall code = -1; 24511219Ssam return (0); 24611219Ssam } 24726048Sminshall oldintr = signal(SIGINT,cmdabort); 24810296Ssam _doprnt(fmt, &args, cout); 24910296Ssam fprintf(cout, "\r\n"); 25010296Ssam (void) fflush(cout); 25126048Sminshall cpend = 1; 25226048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 25326448Slepreau if (abrtflag && oldintr != SIG_IGN) 25426048Sminshall (*oldintr)(); 25526048Sminshall (void) signal(SIGINT, oldintr); 25626048Sminshall return(r); 25710296Ssam } 25810296Ssam 25910296Ssam #include <ctype.h> 26010296Ssam 26110296Ssam getreply(expecteof) 26210296Ssam int expecteof; 26310296Ssam { 26411219Ssam register int c, n; 26526048Sminshall register int dig; 26626048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 26726048Sminshall int pflag = 0; 26826048Sminshall char *pt = pasv; 26910296Ssam 27026048Sminshall oldintr = signal(SIGINT,cmdabort); 27110296Ssam for (;;) { 27210296Ssam dig = n = code = 0; 27310296Ssam while ((c = getc(cin)) != '\n') { 27427687Sminshall if (c == IAC) { /* handle telnet commands */ 27527687Sminshall switch (c = getc(cin)) { 27627687Sminshall case WILL: 27727687Sminshall case WONT: 27827687Sminshall c = getc(cin); 27927687Sminshall fprintf(cout, "%c%c%c",IAC,WONT,c); 28027687Sminshall (void) fflush(cout); 28127687Sminshall break; 28227687Sminshall case DO: 28327687Sminshall case DONT: 28427687Sminshall c = getc(cin); 28527687Sminshall fprintf(cout, "%c%c%c",IAC,DONT,c); 28627687Sminshall (void) fflush(cout); 28727687Sminshall break; 28827687Sminshall default: 28927687Sminshall break; 29027687Sminshall } 29127687Sminshall continue; 29227687Sminshall } 29310296Ssam dig++; 29410296Ssam if (c == EOF) { 29526048Sminshall if (expecteof) { 29626048Sminshall (void) signal(SIGINT,oldintr); 29726048Sminshall code = 221; 29810296Ssam return (0); 29926048Sminshall } 30010296Ssam lostpeer(); 30126048Sminshall if (verbose) { 30226048Sminshall printf("421 Service not available, remote server has closed connection\n"); 30326048Sminshall (void) fflush(stdout); 30426048Sminshall } 30533772Scsvsj code = 421; 30633772Scsvsj return(4); 30710296Ssam } 30826048Sminshall if (c != '\r' && (verbose > 0 || 30926048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 31026448Slepreau if (proxflag && 31126448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 31226048Sminshall printf("%s:",hostname); 31326496Sminshall (void) putchar(c); 31426048Sminshall } 31510296Ssam if (dig < 4 && isdigit(c)) 31610296Ssam code = code * 10 + (c - '0'); 31726448Slepreau if (!pflag && code == 227) 31826048Sminshall pflag = 1; 31926448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 32026048Sminshall pflag = 2; 32126048Sminshall if (pflag == 2) { 32226448Slepreau if (c != '\r' && c != ')') 32326048Sminshall *pt++ = c; 32426048Sminshall else { 32526048Sminshall *pt = '\0'; 32626048Sminshall pflag = 3; 32726048Sminshall } 32826048Sminshall } 32926048Sminshall if (dig == 4 && c == '-') { 33026448Slepreau if (continuation) 33126048Sminshall code = 0; 33210296Ssam continuation++; 33326048Sminshall } 33410296Ssam if (n == 0) 33510296Ssam n = c; 33610296Ssam } 33726048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 33826496Sminshall (void) putchar(c); 33911346Ssam (void) fflush (stdout); 34011346Ssam } 34110296Ssam if (continuation && code != originalcode) { 34210296Ssam if (originalcode == 0) 34310296Ssam originalcode = code; 34410296Ssam continue; 34510296Ssam } 34626448Slepreau if (n != '1') 34726048Sminshall cpend = 0; 34826048Sminshall (void) signal(SIGINT,oldintr); 34926448Slepreau if (code == 421 || originalcode == 421) 35026048Sminshall lostpeer(); 35126448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 35226048Sminshall (*oldintr)(); 35325907Smckusick return (n - '0'); 35410296Ssam } 35510296Ssam } 35610296Ssam 35726048Sminshall empty(mask, sec) 35827687Sminshall struct fd_set *mask; 35926048Sminshall int sec; 36026048Sminshall { 36126048Sminshall struct timeval t; 36226048Sminshall 36326048Sminshall t.tv_sec = (long) sec; 36426048Sminshall t.tv_usec = 0; 36527687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 36626048Sminshall } 36726048Sminshall 36810296Ssam jmp_buf sendabort; 36910296Ssam 37010296Ssam abortsend() 37110296Ssam { 37210296Ssam 37326048Sminshall mflag = 0; 37426048Sminshall abrtflag = 0; 37526048Sminshall printf("\nsend aborted\n"); 37626048Sminshall (void) fflush(stdout); 37710296Ssam longjmp(sendabort, 1); 37810296Ssam } 37910296Ssam 38010296Ssam sendrequest(cmd, local, remote) 38110296Ssam char *cmd, *local, *remote; 38210296Ssam { 383*35659Sbostic FILE *fin, *dout = 0, *popen(); 384*35659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 38526048Sminshall int abortsend(); 38611219Ssam char buf[BUFSIZ]; 38711651Ssam long bytes = 0, hashbytes = sizeof (buf); 38811346Ssam register int c, d; 38910296Ssam struct stat st; 39010296Ssam struct timeval start, stop; 39110296Ssam 39226048Sminshall if (proxy) { 39326048Sminshall proxtrans(cmd, local, remote); 39426048Sminshall return; 39526048Sminshall } 39610296Ssam closefunc = NULL; 39726048Sminshall oldintr = NULL; 39826048Sminshall oldintp = NULL; 39926048Sminshall if (setjmp(sendabort)) { 40026048Sminshall while (cpend) { 40126048Sminshall (void) getreply(0); 40226048Sminshall } 40326048Sminshall if (data >= 0) { 40426048Sminshall (void) close(data); 40526048Sminshall data = -1; 40626048Sminshall } 40726448Slepreau if (oldintr) 40826048Sminshall (void) signal(SIGINT,oldintr); 40926448Slepreau if (oldintp) 41026048Sminshall (void) signal(SIGPIPE,oldintp); 41126048Sminshall code = -1; 41226048Sminshall return; 41326048Sminshall } 41410296Ssam oldintr = signal(SIGINT, abortsend); 41510296Ssam if (strcmp(local, "-") == 0) 41610296Ssam fin = stdin; 41710296Ssam else if (*local == '|') { 41826048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 419*35659Sbostic fin = popen(local + 1, "r"); 42010296Ssam if (fin == NULL) { 42126048Sminshall perror(local + 1); 42226048Sminshall (void) signal(SIGINT, oldintr); 42326048Sminshall (void) signal(SIGPIPE, oldintp); 42426048Sminshall code = -1; 42526048Sminshall return; 42610296Ssam } 427*35659Sbostic closefunc = pclose; 42810296Ssam } else { 42910296Ssam fin = fopen(local, "r"); 43010296Ssam if (fin == NULL) { 43110296Ssam perror(local); 43226048Sminshall (void) signal(SIGINT, oldintr); 43326048Sminshall code = -1; 43426048Sminshall return; 43510296Ssam } 43610296Ssam closefunc = fclose; 43710296Ssam if (fstat(fileno(fin), &st) < 0 || 43810296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 43926496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 44026048Sminshall (void) signal(SIGINT, oldintr); 44126048Sminshall code = -1; 44226048Sminshall return; 44310296Ssam } 44410296Ssam } 44526048Sminshall if (initconn()) { 44626048Sminshall (void) signal(SIGINT, oldintr); 44726448Slepreau if (oldintp) 44826048Sminshall (void) signal(SIGPIPE, oldintp); 44926048Sminshall code = -1; 45026048Sminshall return; 45126048Sminshall } 45226448Slepreau if (setjmp(sendabort)) 45326048Sminshall goto abort; 45410296Ssam if (remote) { 45526048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 45626048Sminshall (void) signal(SIGINT, oldintr); 45726448Slepreau if (oldintp) 45826048Sminshall (void) signal(SIGPIPE, oldintp); 45926048Sminshall return; 46026048Sminshall } 46110296Ssam } else 46226048Sminshall if (command("%s", cmd) != PRELIM) { 46326048Sminshall (void) signal(SIGINT, oldintr); 46426448Slepreau if (oldintp) 46526048Sminshall (void) signal(SIGPIPE, oldintp); 46626048Sminshall return; 46726048Sminshall } 46810296Ssam dout = dataconn("w"); 46926448Slepreau if (dout == NULL) 47026048Sminshall goto abort; 47126496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 47211219Ssam switch (type) { 47311219Ssam 47411219Ssam case TYPE_I: 47511219Ssam case TYPE_L: 47611346Ssam errno = d = 0; 47711219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 47811346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 47911219Ssam break; 48011219Ssam bytes += c; 48111651Ssam if (hash) { 48226496Sminshall (void) putchar('#'); 48326496Sminshall (void) fflush(stdout); 48411651Ssam } 48511219Ssam } 48613213Ssam if (hash && bytes > 0) { 48726496Sminshall (void) putchar('\n'); 48826496Sminshall (void) fflush(stdout); 48911651Ssam } 49011219Ssam if (c < 0) 49111219Ssam perror(local); 49211346Ssam if (d < 0) 49311219Ssam perror("netout"); 49411219Ssam break; 49511219Ssam 49611219Ssam case TYPE_A: 49711219Ssam while ((c = getc(fin)) != EOF) { 49811219Ssam if (c == '\n') { 49911651Ssam while (hash && (bytes >= hashbytes)) { 50026496Sminshall (void) putchar('#'); 50126496Sminshall (void) fflush(stdout); 50211651Ssam hashbytes += sizeof (buf); 50311651Ssam } 50411219Ssam if (ferror(dout)) 50511219Ssam break; 50626496Sminshall (void) putc('\r', dout); 50711219Ssam bytes++; 50811219Ssam } 50926496Sminshall (void) putc(c, dout); 51011219Ssam bytes++; 51126048Sminshall /* if (c == '\r') { */ 51226496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 51326048Sminshall /* bytes++; */ 51426048Sminshall /* } */ 51511219Ssam } 51611651Ssam if (hash) { 51713213Ssam if (bytes < hashbytes) 51826496Sminshall (void) putchar('#'); 51926496Sminshall (void) putchar('\n'); 52026496Sminshall (void) fflush(stdout); 52111651Ssam } 52211219Ssam if (ferror(fin)) 52311219Ssam perror(local); 52411346Ssam if (ferror(dout)) 52511219Ssam perror("netout"); 52611219Ssam break; 52710296Ssam } 52826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 52910296Ssam if (closefunc != NULL) 53026048Sminshall (*closefunc)(fin); 53110296Ssam (void) fclose(dout); 53226048Sminshall (void) getreply(0); 53326048Sminshall (void) signal(SIGINT, oldintr); 53410296Ssam if (bytes > 0 && verbose) 53526048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 53610296Ssam return; 53726048Sminshall abort: 53826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 53926048Sminshall (void) signal(SIGINT, oldintr); 54026448Slepreau if (oldintp) 54126048Sminshall (void) signal(SIGPIPE, oldintp); 54226048Sminshall if (!cpend) { 54326048Sminshall code = -1; 54426048Sminshall return; 54526048Sminshall } 54626048Sminshall if (data >= 0) { 54726048Sminshall (void) close(data); 54826048Sminshall data = -1; 54926048Sminshall } 55026448Slepreau if (dout) 55126048Sminshall (void) fclose(dout); 55226048Sminshall (void) getreply(0); 55326048Sminshall code = -1; 55410296Ssam if (closefunc != NULL && fin != NULL) 55526048Sminshall (*closefunc)(fin); 55626048Sminshall if (bytes > 0 && verbose) 55726048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 55810296Ssam } 55910296Ssam 56010296Ssam jmp_buf recvabort; 56110296Ssam 56210296Ssam abortrecv() 56310296Ssam { 56410296Ssam 56526048Sminshall mflag = 0; 56626048Sminshall abrtflag = 0; 56726048Sminshall printf("\n"); 56826048Sminshall (void) fflush(stdout); 56910296Ssam longjmp(recvabort, 1); 57010296Ssam } 57110296Ssam 57211651Ssam recvrequest(cmd, local, remote, mode) 57311651Ssam char *cmd, *local, *remote, *mode; 57410296Ssam { 575*35659Sbostic FILE *fout, *din = 0, *popen(); 576*35659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 57727687Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag, nfnd; 57827687Sminshall char buf[BUFSIZ], *gunique(), msg; 57926496Sminshall long bytes = 0, hashbytes = sizeof (buf); 58026496Sminshall struct fd_set mask; 58111346Ssam register int c, d; 58210296Ssam struct timeval start, stop; 58310296Ssam 58426048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 58526048Sminshall proxtrans(cmd, local, remote); 58626048Sminshall return; 58726048Sminshall } 58810296Ssam closefunc = NULL; 58926048Sminshall oldintr = NULL; 59026048Sminshall oldintp = NULL; 59126048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 59226048Sminshall if (setjmp(recvabort)) { 59326048Sminshall while (cpend) { 59426048Sminshall (void) getreply(0); 59526048Sminshall } 59626048Sminshall if (data >= 0) { 59726048Sminshall (void) close(data); 59826048Sminshall data = -1; 59926048Sminshall } 60026448Slepreau if (oldintr) 60126048Sminshall (void) signal(SIGINT, oldintr); 60226048Sminshall code = -1; 60326048Sminshall return; 60426048Sminshall } 60510296Ssam oldintr = signal(SIGINT, abortrecv); 60626048Sminshall if (strcmp(local, "-") && *local != '|') { 60710296Ssam if (access(local, 2) < 0) { 60826048Sminshall char *dir = rindex(local, '/'); 60910296Ssam 61026048Sminshall if (errno != ENOENT && errno != EACCES) { 61110296Ssam perror(local); 61226048Sminshall (void) signal(SIGINT, oldintr); 61326048Sminshall code = -1; 61426048Sminshall return; 61510296Ssam } 61626048Sminshall if (dir != NULL) 61726048Sminshall *dir = 0; 61826048Sminshall d = access(dir ? local : ".", 2); 61926048Sminshall if (dir != NULL) 62026048Sminshall *dir = '/'; 62126048Sminshall if (d < 0) { 62226048Sminshall perror(local); 62326048Sminshall (void) signal(SIGINT, oldintr); 62426048Sminshall code = -1; 62526048Sminshall return; 62626048Sminshall } 62726048Sminshall if (!runique && errno == EACCES && 62826048Sminshall chmod(local,0600) < 0) { 62926048Sminshall perror(local); 63026048Sminshall (void) signal(SIGINT, oldintr); 63126048Sminshall code = -1; 63226048Sminshall return; 63326048Sminshall } 63426048Sminshall if (runique && errno == EACCES && 63526048Sminshall (local = gunique(local)) == NULL) { 63626048Sminshall (void) signal(SIGINT, oldintr); 63726048Sminshall code = -1; 63826048Sminshall return; 63926048Sminshall } 64010296Ssam } 64126048Sminshall else if (runique && (local = gunique(local)) == NULL) { 64226048Sminshall (void) signal(SIGINT, oldintr); 64326048Sminshall code = -1; 64426048Sminshall return; 64526048Sminshall } 64626048Sminshall } 64726048Sminshall if (initconn()) { 64826048Sminshall (void) signal(SIGINT, oldintr); 64926048Sminshall code = -1; 65026048Sminshall return; 65126048Sminshall } 65226448Slepreau if (setjmp(recvabort)) 65326048Sminshall goto abort; 65426048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 65526048Sminshall oldtype = type; 65626048Sminshall oldverbose = verbose; 65726448Slepreau if (!debug) 65826048Sminshall verbose = 0; 65926048Sminshall setascii(); 66026048Sminshall verbose = oldverbose; 66126048Sminshall } 66210296Ssam if (remote) { 66326048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 66426048Sminshall (void) signal(SIGINT, oldintr); 66526048Sminshall if (oldtype) { 66626448Slepreau if (!debug) 66726048Sminshall verbose = 0; 66826048Sminshall switch (oldtype) { 66926048Sminshall case TYPE_I: 67026048Sminshall setbinary(); 67126048Sminshall break; 67226048Sminshall case TYPE_E: 67326048Sminshall setebcdic(); 67426048Sminshall break; 67526048Sminshall case TYPE_L: 67626048Sminshall settenex(); 67726048Sminshall break; 67826048Sminshall } 67926048Sminshall verbose = oldverbose; 68026048Sminshall } 68126048Sminshall return; 68226048Sminshall } 68326048Sminshall } else { 68426048Sminshall if (command("%s", cmd) != PRELIM) { 68526048Sminshall (void) signal(SIGINT, oldintr); 68626048Sminshall if (oldtype) { 68726448Slepreau if (!debug) 68826048Sminshall verbose = 0; 68926048Sminshall switch (oldtype) { 69026048Sminshall case TYPE_I: 69126048Sminshall setbinary(); 69226048Sminshall break; 69326048Sminshall case TYPE_E: 69426048Sminshall setebcdic(); 69526048Sminshall break; 69626048Sminshall case TYPE_L: 69726048Sminshall settenex(); 69826048Sminshall break; 69926048Sminshall } 70026048Sminshall verbose = oldverbose; 70126048Sminshall } 70226048Sminshall return; 70326048Sminshall } 70426048Sminshall } 70526048Sminshall din = dataconn("r"); 70626048Sminshall if (din == NULL) 70726048Sminshall goto abort; 70826448Slepreau if (strcmp(local, "-") == 0) 70910296Ssam fout = stdout; 71010296Ssam else if (*local == '|') { 71126048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 712*35659Sbostic fout = popen(local + 1, "w"); 71326048Sminshall if (fout == NULL) { 71426048Sminshall perror(local+1); 71526048Sminshall goto abort; 71626048Sminshall } 717*35659Sbostic closefunc = pclose; 71826048Sminshall } 71926048Sminshall else { 72011651Ssam fout = fopen(local, mode); 72126048Sminshall if (fout == NULL) { 72226048Sminshall perror(local); 72326048Sminshall goto abort; 72426048Sminshall } 72510296Ssam closefunc = fclose; 72610296Ssam } 72726496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 72811219Ssam switch (type) { 72911219Ssam 73011219Ssam case TYPE_I: 73111219Ssam case TYPE_L: 73211346Ssam errno = d = 0; 73311219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 73411346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 73511219Ssam break; 73611219Ssam bytes += c; 73711651Ssam if (hash) { 73826496Sminshall (void) putchar('#'); 73926496Sminshall (void) fflush(stdout); 74011651Ssam } 74111219Ssam } 74213213Ssam if (hash && bytes > 0) { 74326496Sminshall (void) putchar('\n'); 74426496Sminshall (void) fflush(stdout); 74511651Ssam } 74611219Ssam if (c < 0) 74711219Ssam perror("netin"); 74811346Ssam if (d < 0) 74910296Ssam perror(local); 75011219Ssam break; 75111219Ssam 75211219Ssam case TYPE_A: 75311219Ssam while ((c = getc(din)) != EOF) { 75427749Sminshall while (c == '\r') { 75511651Ssam while (hash && (bytes >= hashbytes)) { 75626496Sminshall (void) putchar('#'); 75726496Sminshall (void) fflush(stdout); 75811651Ssam hashbytes += sizeof (buf); 75911651Ssam } 76010296Ssam bytes++; 76126048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 76211219Ssam if (ferror (fout)) 76311219Ssam break; 76426496Sminshall (void) putc ('\r', fout); 76511219Ssam } 76626048Sminshall /*if (c == '\0') { 76711219Ssam bytes++; 76811219Ssam continue; 76926048Sminshall }*/ 77011219Ssam } 77126496Sminshall (void) putc (c, fout); 77211219Ssam bytes++; 77310296Ssam } 77411651Ssam if (hash) { 77513213Ssam if (bytes < hashbytes) 77626496Sminshall (void) putchar('#'); 77726496Sminshall (void) putchar('\n'); 77826496Sminshall (void) fflush(stdout); 77911651Ssam } 78011219Ssam if (ferror (din)) 78111219Ssam perror ("netin"); 78211219Ssam if (ferror (fout)) 78311219Ssam perror (local); 78411219Ssam break; 78510296Ssam } 78626448Slepreau if (closefunc != NULL) 78726048Sminshall (*closefunc)(fout); 78826496Sminshall (void) signal(SIGINT, oldintr); 78926448Slepreau if (oldintp) 79026048Sminshall (void) signal(SIGPIPE, oldintp); 79126496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 79210296Ssam (void) fclose(din); 79326048Sminshall (void) getreply(0); 79426048Sminshall if (bytes > 0 && verbose) 79526048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 79626048Sminshall if (oldtype) { 79726448Slepreau if (!debug) 79826048Sminshall verbose = 0; 79926048Sminshall switch (oldtype) { 80026048Sminshall case TYPE_I: 80126048Sminshall setbinary(); 80226048Sminshall break; 80326048Sminshall case TYPE_E: 80426048Sminshall setebcdic(); 80526048Sminshall break; 80626048Sminshall case TYPE_L: 80726048Sminshall settenex(); 80826048Sminshall break; 80926048Sminshall } 81026048Sminshall verbose = oldverbose; 81126048Sminshall } 81226048Sminshall return; 81326048Sminshall abort: 81426048Sminshall 81527687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 81626048Sminshall 81726496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 81826448Slepreau if (oldintp) 81926048Sminshall (void) signal(SIGPIPE, oldintr); 82026048Sminshall (void) signal(SIGINT,SIG_IGN); 82126048Sminshall if (oldtype) { 82226448Slepreau if (!debug) 82326048Sminshall verbose = 0; 82426048Sminshall switch (oldtype) { 82526048Sminshall case TYPE_I: 82626048Sminshall setbinary(); 82726048Sminshall break; 82826048Sminshall case TYPE_E: 82926048Sminshall setebcdic(); 83026048Sminshall break; 83126048Sminshall case TYPE_L: 83226048Sminshall settenex(); 83326048Sminshall break; 83426048Sminshall } 83526048Sminshall verbose = oldverbose; 83626048Sminshall } 83726048Sminshall if (!cpend) { 83826048Sminshall code = -1; 83926048Sminshall (void) signal(SIGINT,oldintr); 84026048Sminshall return; 84126048Sminshall } 84226048Sminshall 84327687Sminshall fprintf(cout,"%c%c",IAC,IP); 84427687Sminshall (void) fflush(cout); 84527687Sminshall msg = IAC; 84627687Sminshall /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 84727687Sminshall /* after urgent byte rather than before as now is protocol */ 84827687Sminshall if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 84927687Sminshall perror("abort"); 85026048Sminshall } 85127687Sminshall fprintf(cout,"%cABOR\r\n",DM); 85226048Sminshall (void) fflush(cout); 85327687Sminshall FD_ZERO(&mask); 85426496Sminshall FD_SET(fileno(cin), &mask); 85526496Sminshall if (din) { 85626496Sminshall FD_SET(fileno(din), &mask); 85726496Sminshall } 85827687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 85927687Sminshall if (nfnd < 0) { 86027687Sminshall perror("abort"); 86127687Sminshall } 86226048Sminshall code = -1; 86326048Sminshall lostpeer(); 86426048Sminshall } 86526496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 86626448Slepreau while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 86726448Slepreau ; 86826496Sminshall } 86927687Sminshall if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 87026048Sminshall if (data >= 0) { 87126496Sminshall (void) close(data); 87226048Sminshall data = -1; 87326048Sminshall } 87425907Smckusick (void) getreply(0); 87525907Smckusick } 87626048Sminshall (void) getreply(0); 87726048Sminshall code = -1; 87826048Sminshall if (data >= 0) { 87926048Sminshall (void) close(data); 88026048Sminshall data = -1; 88126048Sminshall } 88226448Slepreau if (closefunc != NULL && fout != NULL) 88326048Sminshall (*closefunc)(fout); 88426448Slepreau if (din) 88526048Sminshall (void) fclose(din); 88610296Ssam if (bytes > 0 && verbose) 88726048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 88826048Sminshall (void) signal(SIGINT,oldintr); 88910296Ssam } 89010296Ssam 89110296Ssam /* 89210296Ssam * Need to start a listen on the data channel 89310296Ssam * before we send the command, otherwise the 89410296Ssam * server's connect may fail. 89510296Ssam */ 89633224Sbostic int sendport = -1; 89711651Ssam 89810296Ssam initconn() 89910296Ssam { 90010296Ssam register char *p, *a; 90126048Sminshall int result, len, tmpno = 0; 90226993Skarels int on = 1; 90310296Ssam 90411651Ssam noport: 90510296Ssam data_addr = myctladdr; 90611651Ssam if (sendport) 90711651Ssam data_addr.sin_port = 0; /* let system pick one */ 90811651Ssam if (data != -1) 90911651Ssam (void) close (data); 91018287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 91110296Ssam if (data < 0) { 91210296Ssam perror("ftp: socket"); 91326448Slepreau if (tmpno) 91426048Sminshall sendport = 1; 91510296Ssam return (1); 91610296Ssam } 91712397Ssam if (!sendport) 91827687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 91933224Sbostic perror("ftp: setsockopt (reuse address)"); 92012397Ssam goto bad; 92112397Ssam } 92226496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 92310296Ssam perror("ftp: bind"); 92410296Ssam goto bad; 92510296Ssam } 92610296Ssam if (options & SO_DEBUG && 92727687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 92810296Ssam perror("ftp: setsockopt (ignored)"); 92911627Ssam len = sizeof (data_addr); 93011627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 93111627Ssam perror("ftp: getsockname"); 93210296Ssam goto bad; 93310296Ssam } 93426448Slepreau if (listen(data, 1) < 0) 93510296Ssam perror("ftp: listen"); 93611651Ssam if (sendport) { 93711651Ssam a = (char *)&data_addr.sin_addr; 93811651Ssam p = (char *)&data_addr.sin_port; 93910296Ssam #define UC(b) (((int)b)&0xff) 94011651Ssam result = 94111651Ssam command("PORT %d,%d,%d,%d,%d,%d", 94211651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 94311651Ssam UC(p[0]), UC(p[1])); 94411651Ssam if (result == ERROR && sendport == -1) { 94511651Ssam sendport = 0; 94626048Sminshall tmpno = 1; 94711651Ssam goto noport; 94811651Ssam } 94911651Ssam return (result != COMPLETE); 95011651Ssam } 95126448Slepreau if (tmpno) 95226048Sminshall sendport = 1; 95311651Ssam return (0); 95410296Ssam bad: 95510296Ssam (void) close(data), data = -1; 95626448Slepreau if (tmpno) 95726048Sminshall sendport = 1; 95810296Ssam return (1); 95910296Ssam } 96010296Ssam 96110296Ssam FILE * 96210296Ssam dataconn(mode) 96310296Ssam char *mode; 96410296Ssam { 96510296Ssam struct sockaddr_in from; 96610296Ssam int s, fromlen = sizeof (from); 96710296Ssam 96826496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 96910296Ssam if (s < 0) { 97010296Ssam perror("ftp: accept"); 97110296Ssam (void) close(data), data = -1; 97210296Ssam return (NULL); 97310296Ssam } 97410296Ssam (void) close(data); 97510296Ssam data = s; 97610296Ssam return (fdopen(data, mode)); 97710296Ssam } 97810296Ssam 97926048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 98026048Sminshall char *direction, *local, *remote; 98111651Ssam long bytes; 98210296Ssam struct timeval *t0, *t1; 98310296Ssam { 98410296Ssam struct timeval td; 98516437Sleres float s, bs; 98610296Ssam 98710296Ssam tvsub(&td, t1, t0); 98816437Sleres s = td.tv_sec + (td.tv_usec / 1000000.); 98910296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 99016437Sleres bs = bytes / nz(s); 99126448Slepreau if (local && *local != '-') 99226048Sminshall printf("local: %s ", local); 99326448Slepreau if (remote) 99426048Sminshall printf("remote: %s\n", remote); 99516437Sleres printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 99616437Sleres bytes, direction, s, bs / 1024.); 99710296Ssam } 99810296Ssam 99926496Sminshall /*tvadd(tsum, t0) 100010296Ssam struct timeval *tsum, *t0; 100110296Ssam { 100210296Ssam 100310296Ssam tsum->tv_sec += t0->tv_sec; 100410296Ssam tsum->tv_usec += t0->tv_usec; 100510296Ssam if (tsum->tv_usec > 1000000) 100610296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 100726496Sminshall } */ 100810296Ssam 100910296Ssam tvsub(tdiff, t1, t0) 101010296Ssam struct timeval *tdiff, *t1, *t0; 101110296Ssam { 101210296Ssam 101310296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 101410296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 101510296Ssam if (tdiff->tv_usec < 0) 101610296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 101710296Ssam } 101826048Sminshall 101926048Sminshall psabort() 102026048Sminshall { 102126048Sminshall extern int abrtflag; 102226048Sminshall 102326048Sminshall abrtflag++; 102426048Sminshall } 102526048Sminshall 102626048Sminshall pswitch(flag) 102726048Sminshall int flag; 102826048Sminshall { 102926048Sminshall extern int proxy, abrtflag; 103026048Sminshall int (*oldintr)(); 103126048Sminshall static struct comvars { 103226048Sminshall int connect; 103328469Skarels char name[MAXHOSTNAMELEN]; 103426048Sminshall struct sockaddr_in mctl; 103526048Sminshall struct sockaddr_in hctl; 103626048Sminshall FILE *in; 103726048Sminshall FILE *out; 103826048Sminshall int tpe; 103926048Sminshall int cpnd; 104026048Sminshall int sunqe; 104126048Sminshall int runqe; 104226048Sminshall int mcse; 104326048Sminshall int ntflg; 104426048Sminshall char nti[17]; 104526048Sminshall char nto[17]; 104626048Sminshall int mapflg; 104726048Sminshall char mi[MAXPATHLEN]; 104826048Sminshall char mo[MAXPATHLEN]; 104926048Sminshall } proxstruct, tmpstruct; 105026048Sminshall struct comvars *ip, *op; 105126048Sminshall 105226048Sminshall abrtflag = 0; 105326048Sminshall oldintr = signal(SIGINT, psabort); 105426048Sminshall if (flag) { 105526448Slepreau if (proxy) 105626048Sminshall return; 105726048Sminshall ip = &tmpstruct; 105826048Sminshall op = &proxstruct; 105926048Sminshall proxy++; 106026048Sminshall } 106126048Sminshall else { 106226448Slepreau if (!proxy) 106326048Sminshall return; 106426048Sminshall ip = &proxstruct; 106526048Sminshall op = &tmpstruct; 106626048Sminshall proxy = 0; 106726048Sminshall } 106826048Sminshall ip->connect = connected; 106926048Sminshall connected = op->connect; 107028469Skarels if (hostname) { 107128469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 107228469Skarels ip->name[strlen(ip->name)] = '\0'; 107328469Skarels } else 107428469Skarels ip->name[0] = 0; 107526048Sminshall hostname = op->name; 107626048Sminshall ip->hctl = hisctladdr; 107726048Sminshall hisctladdr = op->hctl; 107826048Sminshall ip->mctl = myctladdr; 107926048Sminshall myctladdr = op->mctl; 108026048Sminshall ip->in = cin; 108126048Sminshall cin = op->in; 108226048Sminshall ip->out = cout; 108326048Sminshall cout = op->out; 108426048Sminshall ip->tpe = type; 108526048Sminshall type = op->tpe; 108626448Slepreau if (!type) 108726048Sminshall type = 1; 108826048Sminshall ip->cpnd = cpend; 108926048Sminshall cpend = op->cpnd; 109026048Sminshall ip->sunqe = sunique; 109126048Sminshall sunique = op->sunqe; 109226048Sminshall ip->runqe = runique; 109326048Sminshall runique = op->runqe; 109426048Sminshall ip->mcse = mcase; 109526048Sminshall mcase = op->mcse; 109626048Sminshall ip->ntflg = ntflag; 109726048Sminshall ntflag = op->ntflg; 109826496Sminshall (void) strncpy(ip->nti, ntin, 16); 109926048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 110026496Sminshall (void) strcpy(ntin, op->nti); 110126496Sminshall (void) strncpy(ip->nto, ntout, 16); 110226048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 110326496Sminshall (void) strcpy(ntout, op->nto); 110426048Sminshall ip->mapflg = mapflag; 110526048Sminshall mapflag = op->mapflg; 110626496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 110726048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 110826496Sminshall (void) strcpy(mapin, op->mi); 110926496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 111026048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 111126496Sminshall (void) strcpy(mapout, op->mo); 111226048Sminshall (void) signal(SIGINT, oldintr); 111326048Sminshall if (abrtflag) { 111426048Sminshall abrtflag = 0; 111526048Sminshall (*oldintr)(); 111626448Slepreau } 111726048Sminshall } 111826048Sminshall 111926048Sminshall jmp_buf ptabort; 112026048Sminshall int ptabflg; 112126048Sminshall 112226048Sminshall abortpt() 112326048Sminshall { 112426048Sminshall printf("\n"); 112526496Sminshall (void) fflush(stdout); 112626048Sminshall ptabflg++; 112726048Sminshall mflag = 0; 112826048Sminshall abrtflag = 0; 112926048Sminshall longjmp(ptabort, 1); 113026048Sminshall } 113126048Sminshall 113226048Sminshall proxtrans(cmd, local, remote) 113326048Sminshall char *cmd, *local, *remote; 113426048Sminshall { 113527687Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 113626048Sminshall extern jmp_buf ptabort; 113726048Sminshall char *cmd2; 113826496Sminshall struct fd_set mask; 113926048Sminshall 114026448Slepreau if (strcmp(cmd, "RETR")) 114126048Sminshall cmd2 = "RETR"; 114226448Slepreau else 114326048Sminshall cmd2 = runique ? "STOU" : "STOR"; 114426048Sminshall if (command("PASV") != COMPLETE) { 114526048Sminshall printf("proxy server does not support third part transfers.\n"); 114626048Sminshall return; 114726048Sminshall } 114826048Sminshall tmptype = type; 114926048Sminshall pswitch(0); 115026048Sminshall if (!connected) { 115126048Sminshall printf("No primary connection\n"); 115226048Sminshall pswitch(1); 115326048Sminshall code = -1; 115426048Sminshall return; 115526048Sminshall } 115626048Sminshall if (type != tmptype) { 115726048Sminshall oldtype = type; 115826048Sminshall switch (tmptype) { 115926048Sminshall case TYPE_A: 116026048Sminshall setascii(); 116126048Sminshall break; 116226048Sminshall case TYPE_I: 116326048Sminshall setbinary(); 116426048Sminshall break; 116526048Sminshall case TYPE_E: 116626048Sminshall setebcdic(); 116726048Sminshall break; 116826048Sminshall case TYPE_L: 116926048Sminshall settenex(); 117026048Sminshall break; 117126048Sminshall } 117226048Sminshall } 117326048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 117426048Sminshall switch (oldtype) { 117526048Sminshall case 0: 117626048Sminshall break; 117726048Sminshall case TYPE_A: 117826048Sminshall setascii(); 117926048Sminshall break; 118026048Sminshall case TYPE_I: 118126048Sminshall setbinary(); 118226048Sminshall break; 118326048Sminshall case TYPE_E: 118426048Sminshall setebcdic(); 118526048Sminshall break; 118626048Sminshall case TYPE_L: 118726048Sminshall settenex(); 118826048Sminshall break; 118926048Sminshall } 119026048Sminshall pswitch(1); 119126048Sminshall return; 119226048Sminshall } 119326448Slepreau if (setjmp(ptabort)) 119426048Sminshall goto abort; 119526048Sminshall oldintr = signal(SIGINT, abortpt); 119626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 119726048Sminshall (void) signal(SIGINT, oldintr); 119826048Sminshall switch (oldtype) { 119926048Sminshall case 0: 120026048Sminshall break; 120126048Sminshall case TYPE_A: 120226048Sminshall setascii(); 120326048Sminshall break; 120426048Sminshall case TYPE_I: 120526048Sminshall setbinary(); 120626048Sminshall break; 120726048Sminshall case TYPE_E: 120826048Sminshall setebcdic(); 120926048Sminshall break; 121026048Sminshall case TYPE_L: 121126048Sminshall settenex(); 121226048Sminshall break; 121326048Sminshall } 121426048Sminshall pswitch(1); 121526048Sminshall return; 121626048Sminshall } 121726048Sminshall sleep(2); 121826048Sminshall pswitch(1); 121926048Sminshall secndflag++; 122026448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 122126048Sminshall goto abort; 122226048Sminshall ptflag++; 122326048Sminshall (void) getreply(0); 122426048Sminshall pswitch(0); 122526048Sminshall (void) getreply(0); 122626048Sminshall (void) signal(SIGINT, oldintr); 122726048Sminshall switch (oldtype) { 122826048Sminshall case 0: 122926048Sminshall break; 123026048Sminshall case TYPE_A: 123126048Sminshall setascii(); 123226048Sminshall break; 123326048Sminshall case TYPE_I: 123426048Sminshall setbinary(); 123526048Sminshall break; 123626048Sminshall case TYPE_E: 123726048Sminshall setebcdic(); 123826048Sminshall break; 123926048Sminshall case TYPE_L: 124026048Sminshall settenex(); 124126048Sminshall break; 124226048Sminshall } 124326048Sminshall pswitch(1); 124426048Sminshall ptflag = 0; 124526048Sminshall printf("local: %s remote: %s\n", local, remote); 124626048Sminshall return; 124726048Sminshall abort: 124826048Sminshall (void) signal(SIGINT, SIG_IGN); 124926048Sminshall ptflag = 0; 125026448Slepreau if (strcmp(cmd, "RETR") && !proxy) 125126048Sminshall pswitch(1); 125226448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 125326048Sminshall pswitch(0); 125426048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 125526048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 125626048Sminshall pswitch(0); 125726048Sminshall switch (oldtype) { 125826048Sminshall case 0: 125926048Sminshall break; 126026048Sminshall case TYPE_A: 126126048Sminshall setascii(); 126226048Sminshall break; 126326048Sminshall case TYPE_I: 126426048Sminshall setbinary(); 126526048Sminshall break; 126626048Sminshall case TYPE_E: 126726048Sminshall setebcdic(); 126826048Sminshall break; 126926048Sminshall case TYPE_L: 127026048Sminshall settenex(); 127126048Sminshall break; 127226048Sminshall } 127327687Sminshall if (cpend) { 127426048Sminshall char msg[2]; 127526048Sminshall 127626048Sminshall fprintf(cout,"%c%c",IAC,IP); 127726048Sminshall (void) fflush(cout); 127826048Sminshall *msg = IAC; 127926048Sminshall *(msg+1) = DM; 128026448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 128126048Sminshall perror("abort"); 128226048Sminshall fprintf(cout,"ABOR\r\n"); 128326048Sminshall (void) fflush(cout); 128427687Sminshall FD_ZERO(&mask); 128526496Sminshall FD_SET(fileno(cin), &mask); 128627687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 128727687Sminshall if (nfnd < 0) { 128827687Sminshall perror("abort"); 128927687Sminshall } 129026448Slepreau if (ptabflg) 129126048Sminshall code = -1; 129226048Sminshall lostpeer(); 129326048Sminshall } 129426048Sminshall (void) getreply(0); 129526048Sminshall (void) getreply(0); 129626048Sminshall } 129726048Sminshall } 129826048Sminshall pswitch(1); 129926448Slepreau if (ptabflg) 130026048Sminshall code = -1; 130126048Sminshall (void) signal(SIGINT, oldintr); 130226048Sminshall return; 130326048Sminshall } 130427687Sminshall if (cpend) { 130526048Sminshall char msg[2]; 130626048Sminshall 130726048Sminshall fprintf(cout,"%c%c",IAC,IP); 130826048Sminshall (void) fflush(cout); 130926048Sminshall *msg = IAC; 131026048Sminshall *(msg+1) = DM; 131126448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 131226048Sminshall perror("abort"); 131326048Sminshall fprintf(cout,"ABOR\r\n"); 131426048Sminshall (void) fflush(cout); 131527687Sminshall FD_ZERO(&mask); 131626496Sminshall FD_SET(fileno(cin), &mask); 131727687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 131827687Sminshall if (nfnd < 0) { 131927687Sminshall perror("abort"); 132027687Sminshall } 132126448Slepreau if (ptabflg) 132226048Sminshall code = -1; 132326048Sminshall lostpeer(); 132426048Sminshall } 132526048Sminshall (void) getreply(0); 132626048Sminshall (void) getreply(0); 132726048Sminshall } 132826048Sminshall pswitch(!proxy); 132926048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 133026048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 133126048Sminshall pswitch(0); 133226048Sminshall switch (oldtype) { 133326048Sminshall case 0: 133426048Sminshall break; 133526048Sminshall case TYPE_A: 133626048Sminshall setascii(); 133726048Sminshall break; 133826048Sminshall case TYPE_I: 133926048Sminshall setbinary(); 134026048Sminshall break; 134126048Sminshall case TYPE_E: 134226048Sminshall setebcdic(); 134326048Sminshall break; 134426048Sminshall case TYPE_L: 134526048Sminshall settenex(); 134626048Sminshall break; 134726048Sminshall } 134827687Sminshall if (cpend) { 134926048Sminshall char msg[2]; 135026048Sminshall 135126048Sminshall fprintf(cout,"%c%c",IAC,IP); 135226048Sminshall (void) fflush(cout); 135326048Sminshall *msg = IAC; 135426048Sminshall *(msg+1) = DM; 135526448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 135626048Sminshall perror("abort"); 135726048Sminshall fprintf(cout,"ABOR\r\n"); 135826048Sminshall (void) fflush(cout); 135927687Sminshall FD_ZERO(&mask); 136026496Sminshall FD_SET(fileno(cin), &mask); 136127687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 136227687Sminshall if (nfnd < 0) { 136327687Sminshall perror("abort"); 136427687Sminshall } 136526448Slepreau if (ptabflg) 136626048Sminshall code = -1; 136726048Sminshall lostpeer(); 136826048Sminshall } 136926048Sminshall (void) getreply(0); 137026048Sminshall (void) getreply(0); 137126048Sminshall } 137226048Sminshall pswitch(1); 137326448Slepreau if (ptabflg) 137426048Sminshall code = -1; 137526048Sminshall (void) signal(SIGINT, oldintr); 137626048Sminshall return; 137726048Sminshall } 137826048Sminshall } 137927687Sminshall if (cpend) { 138026048Sminshall char msg[2]; 138126048Sminshall 138226048Sminshall fprintf(cout,"%c%c",IAC,IP); 138326048Sminshall (void) fflush(cout); 138426048Sminshall *msg = IAC; 138526048Sminshall *(msg+1) = DM; 138626448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 138726048Sminshall perror("abort"); 138826048Sminshall fprintf(cout,"ABOR\r\n"); 138926048Sminshall (void) fflush(cout); 139027687Sminshall FD_ZERO(&mask); 139126496Sminshall FD_SET(fileno(cin), &mask); 139227687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 139327687Sminshall if (nfnd < 0) { 139427687Sminshall perror("abort"); 139527687Sminshall } 139626448Slepreau if (ptabflg) 139726048Sminshall code = -1; 139826048Sminshall lostpeer(); 139926048Sminshall } 140026048Sminshall (void) getreply(0); 140126048Sminshall (void) getreply(0); 140226048Sminshall } 140326048Sminshall pswitch(!proxy); 140426048Sminshall if (cpend) { 140527687Sminshall FD_ZERO(&mask); 140626496Sminshall FD_SET(fileno(cin), &mask); 140727687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 140827687Sminshall if (nfnd < 0) { 140927687Sminshall perror("abort"); 141027687Sminshall } 141126448Slepreau if (ptabflg) 141226048Sminshall code = -1; 141326048Sminshall lostpeer(); 141426048Sminshall } 141526048Sminshall (void) getreply(0); 141626048Sminshall (void) getreply(0); 141726048Sminshall } 141826448Slepreau if (proxy) 141926048Sminshall pswitch(0); 142026048Sminshall switch (oldtype) { 142126048Sminshall case 0: 142226048Sminshall break; 142326048Sminshall case TYPE_A: 142426048Sminshall setascii(); 142526048Sminshall break; 142626048Sminshall case TYPE_I: 142726048Sminshall setbinary(); 142826048Sminshall break; 142926048Sminshall case TYPE_E: 143026048Sminshall setebcdic(); 143126048Sminshall break; 143226048Sminshall case TYPE_L: 143326048Sminshall settenex(); 143426048Sminshall break; 143526048Sminshall } 143626048Sminshall pswitch(1); 143726448Slepreau if (ptabflg) 143826048Sminshall code = -1; 143926048Sminshall (void) signal(SIGINT, oldintr); 144026048Sminshall } 144126048Sminshall 144226048Sminshall reset() 144326048Sminshall { 144426496Sminshall struct fd_set mask; 144526496Sminshall int nfnd = 1; 144626048Sminshall 144727687Sminshall FD_ZERO(&mask); 144830946Scsvsj while (nfnd > 0) { 144926496Sminshall FD_SET(fileno(cin), &mask); 145027687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 145126048Sminshall perror("reset"); 145226048Sminshall code = -1; 145326048Sminshall lostpeer(); 145426048Sminshall } 145527687Sminshall else if (nfnd) { 145626048Sminshall (void) getreply(0); 145726496Sminshall } 145826048Sminshall } 145926048Sminshall } 146026048Sminshall 146126048Sminshall char * 146226048Sminshall gunique(local) 146326048Sminshall char *local; 146426048Sminshall { 146526048Sminshall static char new[MAXPATHLEN]; 146626048Sminshall char *cp = rindex(local, '/'); 146726048Sminshall int d, count=0; 146826048Sminshall char ext = '1'; 146926048Sminshall 147026448Slepreau if (cp) 147126048Sminshall *cp = '\0'; 147226048Sminshall d = access(cp ? local : ".", 2); 147326448Slepreau if (cp) 147426048Sminshall *cp = '/'; 147526048Sminshall if (d < 0) { 147626048Sminshall perror(local); 147726048Sminshall return((char *) 0); 147826048Sminshall } 147926048Sminshall (void) strcpy(new, local); 148026048Sminshall cp = new + strlen(new); 148126048Sminshall *cp++ = '.'; 148226048Sminshall while (!d) { 148326048Sminshall if (++count == 100) { 148426048Sminshall printf("runique: can't find unique file name.\n"); 148526048Sminshall return((char *) 0); 148626048Sminshall } 148726048Sminshall *cp++ = ext; 148826048Sminshall *cp = '\0'; 148926448Slepreau if (ext == '9') 149026048Sminshall ext = '0'; 149126448Slepreau else 149226048Sminshall ext++; 149326448Slepreau if ((d = access(new, 0)) < 0) 149426048Sminshall break; 149526448Slepreau if (ext != '0') 149626048Sminshall cp--; 149726448Slepreau else if (*(cp - 2) == '.') 149826048Sminshall *(cp - 1) = '1'; 149926048Sminshall else { 150026048Sminshall *(cp - 2) = *(cp - 2) + 1; 150126048Sminshall cp--; 150226048Sminshall } 150326048Sminshall } 150426048Sminshall return(new); 150526048Sminshall } 1506