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*26067Sminshall static char sccsid[] = "@(#)ftp.c 5.7 (Berkeley) 02/04/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> 1710296Ssam 1810296Ssam #include <netinet/in.h> 1912397Ssam #include <arpa/ftp.h> 2026048Sminshall #include <arpa/telnet.h> 2110296Ssam 2210296Ssam #include <stdio.h> 2310296Ssam #include <signal.h> 2410296Ssam #include <errno.h> 2510296Ssam #include <netdb.h> 2626048Sminshall #include <fcntl.h> 2726048Sminshall #include <pwd.h> 2810296Ssam 2910296Ssam struct sockaddr_in hisctladdr; 3010296Ssam struct sockaddr_in data_addr; 3110296Ssam int data = -1; 3226048Sminshall int telflag = 0; 3326048Sminshall int abrtflag = 0; 3426048Sminshall int ptflag = 0; 3510296Ssam int connected; 3610296Ssam struct sockaddr_in myctladdr; 3710296Ssam 3810296Ssam FILE *cin, *cout; 3910296Ssam FILE *dataconn(); 4010296Ssam 4125904Skarels char * 4210296Ssam hookup(host, port) 4310296Ssam char *host; 4410296Ssam int port; 4510296Ssam { 4625904Skarels register struct hostent *hp = 0; 4726048Sminshall int s,len,oldverbose; 4825904Skarels static char hostnamebuf[80]; 4926048Sminshall char msg[2]; 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; 7725904Skarels while (connect(s, (caddr_t)&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; 8425904Skarels perror(0); 8525904Skarels hp->h_addr_list++; 8625904Skarels bcopy(hp->h_addr_list[0], 8726048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 8825904Skarels fprintf(stderr, "Trying %s...\n", 8925904Skarels inet_ntoa(hisctladdr.sin_addr)); 9025904Skarels continue; 9125904Skarels } 9210296Ssam perror("ftp: connect"); 9326048Sminshall code = -1; 9410296Ssam goto bad; 9510296Ssam } 9611627Ssam len = sizeof (myctladdr); 9711627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 9811627Ssam perror("ftp: getsockname"); 9926048Sminshall code = -1; 10010296Ssam goto bad; 10110296Ssam } 10210296Ssam cin = fdopen(s, "r"); 10310296Ssam cout = fdopen(s, "w"); 10411219Ssam if (cin == NULL || cout == NULL) { 10510296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 10610296Ssam if (cin) 10710296Ssam fclose(cin); 10810296Ssam if (cout) 10910296Ssam fclose(cout); 11026048Sminshall code = -1; 11110296Ssam goto bad; 11210296Ssam } 11310296Ssam if (verbose) 114*26067Sminshall printf("Connected to %s.\n", hostname); 11526048Sminshall if (getreply(0) != 2) { /* read startup message from server */ 11626048Sminshall if (cin) 11726048Sminshall fclose(cin); 11826048Sminshall if (cout) 11926048Sminshall fclose(cout); 12026048Sminshall code = -1; 12126048Sminshall goto bad; 12226048Sminshall } 12326048Sminshall 12426048Sminshall /* test to see if server command parser understands TELNET SYNC command */ 12526048Sminshall 12626048Sminshall fprintf(cout,"%c%c",IAC,NOP); 12726048Sminshall (void) fflush(cout); 12826048Sminshall *msg = IAC; 12926048Sminshall *(msg+1) = DM; 13026048Sminshall if (send(s,msg,2,MSG_OOB) != 2) { 13126048Sminshall perror("sync"); 13226048Sminshall } 13326048Sminshall oldverbose = verbose; 13426048Sminshall if (!debug) { 13526048Sminshall verbose = -1; 13626048Sminshall } 13726048Sminshall if (command("NOOP") == COMPLETE) { 13826048Sminshall telflag = 1; 13926048Sminshall } 14026048Sminshall else { 14126048Sminshall telflag = 0; 14226048Sminshall } 14326048Sminshall verbose = oldverbose; 14425904Skarels return (hostname); 14510296Ssam bad: 14610296Ssam close(s); 14725904Skarels return ((char *)0); 14810296Ssam } 14910296Ssam 15025904Skarels login(host) 15125904Skarels char *host; 15210296Ssam { 15326048Sminshall char tmp[80]; 15426048Sminshall char *user, *pass, *acct, *getlogin(), *getpass(); 15526048Sminshall int n, aflag = 0; 15610296Ssam 15726048Sminshall user = pass = acct = 0; 15826048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 15926048Sminshall disconnect(); 16026048Sminshall code = -1; 16126048Sminshall return(0); 16226048Sminshall } 16326048Sminshall if (user == NULL) { 16426048Sminshall char *myname = getlogin(); 16526048Sminshall 16626048Sminshall if (myname == NULL) { 16726048Sminshall struct passwd *pp = getpwuid(getuid()); 16826048Sminshall 16926048Sminshall if (pp != NULL) { 17026048Sminshall myname = pp->pw_name; 17126048Sminshall } 17226048Sminshall } 17326048Sminshall printf("Name (%s:%s): ", host, myname); 17426048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 17526048Sminshall tmp[strlen(tmp) - 1] = '\0'; 17626048Sminshall if (*tmp == '\0') { 17726048Sminshall user = myname; 17826048Sminshall } 17926048Sminshall else { 18026048Sminshall user = tmp; 18126048Sminshall } 18226048Sminshall } 18310296Ssam n = command("USER %s", user); 18426048Sminshall if (n == CONTINUE) { 18526048Sminshall if (pass == NULL) { 18626048Sminshall pass = getpass("Password:"); 18726048Sminshall } 18810296Ssam n = command("PASS %s", pass); 18926048Sminshall } 19010296Ssam if (n == CONTINUE) { 19126048Sminshall aflag++; 19226048Sminshall acct = getpass("Account:"); 19310296Ssam n = command("ACCT %s", acct); 19410296Ssam } 19510296Ssam if (n != COMPLETE) { 19610296Ssam fprintf(stderr, "Login failed.\n"); 19710296Ssam return (0); 19810296Ssam } 19926048Sminshall if (!aflag && acct != NULL) { 20026048Sminshall (void) command("ACCT %s", acct); 20126048Sminshall } 20226048Sminshall if (proxy) { 20326048Sminshall return(1); 20426048Sminshall } 20526048Sminshall for (n = 0; n < macnum; ++n) { 20626048Sminshall if (!strcmp("init", macros[n].mac_name)) { 20726048Sminshall strcpy(line, "$init"); 20826048Sminshall makeargv(); 20926048Sminshall domacro(margc, margv); 21026048Sminshall break; 21126048Sminshall } 21226048Sminshall } 21310296Ssam return (1); 21410296Ssam } 21510296Ssam 21626048Sminshall cmdabort() 21726048Sminshall { 21826048Sminshall extern jmp_buf ptabort; 21926048Sminshall 22026048Sminshall printf("\n"); 22126048Sminshall (void) fflush(stdout); 22226048Sminshall abrtflag++; 22326048Sminshall if (ptflag) { 22426048Sminshall longjmp(ptabort,1); 22526048Sminshall } 22626048Sminshall } 22726048Sminshall 22810296Ssam /*VARARGS 1*/ 22910296Ssam command(fmt, args) 23010296Ssam char *fmt; 23110296Ssam { 23226048Sminshall int r, (*oldintr)(), cmdabort(); 23310296Ssam 23426048Sminshall abrtflag = 0; 23510296Ssam if (debug) { 23610296Ssam printf("---> "); 23710296Ssam _doprnt(fmt, &args, stdout); 23810296Ssam printf("\n"); 23910296Ssam (void) fflush(stdout); 24010296Ssam } 24111219Ssam if (cout == NULL) { 24211219Ssam perror ("No control connection for command"); 24326048Sminshall code = -1; 24411219Ssam return (0); 24511219Ssam } 24626048Sminshall oldintr = signal(SIGINT,cmdabort); 24710296Ssam _doprnt(fmt, &args, cout); 24810296Ssam fprintf(cout, "\r\n"); 24910296Ssam (void) fflush(cout); 25026048Sminshall cpend = 1; 25126048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 25226048Sminshall if (abrtflag && oldintr != SIG_IGN) { 25326048Sminshall (*oldintr)(); 25426048Sminshall } 25526048Sminshall (void) signal(SIGINT, oldintr); 25626048Sminshall return(r); 25710296Ssam } 25810296Ssam 25910296Ssam #include <ctype.h> 26010296Ssam 26110296Ssam getreply(expecteof) 26210296Ssam int expecteof; 26310296Ssam { 26411219Ssam register int c, n; 26526048Sminshall register int dig; 26626048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 26726048Sminshall int pflag = 0; 26826048Sminshall char *pt = pasv; 26910296Ssam 27026048Sminshall oldintr = signal(SIGINT,cmdabort); 27110296Ssam for (;;) { 27210296Ssam dig = n = code = 0; 27310296Ssam while ((c = getc(cin)) != '\n') { 27410296Ssam dig++; 27510296Ssam if (c == EOF) { 27626048Sminshall if (expecteof) { 27726048Sminshall (void) signal(SIGINT,oldintr); 27826048Sminshall code = 221; 27910296Ssam return (0); 28026048Sminshall } 28110296Ssam lostpeer(); 28226048Sminshall if (verbose) { 28326048Sminshall printf("421 Service not available, remote server has closed connection\n"); 28426048Sminshall (void) fflush(stdout); 28526048Sminshall code = 421; 28626048Sminshall return(4); 28726048Sminshall } 28810296Ssam } 28926048Sminshall if (c != '\r' && (verbose > 0 || 29026048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 29126048Sminshall if ( proxflag && 29226048Sminshall (dig == 1 || dig == 5 && verbose == 0)) { 29326048Sminshall printf("%s:",hostname); 29426048Sminshall } 29510296Ssam putchar(c); 29626048Sminshall } 29710296Ssam if (dig < 4 && isdigit(c)) 29810296Ssam code = code * 10 + (c - '0'); 29926048Sminshall if (!pflag && code == 227) { 30026048Sminshall pflag = 1; 30126048Sminshall } 30226048Sminshall if (dig > 4 && pflag == 1 && isdigit(c)) { 30326048Sminshall pflag = 2; 30426048Sminshall } 30526048Sminshall if (pflag == 2) { 30626048Sminshall if (c != '\r' && c != ')') { 30726048Sminshall *pt++ = c; 30826048Sminshall } 30926048Sminshall else { 31026048Sminshall *pt = '\0'; 31126048Sminshall pflag = 3; 31226048Sminshall } 31326048Sminshall } 31426048Sminshall if (dig == 4 && c == '-') { 31526048Sminshall if (continuation) { 31626048Sminshall code = 0; 31726048Sminshall } 31810296Ssam continuation++; 31926048Sminshall } 32010296Ssam if (n == 0) 32110296Ssam n = c; 32210296Ssam } 32326048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 32410296Ssam putchar(c); 32511346Ssam (void) fflush (stdout); 32611346Ssam } 32710296Ssam if (continuation && code != originalcode) { 32810296Ssam if (originalcode == 0) 32910296Ssam originalcode = code; 33010296Ssam continue; 33110296Ssam } 33226048Sminshall if (n != '1') { 33326048Sminshall cpend = 0; 33426048Sminshall } 33526048Sminshall (void) signal(SIGINT,oldintr); 33626048Sminshall if (code == 421 || originalcode == 421) { 33726048Sminshall lostpeer(); 33826048Sminshall } 33926048Sminshall if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) { 34026048Sminshall (*oldintr)(); 34126048Sminshall } 34225907Smckusick return (n - '0'); 34310296Ssam } 34410296Ssam } 34510296Ssam 34626048Sminshall empty(mask, sec) 34726048Sminshall long mask; 34826048Sminshall int sec; 34926048Sminshall { 35026048Sminshall struct timeval t; 35126048Sminshall 35226048Sminshall t.tv_sec = (long) sec; 35326048Sminshall t.tv_usec = 0; 35426048Sminshall if (select(20, &mask, 0, 0, &t) < 0) { 35526048Sminshall return(-1); 35626048Sminshall } 35726048Sminshall return (mask); 35826048Sminshall } 35926048Sminshall 36010296Ssam jmp_buf sendabort; 36110296Ssam 36210296Ssam abortsend() 36310296Ssam { 36410296Ssam 36526048Sminshall mflag = 0; 36626048Sminshall abrtflag = 0; 36726048Sminshall printf("\nsend aborted\n"); 36826048Sminshall (void) fflush(stdout); 36910296Ssam longjmp(sendabort, 1); 37010296Ssam } 37110296Ssam 37210296Ssam sendrequest(cmd, local, remote) 37310296Ssam char *cmd, *local, *remote; 37410296Ssam { 37526048Sminshall FILE *fin, *dout = 0, *popen(); 37626048Sminshall int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 37726048Sminshall int abortsend(); 37811219Ssam char buf[BUFSIZ]; 37911651Ssam long bytes = 0, hashbytes = sizeof (buf); 38011346Ssam register int c, d; 38110296Ssam struct stat st; 38210296Ssam struct timeval start, stop; 38310296Ssam 38426048Sminshall if (proxy) { 38526048Sminshall proxtrans(cmd, local, remote); 38626048Sminshall return; 38726048Sminshall } 38810296Ssam closefunc = NULL; 38926048Sminshall oldintr = NULL; 39026048Sminshall oldintp = NULL; 39126048Sminshall if (setjmp(sendabort)) { 39226048Sminshall while (cpend) { 39326048Sminshall (void) getreply(0); 39426048Sminshall } 39526048Sminshall if (data >= 0) { 39626048Sminshall (void) close(data); 39726048Sminshall data = -1; 39826048Sminshall } 39926048Sminshall if (oldintr) { 40026048Sminshall (void) signal(SIGINT,oldintr); 40126048Sminshall } 40226048Sminshall if (oldintp) { 40326048Sminshall (void) signal(SIGPIPE,oldintp); 40426048Sminshall } 40526048Sminshall code = -1; 40626048Sminshall return; 40726048Sminshall } 40810296Ssam oldintr = signal(SIGINT, abortsend); 40910296Ssam if (strcmp(local, "-") == 0) 41010296Ssam fin = stdin; 41110296Ssam else if (*local == '|') { 41226048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 41326048Sminshall fin = popen(local + 1, "r"); 41410296Ssam if (fin == NULL) { 41526048Sminshall perror(local + 1); 41626048Sminshall (void) signal(SIGINT, oldintr); 41726048Sminshall (void) signal(SIGPIPE, oldintp); 41826048Sminshall code = -1; 41926048Sminshall return; 42010296Ssam } 42110296Ssam closefunc = pclose; 42210296Ssam } else { 42310296Ssam fin = fopen(local, "r"); 42410296Ssam if (fin == NULL) { 42510296Ssam perror(local); 42626048Sminshall (void) signal(SIGINT, oldintr); 42726048Sminshall code = -1; 42826048Sminshall return; 42910296Ssam } 43010296Ssam closefunc = fclose; 43110296Ssam if (fstat(fileno(fin), &st) < 0 || 43210296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 43317949Sralph fprintf(stderr, "%s: not a plain file.\n", local); 43426048Sminshall (void) signal(SIGINT, oldintr); 43526048Sminshall code = -1; 43626048Sminshall return; 43710296Ssam } 43810296Ssam } 43926048Sminshall if (initconn()) { 44026048Sminshall (void) signal(SIGINT, oldintr); 44126048Sminshall if (oldintp) { 44226048Sminshall (void) signal(SIGPIPE, oldintp); 44326048Sminshall } 44426048Sminshall code = -1; 44526048Sminshall return; 44626048Sminshall } 44726048Sminshall if (setjmp(sendabort)) { 44826048Sminshall goto abort; 44926048Sminshall } 45010296Ssam if (remote) { 45126048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 45226048Sminshall (void) signal(SIGINT, oldintr); 45326048Sminshall if (oldintp) { 45426048Sminshall (void) signal(SIGPIPE, oldintp); 45526048Sminshall } 45626048Sminshall return; 45726048Sminshall } 45810296Ssam } else 45926048Sminshall if (command("%s", cmd) != PRELIM) { 46026048Sminshall (void) signal(SIGINT, oldintr); 46126048Sminshall if (oldintp) { 46226048Sminshall (void) signal(SIGPIPE, oldintp); 46326048Sminshall } 46426048Sminshall return; 46526048Sminshall } 46610296Ssam dout = dataconn("w"); 46726048Sminshall if (dout == NULL) { 46826048Sminshall goto abort; 46926048Sminshall } 47010296Ssam gettimeofday(&start, (struct timezone *)0); 47111219Ssam switch (type) { 47211219Ssam 47311219Ssam case TYPE_I: 47411219Ssam case TYPE_L: 47511346Ssam errno = d = 0; 47611219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 47711346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 47811219Ssam break; 47911219Ssam bytes += c; 48011651Ssam if (hash) { 48111651Ssam putchar('#'); 48211651Ssam fflush(stdout); 48311651Ssam } 48411219Ssam } 48513213Ssam if (hash && bytes > 0) { 48611651Ssam putchar('\n'); 48711651Ssam fflush(stdout); 48811651Ssam } 48911219Ssam if (c < 0) 49011219Ssam perror(local); 49111346Ssam if (d < 0) 49211219Ssam perror("netout"); 49311219Ssam break; 49411219Ssam 49511219Ssam case TYPE_A: 49611219Ssam while ((c = getc(fin)) != EOF) { 49711219Ssam if (c == '\n') { 49811651Ssam while (hash && (bytes >= hashbytes)) { 49911651Ssam putchar('#'); 50011651Ssam fflush(stdout); 50111651Ssam hashbytes += sizeof (buf); 50211651Ssam } 50311219Ssam if (ferror(dout)) 50411219Ssam break; 50511219Ssam putc('\r', dout); 50611219Ssam bytes++; 50711219Ssam } 50811219Ssam putc(c, dout); 50911219Ssam bytes++; 51026048Sminshall /* if (c == '\r') { */ 51126048Sminshall /* putc('\0', dout); /* this violates rfc */ 51226048Sminshall /* bytes++; */ 51326048Sminshall /* } */ 51411219Ssam } 51511651Ssam if (hash) { 51613213Ssam if (bytes < hashbytes) 51713213Ssam putchar('#'); 51811651Ssam putchar('\n'); 51911651Ssam fflush(stdout); 52011651Ssam } 52111219Ssam if (ferror(fin)) 52211219Ssam perror(local); 52311346Ssam if (ferror(dout)) 52411219Ssam perror("netout"); 52511219Ssam break; 52610296Ssam } 52710296Ssam gettimeofday(&stop, (struct timezone *)0); 52810296Ssam if (closefunc != NULL) 52926048Sminshall (*closefunc)(fin); 53010296Ssam (void) fclose(dout); 53126048Sminshall (void) getreply(0); 53226048Sminshall (void) signal(SIGINT, oldintr); 53310296Ssam if (bytes > 0 && verbose) 53426048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 53510296Ssam return; 53626048Sminshall abort: 53726048Sminshall gettimeofday(&stop, (struct timezone *)0); 53826048Sminshall (void) signal(SIGINT, oldintr); 53926048Sminshall if (oldintp) { 54026048Sminshall (void) signal(SIGPIPE, oldintp); 54126048Sminshall } 54226048Sminshall if (!cpend) { 54326048Sminshall code = -1; 54426048Sminshall return; 54526048Sminshall } 54626048Sminshall if (data >= 0) { 54726048Sminshall (void) close(data); 54826048Sminshall data = -1; 54926048Sminshall } 55026048Sminshall if (dout) { 55126048Sminshall (void) fclose(dout); 55226048Sminshall } 55326048Sminshall (void) getreply(0); 55426048Sminshall code = -1; 55510296Ssam if (closefunc != NULL && fin != NULL) 55626048Sminshall (*closefunc)(fin); 55726048Sminshall if (bytes > 0 && verbose) 55826048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 55910296Ssam } 56010296Ssam 56110296Ssam jmp_buf recvabort; 56210296Ssam 56310296Ssam abortrecv() 56410296Ssam { 56510296Ssam 56626048Sminshall mflag = 0; 56726048Sminshall abrtflag = 0; 56826048Sminshall printf("\n"); 56926048Sminshall (void) fflush(stdout); 57010296Ssam longjmp(recvabort, 1); 57110296Ssam } 57210296Ssam 57311651Ssam recvrequest(cmd, local, remote, mode) 57411651Ssam char *cmd, *local, *remote, *mode; 57510296Ssam { 57626048Sminshall FILE *fout, *din = 0, *popen(); 57726048Sminshall int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 57826048Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag; 57926048Sminshall char buf[BUFSIZ], *gunique(); 58026048Sminshall long bytes = 0, hashbytes = sizeof (buf), mask; 58111346Ssam register int c, d; 58210296Ssam struct timeval start, stop; 58310296Ssam 58426048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 58526048Sminshall proxtrans(cmd, local, remote); 58626048Sminshall return; 58726048Sminshall } 58810296Ssam closefunc = NULL; 58926048Sminshall oldintr = NULL; 59026048Sminshall oldintp = NULL; 59126048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 59226048Sminshall if (setjmp(recvabort)) { 59326048Sminshall while (cpend) { 59426048Sminshall (void) getreply(0); 59526048Sminshall } 59626048Sminshall if (data >= 0) { 59726048Sminshall (void) close(data); 59826048Sminshall data = -1; 59926048Sminshall } 60026048Sminshall if (oldintr) { 60126048Sminshall (void) signal(SIGINT, oldintr); 60226048Sminshall } 60326048Sminshall code = -1; 60426048Sminshall return; 60526048Sminshall } 60610296Ssam oldintr = signal(SIGINT, abortrecv); 60726048Sminshall if (strcmp(local, "-") && *local != '|') { 60810296Ssam if (access(local, 2) < 0) { 60926048Sminshall char *dir = rindex(local, '/'); 61010296Ssam 61126048Sminshall if (errno != ENOENT && errno != EACCES) { 61210296Ssam perror(local); 61326048Sminshall (void) signal(SIGINT, oldintr); 61426048Sminshall code = -1; 61526048Sminshall return; 61610296Ssam } 61726048Sminshall if (dir != NULL) 61826048Sminshall *dir = 0; 61926048Sminshall d = access(dir ? local : ".", 2); 62026048Sminshall if (dir != NULL) 62126048Sminshall *dir = '/'; 62226048Sminshall if (d < 0) { 62326048Sminshall perror(local); 62426048Sminshall (void) signal(SIGINT, oldintr); 62526048Sminshall code = -1; 62626048Sminshall return; 62726048Sminshall } 62826048Sminshall if (!runique && errno == EACCES && 62926048Sminshall chmod(local,0600) < 0) { 63026048Sminshall perror(local); 63126048Sminshall (void) signal(SIGINT, oldintr); 63226048Sminshall code = -1; 63326048Sminshall return; 63426048Sminshall } 63526048Sminshall if (runique && errno == EACCES && 63626048Sminshall (local = gunique(local)) == NULL) { 63726048Sminshall (void) signal(SIGINT, oldintr); 63826048Sminshall code = -1; 63926048Sminshall return; 64026048Sminshall } 64110296Ssam } 64226048Sminshall else if (runique && (local = gunique(local)) == NULL) { 64326048Sminshall (void) signal(SIGINT, oldintr); 64426048Sminshall code = -1; 64526048Sminshall return; 64626048Sminshall } 64726048Sminshall } 64826048Sminshall if (initconn()) { 64926048Sminshall (void) signal(SIGINT, oldintr); 65026048Sminshall code = -1; 65126048Sminshall return; 65226048Sminshall } 65326048Sminshall if (setjmp(recvabort)) { 65426048Sminshall goto abort; 65526048Sminshall } 65626048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 65726048Sminshall oldtype = type; 65826048Sminshall oldverbose = verbose; 65926048Sminshall if (!debug) { 66026048Sminshall verbose = 0; 66126048Sminshall } 66226048Sminshall setascii(); 66326048Sminshall verbose = oldverbose; 66426048Sminshall } 66510296Ssam if (remote) { 66626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 66726048Sminshall (void) signal(SIGINT, oldintr); 66826048Sminshall if (oldtype) { 66926048Sminshall if (!debug) { 67026048Sminshall verbose = 0; 67126048Sminshall } 67226048Sminshall switch (oldtype) { 67326048Sminshall case TYPE_I: 67426048Sminshall setbinary(); 67526048Sminshall break; 67626048Sminshall case TYPE_E: 67726048Sminshall setebcdic(); 67826048Sminshall break; 67926048Sminshall case TYPE_L: 68026048Sminshall settenex(); 68126048Sminshall break; 68226048Sminshall } 68326048Sminshall verbose = oldverbose; 68426048Sminshall } 68526048Sminshall return; 68626048Sminshall } 68726048Sminshall } else { 68826048Sminshall if (command("%s", cmd) != PRELIM) { 68926048Sminshall (void) signal(SIGINT, oldintr); 69026048Sminshall if (oldtype) { 69126048Sminshall if (!debug) { 69226048Sminshall verbose = 0; 69326048Sminshall } 69426048Sminshall switch (oldtype) { 69526048Sminshall case TYPE_I: 69626048Sminshall setbinary(); 69726048Sminshall break; 69826048Sminshall case TYPE_E: 69926048Sminshall setebcdic(); 70026048Sminshall break; 70126048Sminshall case TYPE_L: 70226048Sminshall settenex(); 70326048Sminshall break; 70426048Sminshall } 70526048Sminshall verbose = oldverbose; 70626048Sminshall } 70726048Sminshall return; 70826048Sminshall } 70926048Sminshall } 71026048Sminshall din = dataconn("r"); 71126048Sminshall if (din == NULL) 71226048Sminshall goto abort; 71326048Sminshall if (strcmp(local, "-") == 0) { 71410296Ssam fout = stdout; 71526048Sminshall } 71610296Ssam else if (*local == '|') { 71726048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 71826048Sminshall fout = popen(local + 1, "w"); 71926048Sminshall if (fout == NULL) { 72026048Sminshall perror(local+1); 72126048Sminshall goto abort; 72226048Sminshall } 72310296Ssam closefunc = pclose; 72426048Sminshall } 72526048Sminshall else { 72611651Ssam fout = fopen(local, mode); 72726048Sminshall if (fout == NULL) { 72826048Sminshall perror(local); 72926048Sminshall goto abort; 73026048Sminshall } 73110296Ssam closefunc = fclose; 73210296Ssam } 73310296Ssam gettimeofday(&start, (struct timezone *)0); 73411219Ssam switch (type) { 73511219Ssam 73611219Ssam case TYPE_I: 73711219Ssam case TYPE_L: 73811346Ssam errno = d = 0; 73911219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 74011346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 74111219Ssam break; 74211219Ssam bytes += c; 74311651Ssam if (hash) { 74411651Ssam putchar('#'); 74511651Ssam fflush(stdout); 74611651Ssam } 74711219Ssam } 74813213Ssam if (hash && bytes > 0) { 74911651Ssam putchar('\n'); 75011651Ssam fflush(stdout); 75111651Ssam } 75211219Ssam if (c < 0) 75311219Ssam perror("netin"); 75411346Ssam if (d < 0) 75510296Ssam perror(local); 75611219Ssam break; 75711219Ssam 75811219Ssam case TYPE_A: 75911219Ssam while ((c = getc(din)) != EOF) { 76011219Ssam if (c == '\r') { 76111651Ssam while (hash && (bytes >= hashbytes)) { 76211651Ssam putchar('#'); 76311651Ssam fflush(stdout); 76411651Ssam hashbytes += sizeof (buf); 76511651Ssam } 76610296Ssam bytes++; 76726048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 76811219Ssam if (ferror (fout)) 76911219Ssam break; 77011219Ssam putc ('\r', fout); 77111219Ssam } 77226048Sminshall /*if (c == '\0') { 77311219Ssam bytes++; 77411219Ssam continue; 77526048Sminshall }*/ 77611219Ssam } 77711219Ssam putc (c, fout); 77811219Ssam bytes++; 77910296Ssam } 78011651Ssam if (hash) { 78113213Ssam if (bytes < hashbytes) 78213213Ssam putchar('#'); 78311651Ssam putchar('\n'); 78411651Ssam fflush(stdout); 78511651Ssam } 78611219Ssam if (ferror (din)) 78711219Ssam perror ("netin"); 78811219Ssam if (ferror (fout)) 78911219Ssam perror (local); 79011219Ssam break; 79110296Ssam } 79226048Sminshall if (closefunc != NULL) { 79326048Sminshall (*closefunc)(fout); 79426048Sminshall } 79526048Sminshall signal(SIGINT, oldintr); 79626048Sminshall if (oldintp) { 79726048Sminshall (void) signal(SIGPIPE, oldintp); 79826048Sminshall } 79910296Ssam gettimeofday(&stop, (struct timezone *)0); 80010296Ssam (void) fclose(din); 80126048Sminshall (void) getreply(0); 80226048Sminshall if (bytes > 0 && verbose) 80326048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 80426048Sminshall if (oldtype) { 80526048Sminshall if (!debug) { 80626048Sminshall verbose = 0; 80726048Sminshall } 80826048Sminshall switch (oldtype) { 80926048Sminshall case TYPE_I: 81026048Sminshall setbinary(); 81126048Sminshall break; 81226048Sminshall case TYPE_E: 81326048Sminshall setebcdic(); 81426048Sminshall break; 81526048Sminshall case TYPE_L: 81626048Sminshall settenex(); 81726048Sminshall break; 81826048Sminshall } 81926048Sminshall verbose = oldverbose; 82026048Sminshall } 82126048Sminshall return; 82226048Sminshall abort: 82326048Sminshall 82426048Sminshall /* if server command parser understands TELNET commands, abort using */ 82526048Sminshall /* recommended IP,SYNC sequence */ 82626048Sminshall 82726048Sminshall gettimeofday(&stop, (struct timezone *)0); 82826048Sminshall if (oldintp) { 82926048Sminshall (void) signal(SIGPIPE, oldintr); 83026048Sminshall } 83126048Sminshall (void) signal(SIGINT,SIG_IGN); 83226048Sminshall if (oldtype) { 83326048Sminshall if (!debug) { 83426048Sminshall verbose = 0; 83526048Sminshall } 83626048Sminshall switch (oldtype) { 83726048Sminshall case TYPE_I: 83826048Sminshall setbinary(); 83926048Sminshall break; 84026048Sminshall case TYPE_E: 84126048Sminshall setebcdic(); 84226048Sminshall break; 84326048Sminshall case TYPE_L: 84426048Sminshall settenex(); 84526048Sminshall break; 84626048Sminshall } 84726048Sminshall verbose = oldverbose; 84826048Sminshall } 84926048Sminshall if (!cpend) { 85026048Sminshall code = -1; 85126048Sminshall (void) signal(SIGINT,oldintr); 85226048Sminshall return; 85326048Sminshall } 85426048Sminshall if (telflag) { 85526048Sminshall char msg[2]; 85626048Sminshall 85726048Sminshall fprintf(cout,"%c%c",IAC,IP); 85826048Sminshall (void) fflush(cout); 85926048Sminshall *msg = IAC; 86026048Sminshall *(msg+1) = DM; 86126048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 86226048Sminshall perror("abort"); 86326048Sminshall } 86426048Sminshall } 86526048Sminshall fprintf(cout,"ABOR\r\n"); 86626048Sminshall (void) fflush(cout); 86726048Sminshall mask = (1 << fileno(cin)) | (din ? (1 << fileno(din)) : 0); 86826048Sminshall if ((mask = empty(mask,10)) < 0) { 86926048Sminshall perror("abort"); 87026048Sminshall code = -1; 87126048Sminshall lostpeer(); 87226048Sminshall } 87326048Sminshall if (din && mask & (1 << fileno(din))) { 87426048Sminshall while ((c = read(fileno(din), buf, sizeof (buf))) > 0); 87526048Sminshall } 87626048Sminshall if ((c = getreply(0)) == ERROR) { /* needed for nic style abort */ 87726048Sminshall if (data >= 0) { 87826048Sminshall close(data); 87926048Sminshall data = -1; 88026048Sminshall } 88125907Smckusick (void) getreply(0); 88225907Smckusick } 88326048Sminshall (void) getreply(0); 88426048Sminshall code = -1; 88526048Sminshall if (data >= 0) { 88626048Sminshall (void) close(data); 88726048Sminshall data = -1; 88826048Sminshall } 88926048Sminshall if (closefunc != NULL && fout != NULL) { 89026048Sminshall (*closefunc)(fout); 89126048Sminshall } 89226048Sminshall if (din) { 89326048Sminshall (void) fclose(din); 89426048Sminshall } 89510296Ssam if (bytes > 0 && verbose) 89626048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 89726048Sminshall (void) signal(SIGINT,oldintr); 89810296Ssam } 89910296Ssam 90010296Ssam /* 90110296Ssam * Need to start a listen on the data channel 90210296Ssam * before we send the command, otherwise the 90310296Ssam * server's connect may fail. 90410296Ssam */ 90511651Ssam static int sendport = -1; 90611651Ssam 90710296Ssam initconn() 90810296Ssam { 90910296Ssam register char *p, *a; 91026048Sminshall int result, len, tmpno = 0; 91117450Slepreau int on = 1; 91210296Ssam 91311651Ssam noport: 91410296Ssam data_addr = myctladdr; 91511651Ssam if (sendport) 91611651Ssam data_addr.sin_port = 0; /* let system pick one */ 91711651Ssam if (data != -1) 91811651Ssam (void) close (data); 91918287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 92010296Ssam if (data < 0) { 92110296Ssam perror("ftp: socket"); 92226048Sminshall if (tmpno) { 92326048Sminshall sendport = 1; 92426048Sminshall } 92510296Ssam return (1); 92610296Ssam } 92712397Ssam if (!sendport) 92817450Slepreau if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { 92926048Sminshall perror("ftp: setsockopt (resuse address)"); 93012397Ssam goto bad; 93112397Ssam } 93210296Ssam if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { 93310296Ssam perror("ftp: bind"); 93410296Ssam goto bad; 93510296Ssam } 93610296Ssam if (options & SO_DEBUG && 93717450Slepreau setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 93810296Ssam perror("ftp: setsockopt (ignored)"); 93911627Ssam len = sizeof (data_addr); 94011627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 94111627Ssam perror("ftp: getsockname"); 94210296Ssam goto bad; 94310296Ssam } 94410296Ssam if (listen(data, 1) < 0) { 94510296Ssam perror("ftp: listen"); 94626048Sminshall 94710296Ssam } 94811651Ssam if (sendport) { 94911651Ssam a = (char *)&data_addr.sin_addr; 95011651Ssam p = (char *)&data_addr.sin_port; 95110296Ssam #define UC(b) (((int)b)&0xff) 95211651Ssam result = 95311651Ssam command("PORT %d,%d,%d,%d,%d,%d", 95411651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 95511651Ssam UC(p[0]), UC(p[1])); 95611651Ssam if (result == ERROR && sendport == -1) { 95711651Ssam sendport = 0; 95826048Sminshall tmpno = 1; 95911651Ssam goto noport; 96011651Ssam } 96111651Ssam return (result != COMPLETE); 96211651Ssam } 96326048Sminshall if (tmpno) { 96426048Sminshall sendport = 1; 96526048Sminshall } 96611651Ssam return (0); 96710296Ssam bad: 96810296Ssam (void) close(data), data = -1; 96926048Sminshall if (tmpno) { 97026048Sminshall sendport = 1; 97126048Sminshall } 97210296Ssam return (1); 97310296Ssam } 97410296Ssam 97510296Ssam FILE * 97610296Ssam dataconn(mode) 97710296Ssam char *mode; 97810296Ssam { 97910296Ssam struct sockaddr_in from; 98010296Ssam int s, fromlen = sizeof (from); 98110296Ssam 98210296Ssam s = accept(data, &from, &fromlen, 0); 98310296Ssam if (s < 0) { 98410296Ssam perror("ftp: accept"); 98510296Ssam (void) close(data), data = -1; 98610296Ssam return (NULL); 98710296Ssam } 98810296Ssam (void) close(data); 98910296Ssam data = s; 99010296Ssam return (fdopen(data, mode)); 99110296Ssam } 99210296Ssam 99326048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 99426048Sminshall char *direction, *local, *remote; 99511651Ssam long bytes; 99610296Ssam struct timeval *t0, *t1; 99710296Ssam { 99810296Ssam struct timeval td; 99916437Sleres float s, bs; 100010296Ssam 100110296Ssam tvsub(&td, t1, t0); 100216437Sleres s = td.tv_sec + (td.tv_usec / 1000000.); 100310296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 100416437Sleres bs = bytes / nz(s); 100526048Sminshall if (local && *local != '-') { 100626048Sminshall printf("local: %s ", local); 100726048Sminshall } 100826048Sminshall if (remote) { 100926048Sminshall printf("remote: %s\n", remote); 101026048Sminshall } 101116437Sleres printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 101216437Sleres bytes, direction, s, bs / 1024.); 101310296Ssam } 101410296Ssam 101510296Ssam tvadd(tsum, t0) 101610296Ssam struct timeval *tsum, *t0; 101710296Ssam { 101810296Ssam 101910296Ssam tsum->tv_sec += t0->tv_sec; 102010296Ssam tsum->tv_usec += t0->tv_usec; 102110296Ssam if (tsum->tv_usec > 1000000) 102210296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 102310296Ssam } 102410296Ssam 102510296Ssam tvsub(tdiff, t1, t0) 102610296Ssam struct timeval *tdiff, *t1, *t0; 102710296Ssam { 102810296Ssam 102910296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 103010296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 103110296Ssam if (tdiff->tv_usec < 0) 103210296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 103310296Ssam } 103426048Sminshall 103526048Sminshall psabort() 103626048Sminshall { 103726048Sminshall extern int abrtflag; 103826048Sminshall 103926048Sminshall abrtflag++; 104026048Sminshall } 104126048Sminshall 104226048Sminshall pswitch(flag) 104326048Sminshall int flag; 104426048Sminshall { 104526048Sminshall extern int proxy, abrtflag; 104626048Sminshall int (*oldintr)(); 104726048Sminshall static struct comvars { 104826048Sminshall int connect; 104926048Sminshall char name[32]; 105026048Sminshall struct sockaddr_in mctl; 105126048Sminshall struct sockaddr_in hctl; 105226048Sminshall FILE *in; 105326048Sminshall FILE *out; 105426048Sminshall int tflag; 105526048Sminshall int tpe; 105626048Sminshall int cpnd; 105726048Sminshall int sunqe; 105826048Sminshall int runqe; 105926048Sminshall int mcse; 106026048Sminshall int ntflg; 106126048Sminshall char nti[17]; 106226048Sminshall char nto[17]; 106326048Sminshall int mapflg; 106426048Sminshall char mi[MAXPATHLEN]; 106526048Sminshall char mo[MAXPATHLEN]; 106626048Sminshall } proxstruct, tmpstruct; 106726048Sminshall struct comvars *ip, *op; 106826048Sminshall 106926048Sminshall abrtflag = 0; 107026048Sminshall oldintr = signal(SIGINT, psabort); 107126048Sminshall if (flag) { 107226048Sminshall if (proxy) { 107326048Sminshall return; 107426048Sminshall } 107526048Sminshall ip = &tmpstruct; 107626048Sminshall op = &proxstruct; 107726048Sminshall proxy++; 107826048Sminshall } 107926048Sminshall else { 108026048Sminshall if (!proxy) { 108126048Sminshall return; 108226048Sminshall } 108326048Sminshall ip = &proxstruct; 108426048Sminshall op = &tmpstruct; 108526048Sminshall proxy = 0; 108626048Sminshall } 108726048Sminshall ip->connect = connected; 108826048Sminshall connected = op->connect; 108926048Sminshall strncpy(ip->name, hostname, 31); 109026048Sminshall (ip->name)[strlen(ip->name)] = '\0'; 109126048Sminshall hostname = op->name; 109226048Sminshall ip->hctl = hisctladdr; 109326048Sminshall hisctladdr = op->hctl; 109426048Sminshall ip->mctl = myctladdr; 109526048Sminshall myctladdr = op->mctl; 109626048Sminshall ip->in = cin; 109726048Sminshall cin = op->in; 109826048Sminshall ip->out = cout; 109926048Sminshall cout = op->out; 110026048Sminshall ip->tflag = telflag; 110126048Sminshall telflag = op->tflag; 110226048Sminshall ip->tpe = type; 110326048Sminshall type = op->tpe; 110426048Sminshall if (!type) { 110526048Sminshall type = 1; 110626048Sminshall } 110726048Sminshall ip->cpnd = cpend; 110826048Sminshall cpend = op->cpnd; 110926048Sminshall ip->sunqe = sunique; 111026048Sminshall sunique = op->sunqe; 111126048Sminshall ip->runqe = runique; 111226048Sminshall runique = op->runqe; 111326048Sminshall ip->mcse = mcase; 111426048Sminshall mcase = op->mcse; 111526048Sminshall ip->ntflg = ntflag; 111626048Sminshall ntflag = op->ntflg; 111726048Sminshall strncpy(ip->nti, ntin, 16); 111826048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 111926048Sminshall strcpy(ntin, op->nti); 112026048Sminshall strncpy(ip->nto, ntout, 16); 112126048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 112226048Sminshall strcpy(ntout, op->nto); 112326048Sminshall ip->mapflg = mapflag; 112426048Sminshall mapflag = op->mapflg; 112526048Sminshall strncpy(ip->mi, mapin, MAXPATHLEN - 1); 112626048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 112726048Sminshall strcpy(mapin, op->mi); 112826048Sminshall strncpy(ip->mo, mapout, MAXPATHLEN - 1); 112926048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 113026048Sminshall strcpy(mapout, op->mo); 113126048Sminshall (void) signal(SIGINT, oldintr); 113226048Sminshall if (abrtflag) { 113326048Sminshall abrtflag = 0; 113426048Sminshall (*oldintr)(); 113526048Sminshall } 113626048Sminshall } 113726048Sminshall 113826048Sminshall jmp_buf ptabort; 113926048Sminshall int ptabflg; 114026048Sminshall 114126048Sminshall abortpt() 114226048Sminshall { 114326048Sminshall printf("\n"); 114426048Sminshall fflush(stdout); 114526048Sminshall ptabflg++; 114626048Sminshall mflag = 0; 114726048Sminshall abrtflag = 0; 114826048Sminshall longjmp(ptabort, 1); 114926048Sminshall } 115026048Sminshall 115126048Sminshall proxtrans(cmd, local, remote) 115226048Sminshall char *cmd, *local, *remote; 115326048Sminshall { 115426048Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0; 115526048Sminshall extern jmp_buf ptabort; 115626048Sminshall char *cmd2; 115726048Sminshall long mask; 115826048Sminshall 115926048Sminshall if (strcmp(cmd, "RETR")) { 116026048Sminshall cmd2 = "RETR"; 116126048Sminshall } 116226048Sminshall else { 116326048Sminshall cmd2 = runique ? "STOU" : "STOR"; 116426048Sminshall } 116526048Sminshall if (command("PASV") != COMPLETE) { 116626048Sminshall printf("proxy server does not support third part transfers.\n"); 116726048Sminshall return; 116826048Sminshall } 116926048Sminshall tmptype = type; 117026048Sminshall pswitch(0); 117126048Sminshall if (!connected) { 117226048Sminshall printf("No primary connection\n"); 117326048Sminshall pswitch(1); 117426048Sminshall code = -1; 117526048Sminshall return; 117626048Sminshall } 117726048Sminshall if (type != tmptype) { 117826048Sminshall oldtype = type; 117926048Sminshall switch (tmptype) { 118026048Sminshall case TYPE_A: 118126048Sminshall setascii(); 118226048Sminshall break; 118326048Sminshall case TYPE_I: 118426048Sminshall setbinary(); 118526048Sminshall break; 118626048Sminshall case TYPE_E: 118726048Sminshall setebcdic(); 118826048Sminshall break; 118926048Sminshall case TYPE_L: 119026048Sminshall settenex(); 119126048Sminshall break; 119226048Sminshall } 119326048Sminshall } 119426048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 119526048Sminshall switch (oldtype) { 119626048Sminshall case 0: 119726048Sminshall break; 119826048Sminshall case TYPE_A: 119926048Sminshall setascii(); 120026048Sminshall break; 120126048Sminshall case TYPE_I: 120226048Sminshall setbinary(); 120326048Sminshall break; 120426048Sminshall case TYPE_E: 120526048Sminshall setebcdic(); 120626048Sminshall break; 120726048Sminshall case TYPE_L: 120826048Sminshall settenex(); 120926048Sminshall break; 121026048Sminshall } 121126048Sminshall pswitch(1); 121226048Sminshall return; 121326048Sminshall } 121426048Sminshall if (setjmp(ptabort)) { 121526048Sminshall goto abort; 121626048Sminshall } 121726048Sminshall oldintr = signal(SIGINT, abortpt); 121826048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 121926048Sminshall (void) signal(SIGINT, oldintr); 122026048Sminshall switch (oldtype) { 122126048Sminshall case 0: 122226048Sminshall break; 122326048Sminshall case TYPE_A: 122426048Sminshall setascii(); 122526048Sminshall break; 122626048Sminshall case TYPE_I: 122726048Sminshall setbinary(); 122826048Sminshall break; 122926048Sminshall case TYPE_E: 123026048Sminshall setebcdic(); 123126048Sminshall break; 123226048Sminshall case TYPE_L: 123326048Sminshall settenex(); 123426048Sminshall break; 123526048Sminshall } 123626048Sminshall pswitch(1); 123726048Sminshall return; 123826048Sminshall } 123926048Sminshall sleep(2); 124026048Sminshall pswitch(1); 124126048Sminshall secndflag++; 124226048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 124326048Sminshall goto abort; 124426048Sminshall } 124526048Sminshall ptflag++; 124626048Sminshall (void) getreply(0); 124726048Sminshall pswitch(0); 124826048Sminshall (void) getreply(0); 124926048Sminshall (void) signal(SIGINT, oldintr); 125026048Sminshall switch (oldtype) { 125126048Sminshall case 0: 125226048Sminshall break; 125326048Sminshall case TYPE_A: 125426048Sminshall setascii(); 125526048Sminshall break; 125626048Sminshall case TYPE_I: 125726048Sminshall setbinary(); 125826048Sminshall break; 125926048Sminshall case TYPE_E: 126026048Sminshall setebcdic(); 126126048Sminshall break; 126226048Sminshall case TYPE_L: 126326048Sminshall settenex(); 126426048Sminshall break; 126526048Sminshall } 126626048Sminshall pswitch(1); 126726048Sminshall ptflag = 0; 126826048Sminshall printf("local: %s remote: %s\n", local, remote); 126926048Sminshall return; 127026048Sminshall abort: 127126048Sminshall (void) signal(SIGINT, SIG_IGN); 127226048Sminshall ptflag = 0; 127326048Sminshall if (strcmp(cmd, "RETR") && !proxy) { 127426048Sminshall pswitch(1); 127526048Sminshall } 127626048Sminshall else if (!strcmp(cmd, "RETR") && proxy) { 127726048Sminshall pswitch(0); 127826048Sminshall } 127926048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 128026048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 128126048Sminshall pswitch(0); 128226048Sminshall switch (oldtype) { 128326048Sminshall case 0: 128426048Sminshall break; 128526048Sminshall case TYPE_A: 128626048Sminshall setascii(); 128726048Sminshall break; 128826048Sminshall case TYPE_I: 128926048Sminshall setbinary(); 129026048Sminshall break; 129126048Sminshall case TYPE_E: 129226048Sminshall setebcdic(); 129326048Sminshall break; 129426048Sminshall case TYPE_L: 129526048Sminshall settenex(); 129626048Sminshall break; 129726048Sminshall } 129826048Sminshall if (cpend && telflag) { 129926048Sminshall char msg[2]; 130026048Sminshall 130126048Sminshall fprintf(cout,"%c%c",IAC,IP); 130226048Sminshall (void) fflush(cout); 130326048Sminshall *msg = IAC; 130426048Sminshall *(msg+1) = DM; 130526048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 130626048Sminshall perror("abort"); 130726048Sminshall } 130826048Sminshall } 130926048Sminshall if (cpend) { 131026048Sminshall fprintf(cout,"ABOR\r\n"); 131126048Sminshall (void) fflush(cout); 131226048Sminshall mask = 1 << fileno(cin); 131326048Sminshall if ((mask = empty(mask,10)) < 0) { 131426048Sminshall perror("abort"); 131526048Sminshall if (ptabflg) { 131626048Sminshall code = -1; 131726048Sminshall } 131826048Sminshall lostpeer(); 131926048Sminshall } 132026048Sminshall (void) getreply(0); 132126048Sminshall (void) getreply(0); 132226048Sminshall } 132326048Sminshall } 132426048Sminshall pswitch(1); 132526048Sminshall if (ptabflg) { 132626048Sminshall code = -1; 132726048Sminshall } 132826048Sminshall (void) signal(SIGINT, oldintr); 132926048Sminshall return; 133026048Sminshall } 133126048Sminshall if (cpend && telflag) { 133226048Sminshall char msg[2]; 133326048Sminshall 133426048Sminshall fprintf(cout,"%c%c",IAC,IP); 133526048Sminshall (void) fflush(cout); 133626048Sminshall *msg = IAC; 133726048Sminshall *(msg+1) = DM; 133826048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 133926048Sminshall perror("abort"); 134026048Sminshall } 134126048Sminshall } 134226048Sminshall if (cpend) { 134326048Sminshall fprintf(cout,"ABOR\r\n"); 134426048Sminshall (void) fflush(cout); 134526048Sminshall mask = 1 << fileno(cin); 134626048Sminshall if ((mask = empty(mask,10)) < 0) { 134726048Sminshall perror("abort"); 134826048Sminshall if (ptabflg) { 134926048Sminshall code = -1; 135026048Sminshall } 135126048Sminshall lostpeer(); 135226048Sminshall } 135326048Sminshall (void) getreply(0); 135426048Sminshall (void) getreply(0); 135526048Sminshall } 135626048Sminshall pswitch(!proxy); 135726048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 135826048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 135926048Sminshall pswitch(0); 136026048Sminshall switch (oldtype) { 136126048Sminshall case 0: 136226048Sminshall break; 136326048Sminshall case TYPE_A: 136426048Sminshall setascii(); 136526048Sminshall break; 136626048Sminshall case TYPE_I: 136726048Sminshall setbinary(); 136826048Sminshall break; 136926048Sminshall case TYPE_E: 137026048Sminshall setebcdic(); 137126048Sminshall break; 137226048Sminshall case TYPE_L: 137326048Sminshall settenex(); 137426048Sminshall break; 137526048Sminshall } 137626048Sminshall if (cpend && telflag) { 137726048Sminshall char msg[2]; 137826048Sminshall 137926048Sminshall fprintf(cout,"%c%c",IAC,IP); 138026048Sminshall (void) fflush(cout); 138126048Sminshall *msg = IAC; 138226048Sminshall *(msg+1) = DM; 138326048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 138426048Sminshall perror("abort"); 138526048Sminshall } 138626048Sminshall } 138726048Sminshall if (cpend) { 138826048Sminshall fprintf(cout,"ABOR\r\n"); 138926048Sminshall (void) fflush(cout); 139026048Sminshall mask = 1 << fileno(cin); 139126048Sminshall if ((mask = empty(mask,10)) < 0) { 139226048Sminshall perror("abort"); 139326048Sminshall if (ptabflg) { 139426048Sminshall code = -1; 139526048Sminshall } 139626048Sminshall lostpeer(); 139726048Sminshall } 139826048Sminshall (void) getreply(0); 139926048Sminshall (void) getreply(0); 140026048Sminshall } 140126048Sminshall pswitch(1); 140226048Sminshall if (ptabflg) { 140326048Sminshall code = -1; 140426048Sminshall } 140526048Sminshall (void) signal(SIGINT, oldintr); 140626048Sminshall return; 140726048Sminshall } 140826048Sminshall } 140926048Sminshall if (cpend && telflag) { 141026048Sminshall char msg[2]; 141126048Sminshall 141226048Sminshall fprintf(cout,"%c%c",IAC,IP); 141326048Sminshall (void) fflush(cout); 141426048Sminshall *msg = IAC; 141526048Sminshall *(msg+1) = DM; 141626048Sminshall if (send(fileno(cout),msg,2,MSG_OOB) != 2) { 141726048Sminshall perror("abort"); 141826048Sminshall } 141926048Sminshall } 142026048Sminshall if (cpend) { 142126048Sminshall fprintf(cout,"ABOR\r\n"); 142226048Sminshall (void) fflush(cout); 142326048Sminshall mask = 1 << fileno(cin); 142426048Sminshall if ((mask = empty(mask,10)) < 0) { 142526048Sminshall perror("abort"); 142626048Sminshall if (ptabflg) { 142726048Sminshall code = -1; 142826048Sminshall } 142926048Sminshall lostpeer(); 143026048Sminshall } 143126048Sminshall (void) getreply(0); 143226048Sminshall (void) getreply(0); 143326048Sminshall } 143426048Sminshall pswitch(!proxy); 143526048Sminshall if (cpend) { 143626048Sminshall mask = 1 << fileno(cin); 143726048Sminshall if ((mask = empty(mask,10)) < 0) { 143826048Sminshall perror("abort"); 143926048Sminshall if (ptabflg) { 144026048Sminshall code = -1; 144126048Sminshall } 144226048Sminshall lostpeer(); 144326048Sminshall } 144426048Sminshall (void) getreply(0); 144526048Sminshall (void) getreply(0); 144626048Sminshall } 144726048Sminshall if (proxy) { 144826048Sminshall pswitch(0); 144926048Sminshall } 145026048Sminshall switch (oldtype) { 145126048Sminshall case 0: 145226048Sminshall break; 145326048Sminshall case TYPE_A: 145426048Sminshall setascii(); 145526048Sminshall break; 145626048Sminshall case TYPE_I: 145726048Sminshall setbinary(); 145826048Sminshall break; 145926048Sminshall case TYPE_E: 146026048Sminshall setebcdic(); 146126048Sminshall break; 146226048Sminshall case TYPE_L: 146326048Sminshall settenex(); 146426048Sminshall break; 146526048Sminshall } 146626048Sminshall pswitch(1); 146726048Sminshall if (ptabflg) { 146826048Sminshall code = -1; 146926048Sminshall } 147026048Sminshall (void) signal(SIGINT, oldintr); 147126048Sminshall } 147226048Sminshall 147326048Sminshall reset() 147426048Sminshall { 147526048Sminshall long mask; 147626048Sminshall 147726048Sminshall mask = 1 << fileno(cin); 147826048Sminshall while (mask > 0) { 147926048Sminshall if ((mask = empty(mask,0)) < 0) { 148026048Sminshall perror("reset"); 148126048Sminshall code = -1; 148226048Sminshall lostpeer(); 148326048Sminshall } 148426048Sminshall if (mask > 0) { 148526048Sminshall (void) getreply(0); 148626048Sminshall } 148726048Sminshall } 148826048Sminshall } 148926048Sminshall 149026048Sminshall char * 149126048Sminshall gunique(local) 149226048Sminshall char *local; 149326048Sminshall { 149426048Sminshall static char new[MAXPATHLEN]; 149526048Sminshall char *cp = rindex(local, '/'); 149626048Sminshall int d, count=0; 149726048Sminshall char ext = '1'; 149826048Sminshall 149926048Sminshall if (cp) { 150026048Sminshall *cp = '\0'; 150126048Sminshall } 150226048Sminshall d = access(cp ? local : ".", 2); 150326048Sminshall if (cp) { 150426048Sminshall *cp = '/'; 150526048Sminshall } 150626048Sminshall if (d < 0) { 150726048Sminshall perror(local); 150826048Sminshall return((char *) 0); 150926048Sminshall } 151026048Sminshall (void) strcpy(new, local); 151126048Sminshall cp = new + strlen(new); 151226048Sminshall *cp++ = '.'; 151326048Sminshall while (!d) { 151426048Sminshall if (++count == 100) { 151526048Sminshall printf("runique: can't find unique file name.\n"); 151626048Sminshall return((char *) 0); 151726048Sminshall } 151826048Sminshall *cp++ = ext; 151926048Sminshall *cp = '\0'; 152026048Sminshall if (ext == '9') { 152126048Sminshall ext = '0'; 152226048Sminshall } 152326048Sminshall else { 152426048Sminshall ext++; 152526048Sminshall } 152626048Sminshall if ((d = access(new, 0)) < 0) { 152726048Sminshall break; 152826048Sminshall } 152926048Sminshall if (ext != '0') { 153026048Sminshall cp--; 153126048Sminshall } 153226048Sminshall else if (*(cp - 2) == '.') { 153326048Sminshall *(cp - 1) = '1'; 153426048Sminshall } 153526048Sminshall else { 153626048Sminshall *(cp - 2) = *(cp - 2) + 1; 153726048Sminshall cp--; 153826048Sminshall } 153926048Sminshall } 154026048Sminshall return(new); 154126048Sminshall } 1542