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*35792Sbostic static char sccsid[] = "@(#)ftp.c 5.22 (Berkeley) 10/11/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) { 71*35792Sbostic fprintf(stderr, "ftp: %s: ", host); 72*35792Sbostic herror((char *)NULL); 7326048Sminshall code = -1; 7426048Sminshall return((char *) 0); 7525904Skarels } 7625904Skarels hisctladdr.sin_family = hp->h_addrtype; 7725904Skarels bcopy(hp->h_addr_list[0], 7825904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 7925904Skarels (void) strcpy(hostnamebuf, hp->h_name); 8010296Ssam } 8125904Skarels hostname = hostnamebuf; 8225904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 8310296Ssam if (s < 0) { 8410296Ssam perror("ftp: socket"); 8526048Sminshall code = -1; 8610296Ssam return (0); 8710296Ssam } 8810296Ssam hisctladdr.sin_port = port; 8926496Sminshall while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 9025904Skarels if (hp && hp->h_addr_list[1]) { 9125904Skarels int oerrno = errno; 9225904Skarels 9325904Skarels fprintf(stderr, "ftp: connect to address %s: ", 9425904Skarels inet_ntoa(hisctladdr.sin_addr)); 9525904Skarels errno = oerrno; 9626496Sminshall perror((char *) 0); 9725904Skarels hp->h_addr_list++; 9825904Skarels bcopy(hp->h_addr_list[0], 9926048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 10026496Sminshall fprintf(stdout, "Trying %s...\n", 10125904Skarels inet_ntoa(hisctladdr.sin_addr)); 10226813Skarels (void) close(s); 10326813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 10426813Skarels if (s < 0) { 10526813Skarels perror("ftp: socket"); 10626813Skarels code = -1; 10726813Skarels return (0); 10826813Skarels } 10925904Skarels continue; 11025904Skarels } 11110296Ssam perror("ftp: connect"); 11226048Sminshall code = -1; 11310296Ssam goto bad; 11410296Ssam } 11511627Ssam len = sizeof (myctladdr); 11611627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 11711627Ssam perror("ftp: getsockname"); 11826048Sminshall code = -1; 11910296Ssam goto bad; 12010296Ssam } 12110296Ssam cin = fdopen(s, "r"); 12210296Ssam cout = fdopen(s, "w"); 12311219Ssam if (cin == NULL || cout == NULL) { 12410296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 12510296Ssam if (cin) 12626496Sminshall (void) fclose(cin); 12710296Ssam if (cout) 12826496Sminshall (void) fclose(cout); 12926048Sminshall code = -1; 13010296Ssam goto bad; 13110296Ssam } 13210296Ssam if (verbose) 13326067Sminshall printf("Connected to %s.\n", hostname); 13427687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 13526048Sminshall if (cin) 13626496Sminshall (void) fclose(cin); 13726048Sminshall if (cout) 13826496Sminshall (void) fclose(cout); 13926048Sminshall code = -1; 14026048Sminshall goto bad; 14126048Sminshall } 14227687Sminshall #ifdef SO_OOBINLINE 14327687Sminshall { 14427687Sminshall int on = 1; 14526048Sminshall 14627687Sminshall if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 14727687Sminshall < 0 && debug) { 14827687Sminshall perror("ftp: setsockopt"); 14927687Sminshall } 15027687Sminshall } 15127687Sminshall #endif SO_OOBINLINE 15226048Sminshall 15325904Skarels return (hostname); 15410296Ssam bad: 15526496Sminshall (void) close(s); 15625904Skarels return ((char *)0); 15710296Ssam } 15810296Ssam 15925904Skarels login(host) 16025904Skarels char *host; 16110296Ssam { 16226048Sminshall char tmp[80]; 16335659Sbostic char *user, *pass, *acct, *getlogin(), *getpass(); 16426048Sminshall int n, aflag = 0; 16510296Ssam 16626048Sminshall user = pass = acct = 0; 16726048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 16826048Sminshall disconnect(); 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 26010296Ssam #include <ctype.h> 26110296Ssam 26210296Ssam getreply(expecteof) 26310296Ssam int expecteof; 26410296Ssam { 26511219Ssam register int c, n; 26626048Sminshall register int dig; 26726048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 26826048Sminshall int pflag = 0; 26926048Sminshall char *pt = pasv; 27010296Ssam 27126048Sminshall oldintr = signal(SIGINT,cmdabort); 27210296Ssam for (;;) { 27310296Ssam dig = n = code = 0; 27410296Ssam while ((c = getc(cin)) != '\n') { 27527687Sminshall if (c == IAC) { /* handle telnet commands */ 27627687Sminshall switch (c = getc(cin)) { 27727687Sminshall case WILL: 27827687Sminshall case WONT: 27927687Sminshall c = getc(cin); 28027687Sminshall fprintf(cout, "%c%c%c",IAC,WONT,c); 28127687Sminshall (void) fflush(cout); 28227687Sminshall break; 28327687Sminshall case DO: 28427687Sminshall case DONT: 28527687Sminshall c = getc(cin); 28627687Sminshall fprintf(cout, "%c%c%c",IAC,DONT,c); 28727687Sminshall (void) fflush(cout); 28827687Sminshall break; 28927687Sminshall default: 29027687Sminshall break; 29127687Sminshall } 29227687Sminshall continue; 29327687Sminshall } 29410296Ssam dig++; 29510296Ssam if (c == EOF) { 29626048Sminshall if (expecteof) { 29726048Sminshall (void) signal(SIGINT,oldintr); 29826048Sminshall code = 221; 29910296Ssam return (0); 30026048Sminshall } 30110296Ssam lostpeer(); 30226048Sminshall if (verbose) { 30326048Sminshall printf("421 Service not available, remote server has closed connection\n"); 30426048Sminshall (void) fflush(stdout); 30526048Sminshall } 30633772Scsvsj code = 421; 30733772Scsvsj return(4); 30810296Ssam } 30926048Sminshall if (c != '\r' && (verbose > 0 || 31026048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 31126448Slepreau if (proxflag && 31226448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 31326048Sminshall printf("%s:",hostname); 31426496Sminshall (void) putchar(c); 31526048Sminshall } 31610296Ssam if (dig < 4 && isdigit(c)) 31710296Ssam code = code * 10 + (c - '0'); 31826448Slepreau if (!pflag && code == 227) 31926048Sminshall pflag = 1; 32026448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 32126048Sminshall pflag = 2; 32226048Sminshall if (pflag == 2) { 32326448Slepreau if (c != '\r' && c != ')') 32426048Sminshall *pt++ = c; 32526048Sminshall else { 32626048Sminshall *pt = '\0'; 32726048Sminshall pflag = 3; 32826048Sminshall } 32926048Sminshall } 33026048Sminshall if (dig == 4 && c == '-') { 33126448Slepreau if (continuation) 33226048Sminshall code = 0; 33310296Ssam continuation++; 33426048Sminshall } 33510296Ssam if (n == 0) 33610296Ssam n = c; 33710296Ssam } 33826048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 33926496Sminshall (void) putchar(c); 34011346Ssam (void) fflush (stdout); 34111346Ssam } 34210296Ssam if (continuation && code != originalcode) { 34310296Ssam if (originalcode == 0) 34410296Ssam originalcode = code; 34510296Ssam continue; 34610296Ssam } 34726448Slepreau if (n != '1') 34826048Sminshall cpend = 0; 34926048Sminshall (void) signal(SIGINT,oldintr); 35026448Slepreau if (code == 421 || originalcode == 421) 35126048Sminshall lostpeer(); 35226448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 35326048Sminshall (*oldintr)(); 35425907Smckusick return (n - '0'); 35510296Ssam } 35610296Ssam } 35710296Ssam 35826048Sminshall empty(mask, sec) 35927687Sminshall struct fd_set *mask; 36026048Sminshall int sec; 36126048Sminshall { 36226048Sminshall struct timeval t; 36326048Sminshall 36426048Sminshall t.tv_sec = (long) sec; 36526048Sminshall t.tv_usec = 0; 36627687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 36726048Sminshall } 36826048Sminshall 36910296Ssam jmp_buf sendabort; 37010296Ssam 37110296Ssam abortsend() 37210296Ssam { 37310296Ssam 37426048Sminshall mflag = 0; 37526048Sminshall abrtflag = 0; 37626048Sminshall printf("\nsend aborted\n"); 37726048Sminshall (void) fflush(stdout); 37810296Ssam longjmp(sendabort, 1); 37910296Ssam } 38010296Ssam 38110296Ssam sendrequest(cmd, local, remote) 38210296Ssam char *cmd, *local, *remote; 38310296Ssam { 38435659Sbostic FILE *fin, *dout = 0, *popen(); 38535659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 38626048Sminshall int abortsend(); 38711219Ssam char buf[BUFSIZ]; 38811651Ssam long bytes = 0, hashbytes = sizeof (buf); 38911346Ssam register int c, d; 39010296Ssam struct stat st; 39110296Ssam struct timeval start, stop; 39210296Ssam 39326048Sminshall if (proxy) { 39426048Sminshall proxtrans(cmd, local, remote); 39526048Sminshall return; 39626048Sminshall } 39710296Ssam closefunc = NULL; 39826048Sminshall oldintr = NULL; 39926048Sminshall oldintp = NULL; 40026048Sminshall if (setjmp(sendabort)) { 40126048Sminshall while (cpend) { 40226048Sminshall (void) getreply(0); 40326048Sminshall } 40426048Sminshall if (data >= 0) { 40526048Sminshall (void) close(data); 40626048Sminshall data = -1; 40726048Sminshall } 40826448Slepreau if (oldintr) 40926048Sminshall (void) signal(SIGINT,oldintr); 41026448Slepreau if (oldintp) 41126048Sminshall (void) signal(SIGPIPE,oldintp); 41226048Sminshall code = -1; 41326048Sminshall return; 41426048Sminshall } 41510296Ssam oldintr = signal(SIGINT, abortsend); 41610296Ssam if (strcmp(local, "-") == 0) 41710296Ssam fin = stdin; 41810296Ssam else if (*local == '|') { 41926048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 42035659Sbostic fin = popen(local + 1, "r"); 42110296Ssam if (fin == NULL) { 42226048Sminshall perror(local + 1); 42326048Sminshall (void) signal(SIGINT, oldintr); 42426048Sminshall (void) signal(SIGPIPE, oldintp); 42526048Sminshall code = -1; 42626048Sminshall return; 42710296Ssam } 42835659Sbostic closefunc = pclose; 42910296Ssam } else { 43010296Ssam fin = fopen(local, "r"); 43110296Ssam if (fin == NULL) { 43210296Ssam perror(local); 43326048Sminshall (void) signal(SIGINT, oldintr); 43426048Sminshall code = -1; 43526048Sminshall return; 43610296Ssam } 43710296Ssam closefunc = fclose; 43810296Ssam if (fstat(fileno(fin), &st) < 0 || 43910296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 44026496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 44126048Sminshall (void) signal(SIGINT, oldintr); 44226048Sminshall code = -1; 44326048Sminshall return; 44410296Ssam } 44510296Ssam } 44626048Sminshall if (initconn()) { 44726048Sminshall (void) signal(SIGINT, oldintr); 44826448Slepreau if (oldintp) 44926048Sminshall (void) signal(SIGPIPE, oldintp); 45026048Sminshall code = -1; 45126048Sminshall return; 45226048Sminshall } 45326448Slepreau if (setjmp(sendabort)) 45426048Sminshall goto abort; 45510296Ssam if (remote) { 45626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 45726048Sminshall (void) signal(SIGINT, oldintr); 45826448Slepreau if (oldintp) 45926048Sminshall (void) signal(SIGPIPE, oldintp); 46026048Sminshall return; 46126048Sminshall } 46210296Ssam } else 46326048Sminshall if (command("%s", cmd) != PRELIM) { 46426048Sminshall (void) signal(SIGINT, oldintr); 46526448Slepreau if (oldintp) 46626048Sminshall (void) signal(SIGPIPE, oldintp); 46726048Sminshall return; 46826048Sminshall } 46910296Ssam dout = dataconn("w"); 47026448Slepreau if (dout == NULL) 47126048Sminshall goto abort; 47226496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 47311219Ssam switch (type) { 47411219Ssam 47511219Ssam case TYPE_I: 47611219Ssam case TYPE_L: 47711346Ssam errno = d = 0; 47811219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 47911346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 48011219Ssam break; 48111219Ssam bytes += c; 48211651Ssam if (hash) { 48326496Sminshall (void) putchar('#'); 48426496Sminshall (void) fflush(stdout); 48511651Ssam } 48611219Ssam } 48713213Ssam if (hash && bytes > 0) { 48826496Sminshall (void) putchar('\n'); 48926496Sminshall (void) fflush(stdout); 49011651Ssam } 49111219Ssam if (c < 0) 49211219Ssam perror(local); 49311346Ssam if (d < 0) 49411219Ssam perror("netout"); 49511219Ssam break; 49611219Ssam 49711219Ssam case TYPE_A: 49811219Ssam while ((c = getc(fin)) != EOF) { 49911219Ssam if (c == '\n') { 50011651Ssam while (hash && (bytes >= hashbytes)) { 50126496Sminshall (void) putchar('#'); 50226496Sminshall (void) fflush(stdout); 50311651Ssam hashbytes += sizeof (buf); 50411651Ssam } 50511219Ssam if (ferror(dout)) 50611219Ssam break; 50726496Sminshall (void) putc('\r', dout); 50811219Ssam bytes++; 50911219Ssam } 51026496Sminshall (void) putc(c, dout); 51111219Ssam bytes++; 51226048Sminshall /* if (c == '\r') { */ 51326496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 51426048Sminshall /* bytes++; */ 51526048Sminshall /* } */ 51611219Ssam } 51711651Ssam if (hash) { 51813213Ssam if (bytes < hashbytes) 51926496Sminshall (void) putchar('#'); 52026496Sminshall (void) putchar('\n'); 52126496Sminshall (void) fflush(stdout); 52211651Ssam } 52311219Ssam if (ferror(fin)) 52411219Ssam perror(local); 52511346Ssam if (ferror(dout)) 52611219Ssam perror("netout"); 52711219Ssam break; 52810296Ssam } 52926496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 53010296Ssam if (closefunc != NULL) 53126048Sminshall (*closefunc)(fin); 53210296Ssam (void) fclose(dout); 53326048Sminshall (void) getreply(0); 53426048Sminshall (void) signal(SIGINT, oldintr); 53535699Sbostic if (bytes > 0) 53626048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 53710296Ssam return; 53826048Sminshall abort: 53926496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 54026048Sminshall (void) signal(SIGINT, oldintr); 54126448Slepreau if (oldintp) 54226048Sminshall (void) signal(SIGPIPE, oldintp); 54326048Sminshall if (!cpend) { 54426048Sminshall code = -1; 54526048Sminshall return; 54626048Sminshall } 54726048Sminshall if (data >= 0) { 54826048Sminshall (void) close(data); 54926048Sminshall data = -1; 55026048Sminshall } 55126448Slepreau if (dout) 55226048Sminshall (void) fclose(dout); 55326048Sminshall (void) getreply(0); 55426048Sminshall code = -1; 55510296Ssam if (closefunc != NULL && fin != NULL) 55626048Sminshall (*closefunc)(fin); 55735699Sbostic if (bytes > 0) 55826048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 55910296Ssam } 56010296Ssam 56110296Ssam jmp_buf recvabort; 56210296Ssam 56310296Ssam abortrecv() 56410296Ssam { 56510296Ssam 56626048Sminshall mflag = 0; 56726048Sminshall abrtflag = 0; 56826048Sminshall printf("\n"); 56926048Sminshall (void) fflush(stdout); 57010296Ssam longjmp(recvabort, 1); 57110296Ssam } 57210296Ssam 57311651Ssam recvrequest(cmd, local, remote, mode) 57411651Ssam char *cmd, *local, *remote, *mode; 57510296Ssam { 57635659Sbostic FILE *fout, *din = 0, *popen(); 57735659Sbostic int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 57827687Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag, nfnd; 57927687Sminshall char buf[BUFSIZ], *gunique(), msg; 58026496Sminshall long bytes = 0, hashbytes = sizeof (buf); 58126496Sminshall struct fd_set mask; 58211346Ssam register int c, d; 58310296Ssam struct timeval start, stop; 58410296Ssam 58526048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 58626048Sminshall proxtrans(cmd, local, remote); 58726048Sminshall return; 58826048Sminshall } 58910296Ssam closefunc = NULL; 59026048Sminshall oldintr = NULL; 59126048Sminshall oldintp = NULL; 59226048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 59326048Sminshall if (setjmp(recvabort)) { 59426048Sminshall while (cpend) { 59526048Sminshall (void) getreply(0); 59626048Sminshall } 59726048Sminshall if (data >= 0) { 59826048Sminshall (void) close(data); 59926048Sminshall data = -1; 60026048Sminshall } 60126448Slepreau if (oldintr) 60226048Sminshall (void) signal(SIGINT, oldintr); 60326048Sminshall code = -1; 60426048Sminshall return; 60526048Sminshall } 60610296Ssam oldintr = signal(SIGINT, abortrecv); 60726048Sminshall if (strcmp(local, "-") && *local != '|') { 60810296Ssam if (access(local, 2) < 0) { 60926048Sminshall char *dir = rindex(local, '/'); 61010296Ssam 61126048Sminshall if (errno != ENOENT && errno != EACCES) { 61210296Ssam perror(local); 61326048Sminshall (void) signal(SIGINT, oldintr); 61426048Sminshall code = -1; 61526048Sminshall return; 61610296Ssam } 61726048Sminshall if (dir != NULL) 61826048Sminshall *dir = 0; 61926048Sminshall d = access(dir ? local : ".", 2); 62026048Sminshall if (dir != NULL) 62126048Sminshall *dir = '/'; 62226048Sminshall if (d < 0) { 62326048Sminshall perror(local); 62426048Sminshall (void) signal(SIGINT, oldintr); 62526048Sminshall code = -1; 62626048Sminshall return; 62726048Sminshall } 62826048Sminshall if (!runique && errno == EACCES && 62926048Sminshall chmod(local,0600) < 0) { 63026048Sminshall perror(local); 63126048Sminshall (void) signal(SIGINT, oldintr); 63226048Sminshall code = -1; 63326048Sminshall return; 63426048Sminshall } 63526048Sminshall if (runique && errno == EACCES && 63626048Sminshall (local = gunique(local)) == NULL) { 63726048Sminshall (void) signal(SIGINT, oldintr); 63826048Sminshall code = -1; 63926048Sminshall return; 64026048Sminshall } 64110296Ssam } 64226048Sminshall else if (runique && (local = gunique(local)) == NULL) { 64326048Sminshall (void) signal(SIGINT, oldintr); 64426048Sminshall code = -1; 64526048Sminshall return; 64626048Sminshall } 64726048Sminshall } 64826048Sminshall if (initconn()) { 64926048Sminshall (void) signal(SIGINT, oldintr); 65026048Sminshall code = -1; 65126048Sminshall return; 65226048Sminshall } 65326448Slepreau if (setjmp(recvabort)) 65426048Sminshall goto abort; 65526048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 65626048Sminshall oldtype = type; 65726048Sminshall oldverbose = verbose; 65826448Slepreau if (!debug) 65926048Sminshall verbose = 0; 66026048Sminshall setascii(); 66126048Sminshall verbose = oldverbose; 66226048Sminshall } 66310296Ssam if (remote) { 66426048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 66526048Sminshall (void) signal(SIGINT, oldintr); 66626048Sminshall if (oldtype) { 66726448Slepreau if (!debug) 66826048Sminshall verbose = 0; 66926048Sminshall switch (oldtype) { 67026048Sminshall case TYPE_I: 67126048Sminshall setbinary(); 67226048Sminshall break; 67326048Sminshall case TYPE_E: 67426048Sminshall setebcdic(); 67526048Sminshall break; 67626048Sminshall case TYPE_L: 67726048Sminshall settenex(); 67826048Sminshall break; 67926048Sminshall } 68026048Sminshall verbose = oldverbose; 68126048Sminshall } 68226048Sminshall return; 68326048Sminshall } 68426048Sminshall } else { 68526048Sminshall if (command("%s", cmd) != PRELIM) { 68626048Sminshall (void) signal(SIGINT, oldintr); 68726048Sminshall if (oldtype) { 68826448Slepreau if (!debug) 68926048Sminshall verbose = 0; 69026048Sminshall switch (oldtype) { 69126048Sminshall case TYPE_I: 69226048Sminshall setbinary(); 69326048Sminshall break; 69426048Sminshall case TYPE_E: 69526048Sminshall setebcdic(); 69626048Sminshall break; 69726048Sminshall case TYPE_L: 69826048Sminshall settenex(); 69926048Sminshall break; 70026048Sminshall } 70126048Sminshall verbose = oldverbose; 70226048Sminshall } 70326048Sminshall return; 70426048Sminshall } 70526048Sminshall } 70626048Sminshall din = dataconn("r"); 70726048Sminshall if (din == NULL) 70826048Sminshall goto abort; 70926448Slepreau if (strcmp(local, "-") == 0) 71010296Ssam fout = stdout; 71110296Ssam else if (*local == '|') { 71226048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 71335659Sbostic fout = popen(local + 1, "w"); 71426048Sminshall if (fout == NULL) { 71526048Sminshall perror(local+1); 71626048Sminshall goto abort; 71726048Sminshall } 71835659Sbostic closefunc = pclose; 71926048Sminshall } 72026048Sminshall else { 72111651Ssam fout = fopen(local, mode); 72226048Sminshall if (fout == NULL) { 72326048Sminshall perror(local); 72426048Sminshall goto abort; 72526048Sminshall } 72610296Ssam closefunc = fclose; 72710296Ssam } 72826496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 72911219Ssam switch (type) { 73011219Ssam 73111219Ssam case TYPE_I: 73211219Ssam case TYPE_L: 73311346Ssam errno = d = 0; 73411219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 73511346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 73611219Ssam break; 73711219Ssam bytes += c; 73811651Ssam if (hash) { 73926496Sminshall (void) putchar('#'); 74026496Sminshall (void) fflush(stdout); 74111651Ssam } 74211219Ssam } 74313213Ssam if (hash && bytes > 0) { 74426496Sminshall (void) putchar('\n'); 74526496Sminshall (void) fflush(stdout); 74611651Ssam } 74711219Ssam if (c < 0) 74811219Ssam perror("netin"); 74911346Ssam if (d < 0) 75010296Ssam perror(local); 75111219Ssam break; 75211219Ssam 75311219Ssam case TYPE_A: 75411219Ssam while ((c = getc(din)) != EOF) { 75527749Sminshall while (c == '\r') { 75611651Ssam while (hash && (bytes >= hashbytes)) { 75726496Sminshall (void) putchar('#'); 75826496Sminshall (void) fflush(stdout); 75911651Ssam hashbytes += sizeof (buf); 76011651Ssam } 76110296Ssam bytes++; 76226048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 76311219Ssam if (ferror (fout)) 76411219Ssam break; 76526496Sminshall (void) putc ('\r', fout); 76611219Ssam } 76726048Sminshall /*if (c == '\0') { 76811219Ssam bytes++; 76911219Ssam continue; 77026048Sminshall }*/ 77111219Ssam } 77226496Sminshall (void) putc (c, fout); 77311219Ssam bytes++; 77410296Ssam } 77511651Ssam if (hash) { 77613213Ssam if (bytes < hashbytes) 77726496Sminshall (void) putchar('#'); 77826496Sminshall (void) putchar('\n'); 77926496Sminshall (void) fflush(stdout); 78011651Ssam } 78111219Ssam if (ferror (din)) 78211219Ssam perror ("netin"); 78311219Ssam if (ferror (fout)) 78411219Ssam perror (local); 78511219Ssam break; 78610296Ssam } 78726448Slepreau if (closefunc != NULL) 78826048Sminshall (*closefunc)(fout); 78926496Sminshall (void) signal(SIGINT, oldintr); 79026448Slepreau if (oldintp) 79126048Sminshall (void) signal(SIGPIPE, oldintp); 79226496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 79310296Ssam (void) fclose(din); 79426048Sminshall (void) getreply(0); 79535699Sbostic if (bytes > 0) 79626048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 79726048Sminshall if (oldtype) { 79826448Slepreau if (!debug) 79926048Sminshall verbose = 0; 80026048Sminshall switch (oldtype) { 80126048Sminshall case TYPE_I: 80226048Sminshall setbinary(); 80326048Sminshall break; 80426048Sminshall case TYPE_E: 80526048Sminshall setebcdic(); 80626048Sminshall break; 80726048Sminshall case TYPE_L: 80826048Sminshall settenex(); 80926048Sminshall break; 81026048Sminshall } 81126048Sminshall verbose = oldverbose; 81226048Sminshall } 81326048Sminshall return; 81426048Sminshall abort: 81526048Sminshall 81627687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 81726048Sminshall 81826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 81926448Slepreau if (oldintp) 82026048Sminshall (void) signal(SIGPIPE, oldintr); 82126048Sminshall (void) signal(SIGINT,SIG_IGN); 82226048Sminshall if (oldtype) { 82326448Slepreau if (!debug) 82426048Sminshall verbose = 0; 82526048Sminshall switch (oldtype) { 82626048Sminshall case TYPE_I: 82726048Sminshall setbinary(); 82826048Sminshall break; 82926048Sminshall case TYPE_E: 83026048Sminshall setebcdic(); 83126048Sminshall break; 83226048Sminshall case TYPE_L: 83326048Sminshall settenex(); 83426048Sminshall break; 83526048Sminshall } 83626048Sminshall verbose = oldverbose; 83726048Sminshall } 83826048Sminshall if (!cpend) { 83926048Sminshall code = -1; 84026048Sminshall (void) signal(SIGINT,oldintr); 84126048Sminshall return; 84226048Sminshall } 84326048Sminshall 84427687Sminshall fprintf(cout,"%c%c",IAC,IP); 84527687Sminshall (void) fflush(cout); 84627687Sminshall msg = IAC; 84727687Sminshall /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 84827687Sminshall /* after urgent byte rather than before as now is protocol */ 84927687Sminshall if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 85027687Sminshall perror("abort"); 85126048Sminshall } 85227687Sminshall fprintf(cout,"%cABOR\r\n",DM); 85326048Sminshall (void) fflush(cout); 85427687Sminshall FD_ZERO(&mask); 85526496Sminshall FD_SET(fileno(cin), &mask); 85626496Sminshall if (din) { 85726496Sminshall FD_SET(fileno(din), &mask); 85826496Sminshall } 85927687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 86027687Sminshall if (nfnd < 0) { 86127687Sminshall perror("abort"); 86227687Sminshall } 86326048Sminshall code = -1; 86426048Sminshall lostpeer(); 86526048Sminshall } 86626496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 86726448Slepreau while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 86826448Slepreau ; 86926496Sminshall } 87027687Sminshall if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 87126048Sminshall if (data >= 0) { 87226496Sminshall (void) close(data); 87326048Sminshall data = -1; 87426048Sminshall } 87525907Smckusick (void) getreply(0); 87625907Smckusick } 87726048Sminshall (void) getreply(0); 87826048Sminshall code = -1; 87926048Sminshall if (data >= 0) { 88026048Sminshall (void) close(data); 88126048Sminshall data = -1; 88226048Sminshall } 88326448Slepreau if (closefunc != NULL && fout != NULL) 88426048Sminshall (*closefunc)(fout); 88526448Slepreau if (din) 88626048Sminshall (void) fclose(din); 88735699Sbostic if (bytes > 0) 88826048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 88926048Sminshall (void) signal(SIGINT,oldintr); 89010296Ssam } 89110296Ssam 89210296Ssam /* 89310296Ssam * Need to start a listen on the data channel 89410296Ssam * before we send the command, otherwise the 89510296Ssam * server's connect may fail. 89610296Ssam */ 89733224Sbostic int sendport = -1; 89811651Ssam 89910296Ssam initconn() 90010296Ssam { 90110296Ssam register char *p, *a; 90226048Sminshall int result, len, tmpno = 0; 90326993Skarels int on = 1; 90410296Ssam 90511651Ssam noport: 90610296Ssam data_addr = myctladdr; 90711651Ssam if (sendport) 90811651Ssam data_addr.sin_port = 0; /* let system pick one */ 90911651Ssam if (data != -1) 91011651Ssam (void) close (data); 91118287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 91210296Ssam if (data < 0) { 91310296Ssam perror("ftp: socket"); 91426448Slepreau if (tmpno) 91526048Sminshall sendport = 1; 91610296Ssam return (1); 91710296Ssam } 91812397Ssam if (!sendport) 91927687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 92033224Sbostic perror("ftp: setsockopt (reuse address)"); 92112397Ssam goto bad; 92212397Ssam } 92326496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 92410296Ssam perror("ftp: bind"); 92510296Ssam goto bad; 92610296Ssam } 92710296Ssam if (options & SO_DEBUG && 92827687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 92910296Ssam perror("ftp: setsockopt (ignored)"); 93011627Ssam len = sizeof (data_addr); 93111627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 93211627Ssam perror("ftp: getsockname"); 93310296Ssam goto bad; 93410296Ssam } 93526448Slepreau if (listen(data, 1) < 0) 93610296Ssam perror("ftp: listen"); 93711651Ssam if (sendport) { 93811651Ssam a = (char *)&data_addr.sin_addr; 93911651Ssam p = (char *)&data_addr.sin_port; 94010296Ssam #define UC(b) (((int)b)&0xff) 94111651Ssam result = 94211651Ssam command("PORT %d,%d,%d,%d,%d,%d", 94311651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 94411651Ssam UC(p[0]), UC(p[1])); 94511651Ssam if (result == ERROR && sendport == -1) { 94611651Ssam sendport = 0; 94726048Sminshall tmpno = 1; 94811651Ssam goto noport; 94911651Ssam } 95011651Ssam return (result != COMPLETE); 95111651Ssam } 95226448Slepreau if (tmpno) 95326048Sminshall sendport = 1; 95411651Ssam return (0); 95510296Ssam bad: 95610296Ssam (void) close(data), data = -1; 95726448Slepreau if (tmpno) 95826048Sminshall sendport = 1; 95910296Ssam return (1); 96010296Ssam } 96110296Ssam 96210296Ssam FILE * 96310296Ssam dataconn(mode) 96410296Ssam char *mode; 96510296Ssam { 96610296Ssam struct sockaddr_in from; 96710296Ssam int s, fromlen = sizeof (from); 96810296Ssam 96926496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 97010296Ssam if (s < 0) { 97110296Ssam perror("ftp: accept"); 97210296Ssam (void) close(data), data = -1; 97310296Ssam return (NULL); 97410296Ssam } 97510296Ssam (void) close(data); 97610296Ssam data = s; 97710296Ssam return (fdopen(data, mode)); 97810296Ssam } 97910296Ssam 98026048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 98126048Sminshall char *direction, *local, *remote; 98211651Ssam long bytes; 98310296Ssam struct timeval *t0, *t1; 98410296Ssam { 98510296Ssam struct timeval td; 98616437Sleres float s, bs; 98710296Ssam 98835699Sbostic if (verbose) { 98935699Sbostic tvsub(&td, t1, t0); 99035699Sbostic s = td.tv_sec + (td.tv_usec / 1000000.); 99110296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 99235699Sbostic bs = bytes / nz(s); 99335699Sbostic printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 99435699Sbostic bytes, direction, s, bs / 1024.); 99535699Sbostic } else { 99635699Sbostic if (local && *local != '-') 99735699Sbostic printf("local: %s ", local); 99835699Sbostic if (remote) 99935699Sbostic printf("remote: %s\n", remote); 100035699Sbostic } 100110296Ssam } 100210296Ssam 100326496Sminshall /*tvadd(tsum, t0) 100410296Ssam struct timeval *tsum, *t0; 100510296Ssam { 100610296Ssam 100710296Ssam tsum->tv_sec += t0->tv_sec; 100810296Ssam tsum->tv_usec += t0->tv_usec; 100910296Ssam if (tsum->tv_usec > 1000000) 101010296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 101126496Sminshall } */ 101210296Ssam 101310296Ssam tvsub(tdiff, t1, t0) 101410296Ssam struct timeval *tdiff, *t1, *t0; 101510296Ssam { 101610296Ssam 101710296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 101810296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 101910296Ssam if (tdiff->tv_usec < 0) 102010296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 102110296Ssam } 102226048Sminshall 102326048Sminshall psabort() 102426048Sminshall { 102526048Sminshall extern int abrtflag; 102626048Sminshall 102726048Sminshall abrtflag++; 102826048Sminshall } 102926048Sminshall 103026048Sminshall pswitch(flag) 103126048Sminshall int flag; 103226048Sminshall { 103326048Sminshall extern int proxy, abrtflag; 103426048Sminshall int (*oldintr)(); 103526048Sminshall static struct comvars { 103626048Sminshall int connect; 103728469Skarels char name[MAXHOSTNAMELEN]; 103826048Sminshall struct sockaddr_in mctl; 103926048Sminshall struct sockaddr_in hctl; 104026048Sminshall FILE *in; 104126048Sminshall FILE *out; 104226048Sminshall int tpe; 104326048Sminshall int cpnd; 104426048Sminshall int sunqe; 104526048Sminshall int runqe; 104626048Sminshall int mcse; 104726048Sminshall int ntflg; 104826048Sminshall char nti[17]; 104926048Sminshall char nto[17]; 105026048Sminshall int mapflg; 105126048Sminshall char mi[MAXPATHLEN]; 105226048Sminshall char mo[MAXPATHLEN]; 105326048Sminshall } proxstruct, tmpstruct; 105426048Sminshall struct comvars *ip, *op; 105526048Sminshall 105626048Sminshall abrtflag = 0; 105726048Sminshall oldintr = signal(SIGINT, psabort); 105826048Sminshall if (flag) { 105926448Slepreau if (proxy) 106026048Sminshall return; 106126048Sminshall ip = &tmpstruct; 106226048Sminshall op = &proxstruct; 106326048Sminshall proxy++; 106426048Sminshall } 106526048Sminshall else { 106626448Slepreau if (!proxy) 106726048Sminshall return; 106826048Sminshall ip = &proxstruct; 106926048Sminshall op = &tmpstruct; 107026048Sminshall proxy = 0; 107126048Sminshall } 107226048Sminshall ip->connect = connected; 107326048Sminshall connected = op->connect; 107428469Skarels if (hostname) { 107528469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 107628469Skarels ip->name[strlen(ip->name)] = '\0'; 107728469Skarels } else 107828469Skarels ip->name[0] = 0; 107926048Sminshall hostname = op->name; 108026048Sminshall ip->hctl = hisctladdr; 108126048Sminshall hisctladdr = op->hctl; 108226048Sminshall ip->mctl = myctladdr; 108326048Sminshall myctladdr = op->mctl; 108426048Sminshall ip->in = cin; 108526048Sminshall cin = op->in; 108626048Sminshall ip->out = cout; 108726048Sminshall cout = op->out; 108826048Sminshall ip->tpe = type; 108926048Sminshall type = op->tpe; 109026448Slepreau if (!type) 109126048Sminshall type = 1; 109226048Sminshall ip->cpnd = cpend; 109326048Sminshall cpend = op->cpnd; 109426048Sminshall ip->sunqe = sunique; 109526048Sminshall sunique = op->sunqe; 109626048Sminshall ip->runqe = runique; 109726048Sminshall runique = op->runqe; 109826048Sminshall ip->mcse = mcase; 109926048Sminshall mcase = op->mcse; 110026048Sminshall ip->ntflg = ntflag; 110126048Sminshall ntflag = op->ntflg; 110226496Sminshall (void) strncpy(ip->nti, ntin, 16); 110326048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 110426496Sminshall (void) strcpy(ntin, op->nti); 110526496Sminshall (void) strncpy(ip->nto, ntout, 16); 110626048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 110726496Sminshall (void) strcpy(ntout, op->nto); 110826048Sminshall ip->mapflg = mapflag; 110926048Sminshall mapflag = op->mapflg; 111026496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 111126048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 111226496Sminshall (void) strcpy(mapin, op->mi); 111326496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 111426048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 111526496Sminshall (void) strcpy(mapout, op->mo); 111626048Sminshall (void) signal(SIGINT, oldintr); 111726048Sminshall if (abrtflag) { 111826048Sminshall abrtflag = 0; 111926048Sminshall (*oldintr)(); 112026448Slepreau } 112126048Sminshall } 112226048Sminshall 112326048Sminshall jmp_buf ptabort; 112426048Sminshall int ptabflg; 112526048Sminshall 112626048Sminshall abortpt() 112726048Sminshall { 112826048Sminshall printf("\n"); 112926496Sminshall (void) fflush(stdout); 113026048Sminshall ptabflg++; 113126048Sminshall mflag = 0; 113226048Sminshall abrtflag = 0; 113326048Sminshall longjmp(ptabort, 1); 113426048Sminshall } 113526048Sminshall 113626048Sminshall proxtrans(cmd, local, remote) 113726048Sminshall char *cmd, *local, *remote; 113826048Sminshall { 113927687Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 114026048Sminshall extern jmp_buf ptabort; 114126048Sminshall char *cmd2; 114226496Sminshall struct fd_set mask; 114326048Sminshall 114426448Slepreau if (strcmp(cmd, "RETR")) 114526048Sminshall cmd2 = "RETR"; 114626448Slepreau else 114726048Sminshall cmd2 = runique ? "STOU" : "STOR"; 114826048Sminshall if (command("PASV") != COMPLETE) { 114926048Sminshall printf("proxy server does not support third part transfers.\n"); 115026048Sminshall return; 115126048Sminshall } 115226048Sminshall tmptype = type; 115326048Sminshall pswitch(0); 115426048Sminshall if (!connected) { 115526048Sminshall printf("No primary connection\n"); 115626048Sminshall pswitch(1); 115726048Sminshall code = -1; 115826048Sminshall return; 115926048Sminshall } 116026048Sminshall if (type != tmptype) { 116126048Sminshall oldtype = type; 116226048Sminshall switch (tmptype) { 116326048Sminshall case TYPE_A: 116426048Sminshall setascii(); 116526048Sminshall break; 116626048Sminshall case TYPE_I: 116726048Sminshall setbinary(); 116826048Sminshall break; 116926048Sminshall case TYPE_E: 117026048Sminshall setebcdic(); 117126048Sminshall break; 117226048Sminshall case TYPE_L: 117326048Sminshall settenex(); 117426048Sminshall break; 117526048Sminshall } 117626048Sminshall } 117726048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 117826048Sminshall switch (oldtype) { 117926048Sminshall case 0: 118026048Sminshall break; 118126048Sminshall case TYPE_A: 118226048Sminshall setascii(); 118326048Sminshall break; 118426048Sminshall case TYPE_I: 118526048Sminshall setbinary(); 118626048Sminshall break; 118726048Sminshall case TYPE_E: 118826048Sminshall setebcdic(); 118926048Sminshall break; 119026048Sminshall case TYPE_L: 119126048Sminshall settenex(); 119226048Sminshall break; 119326048Sminshall } 119426048Sminshall pswitch(1); 119526048Sminshall return; 119626048Sminshall } 119726448Slepreau if (setjmp(ptabort)) 119826048Sminshall goto abort; 119926048Sminshall oldintr = signal(SIGINT, abortpt); 120026048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 120126048Sminshall (void) signal(SIGINT, oldintr); 120226048Sminshall switch (oldtype) { 120326048Sminshall case 0: 120426048Sminshall break; 120526048Sminshall case TYPE_A: 120626048Sminshall setascii(); 120726048Sminshall break; 120826048Sminshall case TYPE_I: 120926048Sminshall setbinary(); 121026048Sminshall break; 121126048Sminshall case TYPE_E: 121226048Sminshall setebcdic(); 121326048Sminshall break; 121426048Sminshall case TYPE_L: 121526048Sminshall settenex(); 121626048Sminshall break; 121726048Sminshall } 121826048Sminshall pswitch(1); 121926048Sminshall return; 122026048Sminshall } 122126048Sminshall sleep(2); 122226048Sminshall pswitch(1); 122326048Sminshall secndflag++; 122426448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 122526048Sminshall goto abort; 122626048Sminshall ptflag++; 122726048Sminshall (void) getreply(0); 122826048Sminshall pswitch(0); 122926048Sminshall (void) getreply(0); 123026048Sminshall (void) signal(SIGINT, oldintr); 123126048Sminshall switch (oldtype) { 123226048Sminshall case 0: 123326048Sminshall break; 123426048Sminshall case TYPE_A: 123526048Sminshall setascii(); 123626048Sminshall break; 123726048Sminshall case TYPE_I: 123826048Sminshall setbinary(); 123926048Sminshall break; 124026048Sminshall case TYPE_E: 124126048Sminshall setebcdic(); 124226048Sminshall break; 124326048Sminshall case TYPE_L: 124426048Sminshall settenex(); 124526048Sminshall break; 124626048Sminshall } 124726048Sminshall pswitch(1); 124826048Sminshall ptflag = 0; 124926048Sminshall printf("local: %s remote: %s\n", local, remote); 125026048Sminshall return; 125126048Sminshall abort: 125226048Sminshall (void) signal(SIGINT, SIG_IGN); 125326048Sminshall ptflag = 0; 125426448Slepreau if (strcmp(cmd, "RETR") && !proxy) 125526048Sminshall pswitch(1); 125626448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 125726048Sminshall pswitch(0); 125826048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 125926048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 126026048Sminshall pswitch(0); 126126048Sminshall switch (oldtype) { 126226048Sminshall case 0: 126326048Sminshall break; 126426048Sminshall case TYPE_A: 126526048Sminshall setascii(); 126626048Sminshall break; 126726048Sminshall case TYPE_I: 126826048Sminshall setbinary(); 126926048Sminshall break; 127026048Sminshall case TYPE_E: 127126048Sminshall setebcdic(); 127226048Sminshall break; 127326048Sminshall case TYPE_L: 127426048Sminshall settenex(); 127526048Sminshall break; 127626048Sminshall } 127727687Sminshall if (cpend) { 127826048Sminshall char msg[2]; 127926048Sminshall 128026048Sminshall fprintf(cout,"%c%c",IAC,IP); 128126048Sminshall (void) fflush(cout); 128226048Sminshall *msg = IAC; 128326048Sminshall *(msg+1) = DM; 128426448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 128526048Sminshall perror("abort"); 128626048Sminshall fprintf(cout,"ABOR\r\n"); 128726048Sminshall (void) fflush(cout); 128827687Sminshall FD_ZERO(&mask); 128926496Sminshall FD_SET(fileno(cin), &mask); 129027687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 129127687Sminshall if (nfnd < 0) { 129227687Sminshall perror("abort"); 129327687Sminshall } 129426448Slepreau if (ptabflg) 129526048Sminshall code = -1; 129626048Sminshall lostpeer(); 129726048Sminshall } 129826048Sminshall (void) getreply(0); 129926048Sminshall (void) getreply(0); 130026048Sminshall } 130126048Sminshall } 130226048Sminshall pswitch(1); 130326448Slepreau if (ptabflg) 130426048Sminshall code = -1; 130526048Sminshall (void) signal(SIGINT, oldintr); 130626048Sminshall return; 130726048Sminshall } 130827687Sminshall if (cpend) { 130926048Sminshall char msg[2]; 131026048Sminshall 131126048Sminshall fprintf(cout,"%c%c",IAC,IP); 131226048Sminshall (void) fflush(cout); 131326048Sminshall *msg = IAC; 131426048Sminshall *(msg+1) = DM; 131526448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 131626048Sminshall perror("abort"); 131726048Sminshall fprintf(cout,"ABOR\r\n"); 131826048Sminshall (void) fflush(cout); 131927687Sminshall FD_ZERO(&mask); 132026496Sminshall FD_SET(fileno(cin), &mask); 132127687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 132227687Sminshall if (nfnd < 0) { 132327687Sminshall perror("abort"); 132427687Sminshall } 132526448Slepreau if (ptabflg) 132626048Sminshall code = -1; 132726048Sminshall lostpeer(); 132826048Sminshall } 132926048Sminshall (void) getreply(0); 133026048Sminshall (void) getreply(0); 133126048Sminshall } 133226048Sminshall pswitch(!proxy); 133326048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 133426048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 133526048Sminshall pswitch(0); 133626048Sminshall switch (oldtype) { 133726048Sminshall case 0: 133826048Sminshall break; 133926048Sminshall case TYPE_A: 134026048Sminshall setascii(); 134126048Sminshall break; 134226048Sminshall case TYPE_I: 134326048Sminshall setbinary(); 134426048Sminshall break; 134526048Sminshall case TYPE_E: 134626048Sminshall setebcdic(); 134726048Sminshall break; 134826048Sminshall case TYPE_L: 134926048Sminshall settenex(); 135026048Sminshall break; 135126048Sminshall } 135227687Sminshall if (cpend) { 135326048Sminshall char msg[2]; 135426048Sminshall 135526048Sminshall fprintf(cout,"%c%c",IAC,IP); 135626048Sminshall (void) fflush(cout); 135726048Sminshall *msg = IAC; 135826048Sminshall *(msg+1) = DM; 135926448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 136026048Sminshall perror("abort"); 136126048Sminshall fprintf(cout,"ABOR\r\n"); 136226048Sminshall (void) fflush(cout); 136327687Sminshall FD_ZERO(&mask); 136426496Sminshall FD_SET(fileno(cin), &mask); 136527687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 136627687Sminshall if (nfnd < 0) { 136727687Sminshall perror("abort"); 136827687Sminshall } 136926448Slepreau if (ptabflg) 137026048Sminshall code = -1; 137126048Sminshall lostpeer(); 137226048Sminshall } 137326048Sminshall (void) getreply(0); 137426048Sminshall (void) getreply(0); 137526048Sminshall } 137626048Sminshall pswitch(1); 137726448Slepreau if (ptabflg) 137826048Sminshall code = -1; 137926048Sminshall (void) signal(SIGINT, oldintr); 138026048Sminshall return; 138126048Sminshall } 138226048Sminshall } 138327687Sminshall if (cpend) { 138426048Sminshall char msg[2]; 138526048Sminshall 138626048Sminshall fprintf(cout,"%c%c",IAC,IP); 138726048Sminshall (void) fflush(cout); 138826048Sminshall *msg = IAC; 138926048Sminshall *(msg+1) = DM; 139026448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 139126048Sminshall perror("abort"); 139226048Sminshall fprintf(cout,"ABOR\r\n"); 139326048Sminshall (void) fflush(cout); 139427687Sminshall FD_ZERO(&mask); 139526496Sminshall FD_SET(fileno(cin), &mask); 139627687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 139727687Sminshall if (nfnd < 0) { 139827687Sminshall perror("abort"); 139927687Sminshall } 140026448Slepreau if (ptabflg) 140126048Sminshall code = -1; 140226048Sminshall lostpeer(); 140326048Sminshall } 140426048Sminshall (void) getreply(0); 140526048Sminshall (void) getreply(0); 140626048Sminshall } 140726048Sminshall pswitch(!proxy); 140826048Sminshall if (cpend) { 140927687Sminshall FD_ZERO(&mask); 141026496Sminshall FD_SET(fileno(cin), &mask); 141127687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 141227687Sminshall if (nfnd < 0) { 141327687Sminshall perror("abort"); 141427687Sminshall } 141526448Slepreau if (ptabflg) 141626048Sminshall code = -1; 141726048Sminshall lostpeer(); 141826048Sminshall } 141926048Sminshall (void) getreply(0); 142026048Sminshall (void) getreply(0); 142126048Sminshall } 142226448Slepreau if (proxy) 142326048Sminshall pswitch(0); 142426048Sminshall switch (oldtype) { 142526048Sminshall case 0: 142626048Sminshall break; 142726048Sminshall case TYPE_A: 142826048Sminshall setascii(); 142926048Sminshall break; 143026048Sminshall case TYPE_I: 143126048Sminshall setbinary(); 143226048Sminshall break; 143326048Sminshall case TYPE_E: 143426048Sminshall setebcdic(); 143526048Sminshall break; 143626048Sminshall case TYPE_L: 143726048Sminshall settenex(); 143826048Sminshall break; 143926048Sminshall } 144026048Sminshall pswitch(1); 144126448Slepreau if (ptabflg) 144226048Sminshall code = -1; 144326048Sminshall (void) signal(SIGINT, oldintr); 144426048Sminshall } 144526048Sminshall 144626048Sminshall reset() 144726048Sminshall { 144826496Sminshall struct fd_set mask; 144926496Sminshall int nfnd = 1; 145026048Sminshall 145127687Sminshall FD_ZERO(&mask); 145230946Scsvsj while (nfnd > 0) { 145326496Sminshall FD_SET(fileno(cin), &mask); 145427687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 145526048Sminshall perror("reset"); 145626048Sminshall code = -1; 145726048Sminshall lostpeer(); 145826048Sminshall } 145927687Sminshall else if (nfnd) { 146026048Sminshall (void) getreply(0); 146126496Sminshall } 146226048Sminshall } 146326048Sminshall } 146426048Sminshall 146526048Sminshall char * 146626048Sminshall gunique(local) 146726048Sminshall char *local; 146826048Sminshall { 146926048Sminshall static char new[MAXPATHLEN]; 147026048Sminshall char *cp = rindex(local, '/'); 147126048Sminshall int d, count=0; 147226048Sminshall char ext = '1'; 147326048Sminshall 147426448Slepreau if (cp) 147526048Sminshall *cp = '\0'; 147626048Sminshall d = access(cp ? local : ".", 2); 147726448Slepreau if (cp) 147826048Sminshall *cp = '/'; 147926048Sminshall if (d < 0) { 148026048Sminshall perror(local); 148126048Sminshall return((char *) 0); 148226048Sminshall } 148326048Sminshall (void) strcpy(new, local); 148426048Sminshall cp = new + strlen(new); 148526048Sminshall *cp++ = '.'; 148626048Sminshall while (!d) { 148726048Sminshall if (++count == 100) { 148826048Sminshall printf("runique: can't find unique file name.\n"); 148926048Sminshall return((char *) 0); 149026048Sminshall } 149126048Sminshall *cp++ = ext; 149226048Sminshall *cp = '\0'; 149326448Slepreau if (ext == '9') 149426048Sminshall ext = '0'; 149526448Slepreau else 149626048Sminshall ext++; 149726448Slepreau if ((d = access(new, 0)) < 0) 149826048Sminshall break; 149926448Slepreau if (ext != '0') 150026048Sminshall cp--; 150126448Slepreau else if (*(cp - 2) == '.') 150226048Sminshall *(cp - 1) = '1'; 150326048Sminshall else { 150426048Sminshall *(cp - 2) = *(cp - 2) + 1; 150526048Sminshall cp--; 150626048Sminshall } 150726048Sminshall } 150826048Sminshall return(new); 150926048Sminshall } 1510