121739Sdist /* 226048Sminshall * Copyright (c) 1985 Regents of the University of California. 3*33737Sbostic * All rights reserved. 4*33737Sbostic * 5*33737Sbostic * Redistribution and use in source and binary forms are permitted 6*33737Sbostic * provided that this notice is preserved and that due credit is given 7*33737Sbostic * to the University of California at Berkeley. The name of the University 8*33737Sbostic * may not be used to endorse or promote products derived from this 9*33737Sbostic * software without specific prior written permission. This software 10*33737Sbostic * is provided ``as is'' without express or implied warranty. 1121739Sdist */ 1221739Sdist 1310296Ssam #ifndef lint 14*33737Sbostic static char sccsid[] = "@(#)ftp.c 5.17 (Berkeley) 03/14/88"; 15*33737Sbostic #endif /* not lint */ 1610296Ssam 1726048Sminshall #include "ftp_var.h" 1826048Sminshall 1910296Ssam #include <sys/stat.h> 2010296Ssam #include <sys/ioctl.h> 2110296Ssam #include <sys/socket.h> 2213614Ssam #include <sys/time.h> 2328469Skarels #include <sys/param.h> 2410296Ssam 2510296Ssam #include <netinet/in.h> 2612397Ssam #include <arpa/ftp.h> 2726048Sminshall #include <arpa/telnet.h> 2810296Ssam 2910296Ssam #include <stdio.h> 3010296Ssam #include <signal.h> 3110296Ssam #include <errno.h> 3210296Ssam #include <netdb.h> 3326048Sminshall #include <fcntl.h> 3426048Sminshall #include <pwd.h> 3510296Ssam 3610296Ssam struct sockaddr_in hisctladdr; 3710296Ssam struct sockaddr_in data_addr; 3810296Ssam int data = -1; 3926048Sminshall int abrtflag = 0; 4026048Sminshall int ptflag = 0; 4110296Ssam int connected; 4210296Ssam struct sockaddr_in myctladdr; 4326496Sminshall uid_t getuid(); 4410296Ssam 4510296Ssam FILE *cin, *cout; 4610296Ssam FILE *dataconn(); 4710296Ssam 4825904Skarels char * 4910296Ssam hookup(host, port) 5010296Ssam char *host; 5110296Ssam int port; 5210296Ssam { 5325904Skarels register struct hostent *hp = 0; 5427687Sminshall int s,len; 5525904Skarels static char hostnamebuf[80]; 5610296Ssam 5710296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 5825904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 5925904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 6025904Skarels hisctladdr.sin_family = AF_INET; 6125904Skarels (void) strcpy(hostnamebuf, host); 6226048Sminshall } 6326048Sminshall else { 6425100Sbloom hp = gethostbyname(host); 6525904Skarels if (hp == NULL) { 6625904Skarels printf("%s: unknown host\n", host); 6726048Sminshall code = -1; 6826048Sminshall return((char *) 0); 6925904Skarels } 7025904Skarels hisctladdr.sin_family = hp->h_addrtype; 7125904Skarels bcopy(hp->h_addr_list[0], 7225904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 7325904Skarels (void) strcpy(hostnamebuf, hp->h_name); 7410296Ssam } 7525904Skarels hostname = hostnamebuf; 7625904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 7710296Ssam if (s < 0) { 7810296Ssam perror("ftp: socket"); 7926048Sminshall code = -1; 8010296Ssam return (0); 8110296Ssam } 8210296Ssam hisctladdr.sin_port = port; 8326496Sminshall while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 8425904Skarels if (hp && hp->h_addr_list[1]) { 8525904Skarels int oerrno = errno; 8625904Skarels 8725904Skarels fprintf(stderr, "ftp: connect to address %s: ", 8825904Skarels inet_ntoa(hisctladdr.sin_addr)); 8925904Skarels errno = oerrno; 9026496Sminshall perror((char *) 0); 9125904Skarels hp->h_addr_list++; 9225904Skarels bcopy(hp->h_addr_list[0], 9326048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 9426496Sminshall fprintf(stdout, "Trying %s...\n", 9525904Skarels inet_ntoa(hisctladdr.sin_addr)); 9626813Skarels (void) close(s); 9726813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 9826813Skarels if (s < 0) { 9926813Skarels perror("ftp: socket"); 10026813Skarels code = -1; 10126813Skarels return (0); 10226813Skarels } 10325904Skarels continue; 10425904Skarels } 10510296Ssam perror("ftp: connect"); 10626048Sminshall code = -1; 10710296Ssam goto bad; 10810296Ssam } 10911627Ssam len = sizeof (myctladdr); 11011627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 11111627Ssam perror("ftp: getsockname"); 11226048Sminshall code = -1; 11310296Ssam goto bad; 11410296Ssam } 11510296Ssam cin = fdopen(s, "r"); 11610296Ssam cout = fdopen(s, "w"); 11711219Ssam if (cin == NULL || cout == NULL) { 11810296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 11910296Ssam if (cin) 12026496Sminshall (void) fclose(cin); 12110296Ssam if (cout) 12226496Sminshall (void) fclose(cout); 12326048Sminshall code = -1; 12410296Ssam goto bad; 12510296Ssam } 12610296Ssam if (verbose) 12726067Sminshall printf("Connected to %s.\n", hostname); 12827687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 12926048Sminshall if (cin) 13026496Sminshall (void) fclose(cin); 13126048Sminshall if (cout) 13226496Sminshall (void) fclose(cout); 13326048Sminshall code = -1; 13426048Sminshall goto bad; 13526048Sminshall } 13627687Sminshall #ifdef SO_OOBINLINE 13727687Sminshall { 13827687Sminshall int on = 1; 13926048Sminshall 14027687Sminshall if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 14127687Sminshall < 0 && debug) { 14227687Sminshall perror("ftp: setsockopt"); 14327687Sminshall } 14427687Sminshall } 14527687Sminshall #endif SO_OOBINLINE 14626048Sminshall 14725904Skarels return (hostname); 14810296Ssam bad: 14926496Sminshall (void) close(s); 15025904Skarels return ((char *)0); 15110296Ssam } 15210296Ssam 15325904Skarels login(host) 15425904Skarels char *host; 15510296Ssam { 15626048Sminshall char tmp[80]; 15726496Sminshall char *user, *pass, *acct, *getlogin(), *mygetpass(); 15826048Sminshall int n, aflag = 0; 15910296Ssam 16026048Sminshall user = pass = acct = 0; 16126048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 16226048Sminshall disconnect(); 16326048Sminshall code = -1; 16426048Sminshall return(0); 16526048Sminshall } 16626048Sminshall if (user == NULL) { 16726048Sminshall char *myname = getlogin(); 16826048Sminshall 16926048Sminshall if (myname == NULL) { 17026048Sminshall struct passwd *pp = getpwuid(getuid()); 17126048Sminshall 17226448Slepreau if (pp != NULL) 17326048Sminshall myname = pp->pw_name; 17426048Sminshall } 17526048Sminshall printf("Name (%s:%s): ", host, myname); 17626048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 17726048Sminshall tmp[strlen(tmp) - 1] = '\0'; 17826448Slepreau if (*tmp == '\0') 17926048Sminshall user = myname; 18026448Slepreau else 18126048Sminshall user = tmp; 18226048Sminshall } 18310296Ssam n = command("USER %s", user); 18426048Sminshall if (n == CONTINUE) { 18526448Slepreau if (pass == NULL) 18626496Sminshall pass = mygetpass("Password:"); 18710296Ssam n = command("PASS %s", pass); 18826048Sminshall } 18910296Ssam if (n == CONTINUE) { 19026048Sminshall aflag++; 19126496Sminshall acct = mygetpass("Account:"); 19210296Ssam n = command("ACCT %s", acct); 19310296Ssam } 19410296Ssam if (n != COMPLETE) { 19510296Ssam fprintf(stderr, "Login failed.\n"); 19610296Ssam return (0); 19710296Ssam } 19826448Slepreau if (!aflag && acct != NULL) 19926048Sminshall (void) command("ACCT %s", acct); 20026448Slepreau if (proxy) 20126048Sminshall return(1); 20226048Sminshall for (n = 0; n < macnum; ++n) { 20326048Sminshall if (!strcmp("init", macros[n].mac_name)) { 20426496Sminshall (void) strcpy(line, "$init"); 20526048Sminshall makeargv(); 20626048Sminshall domacro(margc, margv); 20726048Sminshall break; 20826048Sminshall } 20926048Sminshall } 21010296Ssam return (1); 21110296Ssam } 21210296Ssam 21326048Sminshall cmdabort() 21426048Sminshall { 21526048Sminshall extern jmp_buf ptabort; 21626048Sminshall 21726048Sminshall printf("\n"); 21826048Sminshall (void) fflush(stdout); 21926048Sminshall abrtflag++; 22026448Slepreau if (ptflag) 22126048Sminshall longjmp(ptabort,1); 22226048Sminshall } 22326048Sminshall 22426496Sminshall /*VARARGS1*/ 22510296Ssam command(fmt, args) 22610296Ssam char *fmt; 22710296Ssam { 22826048Sminshall int r, (*oldintr)(), cmdabort(); 22910296Ssam 23026048Sminshall abrtflag = 0; 23110296Ssam if (debug) { 23210296Ssam printf("---> "); 23310296Ssam _doprnt(fmt, &args, stdout); 23410296Ssam printf("\n"); 23510296Ssam (void) fflush(stdout); 23610296Ssam } 23711219Ssam if (cout == NULL) { 23811219Ssam perror ("No control connection for command"); 23926048Sminshall code = -1; 24011219Ssam return (0); 24111219Ssam } 24226048Sminshall oldintr = signal(SIGINT,cmdabort); 24310296Ssam _doprnt(fmt, &args, cout); 24410296Ssam fprintf(cout, "\r\n"); 24510296Ssam (void) fflush(cout); 24626048Sminshall cpend = 1; 24726048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 24826448Slepreau if (abrtflag && oldintr != SIG_IGN) 24926048Sminshall (*oldintr)(); 25026048Sminshall (void) signal(SIGINT, oldintr); 25126048Sminshall return(r); 25210296Ssam } 25310296Ssam 25410296Ssam #include <ctype.h> 25510296Ssam 25610296Ssam getreply(expecteof) 25710296Ssam int expecteof; 25810296Ssam { 25911219Ssam register int c, n; 26026048Sminshall register int dig; 26126048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 26226048Sminshall int pflag = 0; 26326048Sminshall char *pt = pasv; 26410296Ssam 26526048Sminshall oldintr = signal(SIGINT,cmdabort); 26610296Ssam for (;;) { 26710296Ssam dig = n = code = 0; 26810296Ssam while ((c = getc(cin)) != '\n') { 26927687Sminshall if (c == IAC) { /* handle telnet commands */ 27027687Sminshall switch (c = getc(cin)) { 27127687Sminshall case WILL: 27227687Sminshall case WONT: 27327687Sminshall c = getc(cin); 27427687Sminshall fprintf(cout, "%c%c%c",IAC,WONT,c); 27527687Sminshall (void) fflush(cout); 27627687Sminshall break; 27727687Sminshall case DO: 27827687Sminshall case DONT: 27927687Sminshall c = getc(cin); 28027687Sminshall fprintf(cout, "%c%c%c",IAC,DONT,c); 28127687Sminshall (void) fflush(cout); 28227687Sminshall break; 28327687Sminshall default: 28427687Sminshall break; 28527687Sminshall } 28627687Sminshall continue; 28727687Sminshall } 28810296Ssam dig++; 28910296Ssam if (c == EOF) { 29026048Sminshall if (expecteof) { 29126048Sminshall (void) signal(SIGINT,oldintr); 29226048Sminshall code = 221; 29310296Ssam return (0); 29426048Sminshall } 29510296Ssam lostpeer(); 29626048Sminshall if (verbose) { 29726048Sminshall printf("421 Service not available, remote server has closed connection\n"); 29826048Sminshall (void) fflush(stdout); 29926048Sminshall code = 421; 30026048Sminshall return(4); 30126048Sminshall } 30210296Ssam } 30326048Sminshall if (c != '\r' && (verbose > 0 || 30426048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 30526448Slepreau if (proxflag && 30626448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 30726048Sminshall printf("%s:",hostname); 30826496Sminshall (void) putchar(c); 30926048Sminshall } 31010296Ssam if (dig < 4 && isdigit(c)) 31110296Ssam code = code * 10 + (c - '0'); 31226448Slepreau if (!pflag && code == 227) 31326048Sminshall pflag = 1; 31426448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 31526048Sminshall pflag = 2; 31626048Sminshall if (pflag == 2) { 31726448Slepreau if (c != '\r' && c != ')') 31826048Sminshall *pt++ = c; 31926048Sminshall else { 32026048Sminshall *pt = '\0'; 32126048Sminshall pflag = 3; 32226048Sminshall } 32326048Sminshall } 32426048Sminshall if (dig == 4 && c == '-') { 32526448Slepreau if (continuation) 32626048Sminshall code = 0; 32710296Ssam continuation++; 32826048Sminshall } 32910296Ssam if (n == 0) 33010296Ssam n = c; 33110296Ssam } 33226048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 33326496Sminshall (void) putchar(c); 33411346Ssam (void) fflush (stdout); 33511346Ssam } 33610296Ssam if (continuation && code != originalcode) { 33710296Ssam if (originalcode == 0) 33810296Ssam originalcode = code; 33910296Ssam continue; 34010296Ssam } 34126448Slepreau if (n != '1') 34226048Sminshall cpend = 0; 34326048Sminshall (void) signal(SIGINT,oldintr); 34426448Slepreau if (code == 421 || originalcode == 421) 34526048Sminshall lostpeer(); 34626448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 34726048Sminshall (*oldintr)(); 34825907Smckusick return (n - '0'); 34910296Ssam } 35010296Ssam } 35110296Ssam 35226048Sminshall empty(mask, sec) 35327687Sminshall struct fd_set *mask; 35426048Sminshall int sec; 35526048Sminshall { 35626048Sminshall struct timeval t; 35726048Sminshall 35826048Sminshall t.tv_sec = (long) sec; 35926048Sminshall t.tv_usec = 0; 36027687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 36126048Sminshall } 36226048Sminshall 36310296Ssam jmp_buf sendabort; 36410296Ssam 36510296Ssam abortsend() 36610296Ssam { 36710296Ssam 36826048Sminshall mflag = 0; 36926048Sminshall abrtflag = 0; 37026048Sminshall printf("\nsend aborted\n"); 37126048Sminshall (void) fflush(stdout); 37210296Ssam longjmp(sendabort, 1); 37310296Ssam } 37410296Ssam 37510296Ssam sendrequest(cmd, local, remote) 37610296Ssam char *cmd, *local, *remote; 37710296Ssam { 37826496Sminshall FILE *fin, *dout = 0, *mypopen(); 37926496Sminshall int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 38026048Sminshall int abortsend(); 38111219Ssam char buf[BUFSIZ]; 38211651Ssam long bytes = 0, hashbytes = sizeof (buf); 38311346Ssam register int c, d; 38410296Ssam struct stat st; 38510296Ssam struct timeval start, stop; 38610296Ssam 38726048Sminshall if (proxy) { 38826048Sminshall proxtrans(cmd, local, remote); 38926048Sminshall return; 39026048Sminshall } 39110296Ssam closefunc = NULL; 39226048Sminshall oldintr = NULL; 39326048Sminshall oldintp = NULL; 39426048Sminshall if (setjmp(sendabort)) { 39526048Sminshall while (cpend) { 39626048Sminshall (void) getreply(0); 39726048Sminshall } 39826048Sminshall if (data >= 0) { 39926048Sminshall (void) close(data); 40026048Sminshall data = -1; 40126048Sminshall } 40226448Slepreau if (oldintr) 40326048Sminshall (void) signal(SIGINT,oldintr); 40426448Slepreau if (oldintp) 40526048Sminshall (void) signal(SIGPIPE,oldintp); 40626048Sminshall code = -1; 40726048Sminshall return; 40826048Sminshall } 40910296Ssam oldintr = signal(SIGINT, abortsend); 41010296Ssam if (strcmp(local, "-") == 0) 41110296Ssam fin = stdin; 41210296Ssam else if (*local == '|') { 41326048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 41426496Sminshall fin = mypopen(local + 1, "r"); 41510296Ssam if (fin == NULL) { 41626048Sminshall perror(local + 1); 41726048Sminshall (void) signal(SIGINT, oldintr); 41826048Sminshall (void) signal(SIGPIPE, oldintp); 41926048Sminshall code = -1; 42026048Sminshall return; 42110296Ssam } 42226496Sminshall closefunc = mypclose; 42310296Ssam } else { 42410296Ssam fin = fopen(local, "r"); 42510296Ssam if (fin == NULL) { 42610296Ssam perror(local); 42726048Sminshall (void) signal(SIGINT, oldintr); 42826048Sminshall code = -1; 42926048Sminshall return; 43010296Ssam } 43110296Ssam closefunc = fclose; 43210296Ssam if (fstat(fileno(fin), &st) < 0 || 43310296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 43426496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 43526048Sminshall (void) signal(SIGINT, oldintr); 43626048Sminshall code = -1; 43726048Sminshall return; 43810296Ssam } 43910296Ssam } 44026048Sminshall if (initconn()) { 44126048Sminshall (void) signal(SIGINT, oldintr); 44226448Slepreau if (oldintp) 44326048Sminshall (void) signal(SIGPIPE, oldintp); 44426048Sminshall code = -1; 44526048Sminshall return; 44626048Sminshall } 44726448Slepreau if (setjmp(sendabort)) 44826048Sminshall goto abort; 44910296Ssam if (remote) { 45026048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 45126048Sminshall (void) signal(SIGINT, oldintr); 45226448Slepreau if (oldintp) 45326048Sminshall (void) signal(SIGPIPE, oldintp); 45426048Sminshall return; 45526048Sminshall } 45610296Ssam } else 45726048Sminshall if (command("%s", cmd) != PRELIM) { 45826048Sminshall (void) signal(SIGINT, oldintr); 45926448Slepreau if (oldintp) 46026048Sminshall (void) signal(SIGPIPE, oldintp); 46126048Sminshall return; 46226048Sminshall } 46310296Ssam dout = dataconn("w"); 46426448Slepreau if (dout == NULL) 46526048Sminshall goto abort; 46626496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 46711219Ssam switch (type) { 46811219Ssam 46911219Ssam case TYPE_I: 47011219Ssam case TYPE_L: 47111346Ssam errno = d = 0; 47211219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 47311346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 47411219Ssam break; 47511219Ssam bytes += c; 47611651Ssam if (hash) { 47726496Sminshall (void) putchar('#'); 47826496Sminshall (void) fflush(stdout); 47911651Ssam } 48011219Ssam } 48113213Ssam if (hash && bytes > 0) { 48226496Sminshall (void) putchar('\n'); 48326496Sminshall (void) fflush(stdout); 48411651Ssam } 48511219Ssam if (c < 0) 48611219Ssam perror(local); 48711346Ssam if (d < 0) 48811219Ssam perror("netout"); 48911219Ssam break; 49011219Ssam 49111219Ssam case TYPE_A: 49211219Ssam while ((c = getc(fin)) != EOF) { 49311219Ssam if (c == '\n') { 49411651Ssam while (hash && (bytes >= hashbytes)) { 49526496Sminshall (void) putchar('#'); 49626496Sminshall (void) fflush(stdout); 49711651Ssam hashbytes += sizeof (buf); 49811651Ssam } 49911219Ssam if (ferror(dout)) 50011219Ssam break; 50126496Sminshall (void) putc('\r', dout); 50211219Ssam bytes++; 50311219Ssam } 50426496Sminshall (void) putc(c, dout); 50511219Ssam bytes++; 50626048Sminshall /* if (c == '\r') { */ 50726496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 50826048Sminshall /* bytes++; */ 50926048Sminshall /* } */ 51011219Ssam } 51111651Ssam if (hash) { 51213213Ssam if (bytes < hashbytes) 51326496Sminshall (void) putchar('#'); 51426496Sminshall (void) putchar('\n'); 51526496Sminshall (void) fflush(stdout); 51611651Ssam } 51711219Ssam if (ferror(fin)) 51811219Ssam perror(local); 51911346Ssam if (ferror(dout)) 52011219Ssam perror("netout"); 52111219Ssam break; 52210296Ssam } 52326496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 52410296Ssam if (closefunc != NULL) 52526048Sminshall (*closefunc)(fin); 52610296Ssam (void) fclose(dout); 52726048Sminshall (void) getreply(0); 52826048Sminshall (void) signal(SIGINT, oldintr); 52910296Ssam if (bytes > 0 && verbose) 53026048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 53110296Ssam return; 53226048Sminshall abort: 53326496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 53426048Sminshall (void) signal(SIGINT, oldintr); 53526448Slepreau if (oldintp) 53626048Sminshall (void) signal(SIGPIPE, oldintp); 53726048Sminshall if (!cpend) { 53826048Sminshall code = -1; 53926048Sminshall return; 54026048Sminshall } 54126048Sminshall if (data >= 0) { 54226048Sminshall (void) close(data); 54326048Sminshall data = -1; 54426048Sminshall } 54526448Slepreau if (dout) 54626048Sminshall (void) fclose(dout); 54726048Sminshall (void) getreply(0); 54826048Sminshall code = -1; 54910296Ssam if (closefunc != NULL && fin != NULL) 55026048Sminshall (*closefunc)(fin); 55126048Sminshall if (bytes > 0 && verbose) 55226048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 55310296Ssam } 55410296Ssam 55510296Ssam jmp_buf recvabort; 55610296Ssam 55710296Ssam abortrecv() 55810296Ssam { 55910296Ssam 56026048Sminshall mflag = 0; 56126048Sminshall abrtflag = 0; 56226048Sminshall printf("\n"); 56326048Sminshall (void) fflush(stdout); 56410296Ssam longjmp(recvabort, 1); 56510296Ssam } 56610296Ssam 56711651Ssam recvrequest(cmd, local, remote, mode) 56811651Ssam char *cmd, *local, *remote, *mode; 56910296Ssam { 57026496Sminshall FILE *fout, *din = 0, *mypopen(); 57126496Sminshall int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 57227687Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag, nfnd; 57327687Sminshall char buf[BUFSIZ], *gunique(), msg; 57426496Sminshall long bytes = 0, hashbytes = sizeof (buf); 57526496Sminshall struct fd_set mask; 57611346Ssam register int c, d; 57710296Ssam struct timeval start, stop; 57810296Ssam 57926048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 58026048Sminshall proxtrans(cmd, local, remote); 58126048Sminshall return; 58226048Sminshall } 58310296Ssam closefunc = NULL; 58426048Sminshall oldintr = NULL; 58526048Sminshall oldintp = NULL; 58626048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 58726048Sminshall if (setjmp(recvabort)) { 58826048Sminshall while (cpend) { 58926048Sminshall (void) getreply(0); 59026048Sminshall } 59126048Sminshall if (data >= 0) { 59226048Sminshall (void) close(data); 59326048Sminshall data = -1; 59426048Sminshall } 59526448Slepreau if (oldintr) 59626048Sminshall (void) signal(SIGINT, oldintr); 59726048Sminshall code = -1; 59826048Sminshall return; 59926048Sminshall } 60010296Ssam oldintr = signal(SIGINT, abortrecv); 60126048Sminshall if (strcmp(local, "-") && *local != '|') { 60210296Ssam if (access(local, 2) < 0) { 60326048Sminshall char *dir = rindex(local, '/'); 60410296Ssam 60526048Sminshall if (errno != ENOENT && errno != EACCES) { 60610296Ssam perror(local); 60726048Sminshall (void) signal(SIGINT, oldintr); 60826048Sminshall code = -1; 60926048Sminshall return; 61010296Ssam } 61126048Sminshall if (dir != NULL) 61226048Sminshall *dir = 0; 61326048Sminshall d = access(dir ? local : ".", 2); 61426048Sminshall if (dir != NULL) 61526048Sminshall *dir = '/'; 61626048Sminshall if (d < 0) { 61726048Sminshall perror(local); 61826048Sminshall (void) signal(SIGINT, oldintr); 61926048Sminshall code = -1; 62026048Sminshall return; 62126048Sminshall } 62226048Sminshall if (!runique && errno == EACCES && 62326048Sminshall chmod(local,0600) < 0) { 62426048Sminshall perror(local); 62526048Sminshall (void) signal(SIGINT, oldintr); 62626048Sminshall code = -1; 62726048Sminshall return; 62826048Sminshall } 62926048Sminshall if (runique && errno == EACCES && 63026048Sminshall (local = gunique(local)) == NULL) { 63126048Sminshall (void) signal(SIGINT, oldintr); 63226048Sminshall code = -1; 63326048Sminshall return; 63426048Sminshall } 63510296Ssam } 63626048Sminshall else if (runique && (local = gunique(local)) == NULL) { 63726048Sminshall (void) signal(SIGINT, oldintr); 63826048Sminshall code = -1; 63926048Sminshall return; 64026048Sminshall } 64126048Sminshall } 64226048Sminshall if (initconn()) { 64326048Sminshall (void) signal(SIGINT, oldintr); 64426048Sminshall code = -1; 64526048Sminshall return; 64626048Sminshall } 64726448Slepreau if (setjmp(recvabort)) 64826048Sminshall goto abort; 64926048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 65026048Sminshall oldtype = type; 65126048Sminshall oldverbose = verbose; 65226448Slepreau if (!debug) 65326048Sminshall verbose = 0; 65426048Sminshall setascii(); 65526048Sminshall verbose = oldverbose; 65626048Sminshall } 65710296Ssam if (remote) { 65826048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 65926048Sminshall (void) signal(SIGINT, oldintr); 66026048Sminshall if (oldtype) { 66126448Slepreau if (!debug) 66226048Sminshall verbose = 0; 66326048Sminshall switch (oldtype) { 66426048Sminshall case TYPE_I: 66526048Sminshall setbinary(); 66626048Sminshall break; 66726048Sminshall case TYPE_E: 66826048Sminshall setebcdic(); 66926048Sminshall break; 67026048Sminshall case TYPE_L: 67126048Sminshall settenex(); 67226048Sminshall break; 67326048Sminshall } 67426048Sminshall verbose = oldverbose; 67526048Sminshall } 67626048Sminshall return; 67726048Sminshall } 67826048Sminshall } else { 67926048Sminshall if (command("%s", cmd) != PRELIM) { 68026048Sminshall (void) signal(SIGINT, oldintr); 68126048Sminshall if (oldtype) { 68226448Slepreau if (!debug) 68326048Sminshall verbose = 0; 68426048Sminshall switch (oldtype) { 68526048Sminshall case TYPE_I: 68626048Sminshall setbinary(); 68726048Sminshall break; 68826048Sminshall case TYPE_E: 68926048Sminshall setebcdic(); 69026048Sminshall break; 69126048Sminshall case TYPE_L: 69226048Sminshall settenex(); 69326048Sminshall break; 69426048Sminshall } 69526048Sminshall verbose = oldverbose; 69626048Sminshall } 69726048Sminshall return; 69826048Sminshall } 69926048Sminshall } 70026048Sminshall din = dataconn("r"); 70126048Sminshall if (din == NULL) 70226048Sminshall goto abort; 70326448Slepreau if (strcmp(local, "-") == 0) 70410296Ssam fout = stdout; 70510296Ssam else if (*local == '|') { 70626048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 70726496Sminshall fout = mypopen(local + 1, "w"); 70826048Sminshall if (fout == NULL) { 70926048Sminshall perror(local+1); 71026048Sminshall goto abort; 71126048Sminshall } 71226496Sminshall closefunc = mypclose; 71326048Sminshall } 71426048Sminshall else { 71511651Ssam fout = fopen(local, mode); 71626048Sminshall if (fout == NULL) { 71726048Sminshall perror(local); 71826048Sminshall goto abort; 71926048Sminshall } 72010296Ssam closefunc = fclose; 72110296Ssam } 72226496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 72311219Ssam switch (type) { 72411219Ssam 72511219Ssam case TYPE_I: 72611219Ssam case TYPE_L: 72711346Ssam errno = d = 0; 72811219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 72911346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 73011219Ssam break; 73111219Ssam bytes += c; 73211651Ssam if (hash) { 73326496Sminshall (void) putchar('#'); 73426496Sminshall (void) fflush(stdout); 73511651Ssam } 73611219Ssam } 73713213Ssam if (hash && bytes > 0) { 73826496Sminshall (void) putchar('\n'); 73926496Sminshall (void) fflush(stdout); 74011651Ssam } 74111219Ssam if (c < 0) 74211219Ssam perror("netin"); 74311346Ssam if (d < 0) 74410296Ssam perror(local); 74511219Ssam break; 74611219Ssam 74711219Ssam case TYPE_A: 74811219Ssam while ((c = getc(din)) != EOF) { 74927749Sminshall while (c == '\r') { 75011651Ssam while (hash && (bytes >= hashbytes)) { 75126496Sminshall (void) putchar('#'); 75226496Sminshall (void) fflush(stdout); 75311651Ssam hashbytes += sizeof (buf); 75411651Ssam } 75510296Ssam bytes++; 75626048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 75711219Ssam if (ferror (fout)) 75811219Ssam break; 75926496Sminshall (void) putc ('\r', fout); 76011219Ssam } 76126048Sminshall /*if (c == '\0') { 76211219Ssam bytes++; 76311219Ssam continue; 76426048Sminshall }*/ 76511219Ssam } 76626496Sminshall (void) putc (c, fout); 76711219Ssam bytes++; 76810296Ssam } 76911651Ssam if (hash) { 77013213Ssam if (bytes < hashbytes) 77126496Sminshall (void) putchar('#'); 77226496Sminshall (void) putchar('\n'); 77326496Sminshall (void) fflush(stdout); 77411651Ssam } 77511219Ssam if (ferror (din)) 77611219Ssam perror ("netin"); 77711219Ssam if (ferror (fout)) 77811219Ssam perror (local); 77911219Ssam break; 78010296Ssam } 78126448Slepreau if (closefunc != NULL) 78226048Sminshall (*closefunc)(fout); 78326496Sminshall (void) signal(SIGINT, oldintr); 78426448Slepreau if (oldintp) 78526048Sminshall (void) signal(SIGPIPE, oldintp); 78626496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 78710296Ssam (void) fclose(din); 78826048Sminshall (void) getreply(0); 78926048Sminshall if (bytes > 0 && verbose) 79026048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 79126048Sminshall if (oldtype) { 79226448Slepreau if (!debug) 79326048Sminshall verbose = 0; 79426048Sminshall switch (oldtype) { 79526048Sminshall case TYPE_I: 79626048Sminshall setbinary(); 79726048Sminshall break; 79826048Sminshall case TYPE_E: 79926048Sminshall setebcdic(); 80026048Sminshall break; 80126048Sminshall case TYPE_L: 80226048Sminshall settenex(); 80326048Sminshall break; 80426048Sminshall } 80526048Sminshall verbose = oldverbose; 80626048Sminshall } 80726048Sminshall return; 80826048Sminshall abort: 80926048Sminshall 81027687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 81126048Sminshall 81226496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 81326448Slepreau if (oldintp) 81426048Sminshall (void) signal(SIGPIPE, oldintr); 81526048Sminshall (void) signal(SIGINT,SIG_IGN); 81626048Sminshall if (oldtype) { 81726448Slepreau if (!debug) 81826048Sminshall verbose = 0; 81926048Sminshall switch (oldtype) { 82026048Sminshall case TYPE_I: 82126048Sminshall setbinary(); 82226048Sminshall break; 82326048Sminshall case TYPE_E: 82426048Sminshall setebcdic(); 82526048Sminshall break; 82626048Sminshall case TYPE_L: 82726048Sminshall settenex(); 82826048Sminshall break; 82926048Sminshall } 83026048Sminshall verbose = oldverbose; 83126048Sminshall } 83226048Sminshall if (!cpend) { 83326048Sminshall code = -1; 83426048Sminshall (void) signal(SIGINT,oldintr); 83526048Sminshall return; 83626048Sminshall } 83726048Sminshall 83827687Sminshall fprintf(cout,"%c%c",IAC,IP); 83927687Sminshall (void) fflush(cout); 84027687Sminshall msg = IAC; 84127687Sminshall /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 84227687Sminshall /* after urgent byte rather than before as now is protocol */ 84327687Sminshall if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 84427687Sminshall perror("abort"); 84526048Sminshall } 84627687Sminshall fprintf(cout,"%cABOR\r\n",DM); 84726048Sminshall (void) fflush(cout); 84827687Sminshall FD_ZERO(&mask); 84926496Sminshall FD_SET(fileno(cin), &mask); 85026496Sminshall if (din) { 85126496Sminshall FD_SET(fileno(din), &mask); 85226496Sminshall } 85327687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 85427687Sminshall if (nfnd < 0) { 85527687Sminshall perror("abort"); 85627687Sminshall } 85726048Sminshall code = -1; 85826048Sminshall lostpeer(); 85926048Sminshall } 86026496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 86126448Slepreau while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 86226448Slepreau ; 86326496Sminshall } 86427687Sminshall if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 86526048Sminshall if (data >= 0) { 86626496Sminshall (void) close(data); 86726048Sminshall data = -1; 86826048Sminshall } 86925907Smckusick (void) getreply(0); 87025907Smckusick } 87126048Sminshall (void) getreply(0); 87226048Sminshall code = -1; 87326048Sminshall if (data >= 0) { 87426048Sminshall (void) close(data); 87526048Sminshall data = -1; 87626048Sminshall } 87726448Slepreau if (closefunc != NULL && fout != NULL) 87826048Sminshall (*closefunc)(fout); 87926448Slepreau if (din) 88026048Sminshall (void) fclose(din); 88110296Ssam if (bytes > 0 && verbose) 88226048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 88326048Sminshall (void) signal(SIGINT,oldintr); 88410296Ssam } 88510296Ssam 88610296Ssam /* 88710296Ssam * Need to start a listen on the data channel 88810296Ssam * before we send the command, otherwise the 88910296Ssam * server's connect may fail. 89010296Ssam */ 89133224Sbostic int sendport = -1; 89211651Ssam 89310296Ssam initconn() 89410296Ssam { 89510296Ssam register char *p, *a; 89626048Sminshall int result, len, tmpno = 0; 89726993Skarels int on = 1; 89810296Ssam 89911651Ssam noport: 90010296Ssam data_addr = myctladdr; 90111651Ssam if (sendport) 90211651Ssam data_addr.sin_port = 0; /* let system pick one */ 90311651Ssam if (data != -1) 90411651Ssam (void) close (data); 90518287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 90610296Ssam if (data < 0) { 90710296Ssam perror("ftp: socket"); 90826448Slepreau if (tmpno) 90926048Sminshall sendport = 1; 91010296Ssam return (1); 91110296Ssam } 91212397Ssam if (!sendport) 91327687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 91433224Sbostic perror("ftp: setsockopt (reuse address)"); 91512397Ssam goto bad; 91612397Ssam } 91726496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 91810296Ssam perror("ftp: bind"); 91910296Ssam goto bad; 92010296Ssam } 92110296Ssam if (options & SO_DEBUG && 92227687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 92310296Ssam perror("ftp: setsockopt (ignored)"); 92411627Ssam len = sizeof (data_addr); 92511627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 92611627Ssam perror("ftp: getsockname"); 92710296Ssam goto bad; 92810296Ssam } 92926448Slepreau if (listen(data, 1) < 0) 93010296Ssam perror("ftp: listen"); 93111651Ssam if (sendport) { 93211651Ssam a = (char *)&data_addr.sin_addr; 93311651Ssam p = (char *)&data_addr.sin_port; 93410296Ssam #define UC(b) (((int)b)&0xff) 93511651Ssam result = 93611651Ssam command("PORT %d,%d,%d,%d,%d,%d", 93711651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 93811651Ssam UC(p[0]), UC(p[1])); 93911651Ssam if (result == ERROR && sendport == -1) { 94011651Ssam sendport = 0; 94126048Sminshall tmpno = 1; 94211651Ssam goto noport; 94311651Ssam } 94411651Ssam return (result != COMPLETE); 94511651Ssam } 94626448Slepreau if (tmpno) 94726048Sminshall sendport = 1; 94811651Ssam return (0); 94910296Ssam bad: 95010296Ssam (void) close(data), data = -1; 95126448Slepreau if (tmpno) 95226048Sminshall sendport = 1; 95310296Ssam return (1); 95410296Ssam } 95510296Ssam 95610296Ssam FILE * 95710296Ssam dataconn(mode) 95810296Ssam char *mode; 95910296Ssam { 96010296Ssam struct sockaddr_in from; 96110296Ssam int s, fromlen = sizeof (from); 96210296Ssam 96326496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 96410296Ssam if (s < 0) { 96510296Ssam perror("ftp: accept"); 96610296Ssam (void) close(data), data = -1; 96710296Ssam return (NULL); 96810296Ssam } 96910296Ssam (void) close(data); 97010296Ssam data = s; 97110296Ssam return (fdopen(data, mode)); 97210296Ssam } 97310296Ssam 97426048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 97526048Sminshall char *direction, *local, *remote; 97611651Ssam long bytes; 97710296Ssam struct timeval *t0, *t1; 97810296Ssam { 97910296Ssam struct timeval td; 98016437Sleres float s, bs; 98110296Ssam 98210296Ssam tvsub(&td, t1, t0); 98316437Sleres s = td.tv_sec + (td.tv_usec / 1000000.); 98410296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 98516437Sleres bs = bytes / nz(s); 98626448Slepreau if (local && *local != '-') 98726048Sminshall printf("local: %s ", local); 98826448Slepreau if (remote) 98926048Sminshall printf("remote: %s\n", remote); 99016437Sleres printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 99116437Sleres bytes, direction, s, bs / 1024.); 99210296Ssam } 99310296Ssam 99426496Sminshall /*tvadd(tsum, t0) 99510296Ssam struct timeval *tsum, *t0; 99610296Ssam { 99710296Ssam 99810296Ssam tsum->tv_sec += t0->tv_sec; 99910296Ssam tsum->tv_usec += t0->tv_usec; 100010296Ssam if (tsum->tv_usec > 1000000) 100110296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 100226496Sminshall } */ 100310296Ssam 100410296Ssam tvsub(tdiff, t1, t0) 100510296Ssam struct timeval *tdiff, *t1, *t0; 100610296Ssam { 100710296Ssam 100810296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 100910296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 101010296Ssam if (tdiff->tv_usec < 0) 101110296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 101210296Ssam } 101326048Sminshall 101426048Sminshall psabort() 101526048Sminshall { 101626048Sminshall extern int abrtflag; 101726048Sminshall 101826048Sminshall abrtflag++; 101926048Sminshall } 102026048Sminshall 102126048Sminshall pswitch(flag) 102226048Sminshall int flag; 102326048Sminshall { 102426048Sminshall extern int proxy, abrtflag; 102526048Sminshall int (*oldintr)(); 102626048Sminshall static struct comvars { 102726048Sminshall int connect; 102828469Skarels char name[MAXHOSTNAMELEN]; 102926048Sminshall struct sockaddr_in mctl; 103026048Sminshall struct sockaddr_in hctl; 103126048Sminshall FILE *in; 103226048Sminshall FILE *out; 103326048Sminshall int tpe; 103426048Sminshall int cpnd; 103526048Sminshall int sunqe; 103626048Sminshall int runqe; 103726048Sminshall int mcse; 103826048Sminshall int ntflg; 103926048Sminshall char nti[17]; 104026048Sminshall char nto[17]; 104126048Sminshall int mapflg; 104226048Sminshall char mi[MAXPATHLEN]; 104326048Sminshall char mo[MAXPATHLEN]; 104426048Sminshall } proxstruct, tmpstruct; 104526048Sminshall struct comvars *ip, *op; 104626048Sminshall 104726048Sminshall abrtflag = 0; 104826048Sminshall oldintr = signal(SIGINT, psabort); 104926048Sminshall if (flag) { 105026448Slepreau if (proxy) 105126048Sminshall return; 105226048Sminshall ip = &tmpstruct; 105326048Sminshall op = &proxstruct; 105426048Sminshall proxy++; 105526048Sminshall } 105626048Sminshall else { 105726448Slepreau if (!proxy) 105826048Sminshall return; 105926048Sminshall ip = &proxstruct; 106026048Sminshall op = &tmpstruct; 106126048Sminshall proxy = 0; 106226048Sminshall } 106326048Sminshall ip->connect = connected; 106426048Sminshall connected = op->connect; 106528469Skarels if (hostname) { 106628469Skarels (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 106728469Skarels ip->name[strlen(ip->name)] = '\0'; 106828469Skarels } else 106928469Skarels ip->name[0] = 0; 107026048Sminshall hostname = op->name; 107126048Sminshall ip->hctl = hisctladdr; 107226048Sminshall hisctladdr = op->hctl; 107326048Sminshall ip->mctl = myctladdr; 107426048Sminshall myctladdr = op->mctl; 107526048Sminshall ip->in = cin; 107626048Sminshall cin = op->in; 107726048Sminshall ip->out = cout; 107826048Sminshall cout = op->out; 107926048Sminshall ip->tpe = type; 108026048Sminshall type = op->tpe; 108126448Slepreau if (!type) 108226048Sminshall type = 1; 108326048Sminshall ip->cpnd = cpend; 108426048Sminshall cpend = op->cpnd; 108526048Sminshall ip->sunqe = sunique; 108626048Sminshall sunique = op->sunqe; 108726048Sminshall ip->runqe = runique; 108826048Sminshall runique = op->runqe; 108926048Sminshall ip->mcse = mcase; 109026048Sminshall mcase = op->mcse; 109126048Sminshall ip->ntflg = ntflag; 109226048Sminshall ntflag = op->ntflg; 109326496Sminshall (void) strncpy(ip->nti, ntin, 16); 109426048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 109526496Sminshall (void) strcpy(ntin, op->nti); 109626496Sminshall (void) strncpy(ip->nto, ntout, 16); 109726048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 109826496Sminshall (void) strcpy(ntout, op->nto); 109926048Sminshall ip->mapflg = mapflag; 110026048Sminshall mapflag = op->mapflg; 110126496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 110226048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 110326496Sminshall (void) strcpy(mapin, op->mi); 110426496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 110526048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 110626496Sminshall (void) strcpy(mapout, op->mo); 110726048Sminshall (void) signal(SIGINT, oldintr); 110826048Sminshall if (abrtflag) { 110926048Sminshall abrtflag = 0; 111026048Sminshall (*oldintr)(); 111126448Slepreau } 111226048Sminshall } 111326048Sminshall 111426048Sminshall jmp_buf ptabort; 111526048Sminshall int ptabflg; 111626048Sminshall 111726048Sminshall abortpt() 111826048Sminshall { 111926048Sminshall printf("\n"); 112026496Sminshall (void) fflush(stdout); 112126048Sminshall ptabflg++; 112226048Sminshall mflag = 0; 112326048Sminshall abrtflag = 0; 112426048Sminshall longjmp(ptabort, 1); 112526048Sminshall } 112626048Sminshall 112726048Sminshall proxtrans(cmd, local, remote) 112826048Sminshall char *cmd, *local, *remote; 112926048Sminshall { 113027687Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 113126048Sminshall extern jmp_buf ptabort; 113226048Sminshall char *cmd2; 113326496Sminshall struct fd_set mask; 113426048Sminshall 113526448Slepreau if (strcmp(cmd, "RETR")) 113626048Sminshall cmd2 = "RETR"; 113726448Slepreau else 113826048Sminshall cmd2 = runique ? "STOU" : "STOR"; 113926048Sminshall if (command("PASV") != COMPLETE) { 114026048Sminshall printf("proxy server does not support third part transfers.\n"); 114126048Sminshall return; 114226048Sminshall } 114326048Sminshall tmptype = type; 114426048Sminshall pswitch(0); 114526048Sminshall if (!connected) { 114626048Sminshall printf("No primary connection\n"); 114726048Sminshall pswitch(1); 114826048Sminshall code = -1; 114926048Sminshall return; 115026048Sminshall } 115126048Sminshall if (type != tmptype) { 115226048Sminshall oldtype = type; 115326048Sminshall switch (tmptype) { 115426048Sminshall case TYPE_A: 115526048Sminshall setascii(); 115626048Sminshall break; 115726048Sminshall case TYPE_I: 115826048Sminshall setbinary(); 115926048Sminshall break; 116026048Sminshall case TYPE_E: 116126048Sminshall setebcdic(); 116226048Sminshall break; 116326048Sminshall case TYPE_L: 116426048Sminshall settenex(); 116526048Sminshall break; 116626048Sminshall } 116726048Sminshall } 116826048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 116926048Sminshall switch (oldtype) { 117026048Sminshall case 0: 117126048Sminshall break; 117226048Sminshall case TYPE_A: 117326048Sminshall setascii(); 117426048Sminshall break; 117526048Sminshall case TYPE_I: 117626048Sminshall setbinary(); 117726048Sminshall break; 117826048Sminshall case TYPE_E: 117926048Sminshall setebcdic(); 118026048Sminshall break; 118126048Sminshall case TYPE_L: 118226048Sminshall settenex(); 118326048Sminshall break; 118426048Sminshall } 118526048Sminshall pswitch(1); 118626048Sminshall return; 118726048Sminshall } 118826448Slepreau if (setjmp(ptabort)) 118926048Sminshall goto abort; 119026048Sminshall oldintr = signal(SIGINT, abortpt); 119126048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 119226048Sminshall (void) signal(SIGINT, oldintr); 119326048Sminshall switch (oldtype) { 119426048Sminshall case 0: 119526048Sminshall break; 119626048Sminshall case TYPE_A: 119726048Sminshall setascii(); 119826048Sminshall break; 119926048Sminshall case TYPE_I: 120026048Sminshall setbinary(); 120126048Sminshall break; 120226048Sminshall case TYPE_E: 120326048Sminshall setebcdic(); 120426048Sminshall break; 120526048Sminshall case TYPE_L: 120626048Sminshall settenex(); 120726048Sminshall break; 120826048Sminshall } 120926048Sminshall pswitch(1); 121026048Sminshall return; 121126048Sminshall } 121226048Sminshall sleep(2); 121326048Sminshall pswitch(1); 121426048Sminshall secndflag++; 121526448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 121626048Sminshall goto abort; 121726048Sminshall ptflag++; 121826048Sminshall (void) getreply(0); 121926048Sminshall pswitch(0); 122026048Sminshall (void) getreply(0); 122126048Sminshall (void) signal(SIGINT, oldintr); 122226048Sminshall switch (oldtype) { 122326048Sminshall case 0: 122426048Sminshall break; 122526048Sminshall case TYPE_A: 122626048Sminshall setascii(); 122726048Sminshall break; 122826048Sminshall case TYPE_I: 122926048Sminshall setbinary(); 123026048Sminshall break; 123126048Sminshall case TYPE_E: 123226048Sminshall setebcdic(); 123326048Sminshall break; 123426048Sminshall case TYPE_L: 123526048Sminshall settenex(); 123626048Sminshall break; 123726048Sminshall } 123826048Sminshall pswitch(1); 123926048Sminshall ptflag = 0; 124026048Sminshall printf("local: %s remote: %s\n", local, remote); 124126048Sminshall return; 124226048Sminshall abort: 124326048Sminshall (void) signal(SIGINT, SIG_IGN); 124426048Sminshall ptflag = 0; 124526448Slepreau if (strcmp(cmd, "RETR") && !proxy) 124626048Sminshall pswitch(1); 124726448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 124826048Sminshall pswitch(0); 124926048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 125026048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 125126048Sminshall pswitch(0); 125226048Sminshall switch (oldtype) { 125326048Sminshall case 0: 125426048Sminshall break; 125526048Sminshall case TYPE_A: 125626048Sminshall setascii(); 125726048Sminshall break; 125826048Sminshall case TYPE_I: 125926048Sminshall setbinary(); 126026048Sminshall break; 126126048Sminshall case TYPE_E: 126226048Sminshall setebcdic(); 126326048Sminshall break; 126426048Sminshall case TYPE_L: 126526048Sminshall settenex(); 126626048Sminshall break; 126726048Sminshall } 126827687Sminshall if (cpend) { 126926048Sminshall char msg[2]; 127026048Sminshall 127126048Sminshall fprintf(cout,"%c%c",IAC,IP); 127226048Sminshall (void) fflush(cout); 127326048Sminshall *msg = IAC; 127426048Sminshall *(msg+1) = DM; 127526448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 127626048Sminshall perror("abort"); 127726048Sminshall fprintf(cout,"ABOR\r\n"); 127826048Sminshall (void) fflush(cout); 127927687Sminshall FD_ZERO(&mask); 128026496Sminshall FD_SET(fileno(cin), &mask); 128127687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 128227687Sminshall if (nfnd < 0) { 128327687Sminshall perror("abort"); 128427687Sminshall } 128526448Slepreau if (ptabflg) 128626048Sminshall code = -1; 128726048Sminshall lostpeer(); 128826048Sminshall } 128926048Sminshall (void) getreply(0); 129026048Sminshall (void) getreply(0); 129126048Sminshall } 129226048Sminshall } 129326048Sminshall pswitch(1); 129426448Slepreau if (ptabflg) 129526048Sminshall code = -1; 129626048Sminshall (void) signal(SIGINT, oldintr); 129726048Sminshall return; 129826048Sminshall } 129927687Sminshall if (cpend) { 130026048Sminshall char msg[2]; 130126048Sminshall 130226048Sminshall fprintf(cout,"%c%c",IAC,IP); 130326048Sminshall (void) fflush(cout); 130426048Sminshall *msg = IAC; 130526048Sminshall *(msg+1) = DM; 130626448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 130726048Sminshall perror("abort"); 130826048Sminshall fprintf(cout,"ABOR\r\n"); 130926048Sminshall (void) fflush(cout); 131027687Sminshall FD_ZERO(&mask); 131126496Sminshall FD_SET(fileno(cin), &mask); 131227687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 131327687Sminshall if (nfnd < 0) { 131427687Sminshall perror("abort"); 131527687Sminshall } 131626448Slepreau if (ptabflg) 131726048Sminshall code = -1; 131826048Sminshall lostpeer(); 131926048Sminshall } 132026048Sminshall (void) getreply(0); 132126048Sminshall (void) getreply(0); 132226048Sminshall } 132326048Sminshall pswitch(!proxy); 132426048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 132526048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 132626048Sminshall pswitch(0); 132726048Sminshall switch (oldtype) { 132826048Sminshall case 0: 132926048Sminshall break; 133026048Sminshall case TYPE_A: 133126048Sminshall setascii(); 133226048Sminshall break; 133326048Sminshall case TYPE_I: 133426048Sminshall setbinary(); 133526048Sminshall break; 133626048Sminshall case TYPE_E: 133726048Sminshall setebcdic(); 133826048Sminshall break; 133926048Sminshall case TYPE_L: 134026048Sminshall settenex(); 134126048Sminshall break; 134226048Sminshall } 134327687Sminshall if (cpend) { 134426048Sminshall char msg[2]; 134526048Sminshall 134626048Sminshall fprintf(cout,"%c%c",IAC,IP); 134726048Sminshall (void) fflush(cout); 134826048Sminshall *msg = IAC; 134926048Sminshall *(msg+1) = DM; 135026448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 135126048Sminshall perror("abort"); 135226048Sminshall fprintf(cout,"ABOR\r\n"); 135326048Sminshall (void) fflush(cout); 135427687Sminshall FD_ZERO(&mask); 135526496Sminshall FD_SET(fileno(cin), &mask); 135627687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 135727687Sminshall if (nfnd < 0) { 135827687Sminshall perror("abort"); 135927687Sminshall } 136026448Slepreau if (ptabflg) 136126048Sminshall code = -1; 136226048Sminshall lostpeer(); 136326048Sminshall } 136426048Sminshall (void) getreply(0); 136526048Sminshall (void) getreply(0); 136626048Sminshall } 136726048Sminshall pswitch(1); 136826448Slepreau if (ptabflg) 136926048Sminshall code = -1; 137026048Sminshall (void) signal(SIGINT, oldintr); 137126048Sminshall return; 137226048Sminshall } 137326048Sminshall } 137427687Sminshall if (cpend) { 137526048Sminshall char msg[2]; 137626048Sminshall 137726048Sminshall fprintf(cout,"%c%c",IAC,IP); 137826048Sminshall (void) fflush(cout); 137926048Sminshall *msg = IAC; 138026048Sminshall *(msg+1) = DM; 138126448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 138226048Sminshall perror("abort"); 138326048Sminshall fprintf(cout,"ABOR\r\n"); 138426048Sminshall (void) fflush(cout); 138527687Sminshall FD_ZERO(&mask); 138626496Sminshall FD_SET(fileno(cin), &mask); 138727687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 138827687Sminshall if (nfnd < 0) { 138927687Sminshall perror("abort"); 139027687Sminshall } 139126448Slepreau if (ptabflg) 139226048Sminshall code = -1; 139326048Sminshall lostpeer(); 139426048Sminshall } 139526048Sminshall (void) getreply(0); 139626048Sminshall (void) getreply(0); 139726048Sminshall } 139826048Sminshall pswitch(!proxy); 139926048Sminshall if (cpend) { 140027687Sminshall FD_ZERO(&mask); 140126496Sminshall FD_SET(fileno(cin), &mask); 140227687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 140327687Sminshall if (nfnd < 0) { 140427687Sminshall perror("abort"); 140527687Sminshall } 140626448Slepreau if (ptabflg) 140726048Sminshall code = -1; 140826048Sminshall lostpeer(); 140926048Sminshall } 141026048Sminshall (void) getreply(0); 141126048Sminshall (void) getreply(0); 141226048Sminshall } 141326448Slepreau if (proxy) 141426048Sminshall pswitch(0); 141526048Sminshall switch (oldtype) { 141626048Sminshall case 0: 141726048Sminshall break; 141826048Sminshall case TYPE_A: 141926048Sminshall setascii(); 142026048Sminshall break; 142126048Sminshall case TYPE_I: 142226048Sminshall setbinary(); 142326048Sminshall break; 142426048Sminshall case TYPE_E: 142526048Sminshall setebcdic(); 142626048Sminshall break; 142726048Sminshall case TYPE_L: 142826048Sminshall settenex(); 142926048Sminshall break; 143026048Sminshall } 143126048Sminshall pswitch(1); 143226448Slepreau if (ptabflg) 143326048Sminshall code = -1; 143426048Sminshall (void) signal(SIGINT, oldintr); 143526048Sminshall } 143626048Sminshall 143726048Sminshall reset() 143826048Sminshall { 143926496Sminshall struct fd_set mask; 144026496Sminshall int nfnd = 1; 144126048Sminshall 144227687Sminshall FD_ZERO(&mask); 144330946Scsvsj while (nfnd > 0) { 144426496Sminshall FD_SET(fileno(cin), &mask); 144527687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 144626048Sminshall perror("reset"); 144726048Sminshall code = -1; 144826048Sminshall lostpeer(); 144926048Sminshall } 145027687Sminshall else if (nfnd) { 145126048Sminshall (void) getreply(0); 145226496Sminshall } 145326048Sminshall } 145426048Sminshall } 145526048Sminshall 145626048Sminshall char * 145726048Sminshall gunique(local) 145826048Sminshall char *local; 145926048Sminshall { 146026048Sminshall static char new[MAXPATHLEN]; 146126048Sminshall char *cp = rindex(local, '/'); 146226048Sminshall int d, count=0; 146326048Sminshall char ext = '1'; 146426048Sminshall 146526448Slepreau if (cp) 146626048Sminshall *cp = '\0'; 146726048Sminshall d = access(cp ? local : ".", 2); 146826448Slepreau if (cp) 146926048Sminshall *cp = '/'; 147026048Sminshall if (d < 0) { 147126048Sminshall perror(local); 147226048Sminshall return((char *) 0); 147326048Sminshall } 147426048Sminshall (void) strcpy(new, local); 147526048Sminshall cp = new + strlen(new); 147626048Sminshall *cp++ = '.'; 147726048Sminshall while (!d) { 147826048Sminshall if (++count == 100) { 147926048Sminshall printf("runique: can't find unique file name.\n"); 148026048Sminshall return((char *) 0); 148126048Sminshall } 148226048Sminshall *cp++ = ext; 148326048Sminshall *cp = '\0'; 148426448Slepreau if (ext == '9') 148526048Sminshall ext = '0'; 148626448Slepreau else 148726048Sminshall ext++; 148826448Slepreau if ((d = access(new, 0)) < 0) 148926048Sminshall break; 149026448Slepreau if (ext != '0') 149126048Sminshall cp--; 149226448Slepreau else if (*(cp - 2) == '.') 149326048Sminshall *(cp - 1) = '1'; 149426048Sminshall else { 149526048Sminshall *(cp - 2) = *(cp - 2) + 1; 149626048Sminshall cp--; 149726048Sminshall } 149826048Sminshall } 149926048Sminshall return(new); 150026048Sminshall } 1501