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*27687Sminshall static char sccsid[] = "@(#)ftp.c 5.12 (Berkeley) 05/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 abrtflag = 0; 3426048Sminshall int ptflag = 0; 3510296Ssam int connected; 3610296Ssam struct sockaddr_in myctladdr; 3726496Sminshall uid_t getuid(); 3810296Ssam 3910296Ssam FILE *cin, *cout; 4010296Ssam FILE *dataconn(); 4110296Ssam 4225904Skarels char * 4310296Ssam hookup(host, port) 4410296Ssam char *host; 4510296Ssam int port; 4610296Ssam { 4725904Skarels register struct hostent *hp = 0; 48*27687Sminshall int s,len; 4925904Skarels static char hostnamebuf[80]; 5010296Ssam 5110296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 5225904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 5325904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 5425904Skarels hisctladdr.sin_family = AF_INET; 5525904Skarels (void) strcpy(hostnamebuf, host); 5626048Sminshall } 5726048Sminshall else { 5825100Sbloom hp = gethostbyname(host); 5925904Skarels if (hp == NULL) { 6025904Skarels printf("%s: unknown host\n", host); 6126048Sminshall code = -1; 6226048Sminshall return((char *) 0); 6325904Skarels } 6425904Skarels hisctladdr.sin_family = hp->h_addrtype; 6525904Skarels bcopy(hp->h_addr_list[0], 6625904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 6725904Skarels (void) strcpy(hostnamebuf, hp->h_name); 6810296Ssam } 6925904Skarels hostname = hostnamebuf; 7025904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 7110296Ssam if (s < 0) { 7210296Ssam perror("ftp: socket"); 7326048Sminshall code = -1; 7410296Ssam return (0); 7510296Ssam } 7610296Ssam hisctladdr.sin_port = port; 7726496Sminshall while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 7825904Skarels if (hp && hp->h_addr_list[1]) { 7925904Skarels int oerrno = errno; 8025904Skarels 8125904Skarels fprintf(stderr, "ftp: connect to address %s: ", 8225904Skarels inet_ntoa(hisctladdr.sin_addr)); 8325904Skarels errno = oerrno; 8426496Sminshall perror((char *) 0); 8525904Skarels hp->h_addr_list++; 8625904Skarels bcopy(hp->h_addr_list[0], 8726048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 8826496Sminshall fprintf(stdout, "Trying %s...\n", 8925904Skarels inet_ntoa(hisctladdr.sin_addr)); 9026813Skarels (void) close(s); 9126813Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 9226813Skarels if (s < 0) { 9326813Skarels perror("ftp: socket"); 9426813Skarels code = -1; 9526813Skarels return (0); 9626813Skarels } 9725904Skarels continue; 9825904Skarels } 9910296Ssam perror("ftp: connect"); 10026048Sminshall code = -1; 10110296Ssam goto bad; 10210296Ssam } 10311627Ssam len = sizeof (myctladdr); 10411627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 10511627Ssam perror("ftp: getsockname"); 10626048Sminshall code = -1; 10710296Ssam goto bad; 10810296Ssam } 10910296Ssam cin = fdopen(s, "r"); 11010296Ssam cout = fdopen(s, "w"); 11111219Ssam if (cin == NULL || cout == NULL) { 11210296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 11310296Ssam if (cin) 11426496Sminshall (void) fclose(cin); 11510296Ssam if (cout) 11626496Sminshall (void) fclose(cout); 11726048Sminshall code = -1; 11810296Ssam goto bad; 11910296Ssam } 12010296Ssam if (verbose) 12126067Sminshall printf("Connected to %s.\n", hostname); 122*27687Sminshall if (getreply(0) > 2) { /* read startup message from server */ 12326048Sminshall if (cin) 12426496Sminshall (void) fclose(cin); 12526048Sminshall if (cout) 12626496Sminshall (void) fclose(cout); 12726048Sminshall code = -1; 12826048Sminshall goto bad; 12926048Sminshall } 130*27687Sminshall #ifdef SO_OOBINLINE 131*27687Sminshall { 132*27687Sminshall int on = 1; 13326048Sminshall 134*27687Sminshall if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) 135*27687Sminshall < 0 && debug) { 136*27687Sminshall perror("ftp: setsockopt"); 137*27687Sminshall } 138*27687Sminshall } 139*27687Sminshall #endif SO_OOBINLINE 14026048Sminshall 14125904Skarels return (hostname); 14210296Ssam bad: 14326496Sminshall (void) close(s); 14425904Skarels return ((char *)0); 14510296Ssam } 14610296Ssam 14725904Skarels login(host) 14825904Skarels char *host; 14910296Ssam { 15026048Sminshall char tmp[80]; 15126496Sminshall char *user, *pass, *acct, *getlogin(), *mygetpass(); 15226048Sminshall int n, aflag = 0; 15310296Ssam 15426048Sminshall user = pass = acct = 0; 15526048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 15626048Sminshall disconnect(); 15726048Sminshall code = -1; 15826048Sminshall return(0); 15926048Sminshall } 16026048Sminshall if (user == NULL) { 16126048Sminshall char *myname = getlogin(); 16226048Sminshall 16326048Sminshall if (myname == NULL) { 16426048Sminshall struct passwd *pp = getpwuid(getuid()); 16526048Sminshall 16626448Slepreau if (pp != NULL) 16726048Sminshall myname = pp->pw_name; 16826048Sminshall } 16926048Sminshall printf("Name (%s:%s): ", host, myname); 17026048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 17126048Sminshall tmp[strlen(tmp) - 1] = '\0'; 17226448Slepreau if (*tmp == '\0') 17326048Sminshall user = myname; 17426448Slepreau else 17526048Sminshall user = tmp; 17626048Sminshall } 17710296Ssam n = command("USER %s", user); 17826048Sminshall if (n == CONTINUE) { 17926448Slepreau if (pass == NULL) 18026496Sminshall pass = mygetpass("Password:"); 18110296Ssam n = command("PASS %s", pass); 18226048Sminshall } 18310296Ssam if (n == CONTINUE) { 18426048Sminshall aflag++; 18526496Sminshall acct = mygetpass("Account:"); 18610296Ssam n = command("ACCT %s", acct); 18710296Ssam } 18810296Ssam if (n != COMPLETE) { 18910296Ssam fprintf(stderr, "Login failed.\n"); 19010296Ssam return (0); 19110296Ssam } 19226448Slepreau if (!aflag && acct != NULL) 19326048Sminshall (void) command("ACCT %s", acct); 19426448Slepreau if (proxy) 19526048Sminshall return(1); 19626048Sminshall for (n = 0; n < macnum; ++n) { 19726048Sminshall if (!strcmp("init", macros[n].mac_name)) { 19826496Sminshall (void) strcpy(line, "$init"); 19926048Sminshall makeargv(); 20026048Sminshall domacro(margc, margv); 20126048Sminshall break; 20226048Sminshall } 20326048Sminshall } 20410296Ssam return (1); 20510296Ssam } 20610296Ssam 20726048Sminshall cmdabort() 20826048Sminshall { 20926048Sminshall extern jmp_buf ptabort; 21026048Sminshall 21126048Sminshall printf("\n"); 21226048Sminshall (void) fflush(stdout); 21326048Sminshall abrtflag++; 21426448Slepreau if (ptflag) 21526048Sminshall longjmp(ptabort,1); 21626048Sminshall } 21726048Sminshall 21826496Sminshall /*VARARGS1*/ 21910296Ssam command(fmt, args) 22010296Ssam char *fmt; 22110296Ssam { 22226048Sminshall int r, (*oldintr)(), cmdabort(); 22310296Ssam 22426048Sminshall abrtflag = 0; 22510296Ssam if (debug) { 22610296Ssam printf("---> "); 22710296Ssam _doprnt(fmt, &args, stdout); 22810296Ssam printf("\n"); 22910296Ssam (void) fflush(stdout); 23010296Ssam } 23111219Ssam if (cout == NULL) { 23211219Ssam perror ("No control connection for command"); 23326048Sminshall code = -1; 23411219Ssam return (0); 23511219Ssam } 23626048Sminshall oldintr = signal(SIGINT,cmdabort); 23710296Ssam _doprnt(fmt, &args, cout); 23810296Ssam fprintf(cout, "\r\n"); 23910296Ssam (void) fflush(cout); 24026048Sminshall cpend = 1; 24126048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 24226448Slepreau if (abrtflag && oldintr != SIG_IGN) 24326048Sminshall (*oldintr)(); 24426048Sminshall (void) signal(SIGINT, oldintr); 24526048Sminshall return(r); 24610296Ssam } 24710296Ssam 24810296Ssam #include <ctype.h> 24910296Ssam 25010296Ssam getreply(expecteof) 25110296Ssam int expecteof; 25210296Ssam { 25311219Ssam register int c, n; 25426048Sminshall register int dig; 25526048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 25626048Sminshall int pflag = 0; 25726048Sminshall char *pt = pasv; 25810296Ssam 25926048Sminshall oldintr = signal(SIGINT,cmdabort); 26010296Ssam for (;;) { 26110296Ssam dig = n = code = 0; 26210296Ssam while ((c = getc(cin)) != '\n') { 263*27687Sminshall if (c == IAC) { /* handle telnet commands */ 264*27687Sminshall switch (c = getc(cin)) { 265*27687Sminshall case WILL: 266*27687Sminshall case WONT: 267*27687Sminshall c = getc(cin); 268*27687Sminshall fprintf(cout, "%c%c%c",IAC,WONT,c); 269*27687Sminshall (void) fflush(cout); 270*27687Sminshall break; 271*27687Sminshall case DO: 272*27687Sminshall case DONT: 273*27687Sminshall c = getc(cin); 274*27687Sminshall fprintf(cout, "%c%c%c",IAC,DONT,c); 275*27687Sminshall (void) fflush(cout); 276*27687Sminshall break; 277*27687Sminshall default: 278*27687Sminshall break; 279*27687Sminshall } 280*27687Sminshall continue; 281*27687Sminshall } 28210296Ssam dig++; 28310296Ssam if (c == EOF) { 28426048Sminshall if (expecteof) { 28526048Sminshall (void) signal(SIGINT,oldintr); 28626048Sminshall code = 221; 28710296Ssam return (0); 28826048Sminshall } 28910296Ssam lostpeer(); 29026048Sminshall if (verbose) { 29126048Sminshall printf("421 Service not available, remote server has closed connection\n"); 29226048Sminshall (void) fflush(stdout); 29326048Sminshall code = 421; 29426048Sminshall return(4); 29526048Sminshall } 29610296Ssam } 29726048Sminshall if (c != '\r' && (verbose > 0 || 29826048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 29926448Slepreau if (proxflag && 30026448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 30126048Sminshall printf("%s:",hostname); 30226496Sminshall (void) putchar(c); 30326048Sminshall } 30410296Ssam if (dig < 4 && isdigit(c)) 30510296Ssam code = code * 10 + (c - '0'); 30626448Slepreau if (!pflag && code == 227) 30726048Sminshall pflag = 1; 30826448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 30926048Sminshall pflag = 2; 31026048Sminshall if (pflag == 2) { 31126448Slepreau if (c != '\r' && c != ')') 31226048Sminshall *pt++ = c; 31326048Sminshall else { 31426048Sminshall *pt = '\0'; 31526048Sminshall pflag = 3; 31626048Sminshall } 31726048Sminshall } 31826048Sminshall if (dig == 4 && c == '-') { 31926448Slepreau if (continuation) 32026048Sminshall code = 0; 32110296Ssam continuation++; 32226048Sminshall } 32310296Ssam if (n == 0) 32410296Ssam n = c; 32510296Ssam } 32626048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 32726496Sminshall (void) putchar(c); 32811346Ssam (void) fflush (stdout); 32911346Ssam } 33010296Ssam if (continuation && code != originalcode) { 33110296Ssam if (originalcode == 0) 33210296Ssam originalcode = code; 33310296Ssam continue; 33410296Ssam } 33526448Slepreau if (n != '1') 33626048Sminshall cpend = 0; 33726048Sminshall (void) signal(SIGINT,oldintr); 33826448Slepreau if (code == 421 || originalcode == 421) 33926048Sminshall lostpeer(); 34026448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 34126048Sminshall (*oldintr)(); 34225907Smckusick return (n - '0'); 34310296Ssam } 34410296Ssam } 34510296Ssam 34626048Sminshall empty(mask, sec) 347*27687Sminshall struct fd_set *mask; 34826048Sminshall int sec; 34926048Sminshall { 35026048Sminshall struct timeval t; 35126048Sminshall 35226048Sminshall t.tv_sec = (long) sec; 35326048Sminshall t.tv_usec = 0; 354*27687Sminshall return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); 35526048Sminshall } 35626048Sminshall 35710296Ssam jmp_buf sendabort; 35810296Ssam 35910296Ssam abortsend() 36010296Ssam { 36110296Ssam 36226048Sminshall mflag = 0; 36326048Sminshall abrtflag = 0; 36426048Sminshall printf("\nsend aborted\n"); 36526048Sminshall (void) fflush(stdout); 36610296Ssam longjmp(sendabort, 1); 36710296Ssam } 36810296Ssam 36910296Ssam sendrequest(cmd, local, remote) 37010296Ssam char *cmd, *local, *remote; 37110296Ssam { 37226496Sminshall FILE *fin, *dout = 0, *mypopen(); 37326496Sminshall int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 37426048Sminshall int abortsend(); 37511219Ssam char buf[BUFSIZ]; 37611651Ssam long bytes = 0, hashbytes = sizeof (buf); 37711346Ssam register int c, d; 37810296Ssam struct stat st; 37910296Ssam struct timeval start, stop; 38010296Ssam 38126048Sminshall if (proxy) { 38226048Sminshall proxtrans(cmd, local, remote); 38326048Sminshall return; 38426048Sminshall } 38510296Ssam closefunc = NULL; 38626048Sminshall oldintr = NULL; 38726048Sminshall oldintp = NULL; 38826048Sminshall if (setjmp(sendabort)) { 38926048Sminshall while (cpend) { 39026048Sminshall (void) getreply(0); 39126048Sminshall } 39226048Sminshall if (data >= 0) { 39326048Sminshall (void) close(data); 39426048Sminshall data = -1; 39526048Sminshall } 39626448Slepreau if (oldintr) 39726048Sminshall (void) signal(SIGINT,oldintr); 39826448Slepreau if (oldintp) 39926048Sminshall (void) signal(SIGPIPE,oldintp); 40026048Sminshall code = -1; 40126048Sminshall return; 40226048Sminshall } 40310296Ssam oldintr = signal(SIGINT, abortsend); 40410296Ssam if (strcmp(local, "-") == 0) 40510296Ssam fin = stdin; 40610296Ssam else if (*local == '|') { 40726048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 40826496Sminshall fin = mypopen(local + 1, "r"); 40910296Ssam if (fin == NULL) { 41026048Sminshall perror(local + 1); 41126048Sminshall (void) signal(SIGINT, oldintr); 41226048Sminshall (void) signal(SIGPIPE, oldintp); 41326048Sminshall code = -1; 41426048Sminshall return; 41510296Ssam } 41626496Sminshall closefunc = mypclose; 41710296Ssam } else { 41810296Ssam fin = fopen(local, "r"); 41910296Ssam if (fin == NULL) { 42010296Ssam perror(local); 42126048Sminshall (void) signal(SIGINT, oldintr); 42226048Sminshall code = -1; 42326048Sminshall return; 42410296Ssam } 42510296Ssam closefunc = fclose; 42610296Ssam if (fstat(fileno(fin), &st) < 0 || 42710296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 42826496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 42926048Sminshall (void) signal(SIGINT, oldintr); 43026048Sminshall code = -1; 43126048Sminshall return; 43210296Ssam } 43310296Ssam } 43426048Sminshall if (initconn()) { 43526048Sminshall (void) signal(SIGINT, oldintr); 43626448Slepreau if (oldintp) 43726048Sminshall (void) signal(SIGPIPE, oldintp); 43826048Sminshall code = -1; 43926048Sminshall return; 44026048Sminshall } 44126448Slepreau if (setjmp(sendabort)) 44226048Sminshall goto abort; 44310296Ssam if (remote) { 44426048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 44526048Sminshall (void) signal(SIGINT, oldintr); 44626448Slepreau if (oldintp) 44726048Sminshall (void) signal(SIGPIPE, oldintp); 44826048Sminshall return; 44926048Sminshall } 45010296Ssam } else 45126048Sminshall if (command("%s", cmd) != PRELIM) { 45226048Sminshall (void) signal(SIGINT, oldintr); 45326448Slepreau if (oldintp) 45426048Sminshall (void) signal(SIGPIPE, oldintp); 45526048Sminshall return; 45626048Sminshall } 45710296Ssam dout = dataconn("w"); 45826448Slepreau if (dout == NULL) 45926048Sminshall goto abort; 46026496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 46111219Ssam switch (type) { 46211219Ssam 46311219Ssam case TYPE_I: 46411219Ssam case TYPE_L: 46511346Ssam errno = d = 0; 46611219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 46711346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 46811219Ssam break; 46911219Ssam bytes += c; 47011651Ssam if (hash) { 47126496Sminshall (void) putchar('#'); 47226496Sminshall (void) fflush(stdout); 47311651Ssam } 47411219Ssam } 47513213Ssam if (hash && bytes > 0) { 47626496Sminshall (void) putchar('\n'); 47726496Sminshall (void) fflush(stdout); 47811651Ssam } 47911219Ssam if (c < 0) 48011219Ssam perror(local); 48111346Ssam if (d < 0) 48211219Ssam perror("netout"); 48311219Ssam break; 48411219Ssam 48511219Ssam case TYPE_A: 48611219Ssam while ((c = getc(fin)) != EOF) { 48711219Ssam if (c == '\n') { 48811651Ssam while (hash && (bytes >= hashbytes)) { 48926496Sminshall (void) putchar('#'); 49026496Sminshall (void) fflush(stdout); 49111651Ssam hashbytes += sizeof (buf); 49211651Ssam } 49311219Ssam if (ferror(dout)) 49411219Ssam break; 49526496Sminshall (void) putc('\r', dout); 49611219Ssam bytes++; 49711219Ssam } 49826496Sminshall (void) putc(c, dout); 49911219Ssam bytes++; 50026048Sminshall /* if (c == '\r') { */ 50126496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 50226048Sminshall /* bytes++; */ 50326048Sminshall /* } */ 50411219Ssam } 50511651Ssam if (hash) { 50613213Ssam if (bytes < hashbytes) 50726496Sminshall (void) putchar('#'); 50826496Sminshall (void) putchar('\n'); 50926496Sminshall (void) fflush(stdout); 51011651Ssam } 51111219Ssam if (ferror(fin)) 51211219Ssam perror(local); 51311346Ssam if (ferror(dout)) 51411219Ssam perror("netout"); 51511219Ssam break; 51610296Ssam } 51726496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 51810296Ssam if (closefunc != NULL) 51926048Sminshall (*closefunc)(fin); 52010296Ssam (void) fclose(dout); 52126048Sminshall (void) getreply(0); 52226048Sminshall (void) signal(SIGINT, oldintr); 52310296Ssam if (bytes > 0 && verbose) 52426048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 52510296Ssam return; 52626048Sminshall abort: 52726496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 52826048Sminshall (void) signal(SIGINT, oldintr); 52926448Slepreau if (oldintp) 53026048Sminshall (void) signal(SIGPIPE, oldintp); 53126048Sminshall if (!cpend) { 53226048Sminshall code = -1; 53326048Sminshall return; 53426048Sminshall } 53526048Sminshall if (data >= 0) { 53626048Sminshall (void) close(data); 53726048Sminshall data = -1; 53826048Sminshall } 53926448Slepreau if (dout) 54026048Sminshall (void) fclose(dout); 54126048Sminshall (void) getreply(0); 54226048Sminshall code = -1; 54310296Ssam if (closefunc != NULL && fin != NULL) 54426048Sminshall (*closefunc)(fin); 54526048Sminshall if (bytes > 0 && verbose) 54626048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 54710296Ssam } 54810296Ssam 54910296Ssam jmp_buf recvabort; 55010296Ssam 55110296Ssam abortrecv() 55210296Ssam { 55310296Ssam 55426048Sminshall mflag = 0; 55526048Sminshall abrtflag = 0; 55626048Sminshall printf("\n"); 55726048Sminshall (void) fflush(stdout); 55810296Ssam longjmp(recvabort, 1); 55910296Ssam } 56010296Ssam 56111651Ssam recvrequest(cmd, local, remote, mode) 56211651Ssam char *cmd, *local, *remote, *mode; 56310296Ssam { 56426496Sminshall FILE *fout, *din = 0, *mypopen(); 56526496Sminshall int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 566*27687Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag, nfnd; 567*27687Sminshall char buf[BUFSIZ], *gunique(), msg; 56826496Sminshall long bytes = 0, hashbytes = sizeof (buf); 56926496Sminshall struct fd_set mask; 57011346Ssam register int c, d; 57110296Ssam struct timeval start, stop; 57210296Ssam 57326048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 57426048Sminshall proxtrans(cmd, local, remote); 57526048Sminshall return; 57626048Sminshall } 57710296Ssam closefunc = NULL; 57826048Sminshall oldintr = NULL; 57926048Sminshall oldintp = NULL; 58026048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 58126048Sminshall if (setjmp(recvabort)) { 58226048Sminshall while (cpend) { 58326048Sminshall (void) getreply(0); 58426048Sminshall } 58526048Sminshall if (data >= 0) { 58626048Sminshall (void) close(data); 58726048Sminshall data = -1; 58826048Sminshall } 58926448Slepreau if (oldintr) 59026048Sminshall (void) signal(SIGINT, oldintr); 59126048Sminshall code = -1; 59226048Sminshall return; 59326048Sminshall } 59410296Ssam oldintr = signal(SIGINT, abortrecv); 59526048Sminshall if (strcmp(local, "-") && *local != '|') { 59610296Ssam if (access(local, 2) < 0) { 59726048Sminshall char *dir = rindex(local, '/'); 59810296Ssam 59926048Sminshall if (errno != ENOENT && errno != EACCES) { 60010296Ssam perror(local); 60126048Sminshall (void) signal(SIGINT, oldintr); 60226048Sminshall code = -1; 60326048Sminshall return; 60410296Ssam } 60526048Sminshall if (dir != NULL) 60626048Sminshall *dir = 0; 60726048Sminshall d = access(dir ? local : ".", 2); 60826048Sminshall if (dir != NULL) 60926048Sminshall *dir = '/'; 61026048Sminshall if (d < 0) { 61126048Sminshall perror(local); 61226048Sminshall (void) signal(SIGINT, oldintr); 61326048Sminshall code = -1; 61426048Sminshall return; 61526048Sminshall } 61626048Sminshall if (!runique && errno == EACCES && 61726048Sminshall chmod(local,0600) < 0) { 61826048Sminshall perror(local); 61926048Sminshall (void) signal(SIGINT, oldintr); 62026048Sminshall code = -1; 62126048Sminshall return; 62226048Sminshall } 62326048Sminshall if (runique && errno == EACCES && 62426048Sminshall (local = gunique(local)) == NULL) { 62526048Sminshall (void) signal(SIGINT, oldintr); 62626048Sminshall code = -1; 62726048Sminshall return; 62826048Sminshall } 62910296Ssam } 63026048Sminshall else if (runique && (local = gunique(local)) == NULL) { 63126048Sminshall (void) signal(SIGINT, oldintr); 63226048Sminshall code = -1; 63326048Sminshall return; 63426048Sminshall } 63526048Sminshall } 63626048Sminshall if (initconn()) { 63726048Sminshall (void) signal(SIGINT, oldintr); 63826048Sminshall code = -1; 63926048Sminshall return; 64026048Sminshall } 64126448Slepreau if (setjmp(recvabort)) 64226048Sminshall goto abort; 64326048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 64426048Sminshall oldtype = type; 64526048Sminshall oldverbose = verbose; 64626448Slepreau if (!debug) 64726048Sminshall verbose = 0; 64826048Sminshall setascii(); 64926048Sminshall verbose = oldverbose; 65026048Sminshall } 65110296Ssam if (remote) { 65226048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 65326048Sminshall (void) signal(SIGINT, oldintr); 65426048Sminshall if (oldtype) { 65526448Slepreau if (!debug) 65626048Sminshall verbose = 0; 65726048Sminshall switch (oldtype) { 65826048Sminshall case TYPE_I: 65926048Sminshall setbinary(); 66026048Sminshall break; 66126048Sminshall case TYPE_E: 66226048Sminshall setebcdic(); 66326048Sminshall break; 66426048Sminshall case TYPE_L: 66526048Sminshall settenex(); 66626048Sminshall break; 66726048Sminshall } 66826048Sminshall verbose = oldverbose; 66926048Sminshall } 67026048Sminshall return; 67126048Sminshall } 67226048Sminshall } else { 67326048Sminshall if (command("%s", cmd) != PRELIM) { 67426048Sminshall (void) signal(SIGINT, oldintr); 67526048Sminshall if (oldtype) { 67626448Slepreau if (!debug) 67726048Sminshall verbose = 0; 67826048Sminshall switch (oldtype) { 67926048Sminshall case TYPE_I: 68026048Sminshall setbinary(); 68126048Sminshall break; 68226048Sminshall case TYPE_E: 68326048Sminshall setebcdic(); 68426048Sminshall break; 68526048Sminshall case TYPE_L: 68626048Sminshall settenex(); 68726048Sminshall break; 68826048Sminshall } 68926048Sminshall verbose = oldverbose; 69026048Sminshall } 69126048Sminshall return; 69226048Sminshall } 69326048Sminshall } 69426048Sminshall din = dataconn("r"); 69526048Sminshall if (din == NULL) 69626048Sminshall goto abort; 69726448Slepreau if (strcmp(local, "-") == 0) 69810296Ssam fout = stdout; 69910296Ssam else if (*local == '|') { 70026048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 70126496Sminshall fout = mypopen(local + 1, "w"); 70226048Sminshall if (fout == NULL) { 70326048Sminshall perror(local+1); 70426048Sminshall goto abort; 70526048Sminshall } 70626496Sminshall closefunc = mypclose; 70726048Sminshall } 70826048Sminshall else { 70911651Ssam fout = fopen(local, mode); 71026048Sminshall if (fout == NULL) { 71126048Sminshall perror(local); 71226048Sminshall goto abort; 71326048Sminshall } 71410296Ssam closefunc = fclose; 71510296Ssam } 71626496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 71711219Ssam switch (type) { 71811219Ssam 71911219Ssam case TYPE_I: 72011219Ssam case TYPE_L: 72111346Ssam errno = d = 0; 72211219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 72311346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 72411219Ssam break; 72511219Ssam bytes += c; 72611651Ssam if (hash) { 72726496Sminshall (void) putchar('#'); 72826496Sminshall (void) fflush(stdout); 72911651Ssam } 73011219Ssam } 73113213Ssam if (hash && bytes > 0) { 73226496Sminshall (void) putchar('\n'); 73326496Sminshall (void) fflush(stdout); 73411651Ssam } 73511219Ssam if (c < 0) 73611219Ssam perror("netin"); 73711346Ssam if (d < 0) 73810296Ssam perror(local); 73911219Ssam break; 74011219Ssam 74111219Ssam case TYPE_A: 74211219Ssam while ((c = getc(din)) != EOF) { 74311219Ssam if (c == '\r') { 74411651Ssam while (hash && (bytes >= hashbytes)) { 74526496Sminshall (void) putchar('#'); 74626496Sminshall (void) fflush(stdout); 74711651Ssam hashbytes += sizeof (buf); 74811651Ssam } 74910296Ssam bytes++; 75026048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 75111219Ssam if (ferror (fout)) 75211219Ssam break; 75326496Sminshall (void) putc ('\r', fout); 75411219Ssam } 75526048Sminshall /*if (c == '\0') { 75611219Ssam bytes++; 75711219Ssam continue; 75826048Sminshall }*/ 75911219Ssam } 76026496Sminshall (void) putc (c, fout); 76111219Ssam bytes++; 76210296Ssam } 76311651Ssam if (hash) { 76413213Ssam if (bytes < hashbytes) 76526496Sminshall (void) putchar('#'); 76626496Sminshall (void) putchar('\n'); 76726496Sminshall (void) fflush(stdout); 76811651Ssam } 76911219Ssam if (ferror (din)) 77011219Ssam perror ("netin"); 77111219Ssam if (ferror (fout)) 77211219Ssam perror (local); 77311219Ssam break; 77410296Ssam } 77526448Slepreau if (closefunc != NULL) 77626048Sminshall (*closefunc)(fout); 77726496Sminshall (void) signal(SIGINT, oldintr); 77826448Slepreau if (oldintp) 77926048Sminshall (void) signal(SIGPIPE, oldintp); 78026496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 78110296Ssam (void) fclose(din); 78226048Sminshall (void) getreply(0); 78326048Sminshall if (bytes > 0 && verbose) 78426048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 78526048Sminshall if (oldtype) { 78626448Slepreau if (!debug) 78726048Sminshall verbose = 0; 78826048Sminshall switch (oldtype) { 78926048Sminshall case TYPE_I: 79026048Sminshall setbinary(); 79126048Sminshall break; 79226048Sminshall case TYPE_E: 79326048Sminshall setebcdic(); 79426048Sminshall break; 79526048Sminshall case TYPE_L: 79626048Sminshall settenex(); 79726048Sminshall break; 79826048Sminshall } 79926048Sminshall verbose = oldverbose; 80026048Sminshall } 80126048Sminshall return; 80226048Sminshall abort: 80326048Sminshall 804*27687Sminshall /* abort using RFC959 recommended IP,SYNC sequence */ 80526048Sminshall 80626496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 80726448Slepreau if (oldintp) 80826048Sminshall (void) signal(SIGPIPE, oldintr); 80926048Sminshall (void) signal(SIGINT,SIG_IGN); 81026048Sminshall if (oldtype) { 81126448Slepreau if (!debug) 81226048Sminshall verbose = 0; 81326048Sminshall switch (oldtype) { 81426048Sminshall case TYPE_I: 81526048Sminshall setbinary(); 81626048Sminshall break; 81726048Sminshall case TYPE_E: 81826048Sminshall setebcdic(); 81926048Sminshall break; 82026048Sminshall case TYPE_L: 82126048Sminshall settenex(); 82226048Sminshall break; 82326048Sminshall } 82426048Sminshall verbose = oldverbose; 82526048Sminshall } 82626048Sminshall if (!cpend) { 82726048Sminshall code = -1; 82826048Sminshall (void) signal(SIGINT,oldintr); 82926048Sminshall return; 83026048Sminshall } 83126048Sminshall 832*27687Sminshall fprintf(cout,"%c%c",IAC,IP); 833*27687Sminshall (void) fflush(cout); 834*27687Sminshall msg = IAC; 835*27687Sminshall /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 836*27687Sminshall /* after urgent byte rather than before as now is protocol */ 837*27687Sminshall if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 838*27687Sminshall perror("abort"); 83926048Sminshall } 840*27687Sminshall fprintf(cout,"%cABOR\r\n",DM); 84126048Sminshall (void) fflush(cout); 842*27687Sminshall FD_ZERO(&mask); 84326496Sminshall FD_SET(fileno(cin), &mask); 84426496Sminshall if (din) { 84526496Sminshall FD_SET(fileno(din), &mask); 84626496Sminshall } 847*27687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 848*27687Sminshall if (nfnd < 0) { 849*27687Sminshall perror("abort"); 850*27687Sminshall } 85126048Sminshall code = -1; 85226048Sminshall lostpeer(); 85326048Sminshall } 85426496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 85526448Slepreau while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 85626448Slepreau ; 85726496Sminshall } 858*27687Sminshall if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 85926048Sminshall if (data >= 0) { 86026496Sminshall (void) close(data); 86126048Sminshall data = -1; 86226048Sminshall } 86325907Smckusick (void) getreply(0); 86425907Smckusick } 86526048Sminshall (void) getreply(0); 86626048Sminshall code = -1; 86726048Sminshall if (data >= 0) { 86826048Sminshall (void) close(data); 86926048Sminshall data = -1; 87026048Sminshall } 87126448Slepreau if (closefunc != NULL && fout != NULL) 87226048Sminshall (*closefunc)(fout); 87326448Slepreau if (din) 87426048Sminshall (void) fclose(din); 87510296Ssam if (bytes > 0 && verbose) 87626048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 87726048Sminshall (void) signal(SIGINT,oldintr); 87810296Ssam } 87910296Ssam 88010296Ssam /* 88110296Ssam * Need to start a listen on the data channel 88210296Ssam * before we send the command, otherwise the 88310296Ssam * server's connect may fail. 88410296Ssam */ 88511651Ssam static int sendport = -1; 88611651Ssam 88710296Ssam initconn() 88810296Ssam { 88910296Ssam register char *p, *a; 89026048Sminshall int result, len, tmpno = 0; 89126993Skarels int on = 1; 89210296Ssam 89311651Ssam noport: 89410296Ssam data_addr = myctladdr; 89511651Ssam if (sendport) 89611651Ssam data_addr.sin_port = 0; /* let system pick one */ 89711651Ssam if (data != -1) 89811651Ssam (void) close (data); 89918287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 90010296Ssam if (data < 0) { 90110296Ssam perror("ftp: socket"); 90226448Slepreau if (tmpno) 90326048Sminshall sendport = 1; 90410296Ssam return (1); 90510296Ssam } 90612397Ssam if (!sendport) 907*27687Sminshall if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 90826048Sminshall perror("ftp: setsockopt (resuse address)"); 90912397Ssam goto bad; 91012397Ssam } 91126496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 91210296Ssam perror("ftp: bind"); 91310296Ssam goto bad; 91410296Ssam } 91510296Ssam if (options & SO_DEBUG && 916*27687Sminshall setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 91710296Ssam perror("ftp: setsockopt (ignored)"); 91811627Ssam len = sizeof (data_addr); 91911627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 92011627Ssam perror("ftp: getsockname"); 92110296Ssam goto bad; 92210296Ssam } 92326448Slepreau if (listen(data, 1) < 0) 92410296Ssam perror("ftp: listen"); 92511651Ssam if (sendport) { 92611651Ssam a = (char *)&data_addr.sin_addr; 92711651Ssam p = (char *)&data_addr.sin_port; 92810296Ssam #define UC(b) (((int)b)&0xff) 92911651Ssam result = 93011651Ssam command("PORT %d,%d,%d,%d,%d,%d", 93111651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 93211651Ssam UC(p[0]), UC(p[1])); 93311651Ssam if (result == ERROR && sendport == -1) { 93411651Ssam sendport = 0; 93526048Sminshall tmpno = 1; 93611651Ssam goto noport; 93711651Ssam } 93811651Ssam return (result != COMPLETE); 93911651Ssam } 94026448Slepreau if (tmpno) 94126048Sminshall sendport = 1; 94211651Ssam return (0); 94310296Ssam bad: 94410296Ssam (void) close(data), data = -1; 94526448Slepreau if (tmpno) 94626048Sminshall sendport = 1; 94710296Ssam return (1); 94810296Ssam } 94910296Ssam 95010296Ssam FILE * 95110296Ssam dataconn(mode) 95210296Ssam char *mode; 95310296Ssam { 95410296Ssam struct sockaddr_in from; 95510296Ssam int s, fromlen = sizeof (from); 95610296Ssam 95726496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 95810296Ssam if (s < 0) { 95910296Ssam perror("ftp: accept"); 96010296Ssam (void) close(data), data = -1; 96110296Ssam return (NULL); 96210296Ssam } 96310296Ssam (void) close(data); 96410296Ssam data = s; 96510296Ssam return (fdopen(data, mode)); 96610296Ssam } 96710296Ssam 96826048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 96926048Sminshall char *direction, *local, *remote; 97011651Ssam long bytes; 97110296Ssam struct timeval *t0, *t1; 97210296Ssam { 97310296Ssam struct timeval td; 97416437Sleres float s, bs; 97510296Ssam 97610296Ssam tvsub(&td, t1, t0); 97716437Sleres s = td.tv_sec + (td.tv_usec / 1000000.); 97810296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 97916437Sleres bs = bytes / nz(s); 98026448Slepreau if (local && *local != '-') 98126048Sminshall printf("local: %s ", local); 98226448Slepreau if (remote) 98326048Sminshall printf("remote: %s\n", remote); 98416437Sleres printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 98516437Sleres bytes, direction, s, bs / 1024.); 98610296Ssam } 98710296Ssam 98826496Sminshall /*tvadd(tsum, t0) 98910296Ssam struct timeval *tsum, *t0; 99010296Ssam { 99110296Ssam 99210296Ssam tsum->tv_sec += t0->tv_sec; 99310296Ssam tsum->tv_usec += t0->tv_usec; 99410296Ssam if (tsum->tv_usec > 1000000) 99510296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 99626496Sminshall } */ 99710296Ssam 99810296Ssam tvsub(tdiff, t1, t0) 99910296Ssam struct timeval *tdiff, *t1, *t0; 100010296Ssam { 100110296Ssam 100210296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 100310296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 100410296Ssam if (tdiff->tv_usec < 0) 100510296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 100610296Ssam } 100726048Sminshall 100826048Sminshall psabort() 100926048Sminshall { 101026048Sminshall extern int abrtflag; 101126048Sminshall 101226048Sminshall abrtflag++; 101326048Sminshall } 101426048Sminshall 101526048Sminshall pswitch(flag) 101626048Sminshall int flag; 101726048Sminshall { 101826048Sminshall extern int proxy, abrtflag; 101926048Sminshall int (*oldintr)(); 102026048Sminshall static struct comvars { 102126048Sminshall int connect; 102226048Sminshall char name[32]; 102326048Sminshall struct sockaddr_in mctl; 102426048Sminshall struct sockaddr_in hctl; 102526048Sminshall FILE *in; 102626048Sminshall FILE *out; 102726048Sminshall int tpe; 102826048Sminshall int cpnd; 102926048Sminshall int sunqe; 103026048Sminshall int runqe; 103126048Sminshall int mcse; 103226048Sminshall int ntflg; 103326048Sminshall char nti[17]; 103426048Sminshall char nto[17]; 103526048Sminshall int mapflg; 103626048Sminshall char mi[MAXPATHLEN]; 103726048Sminshall char mo[MAXPATHLEN]; 103826048Sminshall } proxstruct, tmpstruct; 103926048Sminshall struct comvars *ip, *op; 104026048Sminshall 104126048Sminshall abrtflag = 0; 104226048Sminshall oldintr = signal(SIGINT, psabort); 104326048Sminshall if (flag) { 104426448Slepreau if (proxy) 104526048Sminshall return; 104626048Sminshall ip = &tmpstruct; 104726048Sminshall op = &proxstruct; 104826048Sminshall proxy++; 104926048Sminshall } 105026048Sminshall else { 105126448Slepreau if (!proxy) 105226048Sminshall return; 105326048Sminshall ip = &proxstruct; 105426048Sminshall op = &tmpstruct; 105526048Sminshall proxy = 0; 105626048Sminshall } 105726048Sminshall ip->connect = connected; 105826048Sminshall connected = op->connect; 105926496Sminshall (void) strncpy(ip->name, hostname, 31); 106026048Sminshall (ip->name)[strlen(ip->name)] = '\0'; 106126048Sminshall hostname = op->name; 106226048Sminshall ip->hctl = hisctladdr; 106326048Sminshall hisctladdr = op->hctl; 106426048Sminshall ip->mctl = myctladdr; 106526048Sminshall myctladdr = op->mctl; 106626048Sminshall ip->in = cin; 106726048Sminshall cin = op->in; 106826048Sminshall ip->out = cout; 106926048Sminshall cout = op->out; 107026048Sminshall ip->tpe = type; 107126048Sminshall type = op->tpe; 107226448Slepreau if (!type) 107326048Sminshall type = 1; 107426048Sminshall ip->cpnd = cpend; 107526048Sminshall cpend = op->cpnd; 107626048Sminshall ip->sunqe = sunique; 107726048Sminshall sunique = op->sunqe; 107826048Sminshall ip->runqe = runique; 107926048Sminshall runique = op->runqe; 108026048Sminshall ip->mcse = mcase; 108126048Sminshall mcase = op->mcse; 108226048Sminshall ip->ntflg = ntflag; 108326048Sminshall ntflag = op->ntflg; 108426496Sminshall (void) strncpy(ip->nti, ntin, 16); 108526048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 108626496Sminshall (void) strcpy(ntin, op->nti); 108726496Sminshall (void) strncpy(ip->nto, ntout, 16); 108826048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 108926496Sminshall (void) strcpy(ntout, op->nto); 109026048Sminshall ip->mapflg = mapflag; 109126048Sminshall mapflag = op->mapflg; 109226496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 109326048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 109426496Sminshall (void) strcpy(mapin, op->mi); 109526496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 109626048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 109726496Sminshall (void) strcpy(mapout, op->mo); 109826048Sminshall (void) signal(SIGINT, oldintr); 109926048Sminshall if (abrtflag) { 110026048Sminshall abrtflag = 0; 110126048Sminshall (*oldintr)(); 110226448Slepreau } 110326048Sminshall } 110426048Sminshall 110526048Sminshall jmp_buf ptabort; 110626048Sminshall int ptabflg; 110726048Sminshall 110826048Sminshall abortpt() 110926048Sminshall { 111026048Sminshall printf("\n"); 111126496Sminshall (void) fflush(stdout); 111226048Sminshall ptabflg++; 111326048Sminshall mflag = 0; 111426048Sminshall abrtflag = 0; 111526048Sminshall longjmp(ptabort, 1); 111626048Sminshall } 111726048Sminshall 111826048Sminshall proxtrans(cmd, local, remote) 111926048Sminshall char *cmd, *local, *remote; 112026048Sminshall { 1121*27687Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 112226048Sminshall extern jmp_buf ptabort; 112326048Sminshall char *cmd2; 112426496Sminshall struct fd_set mask; 112526048Sminshall 112626448Slepreau if (strcmp(cmd, "RETR")) 112726048Sminshall cmd2 = "RETR"; 112826448Slepreau else 112926048Sminshall cmd2 = runique ? "STOU" : "STOR"; 113026048Sminshall if (command("PASV") != COMPLETE) { 113126048Sminshall printf("proxy server does not support third part transfers.\n"); 113226048Sminshall return; 113326048Sminshall } 113426048Sminshall tmptype = type; 113526048Sminshall pswitch(0); 113626048Sminshall if (!connected) { 113726048Sminshall printf("No primary connection\n"); 113826048Sminshall pswitch(1); 113926048Sminshall code = -1; 114026048Sminshall return; 114126048Sminshall } 114226048Sminshall if (type != tmptype) { 114326048Sminshall oldtype = type; 114426048Sminshall switch (tmptype) { 114526048Sminshall case TYPE_A: 114626048Sminshall setascii(); 114726048Sminshall break; 114826048Sminshall case TYPE_I: 114926048Sminshall setbinary(); 115026048Sminshall break; 115126048Sminshall case TYPE_E: 115226048Sminshall setebcdic(); 115326048Sminshall break; 115426048Sminshall case TYPE_L: 115526048Sminshall settenex(); 115626048Sminshall break; 115726048Sminshall } 115826048Sminshall } 115926048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 116026048Sminshall switch (oldtype) { 116126048Sminshall case 0: 116226048Sminshall break; 116326048Sminshall case TYPE_A: 116426048Sminshall setascii(); 116526048Sminshall break; 116626048Sminshall case TYPE_I: 116726048Sminshall setbinary(); 116826048Sminshall break; 116926048Sminshall case TYPE_E: 117026048Sminshall setebcdic(); 117126048Sminshall break; 117226048Sminshall case TYPE_L: 117326048Sminshall settenex(); 117426048Sminshall break; 117526048Sminshall } 117626048Sminshall pswitch(1); 117726048Sminshall return; 117826048Sminshall } 117926448Slepreau if (setjmp(ptabort)) 118026048Sminshall goto abort; 118126048Sminshall oldintr = signal(SIGINT, abortpt); 118226048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 118326048Sminshall (void) signal(SIGINT, oldintr); 118426048Sminshall switch (oldtype) { 118526048Sminshall case 0: 118626048Sminshall break; 118726048Sminshall case TYPE_A: 118826048Sminshall setascii(); 118926048Sminshall break; 119026048Sminshall case TYPE_I: 119126048Sminshall setbinary(); 119226048Sminshall break; 119326048Sminshall case TYPE_E: 119426048Sminshall setebcdic(); 119526048Sminshall break; 119626048Sminshall case TYPE_L: 119726048Sminshall settenex(); 119826048Sminshall break; 119926048Sminshall } 120026048Sminshall pswitch(1); 120126048Sminshall return; 120226048Sminshall } 120326048Sminshall sleep(2); 120426048Sminshall pswitch(1); 120526048Sminshall secndflag++; 120626448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 120726048Sminshall goto abort; 120826048Sminshall ptflag++; 120926048Sminshall (void) getreply(0); 121026048Sminshall pswitch(0); 121126048Sminshall (void) getreply(0); 121226048Sminshall (void) signal(SIGINT, oldintr); 121326048Sminshall switch (oldtype) { 121426048Sminshall case 0: 121526048Sminshall break; 121626048Sminshall case TYPE_A: 121726048Sminshall setascii(); 121826048Sminshall break; 121926048Sminshall case TYPE_I: 122026048Sminshall setbinary(); 122126048Sminshall break; 122226048Sminshall case TYPE_E: 122326048Sminshall setebcdic(); 122426048Sminshall break; 122526048Sminshall case TYPE_L: 122626048Sminshall settenex(); 122726048Sminshall break; 122826048Sminshall } 122926048Sminshall pswitch(1); 123026048Sminshall ptflag = 0; 123126048Sminshall printf("local: %s remote: %s\n", local, remote); 123226048Sminshall return; 123326048Sminshall abort: 123426048Sminshall (void) signal(SIGINT, SIG_IGN); 123526048Sminshall ptflag = 0; 123626448Slepreau if (strcmp(cmd, "RETR") && !proxy) 123726048Sminshall pswitch(1); 123826448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 123926048Sminshall pswitch(0); 124026048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 124126048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 124226048Sminshall pswitch(0); 124326048Sminshall switch (oldtype) { 124426048Sminshall case 0: 124526048Sminshall break; 124626048Sminshall case TYPE_A: 124726048Sminshall setascii(); 124826048Sminshall break; 124926048Sminshall case TYPE_I: 125026048Sminshall setbinary(); 125126048Sminshall break; 125226048Sminshall case TYPE_E: 125326048Sminshall setebcdic(); 125426048Sminshall break; 125526048Sminshall case TYPE_L: 125626048Sminshall settenex(); 125726048Sminshall break; 125826048Sminshall } 1259*27687Sminshall if (cpend) { 126026048Sminshall char msg[2]; 126126048Sminshall 126226048Sminshall fprintf(cout,"%c%c",IAC,IP); 126326048Sminshall (void) fflush(cout); 126426048Sminshall *msg = IAC; 126526048Sminshall *(msg+1) = DM; 126626448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 126726048Sminshall perror("abort"); 126826048Sminshall fprintf(cout,"ABOR\r\n"); 126926048Sminshall (void) fflush(cout); 1270*27687Sminshall FD_ZERO(&mask); 127126496Sminshall FD_SET(fileno(cin), &mask); 1272*27687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 1273*27687Sminshall if (nfnd < 0) { 1274*27687Sminshall perror("abort"); 1275*27687Sminshall } 127626448Slepreau if (ptabflg) 127726048Sminshall code = -1; 127826048Sminshall lostpeer(); 127926048Sminshall } 128026048Sminshall (void) getreply(0); 128126048Sminshall (void) getreply(0); 128226048Sminshall } 128326048Sminshall } 128426048Sminshall pswitch(1); 128526448Slepreau if (ptabflg) 128626048Sminshall code = -1; 128726048Sminshall (void) signal(SIGINT, oldintr); 128826048Sminshall return; 128926048Sminshall } 1290*27687Sminshall if (cpend) { 129126048Sminshall char msg[2]; 129226048Sminshall 129326048Sminshall fprintf(cout,"%c%c",IAC,IP); 129426048Sminshall (void) fflush(cout); 129526048Sminshall *msg = IAC; 129626048Sminshall *(msg+1) = DM; 129726448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 129826048Sminshall perror("abort"); 129926048Sminshall fprintf(cout,"ABOR\r\n"); 130026048Sminshall (void) fflush(cout); 1301*27687Sminshall FD_ZERO(&mask); 130226496Sminshall FD_SET(fileno(cin), &mask); 1303*27687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 1304*27687Sminshall if (nfnd < 0) { 1305*27687Sminshall perror("abort"); 1306*27687Sminshall } 130726448Slepreau if (ptabflg) 130826048Sminshall code = -1; 130926048Sminshall lostpeer(); 131026048Sminshall } 131126048Sminshall (void) getreply(0); 131226048Sminshall (void) getreply(0); 131326048Sminshall } 131426048Sminshall pswitch(!proxy); 131526048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 131626048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 131726048Sminshall pswitch(0); 131826048Sminshall switch (oldtype) { 131926048Sminshall case 0: 132026048Sminshall break; 132126048Sminshall case TYPE_A: 132226048Sminshall setascii(); 132326048Sminshall break; 132426048Sminshall case TYPE_I: 132526048Sminshall setbinary(); 132626048Sminshall break; 132726048Sminshall case TYPE_E: 132826048Sminshall setebcdic(); 132926048Sminshall break; 133026048Sminshall case TYPE_L: 133126048Sminshall settenex(); 133226048Sminshall break; 133326048Sminshall } 1334*27687Sminshall if (cpend) { 133526048Sminshall char msg[2]; 133626048Sminshall 133726048Sminshall fprintf(cout,"%c%c",IAC,IP); 133826048Sminshall (void) fflush(cout); 133926048Sminshall *msg = IAC; 134026048Sminshall *(msg+1) = DM; 134126448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 134226048Sminshall perror("abort"); 134326048Sminshall fprintf(cout,"ABOR\r\n"); 134426048Sminshall (void) fflush(cout); 1345*27687Sminshall FD_ZERO(&mask); 134626496Sminshall FD_SET(fileno(cin), &mask); 1347*27687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 1348*27687Sminshall if (nfnd < 0) { 1349*27687Sminshall perror("abort"); 1350*27687Sminshall } 135126448Slepreau if (ptabflg) 135226048Sminshall code = -1; 135326048Sminshall lostpeer(); 135426048Sminshall } 135526048Sminshall (void) getreply(0); 135626048Sminshall (void) getreply(0); 135726048Sminshall } 135826048Sminshall pswitch(1); 135926448Slepreau if (ptabflg) 136026048Sminshall code = -1; 136126048Sminshall (void) signal(SIGINT, oldintr); 136226048Sminshall return; 136326048Sminshall } 136426048Sminshall } 1365*27687Sminshall if (cpend) { 136626048Sminshall char msg[2]; 136726048Sminshall 136826048Sminshall fprintf(cout,"%c%c",IAC,IP); 136926048Sminshall (void) fflush(cout); 137026048Sminshall *msg = IAC; 137126048Sminshall *(msg+1) = DM; 137226448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 137326048Sminshall perror("abort"); 137426048Sminshall fprintf(cout,"ABOR\r\n"); 137526048Sminshall (void) fflush(cout); 1376*27687Sminshall FD_ZERO(&mask); 137726496Sminshall FD_SET(fileno(cin), &mask); 1378*27687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 1379*27687Sminshall if (nfnd < 0) { 1380*27687Sminshall perror("abort"); 1381*27687Sminshall } 138226448Slepreau if (ptabflg) 138326048Sminshall code = -1; 138426048Sminshall lostpeer(); 138526048Sminshall } 138626048Sminshall (void) getreply(0); 138726048Sminshall (void) getreply(0); 138826048Sminshall } 138926048Sminshall pswitch(!proxy); 139026048Sminshall if (cpend) { 1391*27687Sminshall FD_ZERO(&mask); 139226496Sminshall FD_SET(fileno(cin), &mask); 1393*27687Sminshall if ((nfnd = empty(&mask,10)) <= 0) { 1394*27687Sminshall if (nfnd < 0) { 1395*27687Sminshall perror("abort"); 1396*27687Sminshall } 139726448Slepreau if (ptabflg) 139826048Sminshall code = -1; 139926048Sminshall lostpeer(); 140026048Sminshall } 140126048Sminshall (void) getreply(0); 140226048Sminshall (void) getreply(0); 140326048Sminshall } 140426448Slepreau if (proxy) 140526048Sminshall pswitch(0); 140626048Sminshall switch (oldtype) { 140726048Sminshall case 0: 140826048Sminshall break; 140926048Sminshall case TYPE_A: 141026048Sminshall setascii(); 141126048Sminshall break; 141226048Sminshall case TYPE_I: 141326048Sminshall setbinary(); 141426048Sminshall break; 141526048Sminshall case TYPE_E: 141626048Sminshall setebcdic(); 141726048Sminshall break; 141826048Sminshall case TYPE_L: 141926048Sminshall settenex(); 142026048Sminshall break; 142126048Sminshall } 142226048Sminshall pswitch(1); 142326448Slepreau if (ptabflg) 142426048Sminshall code = -1; 142526048Sminshall (void) signal(SIGINT, oldintr); 142626048Sminshall } 142726048Sminshall 142826048Sminshall reset() 142926048Sminshall { 143026496Sminshall struct fd_set mask; 143126496Sminshall int nfnd = 1; 143226048Sminshall 1433*27687Sminshall FD_ZERO(&mask); 143426496Sminshall while (nfnd) { 143526496Sminshall FD_SET(fileno(cin), &mask); 1436*27687Sminshall if ((nfnd = empty(&mask,0)) < 0) { 143726048Sminshall perror("reset"); 143826048Sminshall code = -1; 143926048Sminshall lostpeer(); 144026048Sminshall } 1441*27687Sminshall else if (nfnd) { 144226048Sminshall (void) getreply(0); 144326496Sminshall } 144426048Sminshall } 144526048Sminshall } 144626048Sminshall 144726048Sminshall char * 144826048Sminshall gunique(local) 144926048Sminshall char *local; 145026048Sminshall { 145126048Sminshall static char new[MAXPATHLEN]; 145226048Sminshall char *cp = rindex(local, '/'); 145326048Sminshall int d, count=0; 145426048Sminshall char ext = '1'; 145526048Sminshall 145626448Slepreau if (cp) 145726048Sminshall *cp = '\0'; 145826048Sminshall d = access(cp ? local : ".", 2); 145926448Slepreau if (cp) 146026048Sminshall *cp = '/'; 146126048Sminshall if (d < 0) { 146226048Sminshall perror(local); 146326048Sminshall return((char *) 0); 146426048Sminshall } 146526048Sminshall (void) strcpy(new, local); 146626048Sminshall cp = new + strlen(new); 146726048Sminshall *cp++ = '.'; 146826048Sminshall while (!d) { 146926048Sminshall if (++count == 100) { 147026048Sminshall printf("runique: can't find unique file name.\n"); 147126048Sminshall return((char *) 0); 147226048Sminshall } 147326048Sminshall *cp++ = ext; 147426048Sminshall *cp = '\0'; 147526448Slepreau if (ext == '9') 147626048Sminshall ext = '0'; 147726448Slepreau else 147826048Sminshall ext++; 147926448Slepreau if ((d = access(new, 0)) < 0) 148026048Sminshall break; 148126448Slepreau if (ext != '0') 148226048Sminshall cp--; 148326448Slepreau else if (*(cp - 2) == '.') 148426048Sminshall *(cp - 1) = '1'; 148526048Sminshall else { 148626048Sminshall *(cp - 2) = *(cp - 2) + 1; 148726048Sminshall cp--; 148826048Sminshall } 148926048Sminshall } 149026048Sminshall return(new); 149126048Sminshall } 1492