121739Sdist /* 226048Sminshall * Copyright (c) 1985 Regents of the University of California. 321739Sdist * All rights reserved. The Berkeley software License Agreement 421739Sdist * specifies the terms and conditions for redistribution. 521739Sdist */ 621739Sdist 710296Ssam #ifndef lint 8*26993Skarels static char sccsid[] = "@(#)ftp.c 5.11 (Berkeley) 04/02/86"; 921739Sdist #endif not lint 1010296Ssam 1126048Sminshall #include "ftp_var.h" 1226048Sminshall 1310296Ssam #include <sys/stat.h> 1410296Ssam #include <sys/ioctl.h> 1510296Ssam #include <sys/socket.h> 1613614Ssam #include <sys/time.h> 1726496Sminshall #include <sys/types.h> 1810296Ssam 1910296Ssam #include <netinet/in.h> 2012397Ssam #include <arpa/ftp.h> 2126048Sminshall #include <arpa/telnet.h> 2210296Ssam 2310296Ssam #include <stdio.h> 2410296Ssam #include <signal.h> 2510296Ssam #include <errno.h> 2610296Ssam #include <netdb.h> 2726048Sminshall #include <fcntl.h> 2826048Sminshall #include <pwd.h> 2910296Ssam 3010296Ssam struct sockaddr_in hisctladdr; 3110296Ssam struct sockaddr_in data_addr; 3210296Ssam int data = -1; 3326048Sminshall int telflag = 0; 3426048Sminshall int abrtflag = 0; 3526048Sminshall int ptflag = 0; 3610296Ssam int connected; 3710296Ssam struct sockaddr_in myctladdr; 3826496Sminshall uid_t getuid(); 3910296Ssam 4010296Ssam FILE *cin, *cout; 4110296Ssam FILE *dataconn(); 4210296Ssam 4325904Skarels char * 4410296Ssam hookup(host, port) 4510296Ssam char *host; 4610296Ssam int port; 4710296Ssam { 4825904Skarels register struct hostent *hp = 0; 4926048Sminshall int s,len,oldverbose; 5025904Skarels static char hostnamebuf[80]; 5126048Sminshall char msg[2]; 5210296Ssam 5310296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 5425904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 5525904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 5625904Skarels hisctladdr.sin_family = AF_INET; 5725904Skarels (void) strcpy(hostnamebuf, host); 5826048Sminshall } 5926048Sminshall else { 6025100Sbloom hp = gethostbyname(host); 6125904Skarels if (hp == NULL) { 6225904Skarels printf("%s: unknown host\n", host); 6326048Sminshall code = -1; 6426048Sminshall return((char *) 0); 6525904Skarels } 6625904Skarels hisctladdr.sin_family = hp->h_addrtype; 6725904Skarels bcopy(hp->h_addr_list[0], 6825904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 6925904Skarels (void) strcpy(hostnamebuf, hp->h_name); 7010296Ssam } 7125904Skarels hostname = hostnamebuf; 7225904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 7310296Ssam if (s < 0) { 7410296Ssam perror("ftp: socket"); 7526048Sminshall code = -1; 7610296Ssam return (0); 7710296Ssam } 7810296Ssam hisctladdr.sin_port = port; 7926496Sminshall while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 8025904Skarels if (hp && hp->h_addr_list[1]) { 8125904Skarels int oerrno = errno; 8225904Skarels 8325904Skarels fprintf(stderr, "ftp: connect to address %s: ", 8425904Skarels inet_ntoa(hisctladdr.sin_addr)); 8525904Skarels errno = oerrno; 8626496Sminshall perror((char *) 0); 8725904Skarels hp->h_addr_list++; 8825904Skarels bcopy(hp->h_addr_list[0], 8926048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 9026496Sminshall fprintf(stdout, "Trying %s...\n", 9125904Skarels inet_ntoa(hisctladdr.sin_addr)); 9226813Skarels (void) close(s); 9326813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 9426813Skarels if (s < 0) { 9526813Skarels perror("ftp: socket"); 9626813Skarels code = -1; 9726813Skarels return (0); 9826813Skarels } 9925904Skarels continue; 10025904Skarels } 10110296Ssam perror("ftp: connect"); 10226048Sminshall code = -1; 10310296Ssam goto bad; 10410296Ssam } 10511627Ssam len = sizeof (myctladdr); 10611627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 10711627Ssam perror("ftp: getsockname"); 10826048Sminshall code = -1; 10910296Ssam goto bad; 11010296Ssam } 11110296Ssam cin = fdopen(s, "r"); 11210296Ssam cout = fdopen(s, "w"); 11311219Ssam if (cin == NULL || cout == NULL) { 11410296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 11510296Ssam if (cin) 11626496Sminshall (void) fclose(cin); 11710296Ssam if (cout) 11826496Sminshall (void) fclose(cout); 11926048Sminshall code = -1; 12010296Ssam goto bad; 12110296Ssam } 12210296Ssam if (verbose) 12326067Sminshall printf("Connected to %s.\n", hostname); 12426048Sminshall if (getreply(0) != 2) { /* read startup message from server */ 12526048Sminshall if (cin) 12626496Sminshall (void) fclose(cin); 12726048Sminshall if (cout) 12826496Sminshall (void) fclose(cout); 12926048Sminshall code = -1; 13026048Sminshall goto bad; 13126048Sminshall } 13226048Sminshall 13326048Sminshall /* test to see if server command parser understands TELNET SYNC command */ 13426048Sminshall 13526048Sminshall fprintf(cout,"%c%c",IAC,NOP); 13626048Sminshall (void) fflush(cout); 13726048Sminshall *msg = IAC; 13826048Sminshall *(msg+1) = DM; 13926448Slepreau if (send(s,msg,2,MSG_OOB) != 2) 14026048Sminshall perror("sync"); 14126048Sminshall oldverbose = verbose; 14226448Slepreau if (!debug) 14326048Sminshall verbose = -1; 14426448Slepreau if (command("NOOP") == COMPLETE) 14526048Sminshall telflag = 1; 14626448Slepreau else 14726048Sminshall telflag = 0; 14826048Sminshall verbose = oldverbose; 14925904Skarels return (hostname); 15010296Ssam bad: 15126496Sminshall (void) close(s); 15225904Skarels return ((char *)0); 15310296Ssam } 15410296Ssam 15525904Skarels login(host) 15625904Skarels char *host; 15710296Ssam { 15826048Sminshall char tmp[80]; 15926496Sminshall char *user, *pass, *acct, *getlogin(), *mygetpass(); 16026048Sminshall int n, aflag = 0; 16110296Ssam 16226048Sminshall user = pass = acct = 0; 16326048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 16426048Sminshall disconnect(); 16526048Sminshall code = -1; 16626048Sminshall return(0); 16726048Sminshall } 16826048Sminshall if (user == NULL) { 16926048Sminshall char *myname = getlogin(); 17026048Sminshall 17126048Sminshall if (myname == NULL) { 17226048Sminshall struct passwd *pp = getpwuid(getuid()); 17326048Sminshall 17426448Slepreau if (pp != NULL) 17526048Sminshall myname = pp->pw_name; 17626048Sminshall } 17726048Sminshall printf("Name (%s:%s): ", host, myname); 17826048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 17926048Sminshall tmp[strlen(tmp) - 1] = '\0'; 18026448Slepreau if (*tmp == '\0') 18126048Sminshall user = myname; 18226448Slepreau else 18326048Sminshall user = tmp; 18426048Sminshall } 18510296Ssam n = command("USER %s", user); 18626048Sminshall if (n == CONTINUE) { 18726448Slepreau if (pass == NULL) 18826496Sminshall pass = mygetpass("Password:"); 18910296Ssam n = command("PASS %s", pass); 19026048Sminshall } 19110296Ssam if (n == CONTINUE) { 19226048Sminshall aflag++; 19326496Sminshall acct = mygetpass("Account:"); 19410296Ssam n = command("ACCT %s", acct); 19510296Ssam } 19610296Ssam if (n != COMPLETE) { 19710296Ssam fprintf(stderr, "Login failed.\n"); 19810296Ssam return (0); 19910296Ssam } 20026448Slepreau if (!aflag && acct != NULL) 20126048Sminshall (void) command("ACCT %s", acct); 20226448Slepreau if (proxy) 20326048Sminshall return(1); 20426048Sminshall for (n = 0; n < macnum; ++n) { 20526048Sminshall if (!strcmp("init", macros[n].mac_name)) { 20626496Sminshall (void) strcpy(line, "$init"); 20726048Sminshall makeargv(); 20826048Sminshall domacro(margc, margv); 20926048Sminshall break; 21026048Sminshall } 21126048Sminshall } 21210296Ssam return (1); 21310296Ssam } 21410296Ssam 21526048Sminshall cmdabort() 21626048Sminshall { 21726048Sminshall extern jmp_buf ptabort; 21826048Sminshall 21926048Sminshall printf("\n"); 22026048Sminshall (void) fflush(stdout); 22126048Sminshall abrtflag++; 22226448Slepreau if (ptflag) 22326048Sminshall longjmp(ptabort,1); 22426048Sminshall } 22526048Sminshall 22626496Sminshall /*VARARGS1*/ 22710296Ssam command(fmt, args) 22810296Ssam char *fmt; 22910296Ssam { 23026048Sminshall int r, (*oldintr)(), cmdabort(); 23110296Ssam 23226048Sminshall abrtflag = 0; 23310296Ssam if (debug) { 23410296Ssam printf("---> "); 23510296Ssam _doprnt(fmt, &args, stdout); 23610296Ssam printf("\n"); 23710296Ssam (void) fflush(stdout); 23810296Ssam } 23911219Ssam if (cout == NULL) { 24011219Ssam perror ("No control connection for command"); 24126048Sminshall code = -1; 24211219Ssam return (0); 24311219Ssam } 24426048Sminshall oldintr = signal(SIGINT,cmdabort); 24510296Ssam _doprnt(fmt, &args, cout); 24610296Ssam fprintf(cout, "\r\n"); 24710296Ssam (void) fflush(cout); 24826048Sminshall cpend = 1; 24926048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 25026448Slepreau if (abrtflag && oldintr != SIG_IGN) 25126048Sminshall (*oldintr)(); 25226048Sminshall (void) signal(SIGINT, oldintr); 25326048Sminshall return(r); 25410296Ssam } 25510296Ssam 25610296Ssam #include <ctype.h> 25710296Ssam 25810296Ssam getreply(expecteof) 25910296Ssam int expecteof; 26010296Ssam { 26111219Ssam register int c, n; 26226048Sminshall register int dig; 26326048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 26426048Sminshall int pflag = 0; 26526048Sminshall char *pt = pasv; 26610296Ssam 26726048Sminshall oldintr = signal(SIGINT,cmdabort); 26810296Ssam for (;;) { 26910296Ssam dig = n = code = 0; 27010296Ssam while ((c = getc(cin)) != '\n') { 27110296Ssam dig++; 27210296Ssam if (c == EOF) { 27326048Sminshall if (expecteof) { 27426048Sminshall (void) signal(SIGINT,oldintr); 27526048Sminshall code = 221; 27610296Ssam return (0); 27726048Sminshall } 27810296Ssam lostpeer(); 27926048Sminshall if (verbose) { 28026048Sminshall printf("421 Service not available, remote server has closed connection\n"); 28126048Sminshall (void) fflush(stdout); 28226048Sminshall code = 421; 28326048Sminshall return(4); 28426048Sminshall } 28510296Ssam } 28626048Sminshall if (c != '\r' && (verbose > 0 || 28726048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 28826448Slepreau if (proxflag && 28926448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 29026048Sminshall printf("%s:",hostname); 29126496Sminshall (void) putchar(c); 29226048Sminshall } 29310296Ssam if (dig < 4 && isdigit(c)) 29410296Ssam code = code * 10 + (c - '0'); 29526448Slepreau if (!pflag && code == 227) 29626048Sminshall pflag = 1; 29726448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 29826048Sminshall pflag = 2; 29926048Sminshall if (pflag == 2) { 30026448Slepreau if (c != '\r' && c != ')') 30126048Sminshall *pt++ = c; 30226048Sminshall else { 30326048Sminshall *pt = '\0'; 30426048Sminshall pflag = 3; 30526048Sminshall } 30626048Sminshall } 30726048Sminshall if (dig == 4 && c == '-') { 30826448Slepreau if (continuation) 30926048Sminshall code = 0; 31010296Ssam continuation++; 31126048Sminshall } 31210296Ssam if (n == 0) 31310296Ssam n = c; 31410296Ssam } 31526048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 31626496Sminshall (void) putchar(c); 31711346Ssam (void) fflush (stdout); 31811346Ssam } 31910296Ssam if (continuation && code != originalcode) { 32010296Ssam if (originalcode == 0) 32110296Ssam originalcode = code; 32210296Ssam continue; 32310296Ssam } 32426448Slepreau if (n != '1') 32526048Sminshall cpend = 0; 32626048Sminshall (void) signal(SIGINT,oldintr); 32726448Slepreau if (code == 421 || originalcode == 421) 32826048Sminshall lostpeer(); 32926448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 33026048Sminshall (*oldintr)(); 33125907Smckusick return (n - '0'); 33210296Ssam } 33310296Ssam } 33410296Ssam 33526048Sminshall empty(mask, sec) 33626496Sminshall struct fd_set mask; 33726048Sminshall int sec; 33826048Sminshall { 33926048Sminshall struct timeval t; 34026048Sminshall 34126048Sminshall t.tv_sec = (long) sec; 34226048Sminshall t.tv_usec = 0; 34326496Sminshall if (select(20, &mask, (struct fd_set *) 0, (struct fd_set *) 0, &t) < 0) 34426048Sminshall return(-1); 34526496Sminshall return (1); 34626048Sminshall } 34726048Sminshall 34810296Ssam jmp_buf sendabort; 34910296Ssam 35010296Ssam abortsend() 35110296Ssam { 35210296Ssam 35326048Sminshall mflag = 0; 35426048Sminshall abrtflag = 0; 35526048Sminshall printf("\nsend aborted\n"); 35626048Sminshall (void) fflush(stdout); 35710296Ssam longjmp(sendabort, 1); 35810296Ssam } 35910296Ssam 36010296Ssam sendrequest(cmd, local, remote) 36110296Ssam char *cmd, *local, *remote; 36210296Ssam { 36326496Sminshall FILE *fin, *dout = 0, *mypopen(); 36426496Sminshall int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 36526048Sminshall int abortsend(); 36611219Ssam char buf[BUFSIZ]; 36711651Ssam long bytes = 0, hashbytes = sizeof (buf); 36811346Ssam register int c, d; 36910296Ssam struct stat st; 37010296Ssam struct timeval start, stop; 37110296Ssam 37226048Sminshall if (proxy) { 37326048Sminshall proxtrans(cmd, local, remote); 37426048Sminshall return; 37526048Sminshall } 37610296Ssam closefunc = NULL; 37726048Sminshall oldintr = NULL; 37826048Sminshall oldintp = NULL; 37926048Sminshall if (setjmp(sendabort)) { 38026048Sminshall while (cpend) { 38126048Sminshall (void) getreply(0); 38226048Sminshall } 38326048Sminshall if (data >= 0) { 38426048Sminshall (void) close(data); 38526048Sminshall data = -1; 38626048Sminshall } 38726448Slepreau if (oldintr) 38826048Sminshall (void) signal(SIGINT,oldintr); 38926448Slepreau if (oldintp) 39026048Sminshall (void) signal(SIGPIPE,oldintp); 39126048Sminshall code = -1; 39226048Sminshall return; 39326048Sminshall } 39410296Ssam oldintr = signal(SIGINT, abortsend); 39510296Ssam if (strcmp(local, "-") == 0) 39610296Ssam fin = stdin; 39710296Ssam else if (*local == '|') { 39826048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 39926496Sminshall fin = mypopen(local + 1, "r"); 40010296Ssam if (fin == NULL) { 40126048Sminshall perror(local + 1); 40226048Sminshall (void) signal(SIGINT, oldintr); 40326048Sminshall (void) signal(SIGPIPE, oldintp); 40426048Sminshall code = -1; 40526048Sminshall return; 40610296Ssam } 40726496Sminshall closefunc = mypclose; 40810296Ssam } else { 40910296Ssam fin = fopen(local, "r"); 41010296Ssam if (fin == NULL) { 41110296Ssam perror(local); 41226048Sminshall (void) signal(SIGINT, oldintr); 41326048Sminshall code = -1; 41426048Sminshall return; 41510296Ssam } 41610296Ssam closefunc = fclose; 41710296Ssam if (fstat(fileno(fin), &st) < 0 || 41810296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 41926496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 42026048Sminshall (void) signal(SIGINT, oldintr); 42126048Sminshall code = -1; 42226048Sminshall return; 42310296Ssam } 42410296Ssam } 42526048Sminshall if (initconn()) { 42626048Sminshall (void) signal(SIGINT, oldintr); 42726448Slepreau if (oldintp) 42826048Sminshall (void) signal(SIGPIPE, oldintp); 42926048Sminshall code = -1; 43026048Sminshall return; 43126048Sminshall } 43226448Slepreau if (setjmp(sendabort)) 43326048Sminshall goto abort; 43410296Ssam if (remote) { 43526048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 43626048Sminshall (void) signal(SIGINT, oldintr); 43726448Slepreau if (oldintp) 43826048Sminshall (void) signal(SIGPIPE, oldintp); 43926048Sminshall return; 44026048Sminshall } 44110296Ssam } else 44226048Sminshall if (command("%s", cmd) != PRELIM) { 44326048Sminshall (void) signal(SIGINT, oldintr); 44426448Slepreau if (oldintp) 44526048Sminshall (void) signal(SIGPIPE, oldintp); 44626048Sminshall return; 44726048Sminshall } 44810296Ssam dout = dataconn("w"); 44926448Slepreau if (dout == NULL) 45026048Sminshall goto abort; 45126496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 45211219Ssam switch (type) { 45311219Ssam 45411219Ssam case TYPE_I: 45511219Ssam case TYPE_L: 45611346Ssam errno = d = 0; 45711219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 45811346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 45911219Ssam break; 46011219Ssam bytes += c; 46111651Ssam if (hash) { 46226496Sminshall (void) putchar('#'); 46326496Sminshall (void) fflush(stdout); 46411651Ssam } 46511219Ssam } 46613213Ssam if (hash && bytes > 0) { 46726496Sminshall (void) putchar('\n'); 46826496Sminshall (void) fflush(stdout); 46911651Ssam } 47011219Ssam if (c < 0) 47111219Ssam perror(local); 47211346Ssam if (d < 0) 47311219Ssam perror("netout"); 47411219Ssam break; 47511219Ssam 47611219Ssam case TYPE_A: 47711219Ssam while ((c = getc(fin)) != EOF) { 47811219Ssam if (c == '\n') { 47911651Ssam while (hash && (bytes >= hashbytes)) { 48026496Sminshall (void) putchar('#'); 48126496Sminshall (void) fflush(stdout); 48211651Ssam hashbytes += sizeof (buf); 48311651Ssam } 48411219Ssam if (ferror(dout)) 48511219Ssam break; 48626496Sminshall (void) putc('\r', dout); 48711219Ssam bytes++; 48811219Ssam } 48926496Sminshall (void) putc(c, dout); 49011219Ssam bytes++; 49126048Sminshall /* if (c == '\r') { */ 49226496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 49326048Sminshall /* bytes++; */ 49426048Sminshall /* } */ 49511219Ssam } 49611651Ssam if (hash) { 49713213Ssam if (bytes < hashbytes) 49826496Sminshall (void) putchar('#'); 49926496Sminshall (void) putchar('\n'); 50026496Sminshall (void) fflush(stdout); 50111651Ssam } 50211219Ssam if (ferror(fin)) 50311219Ssam perror(local); 50411346Ssam if (ferror(dout)) 50511219Ssam perror("netout"); 50611219Ssam break; 50710296Ssam } 50826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 50910296Ssam if (closefunc != NULL) 51026048Sminshall (*closefunc)(fin); 51110296Ssam (void) fclose(dout); 51226048Sminshall (void) getreply(0); 51326048Sminshall (void) signal(SIGINT, oldintr); 51410296Ssam if (bytes > 0 && verbose) 51526048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 51610296Ssam return; 51726048Sminshall abort: 51826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 51926048Sminshall (void) signal(SIGINT, oldintr); 52026448Slepreau if (oldintp) 52126048Sminshall (void) signal(SIGPIPE, oldintp); 52226048Sminshall if (!cpend) { 52326048Sminshall code = -1; 52426048Sminshall return; 52526048Sminshall } 52626048Sminshall if (data >= 0) { 52726048Sminshall (void) close(data); 52826048Sminshall data = -1; 52926048Sminshall } 53026448Slepreau if (dout) 53126048Sminshall (void) fclose(dout); 53226048Sminshall (void) getreply(0); 53326048Sminshall code = -1; 53410296Ssam if (closefunc != NULL && fin != NULL) 53526048Sminshall (*closefunc)(fin); 53626048Sminshall if (bytes > 0 && verbose) 53726048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 53810296Ssam } 53910296Ssam 54010296Ssam jmp_buf recvabort; 54110296Ssam 54210296Ssam abortrecv() 54310296Ssam { 54410296Ssam 54526048Sminshall mflag = 0; 54626048Sminshall abrtflag = 0; 54726048Sminshall printf("\n"); 54826048Sminshall (void) fflush(stdout); 54910296Ssam longjmp(recvabort, 1); 55010296Ssam } 55110296Ssam 55211651Ssam recvrequest(cmd, local, remote, mode) 55311651Ssam char *cmd, *local, *remote, *mode; 55410296Ssam { 55526496Sminshall FILE *fout, *din = 0, *mypopen(); 55626496Sminshall int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 55726048Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag; 55826048Sminshall char buf[BUFSIZ], *gunique(); 55926496Sminshall long bytes = 0, hashbytes = sizeof (buf); 56026496Sminshall struct fd_set mask; 56111346Ssam register int c, d; 56210296Ssam struct timeval start, stop; 56310296Ssam 56426048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 56526048Sminshall proxtrans(cmd, local, remote); 56626048Sminshall return; 56726048Sminshall } 56810296Ssam closefunc = NULL; 56926048Sminshall oldintr = NULL; 57026048Sminshall oldintp = NULL; 57126048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 57226048Sminshall if (setjmp(recvabort)) { 57326048Sminshall while (cpend) { 57426048Sminshall (void) getreply(0); 57526048Sminshall } 57626048Sminshall if (data >= 0) { 57726048Sminshall (void) close(data); 57826048Sminshall data = -1; 57926048Sminshall } 58026448Slepreau if (oldintr) 58126048Sminshall (void) signal(SIGINT, oldintr); 58226048Sminshall code = -1; 58326048Sminshall return; 58426048Sminshall } 58510296Ssam oldintr = signal(SIGINT, abortrecv); 58626048Sminshall if (strcmp(local, "-") && *local != '|') { 58710296Ssam if (access(local, 2) < 0) { 58826048Sminshall char *dir = rindex(local, '/'); 58910296Ssam 59026048Sminshall if (errno != ENOENT && errno != EACCES) { 59110296Ssam perror(local); 59226048Sminshall (void) signal(SIGINT, oldintr); 59326048Sminshall code = -1; 59426048Sminshall return; 59510296Ssam } 59626048Sminshall if (dir != NULL) 59726048Sminshall *dir = 0; 59826048Sminshall d = access(dir ? local : ".", 2); 59926048Sminshall if (dir != NULL) 60026048Sminshall *dir = '/'; 60126048Sminshall if (d < 0) { 60226048Sminshall perror(local); 60326048Sminshall (void) signal(SIGINT, oldintr); 60426048Sminshall code = -1; 60526048Sminshall return; 60626048Sminshall } 60726048Sminshall if (!runique && errno == EACCES && 60826048Sminshall chmod(local,0600) < 0) { 60926048Sminshall perror(local); 61026048Sminshall (void) signal(SIGINT, oldintr); 61126048Sminshall code = -1; 61226048Sminshall return; 61326048Sminshall } 61426048Sminshall if (runique && errno == EACCES && 61526048Sminshall (local = gunique(local)) == NULL) { 61626048Sminshall (void) signal(SIGINT, oldintr); 61726048Sminshall code = -1; 61826048Sminshall return; 61926048Sminshall } 62010296Ssam } 62126048Sminshall else if (runique && (local = gunique(local)) == NULL) { 62226048Sminshall (void) signal(SIGINT, oldintr); 62326048Sminshall code = -1; 62426048Sminshall return; 62526048Sminshall } 62626048Sminshall } 62726048Sminshall if (initconn()) { 62826048Sminshall (void) signal(SIGINT, oldintr); 62926048Sminshall code = -1; 63026048Sminshall return; 63126048Sminshall } 63226448Slepreau if (setjmp(recvabort)) 63326048Sminshall goto abort; 63426048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 63526048Sminshall oldtype = type; 63626048Sminshall oldverbose = verbose; 63726448Slepreau if (!debug) 63826048Sminshall verbose = 0; 63926048Sminshall setascii(); 64026048Sminshall verbose = oldverbose; 64126048Sminshall } 64210296Ssam if (remote) { 64326048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 64426048Sminshall (void) signal(SIGINT, oldintr); 64526048Sminshall if (oldtype) { 64626448Slepreau if (!debug) 64726048Sminshall verbose = 0; 64826048Sminshall switch (oldtype) { 64926048Sminshall case TYPE_I: 65026048Sminshall setbinary(); 65126048Sminshall break; 65226048Sminshall case TYPE_E: 65326048Sminshall setebcdic(); 65426048Sminshall break; 65526048Sminshall case TYPE_L: 65626048Sminshall settenex(); 65726048Sminshall break; 65826048Sminshall } 65926048Sminshall verbose = oldverbose; 66026048Sminshall } 66126048Sminshall return; 66226048Sminshall } 66326048Sminshall } else { 66426048Sminshall if (command("%s", cmd) != 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 } 68526048Sminshall din = dataconn("r"); 68626048Sminshall if (din == NULL) 68726048Sminshall goto abort; 68826448Slepreau if (strcmp(local, "-") == 0) 68910296Ssam fout = stdout; 69010296Ssam else if (*local == '|') { 69126048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 69226496Sminshall fout = mypopen(local + 1, "w"); 69326048Sminshall if (fout == NULL) { 69426048Sminshall perror(local+1); 69526048Sminshall goto abort; 69626048Sminshall } 69726496Sminshall closefunc = mypclose; 69826048Sminshall } 69926048Sminshall else { 70011651Ssam fout = fopen(local, mode); 70126048Sminshall if (fout == NULL) { 70226048Sminshall perror(local); 70326048Sminshall goto abort; 70426048Sminshall } 70510296Ssam closefunc = fclose; 70610296Ssam } 70726496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 70811219Ssam switch (type) { 70911219Ssam 71011219Ssam case TYPE_I: 71111219Ssam case TYPE_L: 71211346Ssam errno = d = 0; 71311219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 71411346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 71511219Ssam break; 71611219Ssam bytes += c; 71711651Ssam if (hash) { 71826496Sminshall (void) putchar('#'); 71926496Sminshall (void) fflush(stdout); 72011651Ssam } 72111219Ssam } 72213213Ssam if (hash && bytes > 0) { 72326496Sminshall (void) putchar('\n'); 72426496Sminshall (void) fflush(stdout); 72511651Ssam } 72611219Ssam if (c < 0) 72711219Ssam perror("netin"); 72811346Ssam if (d < 0) 72910296Ssam perror(local); 73011219Ssam break; 73111219Ssam 73211219Ssam case TYPE_A: 73311219Ssam while ((c = getc(din)) != EOF) { 73411219Ssam if (c == '\r') { 73511651Ssam while (hash && (bytes >= hashbytes)) { 73626496Sminshall (void) putchar('#'); 73726496Sminshall (void) fflush(stdout); 73811651Ssam hashbytes += sizeof (buf); 73911651Ssam } 74010296Ssam bytes++; 74126048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 74211219Ssam if (ferror (fout)) 74311219Ssam break; 74426496Sminshall (void) putc ('\r', fout); 74511219Ssam } 74626048Sminshall /*if (c == '\0') { 74711219Ssam bytes++; 74811219Ssam continue; 74926048Sminshall }*/ 75011219Ssam } 75126496Sminshall (void) putc (c, fout); 75211219Ssam bytes++; 75310296Ssam } 75411651Ssam if (hash) { 75513213Ssam if (bytes < hashbytes) 75626496Sminshall (void) putchar('#'); 75726496Sminshall (void) putchar('\n'); 75826496Sminshall (void) fflush(stdout); 75911651Ssam } 76011219Ssam if (ferror (din)) 76111219Ssam perror ("netin"); 76211219Ssam if (ferror (fout)) 76311219Ssam perror (local); 76411219Ssam break; 76510296Ssam } 76626448Slepreau if (closefunc != NULL) 76726048Sminshall (*closefunc)(fout); 76826496Sminshall (void) signal(SIGINT, oldintr); 76926448Slepreau if (oldintp) 77026048Sminshall (void) signal(SIGPIPE, oldintp); 77126496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 77210296Ssam (void) fclose(din); 77326048Sminshall (void) getreply(0); 77426048Sminshall if (bytes > 0 && verbose) 77526048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 77626048Sminshall if (oldtype) { 77726448Slepreau if (!debug) 77826048Sminshall verbose = 0; 77926048Sminshall switch (oldtype) { 78026048Sminshall case TYPE_I: 78126048Sminshall setbinary(); 78226048Sminshall break; 78326048Sminshall case TYPE_E: 78426048Sminshall setebcdic(); 78526048Sminshall break; 78626048Sminshall case TYPE_L: 78726048Sminshall settenex(); 78826048Sminshall break; 78926048Sminshall } 79026048Sminshall verbose = oldverbose; 79126048Sminshall } 79226048Sminshall return; 79326048Sminshall abort: 79426048Sminshall 79526048Sminshall /* if server command parser understands TELNET commands, abort using */ 79626048Sminshall /* recommended IP,SYNC sequence */ 79726048Sminshall 79826496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 79926448Slepreau if (oldintp) 80026048Sminshall (void) signal(SIGPIPE, oldintr); 80126048Sminshall (void) signal(SIGINT,SIG_IGN); 80226048Sminshall if (oldtype) { 80326448Slepreau if (!debug) 80426048Sminshall verbose = 0; 80526048Sminshall switch (oldtype) { 80626048Sminshall case TYPE_I: 80726048Sminshall setbinary(); 80826048Sminshall break; 80926048Sminshall case TYPE_E: 81026048Sminshall setebcdic(); 81126048Sminshall break; 81226048Sminshall case TYPE_L: 81326048Sminshall settenex(); 81426048Sminshall break; 81526048Sminshall } 81626048Sminshall verbose = oldverbose; 81726048Sminshall } 81826048Sminshall if (!cpend) { 81926048Sminshall code = -1; 82026048Sminshall (void) signal(SIGINT,oldintr); 82126048Sminshall return; 82226048Sminshall } 82326048Sminshall if (telflag) { 82426048Sminshall char msg[2]; 82526048Sminshall 82626048Sminshall fprintf(cout,"%c%c",IAC,IP); 82726048Sminshall (void) fflush(cout); 82826048Sminshall *msg = IAC; 82926048Sminshall *(msg+1) = DM; 83026448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 83126048Sminshall perror("abort"); 83226048Sminshall } 83326048Sminshall fprintf(cout,"ABOR\r\n"); 83426048Sminshall (void) fflush(cout); 83526496Sminshall FD_ZERO((char *) &mask); 83626496Sminshall FD_SET(fileno(cin), &mask); 83726496Sminshall if (din) { 83826496Sminshall FD_SET(fileno(din), &mask); 83926496Sminshall } 84026496Sminshall if (empty(mask,10) < 0) { 84126048Sminshall perror("abort"); 84226048Sminshall code = -1; 84326048Sminshall lostpeer(); 84426048Sminshall } 84526496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 84626448Slepreau while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 84726448Slepreau ; 84826496Sminshall } 84926048Sminshall if ((c = getreply(0)) == ERROR) { /* needed for nic style abort */ 85026048Sminshall if (data >= 0) { 85126496Sminshall (void) close(data); 85226048Sminshall data = -1; 85326048Sminshall } 85425907Smckusick (void) getreply(0); 85525907Smckusick } 85626048Sminshall (void) getreply(0); 85726048Sminshall code = -1; 85826048Sminshall if (data >= 0) { 85926048Sminshall (void) close(data); 86026048Sminshall data = -1; 86126048Sminshall } 86226448Slepreau if (closefunc != NULL && fout != NULL) 86326048Sminshall (*closefunc)(fout); 86426448Slepreau if (din) 86526048Sminshall (void) fclose(din); 86610296Ssam if (bytes > 0 && verbose) 86726048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 86826048Sminshall (void) signal(SIGINT,oldintr); 86910296Ssam } 87010296Ssam 87110296Ssam /* 87210296Ssam * Need to start a listen on the data channel 87310296Ssam * before we send the command, otherwise the 87410296Ssam * server's connect may fail. 87510296Ssam */ 87611651Ssam static int sendport = -1; 87711651Ssam 87810296Ssam initconn() 87910296Ssam { 88010296Ssam register char *p, *a; 88126048Sminshall int result, len, tmpno = 0; 882*26993Skarels int on = 1; 88310296Ssam 88411651Ssam noport: 88510296Ssam data_addr = myctladdr; 88611651Ssam if (sendport) 88711651Ssam data_addr.sin_port = 0; /* let system pick one */ 88811651Ssam if (data != -1) 88911651Ssam (void) close (data); 89018287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 89110296Ssam if (data < 0) { 89210296Ssam perror("ftp: socket"); 89326448Slepreau if (tmpno) 89426048Sminshall sendport = 1; 89510296Ssam return (1); 89610296Ssam } 89712397Ssam if (!sendport) 89817450Slepreau if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { 89926048Sminshall perror("ftp: setsockopt (resuse address)"); 90012397Ssam goto bad; 90112397Ssam } 90226496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 90310296Ssam perror("ftp: bind"); 90410296Ssam goto bad; 90510296Ssam } 90610296Ssam if (options & SO_DEBUG && 90717450Slepreau setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 90810296Ssam perror("ftp: setsockopt (ignored)"); 90911627Ssam len = sizeof (data_addr); 91011627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 91111627Ssam perror("ftp: getsockname"); 91210296Ssam goto bad; 91310296Ssam } 91426448Slepreau if (listen(data, 1) < 0) 91510296Ssam perror("ftp: listen"); 91611651Ssam if (sendport) { 91711651Ssam a = (char *)&data_addr.sin_addr; 91811651Ssam p = (char *)&data_addr.sin_port; 91910296Ssam #define UC(b) (((int)b)&0xff) 92011651Ssam result = 92111651Ssam command("PORT %d,%d,%d,%d,%d,%d", 92211651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 92311651Ssam UC(p[0]), UC(p[1])); 92411651Ssam if (result == ERROR && sendport == -1) { 92511651Ssam sendport = 0; 92626048Sminshall tmpno = 1; 92711651Ssam goto noport; 92811651Ssam } 92911651Ssam return (result != COMPLETE); 93011651Ssam } 93126448Slepreau if (tmpno) 93226048Sminshall sendport = 1; 93311651Ssam return (0); 93410296Ssam bad: 93510296Ssam (void) close(data), data = -1; 93626448Slepreau if (tmpno) 93726048Sminshall sendport = 1; 93810296Ssam return (1); 93910296Ssam } 94010296Ssam 94110296Ssam FILE * 94210296Ssam dataconn(mode) 94310296Ssam char *mode; 94410296Ssam { 94510296Ssam struct sockaddr_in from; 94610296Ssam int s, fromlen = sizeof (from); 94710296Ssam 94826496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 94910296Ssam if (s < 0) { 95010296Ssam perror("ftp: accept"); 95110296Ssam (void) close(data), data = -1; 95210296Ssam return (NULL); 95310296Ssam } 95410296Ssam (void) close(data); 95510296Ssam data = s; 95610296Ssam return (fdopen(data, mode)); 95710296Ssam } 95810296Ssam 95926048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 96026048Sminshall char *direction, *local, *remote; 96111651Ssam long bytes; 96210296Ssam struct timeval *t0, *t1; 96310296Ssam { 96410296Ssam struct timeval td; 96516437Sleres float s, bs; 96610296Ssam 96710296Ssam tvsub(&td, t1, t0); 96816437Sleres s = td.tv_sec + (td.tv_usec / 1000000.); 96910296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 97016437Sleres bs = bytes / nz(s); 97126448Slepreau if (local && *local != '-') 97226048Sminshall printf("local: %s ", local); 97326448Slepreau if (remote) 97426048Sminshall printf("remote: %s\n", remote); 97516437Sleres printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 97616437Sleres bytes, direction, s, bs / 1024.); 97710296Ssam } 97810296Ssam 97926496Sminshall /*tvadd(tsum, t0) 98010296Ssam struct timeval *tsum, *t0; 98110296Ssam { 98210296Ssam 98310296Ssam tsum->tv_sec += t0->tv_sec; 98410296Ssam tsum->tv_usec += t0->tv_usec; 98510296Ssam if (tsum->tv_usec > 1000000) 98610296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 98726496Sminshall } */ 98810296Ssam 98910296Ssam tvsub(tdiff, t1, t0) 99010296Ssam struct timeval *tdiff, *t1, *t0; 99110296Ssam { 99210296Ssam 99310296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 99410296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 99510296Ssam if (tdiff->tv_usec < 0) 99610296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 99710296Ssam } 99826048Sminshall 99926048Sminshall psabort() 100026048Sminshall { 100126048Sminshall extern int abrtflag; 100226048Sminshall 100326048Sminshall abrtflag++; 100426048Sminshall } 100526048Sminshall 100626048Sminshall pswitch(flag) 100726048Sminshall int flag; 100826048Sminshall { 100926048Sminshall extern int proxy, abrtflag; 101026048Sminshall int (*oldintr)(); 101126048Sminshall static struct comvars { 101226048Sminshall int connect; 101326048Sminshall char name[32]; 101426048Sminshall struct sockaddr_in mctl; 101526048Sminshall struct sockaddr_in hctl; 101626048Sminshall FILE *in; 101726048Sminshall FILE *out; 101826048Sminshall int tflag; 101926048Sminshall int tpe; 102026048Sminshall int cpnd; 102126048Sminshall int sunqe; 102226048Sminshall int runqe; 102326048Sminshall int mcse; 102426048Sminshall int ntflg; 102526048Sminshall char nti[17]; 102626048Sminshall char nto[17]; 102726048Sminshall int mapflg; 102826048Sminshall char mi[MAXPATHLEN]; 102926048Sminshall char mo[MAXPATHLEN]; 103026048Sminshall } proxstruct, tmpstruct; 103126048Sminshall struct comvars *ip, *op; 103226048Sminshall 103326048Sminshall abrtflag = 0; 103426048Sminshall oldintr = signal(SIGINT, psabort); 103526048Sminshall if (flag) { 103626448Slepreau if (proxy) 103726048Sminshall return; 103826048Sminshall ip = &tmpstruct; 103926048Sminshall op = &proxstruct; 104026048Sminshall proxy++; 104126048Sminshall } 104226048Sminshall else { 104326448Slepreau if (!proxy) 104426048Sminshall return; 104526048Sminshall ip = &proxstruct; 104626048Sminshall op = &tmpstruct; 104726048Sminshall proxy = 0; 104826048Sminshall } 104926048Sminshall ip->connect = connected; 105026048Sminshall connected = op->connect; 105126496Sminshall (void) strncpy(ip->name, hostname, 31); 105226048Sminshall (ip->name)[strlen(ip->name)] = '\0'; 105326048Sminshall hostname = op->name; 105426048Sminshall ip->hctl = hisctladdr; 105526048Sminshall hisctladdr = op->hctl; 105626048Sminshall ip->mctl = myctladdr; 105726048Sminshall myctladdr = op->mctl; 105826048Sminshall ip->in = cin; 105926048Sminshall cin = op->in; 106026048Sminshall ip->out = cout; 106126048Sminshall cout = op->out; 106226048Sminshall ip->tflag = telflag; 106326048Sminshall telflag = op->tflag; 106426048Sminshall ip->tpe = type; 106526048Sminshall type = op->tpe; 106626448Slepreau if (!type) 106726048Sminshall type = 1; 106826048Sminshall ip->cpnd = cpend; 106926048Sminshall cpend = op->cpnd; 107026048Sminshall ip->sunqe = sunique; 107126048Sminshall sunique = op->sunqe; 107226048Sminshall ip->runqe = runique; 107326048Sminshall runique = op->runqe; 107426048Sminshall ip->mcse = mcase; 107526048Sminshall mcase = op->mcse; 107626048Sminshall ip->ntflg = ntflag; 107726048Sminshall ntflag = op->ntflg; 107826496Sminshall (void) strncpy(ip->nti, ntin, 16); 107926048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 108026496Sminshall (void) strcpy(ntin, op->nti); 108126496Sminshall (void) strncpy(ip->nto, ntout, 16); 108226048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 108326496Sminshall (void) strcpy(ntout, op->nto); 108426048Sminshall ip->mapflg = mapflag; 108526048Sminshall mapflag = op->mapflg; 108626496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 108726048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 108826496Sminshall (void) strcpy(mapin, op->mi); 108926496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 109026048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 109126496Sminshall (void) strcpy(mapout, op->mo); 109226048Sminshall (void) signal(SIGINT, oldintr); 109326048Sminshall if (abrtflag) { 109426048Sminshall abrtflag = 0; 109526048Sminshall (*oldintr)(); 109626448Slepreau } 109726048Sminshall } 109826048Sminshall 109926048Sminshall jmp_buf ptabort; 110026048Sminshall int ptabflg; 110126048Sminshall 110226048Sminshall abortpt() 110326048Sminshall { 110426048Sminshall printf("\n"); 110526496Sminshall (void) fflush(stdout); 110626048Sminshall ptabflg++; 110726048Sminshall mflag = 0; 110826048Sminshall abrtflag = 0; 110926048Sminshall longjmp(ptabort, 1); 111026048Sminshall } 111126048Sminshall 111226048Sminshall proxtrans(cmd, local, remote) 111326048Sminshall char *cmd, *local, *remote; 111426048Sminshall { 111526048Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0; 111626048Sminshall extern jmp_buf ptabort; 111726048Sminshall char *cmd2; 111826496Sminshall struct fd_set mask; 111926048Sminshall 112026448Slepreau if (strcmp(cmd, "RETR")) 112126048Sminshall cmd2 = "RETR"; 112226448Slepreau else 112326048Sminshall cmd2 = runique ? "STOU" : "STOR"; 112426048Sminshall if (command("PASV") != COMPLETE) { 112526048Sminshall printf("proxy server does not support third part transfers.\n"); 112626048Sminshall return; 112726048Sminshall } 112826048Sminshall tmptype = type; 112926048Sminshall pswitch(0); 113026048Sminshall if (!connected) { 113126048Sminshall printf("No primary connection\n"); 113226048Sminshall pswitch(1); 113326048Sminshall code = -1; 113426048Sminshall return; 113526048Sminshall } 113626048Sminshall if (type != tmptype) { 113726048Sminshall oldtype = type; 113826048Sminshall switch (tmptype) { 113926048Sminshall case TYPE_A: 114026048Sminshall setascii(); 114126048Sminshall break; 114226048Sminshall case TYPE_I: 114326048Sminshall setbinary(); 114426048Sminshall break; 114526048Sminshall case TYPE_E: 114626048Sminshall setebcdic(); 114726048Sminshall break; 114826048Sminshall case TYPE_L: 114926048Sminshall settenex(); 115026048Sminshall break; 115126048Sminshall } 115226048Sminshall } 115326048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 115426048Sminshall switch (oldtype) { 115526048Sminshall case 0: 115626048Sminshall break; 115726048Sminshall case TYPE_A: 115826048Sminshall setascii(); 115926048Sminshall break; 116026048Sminshall case TYPE_I: 116126048Sminshall setbinary(); 116226048Sminshall break; 116326048Sminshall case TYPE_E: 116426048Sminshall setebcdic(); 116526048Sminshall break; 116626048Sminshall case TYPE_L: 116726048Sminshall settenex(); 116826048Sminshall break; 116926048Sminshall } 117026048Sminshall pswitch(1); 117126048Sminshall return; 117226048Sminshall } 117326448Slepreau if (setjmp(ptabort)) 117426048Sminshall goto abort; 117526048Sminshall oldintr = signal(SIGINT, abortpt); 117626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 117726048Sminshall (void) signal(SIGINT, oldintr); 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 } 119726048Sminshall sleep(2); 119826048Sminshall pswitch(1); 119926048Sminshall secndflag++; 120026448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 120126048Sminshall goto abort; 120226048Sminshall ptflag++; 120326048Sminshall (void) getreply(0); 120426048Sminshall pswitch(0); 120526048Sminshall (void) getreply(0); 120626048Sminshall (void) signal(SIGINT, oldintr); 120726048Sminshall switch (oldtype) { 120826048Sminshall case 0: 120926048Sminshall break; 121026048Sminshall case TYPE_A: 121126048Sminshall setascii(); 121226048Sminshall break; 121326048Sminshall case TYPE_I: 121426048Sminshall setbinary(); 121526048Sminshall break; 121626048Sminshall case TYPE_E: 121726048Sminshall setebcdic(); 121826048Sminshall break; 121926048Sminshall case TYPE_L: 122026048Sminshall settenex(); 122126048Sminshall break; 122226048Sminshall } 122326048Sminshall pswitch(1); 122426048Sminshall ptflag = 0; 122526048Sminshall printf("local: %s remote: %s\n", local, remote); 122626048Sminshall return; 122726048Sminshall abort: 122826048Sminshall (void) signal(SIGINT, SIG_IGN); 122926048Sminshall ptflag = 0; 123026448Slepreau if (strcmp(cmd, "RETR") && !proxy) 123126048Sminshall pswitch(1); 123226448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 123326048Sminshall pswitch(0); 123426048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 123526048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 123626048Sminshall pswitch(0); 123726048Sminshall switch (oldtype) { 123826048Sminshall case 0: 123926048Sminshall break; 124026048Sminshall case TYPE_A: 124126048Sminshall setascii(); 124226048Sminshall break; 124326048Sminshall case TYPE_I: 124426048Sminshall setbinary(); 124526048Sminshall break; 124626048Sminshall case TYPE_E: 124726048Sminshall setebcdic(); 124826048Sminshall break; 124926048Sminshall case TYPE_L: 125026048Sminshall settenex(); 125126048Sminshall break; 125226048Sminshall } 125326048Sminshall if (cpend && telflag) { 125426048Sminshall char msg[2]; 125526048Sminshall 125626048Sminshall fprintf(cout,"%c%c",IAC,IP); 125726048Sminshall (void) fflush(cout); 125826048Sminshall *msg = IAC; 125926048Sminshall *(msg+1) = DM; 126026448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 126126048Sminshall perror("abort"); 126226048Sminshall } 126326048Sminshall if (cpend) { 126426048Sminshall fprintf(cout,"ABOR\r\n"); 126526048Sminshall (void) fflush(cout); 126626496Sminshall FD_ZERO((char *) &mask); 126726496Sminshall FD_SET(fileno(cin), &mask); 126826496Sminshall if (empty(mask,10) < 0) { 126926048Sminshall perror("abort"); 127026448Slepreau if (ptabflg) 127126048Sminshall code = -1; 127226048Sminshall lostpeer(); 127326048Sminshall } 127426048Sminshall (void) getreply(0); 127526048Sminshall (void) getreply(0); 127626048Sminshall } 127726048Sminshall } 127826048Sminshall pswitch(1); 127926448Slepreau if (ptabflg) 128026048Sminshall code = -1; 128126048Sminshall (void) signal(SIGINT, oldintr); 128226048Sminshall return; 128326048Sminshall } 128426048Sminshall if (cpend && telflag) { 128526048Sminshall char msg[2]; 128626048Sminshall 128726048Sminshall fprintf(cout,"%c%c",IAC,IP); 128826048Sminshall (void) fflush(cout); 128926048Sminshall *msg = IAC; 129026048Sminshall *(msg+1) = DM; 129126448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 129226048Sminshall perror("abort"); 129326048Sminshall } 129426048Sminshall if (cpend) { 129526048Sminshall fprintf(cout,"ABOR\r\n"); 129626048Sminshall (void) fflush(cout); 129726496Sminshall FD_ZERO((char *) &mask); 129826496Sminshall FD_SET(fileno(cin), &mask); 129926496Sminshall if ((empty(mask,10)) < 0) { 130026048Sminshall perror("abort"); 130126448Slepreau if (ptabflg) 130226048Sminshall code = -1; 130326048Sminshall lostpeer(); 130426048Sminshall } 130526048Sminshall (void) getreply(0); 130626048Sminshall (void) getreply(0); 130726048Sminshall } 130826048Sminshall pswitch(!proxy); 130926048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 131026048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 131126048Sminshall pswitch(0); 131226048Sminshall switch (oldtype) { 131326048Sminshall case 0: 131426048Sminshall break; 131526048Sminshall case TYPE_A: 131626048Sminshall setascii(); 131726048Sminshall break; 131826048Sminshall case TYPE_I: 131926048Sminshall setbinary(); 132026048Sminshall break; 132126048Sminshall case TYPE_E: 132226048Sminshall setebcdic(); 132326048Sminshall break; 132426048Sminshall case TYPE_L: 132526048Sminshall settenex(); 132626048Sminshall break; 132726048Sminshall } 132826048Sminshall if (cpend && telflag) { 132926048Sminshall char msg[2]; 133026048Sminshall 133126048Sminshall fprintf(cout,"%c%c",IAC,IP); 133226048Sminshall (void) fflush(cout); 133326048Sminshall *msg = IAC; 133426048Sminshall *(msg+1) = DM; 133526448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 133626048Sminshall perror("abort"); 133726048Sminshall } 133826048Sminshall if (cpend) { 133926048Sminshall fprintf(cout,"ABOR\r\n"); 134026048Sminshall (void) fflush(cout); 134126496Sminshall FD_ZERO((char *) &mask); 134226496Sminshall FD_SET(fileno(cin), &mask); 134326496Sminshall if (empty(mask,10) < 0) { 134426048Sminshall perror("abort"); 134526448Slepreau if (ptabflg) 134626048Sminshall code = -1; 134726048Sminshall lostpeer(); 134826048Sminshall } 134926048Sminshall (void) getreply(0); 135026048Sminshall (void) getreply(0); 135126048Sminshall } 135226048Sminshall pswitch(1); 135326448Slepreau if (ptabflg) 135426048Sminshall code = -1; 135526048Sminshall (void) signal(SIGINT, oldintr); 135626048Sminshall return; 135726048Sminshall } 135826048Sminshall } 135926048Sminshall if (cpend && telflag) { 136026048Sminshall char msg[2]; 136126048Sminshall 136226048Sminshall fprintf(cout,"%c%c",IAC,IP); 136326048Sminshall (void) fflush(cout); 136426048Sminshall *msg = IAC; 136526048Sminshall *(msg+1) = DM; 136626448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 136726048Sminshall perror("abort"); 136826048Sminshall } 136926048Sminshall if (cpend) { 137026048Sminshall fprintf(cout,"ABOR\r\n"); 137126048Sminshall (void) fflush(cout); 137226496Sminshall FD_ZERO((char *) &mask); 137326496Sminshall FD_SET(fileno(cin), &mask); 137426496Sminshall if (empty(mask,10) < 0) { 137526048Sminshall perror("abort"); 137626448Slepreau if (ptabflg) 137726048Sminshall code = -1; 137826048Sminshall lostpeer(); 137926048Sminshall } 138026048Sminshall (void) getreply(0); 138126048Sminshall (void) getreply(0); 138226048Sminshall } 138326048Sminshall pswitch(!proxy); 138426048Sminshall if (cpend) { 138526496Sminshall FD_ZERO((char *) &mask); 138626496Sminshall FD_SET(fileno(cin), &mask); 138726496Sminshall if (empty(mask,10) < 0) { 138826048Sminshall perror("abort"); 138926448Slepreau if (ptabflg) 139026048Sminshall code = -1; 139126048Sminshall lostpeer(); 139226048Sminshall } 139326048Sminshall (void) getreply(0); 139426048Sminshall (void) getreply(0); 139526048Sminshall } 139626448Slepreau if (proxy) 139726048Sminshall pswitch(0); 139826048Sminshall switch (oldtype) { 139926048Sminshall case 0: 140026048Sminshall break; 140126048Sminshall case TYPE_A: 140226048Sminshall setascii(); 140326048Sminshall break; 140426048Sminshall case TYPE_I: 140526048Sminshall setbinary(); 140626048Sminshall break; 140726048Sminshall case TYPE_E: 140826048Sminshall setebcdic(); 140926048Sminshall break; 141026048Sminshall case TYPE_L: 141126048Sminshall settenex(); 141226048Sminshall break; 141326048Sminshall } 141426048Sminshall pswitch(1); 141526448Slepreau if (ptabflg) 141626048Sminshall code = -1; 141726048Sminshall (void) signal(SIGINT, oldintr); 141826048Sminshall } 141926048Sminshall 142026048Sminshall reset() 142126048Sminshall { 142226496Sminshall struct fd_set mask; 142326496Sminshall int nfnd = 1; 142426048Sminshall 142526496Sminshall FD_ZERO((char *) &mask); 142626496Sminshall while (nfnd) { 142726496Sminshall FD_SET(fileno(cin), &mask); 142826496Sminshall if ((nfnd = empty(mask,0)) < 0) { 142926048Sminshall perror("reset"); 143026048Sminshall code = -1; 143126048Sminshall lostpeer(); 143226048Sminshall } 143326496Sminshall else { 143426048Sminshall (void) getreply(0); 143526496Sminshall } 143626048Sminshall } 143726048Sminshall } 143826048Sminshall 143926048Sminshall char * 144026048Sminshall gunique(local) 144126048Sminshall char *local; 144226048Sminshall { 144326048Sminshall static char new[MAXPATHLEN]; 144426048Sminshall char *cp = rindex(local, '/'); 144526048Sminshall int d, count=0; 144626048Sminshall char ext = '1'; 144726048Sminshall 144826448Slepreau if (cp) 144926048Sminshall *cp = '\0'; 145026048Sminshall d = access(cp ? local : ".", 2); 145126448Slepreau if (cp) 145226048Sminshall *cp = '/'; 145326048Sminshall if (d < 0) { 145426048Sminshall perror(local); 145526048Sminshall return((char *) 0); 145626048Sminshall } 145726048Sminshall (void) strcpy(new, local); 145826048Sminshall cp = new + strlen(new); 145926048Sminshall *cp++ = '.'; 146026048Sminshall while (!d) { 146126048Sminshall if (++count == 100) { 146226048Sminshall printf("runique: can't find unique file name.\n"); 146326048Sminshall return((char *) 0); 146426048Sminshall } 146526048Sminshall *cp++ = ext; 146626048Sminshall *cp = '\0'; 146726448Slepreau if (ext == '9') 146826048Sminshall ext = '0'; 146926448Slepreau else 147026048Sminshall ext++; 147126448Slepreau if ((d = access(new, 0)) < 0) 147226048Sminshall break; 147326448Slepreau if (ext != '0') 147426048Sminshall cp--; 147526448Slepreau else if (*(cp - 2) == '.') 147626048Sminshall *(cp - 1) = '1'; 147726048Sminshall else { 147826048Sminshall *(cp - 2) = *(cp - 2) + 1; 147926048Sminshall cp--; 148026048Sminshall } 148126048Sminshall } 148226048Sminshall return(new); 148326048Sminshall } 1484