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*26496Sminshall static char sccsid[] = "@(#)ftp.c 5.9 (Berkeley) 03/07/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> 17*26496Sminshall #include <sys/types.h> 1810296Ssam 1910296Ssam #include <netinet/in.h> 2012397Ssam #include <arpa/ftp.h> 2126048Sminshall #include <arpa/telnet.h> 2210296Ssam 2310296Ssam #include <stdio.h> 2410296Ssam #include <signal.h> 2510296Ssam #include <errno.h> 2610296Ssam #include <netdb.h> 2726048Sminshall #include <fcntl.h> 2826048Sminshall #include <pwd.h> 2910296Ssam 3010296Ssam struct sockaddr_in hisctladdr; 3110296Ssam struct sockaddr_in data_addr; 3210296Ssam int data = -1; 3326048Sminshall int telflag = 0; 3426048Sminshall int abrtflag = 0; 3526048Sminshall int ptflag = 0; 3610296Ssam int connected; 3710296Ssam struct sockaddr_in myctladdr; 38*26496Sminshall uid_t getuid(); 3910296Ssam 4010296Ssam FILE *cin, *cout; 4110296Ssam FILE *dataconn(); 4210296Ssam 4325904Skarels char * 4410296Ssam hookup(host, port) 4510296Ssam char *host; 4610296Ssam int port; 4710296Ssam { 4825904Skarels register struct hostent *hp = 0; 4926048Sminshall int s,len,oldverbose; 5025904Skarels static char hostnamebuf[80]; 5126048Sminshall char msg[2]; 5210296Ssam 5310296Ssam bzero((char *)&hisctladdr, sizeof (hisctladdr)); 5425904Skarels hisctladdr.sin_addr.s_addr = inet_addr(host); 5525904Skarels if (hisctladdr.sin_addr.s_addr != -1) { 5625904Skarels hisctladdr.sin_family = AF_INET; 5725904Skarels (void) strcpy(hostnamebuf, host); 5826048Sminshall } 5926048Sminshall else { 6025100Sbloom hp = gethostbyname(host); 6125904Skarels if (hp == NULL) { 6225904Skarels printf("%s: unknown host\n", host); 6326048Sminshall code = -1; 6426048Sminshall return((char *) 0); 6525904Skarels } 6625904Skarels hisctladdr.sin_family = hp->h_addrtype; 6725904Skarels bcopy(hp->h_addr_list[0], 6825904Skarels (caddr_t)&hisctladdr.sin_addr, hp->h_length); 6925904Skarels (void) strcpy(hostnamebuf, hp->h_name); 7010296Ssam } 7125904Skarels hostname = hostnamebuf; 7225904Skarels s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 7310296Ssam if (s < 0) { 7410296Ssam perror("ftp: socket"); 7526048Sminshall code = -1; 7610296Ssam return (0); 7710296Ssam } 7810296Ssam hisctladdr.sin_port = port; 79*26496Sminshall while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 8025904Skarels if (hp && hp->h_addr_list[1]) { 8125904Skarels int oerrno = errno; 8225904Skarels 8325904Skarels fprintf(stderr, "ftp: connect to address %s: ", 8425904Skarels inet_ntoa(hisctladdr.sin_addr)); 8525904Skarels errno = oerrno; 86*26496Sminshall perror((char *) 0); 8725904Skarels hp->h_addr_list++; 8825904Skarels bcopy(hp->h_addr_list[0], 8926048Sminshall (caddr_t)&hisctladdr.sin_addr, hp->h_length); 90*26496Sminshall fprintf(stdout, "Trying %s...\n", 9125904Skarels inet_ntoa(hisctladdr.sin_addr)); 9225904Skarels continue; 9325904Skarels } 9410296Ssam perror("ftp: connect"); 9526048Sminshall code = -1; 9610296Ssam goto bad; 9710296Ssam } 9811627Ssam len = sizeof (myctladdr); 9911627Ssam if (getsockname(s, (char *)&myctladdr, &len) < 0) { 10011627Ssam perror("ftp: getsockname"); 10126048Sminshall code = -1; 10210296Ssam goto bad; 10310296Ssam } 10410296Ssam cin = fdopen(s, "r"); 10510296Ssam cout = fdopen(s, "w"); 10611219Ssam if (cin == NULL || cout == NULL) { 10710296Ssam fprintf(stderr, "ftp: fdopen failed.\n"); 10810296Ssam if (cin) 109*26496Sminshall (void) fclose(cin); 11010296Ssam if (cout) 111*26496Sminshall (void) fclose(cout); 11226048Sminshall code = -1; 11310296Ssam goto bad; 11410296Ssam } 11510296Ssam if (verbose) 11626067Sminshall printf("Connected to %s.\n", hostname); 11726048Sminshall if (getreply(0) != 2) { /* read startup message from server */ 11826048Sminshall if (cin) 119*26496Sminshall (void) fclose(cin); 12026048Sminshall if (cout) 121*26496Sminshall (void) fclose(cout); 12226048Sminshall code = -1; 12326048Sminshall goto bad; 12426048Sminshall } 12526048Sminshall 12626048Sminshall /* test to see if server command parser understands TELNET SYNC command */ 12726048Sminshall 12826048Sminshall fprintf(cout,"%c%c",IAC,NOP); 12926048Sminshall (void) fflush(cout); 13026048Sminshall *msg = IAC; 13126048Sminshall *(msg+1) = DM; 13226448Slepreau if (send(s,msg,2,MSG_OOB) != 2) 13326048Sminshall perror("sync"); 13426048Sminshall oldverbose = verbose; 13526448Slepreau if (!debug) 13626048Sminshall verbose = -1; 13726448Slepreau if (command("NOOP") == COMPLETE) 13826048Sminshall telflag = 1; 13926448Slepreau else 14026048Sminshall telflag = 0; 14126048Sminshall verbose = oldverbose; 14225904Skarels return (hostname); 14310296Ssam bad: 144*26496Sminshall (void) close(s); 14525904Skarels return ((char *)0); 14610296Ssam } 14710296Ssam 14825904Skarels login(host) 14925904Skarels char *host; 15010296Ssam { 15126048Sminshall char tmp[80]; 152*26496Sminshall char *user, *pass, *acct, *getlogin(), *mygetpass(); 15326048Sminshall int n, aflag = 0; 15410296Ssam 15526048Sminshall user = pass = acct = 0; 15626048Sminshall if (ruserpass(host, &user, &pass, &acct) < 0) { 15726048Sminshall disconnect(); 15826048Sminshall code = -1; 15926048Sminshall return(0); 16026048Sminshall } 16126048Sminshall if (user == NULL) { 16226048Sminshall char *myname = getlogin(); 16326048Sminshall 16426048Sminshall if (myname == NULL) { 16526048Sminshall struct passwd *pp = getpwuid(getuid()); 16626048Sminshall 16726448Slepreau if (pp != NULL) 16826048Sminshall myname = pp->pw_name; 16926048Sminshall } 17026048Sminshall printf("Name (%s:%s): ", host, myname); 17126048Sminshall (void) fgets(tmp, sizeof(tmp) - 1, stdin); 17226048Sminshall tmp[strlen(tmp) - 1] = '\0'; 17326448Slepreau if (*tmp == '\0') 17426048Sminshall user = myname; 17526448Slepreau else 17626048Sminshall user = tmp; 17726048Sminshall } 17810296Ssam n = command("USER %s", user); 17926048Sminshall if (n == CONTINUE) { 18026448Slepreau if (pass == NULL) 181*26496Sminshall pass = mygetpass("Password:"); 18210296Ssam n = command("PASS %s", pass); 18326048Sminshall } 18410296Ssam if (n == CONTINUE) { 18526048Sminshall aflag++; 186*26496Sminshall acct = mygetpass("Account:"); 18710296Ssam n = command("ACCT %s", acct); 18810296Ssam } 18910296Ssam if (n != COMPLETE) { 19010296Ssam fprintf(stderr, "Login failed.\n"); 19110296Ssam return (0); 19210296Ssam } 19326448Slepreau if (!aflag && acct != NULL) 19426048Sminshall (void) command("ACCT %s", acct); 19526448Slepreau if (proxy) 19626048Sminshall return(1); 19726048Sminshall for (n = 0; n < macnum; ++n) { 19826048Sminshall if (!strcmp("init", macros[n].mac_name)) { 199*26496Sminshall (void) strcpy(line, "$init"); 20026048Sminshall makeargv(); 20126048Sminshall domacro(margc, margv); 20226048Sminshall break; 20326048Sminshall } 20426048Sminshall } 20510296Ssam return (1); 20610296Ssam } 20710296Ssam 20826048Sminshall cmdabort() 20926048Sminshall { 21026048Sminshall extern jmp_buf ptabort; 21126048Sminshall 21226048Sminshall printf("\n"); 21326048Sminshall (void) fflush(stdout); 21426048Sminshall abrtflag++; 21526448Slepreau if (ptflag) 21626048Sminshall longjmp(ptabort,1); 21726048Sminshall } 21826048Sminshall 219*26496Sminshall /*VARARGS1*/ 22010296Ssam command(fmt, args) 22110296Ssam char *fmt; 22210296Ssam { 22326048Sminshall int r, (*oldintr)(), cmdabort(); 22410296Ssam 22526048Sminshall abrtflag = 0; 22610296Ssam if (debug) { 22710296Ssam printf("---> "); 22810296Ssam _doprnt(fmt, &args, stdout); 22910296Ssam printf("\n"); 23010296Ssam (void) fflush(stdout); 23110296Ssam } 23211219Ssam if (cout == NULL) { 23311219Ssam perror ("No control connection for command"); 23426048Sminshall code = -1; 23511219Ssam return (0); 23611219Ssam } 23726048Sminshall oldintr = signal(SIGINT,cmdabort); 23810296Ssam _doprnt(fmt, &args, cout); 23910296Ssam fprintf(cout, "\r\n"); 24010296Ssam (void) fflush(cout); 24126048Sminshall cpend = 1; 24226048Sminshall r = getreply(!strcmp(fmt, "QUIT")); 24326448Slepreau if (abrtflag && oldintr != SIG_IGN) 24426048Sminshall (*oldintr)(); 24526048Sminshall (void) signal(SIGINT, oldintr); 24626048Sminshall return(r); 24710296Ssam } 24810296Ssam 24910296Ssam #include <ctype.h> 25010296Ssam 25110296Ssam getreply(expecteof) 25210296Ssam int expecteof; 25310296Ssam { 25411219Ssam register int c, n; 25526048Sminshall register int dig; 25626048Sminshall int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 25726048Sminshall int pflag = 0; 25826048Sminshall char *pt = pasv; 25910296Ssam 26026048Sminshall oldintr = signal(SIGINT,cmdabort); 26110296Ssam for (;;) { 26210296Ssam dig = n = code = 0; 26310296Ssam while ((c = getc(cin)) != '\n') { 26410296Ssam dig++; 26510296Ssam if (c == EOF) { 26626048Sminshall if (expecteof) { 26726048Sminshall (void) signal(SIGINT,oldintr); 26826048Sminshall code = 221; 26910296Ssam return (0); 27026048Sminshall } 27110296Ssam lostpeer(); 27226048Sminshall if (verbose) { 27326048Sminshall printf("421 Service not available, remote server has closed connection\n"); 27426048Sminshall (void) fflush(stdout); 27526048Sminshall code = 421; 27626048Sminshall return(4); 27726048Sminshall } 27810296Ssam } 27926048Sminshall if (c != '\r' && (verbose > 0 || 28026048Sminshall (verbose > -1 && n == '5' && dig > 4))) { 28126448Slepreau if (proxflag && 28226448Slepreau (dig == 1 || dig == 5 && verbose == 0)) 28326048Sminshall printf("%s:",hostname); 284*26496Sminshall (void) putchar(c); 28526048Sminshall } 28610296Ssam if (dig < 4 && isdigit(c)) 28710296Ssam code = code * 10 + (c - '0'); 28826448Slepreau if (!pflag && code == 227) 28926048Sminshall pflag = 1; 29026448Slepreau if (dig > 4 && pflag == 1 && isdigit(c)) 29126048Sminshall pflag = 2; 29226048Sminshall if (pflag == 2) { 29326448Slepreau if (c != '\r' && c != ')') 29426048Sminshall *pt++ = c; 29526048Sminshall else { 29626048Sminshall *pt = '\0'; 29726048Sminshall pflag = 3; 29826048Sminshall } 29926048Sminshall } 30026048Sminshall if (dig == 4 && c == '-') { 30126448Slepreau if (continuation) 30226048Sminshall code = 0; 30310296Ssam continuation++; 30426048Sminshall } 30510296Ssam if (n == 0) 30610296Ssam n = c; 30710296Ssam } 30826048Sminshall if (verbose > 0 || verbose > -1 && n == '5') { 309*26496Sminshall (void) putchar(c); 31011346Ssam (void) fflush (stdout); 31111346Ssam } 31210296Ssam if (continuation && code != originalcode) { 31310296Ssam if (originalcode == 0) 31410296Ssam originalcode = code; 31510296Ssam continue; 31610296Ssam } 31726448Slepreau if (n != '1') 31826048Sminshall cpend = 0; 31926048Sminshall (void) signal(SIGINT,oldintr); 32026448Slepreau if (code == 421 || originalcode == 421) 32126048Sminshall lostpeer(); 32226448Slepreau if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 32326048Sminshall (*oldintr)(); 32425907Smckusick return (n - '0'); 32510296Ssam } 32610296Ssam } 32710296Ssam 32826048Sminshall empty(mask, sec) 329*26496Sminshall struct fd_set mask; 33026048Sminshall int sec; 33126048Sminshall { 33226048Sminshall struct timeval t; 33326048Sminshall 33426048Sminshall t.tv_sec = (long) sec; 33526048Sminshall t.tv_usec = 0; 336*26496Sminshall if (select(20, &mask, (struct fd_set *) 0, (struct fd_set *) 0, &t) < 0) 33726048Sminshall return(-1); 338*26496Sminshall return (1); 33926048Sminshall } 34026048Sminshall 34110296Ssam jmp_buf sendabort; 34210296Ssam 34310296Ssam abortsend() 34410296Ssam { 34510296Ssam 34626048Sminshall mflag = 0; 34726048Sminshall abrtflag = 0; 34826048Sminshall printf("\nsend aborted\n"); 34926048Sminshall (void) fflush(stdout); 35010296Ssam longjmp(sendabort, 1); 35110296Ssam } 35210296Ssam 35310296Ssam sendrequest(cmd, local, remote) 35410296Ssam char *cmd, *local, *remote; 35510296Ssam { 356*26496Sminshall FILE *fin, *dout = 0, *mypopen(); 357*26496Sminshall int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 35826048Sminshall int abortsend(); 35911219Ssam char buf[BUFSIZ]; 36011651Ssam long bytes = 0, hashbytes = sizeof (buf); 36111346Ssam register int c, d; 36210296Ssam struct stat st; 36310296Ssam struct timeval start, stop; 36410296Ssam 36526048Sminshall if (proxy) { 36626048Sminshall proxtrans(cmd, local, remote); 36726048Sminshall return; 36826048Sminshall } 36910296Ssam closefunc = NULL; 37026048Sminshall oldintr = NULL; 37126048Sminshall oldintp = NULL; 37226048Sminshall if (setjmp(sendabort)) { 37326048Sminshall while (cpend) { 37426048Sminshall (void) getreply(0); 37526048Sminshall } 37626048Sminshall if (data >= 0) { 37726048Sminshall (void) close(data); 37826048Sminshall data = -1; 37926048Sminshall } 38026448Slepreau if (oldintr) 38126048Sminshall (void) signal(SIGINT,oldintr); 38226448Slepreau if (oldintp) 38326048Sminshall (void) signal(SIGPIPE,oldintp); 38426048Sminshall code = -1; 38526048Sminshall return; 38626048Sminshall } 38710296Ssam oldintr = signal(SIGINT, abortsend); 38810296Ssam if (strcmp(local, "-") == 0) 38910296Ssam fin = stdin; 39010296Ssam else if (*local == '|') { 39126048Sminshall oldintp = signal(SIGPIPE,SIG_IGN); 392*26496Sminshall fin = mypopen(local + 1, "r"); 39310296Ssam if (fin == NULL) { 39426048Sminshall perror(local + 1); 39526048Sminshall (void) signal(SIGINT, oldintr); 39626048Sminshall (void) signal(SIGPIPE, oldintp); 39726048Sminshall code = -1; 39826048Sminshall return; 39910296Ssam } 400*26496Sminshall closefunc = mypclose; 40110296Ssam } else { 40210296Ssam fin = fopen(local, "r"); 40310296Ssam if (fin == NULL) { 40410296Ssam perror(local); 40526048Sminshall (void) signal(SIGINT, oldintr); 40626048Sminshall code = -1; 40726048Sminshall return; 40810296Ssam } 40910296Ssam closefunc = fclose; 41010296Ssam if (fstat(fileno(fin), &st) < 0 || 41110296Ssam (st.st_mode&S_IFMT) != S_IFREG) { 412*26496Sminshall fprintf(stdout, "%s: not a plain file.\n", local); 41326048Sminshall (void) signal(SIGINT, oldintr); 41426048Sminshall code = -1; 41526048Sminshall return; 41610296Ssam } 41710296Ssam } 41826048Sminshall if (initconn()) { 41926048Sminshall (void) signal(SIGINT, oldintr); 42026448Slepreau if (oldintp) 42126048Sminshall (void) signal(SIGPIPE, oldintp); 42226048Sminshall code = -1; 42326048Sminshall return; 42426048Sminshall } 42526448Slepreau if (setjmp(sendabort)) 42626048Sminshall goto abort; 42710296Ssam if (remote) { 42826048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 42926048Sminshall (void) signal(SIGINT, oldintr); 43026448Slepreau if (oldintp) 43126048Sminshall (void) signal(SIGPIPE, oldintp); 43226048Sminshall return; 43326048Sminshall } 43410296Ssam } else 43526048Sminshall if (command("%s", cmd) != PRELIM) { 43626048Sminshall (void) signal(SIGINT, oldintr); 43726448Slepreau if (oldintp) 43826048Sminshall (void) signal(SIGPIPE, oldintp); 43926048Sminshall return; 44026048Sminshall } 44110296Ssam dout = dataconn("w"); 44226448Slepreau if (dout == NULL) 44326048Sminshall goto abort; 444*26496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 44511219Ssam switch (type) { 44611219Ssam 44711219Ssam case TYPE_I: 44811219Ssam case TYPE_L: 44911346Ssam errno = d = 0; 45011219Ssam while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 45111346Ssam if ((d = write(fileno (dout), buf, c)) < 0) 45211219Ssam break; 45311219Ssam bytes += c; 45411651Ssam if (hash) { 455*26496Sminshall (void) putchar('#'); 456*26496Sminshall (void) fflush(stdout); 45711651Ssam } 45811219Ssam } 45913213Ssam if (hash && bytes > 0) { 460*26496Sminshall (void) putchar('\n'); 461*26496Sminshall (void) fflush(stdout); 46211651Ssam } 46311219Ssam if (c < 0) 46411219Ssam perror(local); 46511346Ssam if (d < 0) 46611219Ssam perror("netout"); 46711219Ssam break; 46811219Ssam 46911219Ssam case TYPE_A: 47011219Ssam while ((c = getc(fin)) != EOF) { 47111219Ssam if (c == '\n') { 47211651Ssam while (hash && (bytes >= hashbytes)) { 473*26496Sminshall (void) putchar('#'); 474*26496Sminshall (void) fflush(stdout); 47511651Ssam hashbytes += sizeof (buf); 47611651Ssam } 47711219Ssam if (ferror(dout)) 47811219Ssam break; 479*26496Sminshall (void) putc('\r', dout); 48011219Ssam bytes++; 48111219Ssam } 482*26496Sminshall (void) putc(c, dout); 48311219Ssam bytes++; 48426048Sminshall /* if (c == '\r') { */ 485*26496Sminshall /* (void) putc('\0', dout); /* this violates rfc */ 48626048Sminshall /* bytes++; */ 48726048Sminshall /* } */ 48811219Ssam } 48911651Ssam if (hash) { 49013213Ssam if (bytes < hashbytes) 491*26496Sminshall (void) putchar('#'); 492*26496Sminshall (void) putchar('\n'); 493*26496Sminshall (void) fflush(stdout); 49411651Ssam } 49511219Ssam if (ferror(fin)) 49611219Ssam perror(local); 49711346Ssam if (ferror(dout)) 49811219Ssam perror("netout"); 49911219Ssam break; 50010296Ssam } 501*26496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 50210296Ssam if (closefunc != NULL) 50326048Sminshall (*closefunc)(fin); 50410296Ssam (void) fclose(dout); 50526048Sminshall (void) getreply(0); 50626048Sminshall (void) signal(SIGINT, oldintr); 50710296Ssam if (bytes > 0 && verbose) 50826048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 50910296Ssam return; 51026048Sminshall abort: 511*26496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 51226048Sminshall (void) signal(SIGINT, oldintr); 51326448Slepreau if (oldintp) 51426048Sminshall (void) signal(SIGPIPE, oldintp); 51526048Sminshall if (!cpend) { 51626048Sminshall code = -1; 51726048Sminshall return; 51826048Sminshall } 51926048Sminshall if (data >= 0) { 52026048Sminshall (void) close(data); 52126048Sminshall data = -1; 52226048Sminshall } 52326448Slepreau if (dout) 52426048Sminshall (void) fclose(dout); 52526048Sminshall (void) getreply(0); 52626048Sminshall code = -1; 52710296Ssam if (closefunc != NULL && fin != NULL) 52826048Sminshall (*closefunc)(fin); 52926048Sminshall if (bytes > 0 && verbose) 53026048Sminshall ptransfer("sent", bytes, &start, &stop, local, remote); 53110296Ssam } 53210296Ssam 53310296Ssam jmp_buf recvabort; 53410296Ssam 53510296Ssam abortrecv() 53610296Ssam { 53710296Ssam 53826048Sminshall mflag = 0; 53926048Sminshall abrtflag = 0; 54026048Sminshall printf("\n"); 54126048Sminshall (void) fflush(stdout); 54210296Ssam longjmp(recvabort, 1); 54310296Ssam } 54410296Ssam 54511651Ssam recvrequest(cmd, local, remote, mode) 54611651Ssam char *cmd, *local, *remote, *mode; 54710296Ssam { 548*26496Sminshall FILE *fout, *din = 0, *mypopen(); 549*26496Sminshall int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 55026048Sminshall int abortrecv(), oldverbose, oldtype = 0, tcrflag; 55126048Sminshall char buf[BUFSIZ], *gunique(); 552*26496Sminshall long bytes = 0, hashbytes = sizeof (buf); 553*26496Sminshall struct fd_set mask; 55411346Ssam register int c, d; 55510296Ssam struct timeval start, stop; 55610296Ssam 55726048Sminshall if (proxy && strcmp(cmd,"RETR") == 0) { 55826048Sminshall proxtrans(cmd, local, remote); 55926048Sminshall return; 56026048Sminshall } 56110296Ssam closefunc = NULL; 56226048Sminshall oldintr = NULL; 56326048Sminshall oldintp = NULL; 56426048Sminshall tcrflag = !crflag && !strcmp(cmd, "RETR"); 56526048Sminshall if (setjmp(recvabort)) { 56626048Sminshall while (cpend) { 56726048Sminshall (void) getreply(0); 56826048Sminshall } 56926048Sminshall if (data >= 0) { 57026048Sminshall (void) close(data); 57126048Sminshall data = -1; 57226048Sminshall } 57326448Slepreau if (oldintr) 57426048Sminshall (void) signal(SIGINT, oldintr); 57526048Sminshall code = -1; 57626048Sminshall return; 57726048Sminshall } 57810296Ssam oldintr = signal(SIGINT, abortrecv); 57926048Sminshall if (strcmp(local, "-") && *local != '|') { 58010296Ssam if (access(local, 2) < 0) { 58126048Sminshall char *dir = rindex(local, '/'); 58210296Ssam 58326048Sminshall if (errno != ENOENT && errno != EACCES) { 58410296Ssam perror(local); 58526048Sminshall (void) signal(SIGINT, oldintr); 58626048Sminshall code = -1; 58726048Sminshall return; 58810296Ssam } 58926048Sminshall if (dir != NULL) 59026048Sminshall *dir = 0; 59126048Sminshall d = access(dir ? local : ".", 2); 59226048Sminshall if (dir != NULL) 59326048Sminshall *dir = '/'; 59426048Sminshall if (d < 0) { 59526048Sminshall perror(local); 59626048Sminshall (void) signal(SIGINT, oldintr); 59726048Sminshall code = -1; 59826048Sminshall return; 59926048Sminshall } 60026048Sminshall if (!runique && errno == EACCES && 60126048Sminshall chmod(local,0600) < 0) { 60226048Sminshall perror(local); 60326048Sminshall (void) signal(SIGINT, oldintr); 60426048Sminshall code = -1; 60526048Sminshall return; 60626048Sminshall } 60726048Sminshall if (runique && errno == EACCES && 60826048Sminshall (local = gunique(local)) == NULL) { 60926048Sminshall (void) signal(SIGINT, oldintr); 61026048Sminshall code = -1; 61126048Sminshall return; 61226048Sminshall } 61310296Ssam } 61426048Sminshall else if (runique && (local = gunique(local)) == NULL) { 61526048Sminshall (void) signal(SIGINT, oldintr); 61626048Sminshall code = -1; 61726048Sminshall return; 61826048Sminshall } 61926048Sminshall } 62026048Sminshall if (initconn()) { 62126048Sminshall (void) signal(SIGINT, oldintr); 62226048Sminshall code = -1; 62326048Sminshall return; 62426048Sminshall } 62526448Slepreau if (setjmp(recvabort)) 62626048Sminshall goto abort; 62726048Sminshall if (strcmp(cmd, "RETR") && type != TYPE_A) { 62826048Sminshall oldtype = type; 62926048Sminshall oldverbose = verbose; 63026448Slepreau if (!debug) 63126048Sminshall verbose = 0; 63226048Sminshall setascii(); 63326048Sminshall verbose = oldverbose; 63426048Sminshall } 63510296Ssam if (remote) { 63626048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 63726048Sminshall (void) signal(SIGINT, oldintr); 63826048Sminshall if (oldtype) { 63926448Slepreau if (!debug) 64026048Sminshall verbose = 0; 64126048Sminshall switch (oldtype) { 64226048Sminshall case TYPE_I: 64326048Sminshall setbinary(); 64426048Sminshall break; 64526048Sminshall case TYPE_E: 64626048Sminshall setebcdic(); 64726048Sminshall break; 64826048Sminshall case TYPE_L: 64926048Sminshall settenex(); 65026048Sminshall break; 65126048Sminshall } 65226048Sminshall verbose = oldverbose; 65326048Sminshall } 65426048Sminshall return; 65526048Sminshall } 65626048Sminshall } else { 65726048Sminshall if (command("%s", cmd) != PRELIM) { 65826048Sminshall (void) signal(SIGINT, oldintr); 65926048Sminshall if (oldtype) { 66026448Slepreau if (!debug) 66126048Sminshall verbose = 0; 66226048Sminshall switch (oldtype) { 66326048Sminshall case TYPE_I: 66426048Sminshall setbinary(); 66526048Sminshall break; 66626048Sminshall case TYPE_E: 66726048Sminshall setebcdic(); 66826048Sminshall break; 66926048Sminshall case TYPE_L: 67026048Sminshall settenex(); 67126048Sminshall break; 67226048Sminshall } 67326048Sminshall verbose = oldverbose; 67426048Sminshall } 67526048Sminshall return; 67626048Sminshall } 67726048Sminshall } 67826048Sminshall din = dataconn("r"); 67926048Sminshall if (din == NULL) 68026048Sminshall goto abort; 68126448Slepreau if (strcmp(local, "-") == 0) 68210296Ssam fout = stdout; 68310296Ssam else if (*local == '|') { 68426048Sminshall oldintp = signal(SIGPIPE, SIG_IGN); 685*26496Sminshall fout = mypopen(local + 1, "w"); 68626048Sminshall if (fout == NULL) { 68726048Sminshall perror(local+1); 68826048Sminshall goto abort; 68926048Sminshall } 690*26496Sminshall closefunc = mypclose; 69126048Sminshall } 69226048Sminshall else { 69311651Ssam fout = fopen(local, mode); 69426048Sminshall if (fout == NULL) { 69526048Sminshall perror(local); 69626048Sminshall goto abort; 69726048Sminshall } 69810296Ssam closefunc = fclose; 69910296Ssam } 700*26496Sminshall (void) gettimeofday(&start, (struct timezone *)0); 70111219Ssam switch (type) { 70211219Ssam 70311219Ssam case TYPE_I: 70411219Ssam case TYPE_L: 70511346Ssam errno = d = 0; 70611219Ssam while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 70711346Ssam if ((d = write(fileno(fout), buf, c)) < 0) 70811219Ssam break; 70911219Ssam bytes += c; 71011651Ssam if (hash) { 711*26496Sminshall (void) putchar('#'); 712*26496Sminshall (void) fflush(stdout); 71311651Ssam } 71411219Ssam } 71513213Ssam if (hash && bytes > 0) { 716*26496Sminshall (void) putchar('\n'); 717*26496Sminshall (void) fflush(stdout); 71811651Ssam } 71911219Ssam if (c < 0) 72011219Ssam perror("netin"); 72111346Ssam if (d < 0) 72210296Ssam perror(local); 72311219Ssam break; 72411219Ssam 72511219Ssam case TYPE_A: 72611219Ssam while ((c = getc(din)) != EOF) { 72711219Ssam if (c == '\r') { 72811651Ssam while (hash && (bytes >= hashbytes)) { 729*26496Sminshall (void) putchar('#'); 730*26496Sminshall (void) fflush(stdout); 73111651Ssam hashbytes += sizeof (buf); 73211651Ssam } 73310296Ssam bytes++; 73426048Sminshall if ((c = getc(din)) != '\n' || tcrflag) { 73511219Ssam if (ferror (fout)) 73611219Ssam break; 737*26496Sminshall (void) putc ('\r', fout); 73811219Ssam } 73926048Sminshall /*if (c == '\0') { 74011219Ssam bytes++; 74111219Ssam continue; 74226048Sminshall }*/ 74311219Ssam } 744*26496Sminshall (void) putc (c, fout); 74511219Ssam bytes++; 74610296Ssam } 74711651Ssam if (hash) { 74813213Ssam if (bytes < hashbytes) 749*26496Sminshall (void) putchar('#'); 750*26496Sminshall (void) putchar('\n'); 751*26496Sminshall (void) fflush(stdout); 75211651Ssam } 75311219Ssam if (ferror (din)) 75411219Ssam perror ("netin"); 75511219Ssam if (ferror (fout)) 75611219Ssam perror (local); 75711219Ssam break; 75810296Ssam } 75926448Slepreau if (closefunc != NULL) 76026048Sminshall (*closefunc)(fout); 761*26496Sminshall (void) signal(SIGINT, oldintr); 76226448Slepreau if (oldintp) 76326048Sminshall (void) signal(SIGPIPE, oldintp); 764*26496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 76510296Ssam (void) fclose(din); 76626048Sminshall (void) getreply(0); 76726048Sminshall if (bytes > 0 && verbose) 76826048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 76926048Sminshall if (oldtype) { 77026448Slepreau if (!debug) 77126048Sminshall verbose = 0; 77226048Sminshall switch (oldtype) { 77326048Sminshall case TYPE_I: 77426048Sminshall setbinary(); 77526048Sminshall break; 77626048Sminshall case TYPE_E: 77726048Sminshall setebcdic(); 77826048Sminshall break; 77926048Sminshall case TYPE_L: 78026048Sminshall settenex(); 78126048Sminshall break; 78226048Sminshall } 78326048Sminshall verbose = oldverbose; 78426048Sminshall } 78526048Sminshall return; 78626048Sminshall abort: 78726048Sminshall 78826048Sminshall /* if server command parser understands TELNET commands, abort using */ 78926048Sminshall /* recommended IP,SYNC sequence */ 79026048Sminshall 791*26496Sminshall (void) gettimeofday(&stop, (struct timezone *)0); 79226448Slepreau if (oldintp) 79326048Sminshall (void) signal(SIGPIPE, oldintr); 79426048Sminshall (void) signal(SIGINT,SIG_IGN); 79526048Sminshall if (oldtype) { 79626448Slepreau if (!debug) 79726048Sminshall verbose = 0; 79826048Sminshall switch (oldtype) { 79926048Sminshall case TYPE_I: 80026048Sminshall setbinary(); 80126048Sminshall break; 80226048Sminshall case TYPE_E: 80326048Sminshall setebcdic(); 80426048Sminshall break; 80526048Sminshall case TYPE_L: 80626048Sminshall settenex(); 80726048Sminshall break; 80826048Sminshall } 80926048Sminshall verbose = oldverbose; 81026048Sminshall } 81126048Sminshall if (!cpend) { 81226048Sminshall code = -1; 81326048Sminshall (void) signal(SIGINT,oldintr); 81426048Sminshall return; 81526048Sminshall } 81626048Sminshall if (telflag) { 81726048Sminshall char msg[2]; 81826048Sminshall 81926048Sminshall fprintf(cout,"%c%c",IAC,IP); 82026048Sminshall (void) fflush(cout); 82126048Sminshall *msg = IAC; 82226048Sminshall *(msg+1) = DM; 82326448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 82426048Sminshall perror("abort"); 82526048Sminshall } 82626048Sminshall fprintf(cout,"ABOR\r\n"); 82726048Sminshall (void) fflush(cout); 828*26496Sminshall FD_ZERO((char *) &mask); 829*26496Sminshall FD_SET(fileno(cin), &mask); 830*26496Sminshall if (din) { 831*26496Sminshall FD_SET(fileno(din), &mask); 832*26496Sminshall } 833*26496Sminshall if (empty(mask,10) < 0) { 83426048Sminshall perror("abort"); 83526048Sminshall code = -1; 83626048Sminshall lostpeer(); 83726048Sminshall } 838*26496Sminshall if (din && FD_ISSET(fileno(din), &mask)) { 83926448Slepreau while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 84026448Slepreau ; 841*26496Sminshall } 84226048Sminshall if ((c = getreply(0)) == ERROR) { /* needed for nic style abort */ 84326048Sminshall if (data >= 0) { 844*26496Sminshall (void) close(data); 84526048Sminshall data = -1; 84626048Sminshall } 84725907Smckusick (void) getreply(0); 84825907Smckusick } 84926048Sminshall (void) getreply(0); 85026048Sminshall code = -1; 85126048Sminshall if (data >= 0) { 85226048Sminshall (void) close(data); 85326048Sminshall data = -1; 85426048Sminshall } 85526448Slepreau if (closefunc != NULL && fout != NULL) 85626048Sminshall (*closefunc)(fout); 85726448Slepreau if (din) 85826048Sminshall (void) fclose(din); 85910296Ssam if (bytes > 0 && verbose) 86026048Sminshall ptransfer("received", bytes, &start, &stop, local, remote); 86126048Sminshall (void) signal(SIGINT,oldintr); 86210296Ssam } 86310296Ssam 86410296Ssam /* 86510296Ssam * Need to start a listen on the data channel 86610296Ssam * before we send the command, otherwise the 86710296Ssam * server's connect may fail. 86810296Ssam */ 86911651Ssam static int sendport = -1; 87011651Ssam 87110296Ssam initconn() 87210296Ssam { 87310296Ssam register char *p, *a; 87426048Sminshall int result, len, tmpno = 0; 875*26496Sminshall char on = 1; 87610296Ssam 87711651Ssam noport: 87810296Ssam data_addr = myctladdr; 87911651Ssam if (sendport) 88011651Ssam data_addr.sin_port = 0; /* let system pick one */ 88111651Ssam if (data != -1) 88211651Ssam (void) close (data); 88318287Sralph data = socket(AF_INET, SOCK_STREAM, 0); 88410296Ssam if (data < 0) { 88510296Ssam perror("ftp: socket"); 88626448Slepreau if (tmpno) 88726048Sminshall sendport = 1; 88810296Ssam return (1); 88910296Ssam } 89012397Ssam if (!sendport) 89117450Slepreau if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { 89226048Sminshall perror("ftp: setsockopt (resuse address)"); 89312397Ssam goto bad; 89412397Ssam } 895*26496Sminshall if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 89610296Ssam perror("ftp: bind"); 89710296Ssam goto bad; 89810296Ssam } 89910296Ssam if (options & SO_DEBUG && 90017450Slepreau setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 90110296Ssam perror("ftp: setsockopt (ignored)"); 90211627Ssam len = sizeof (data_addr); 90311627Ssam if (getsockname(data, (char *)&data_addr, &len) < 0) { 90411627Ssam perror("ftp: getsockname"); 90510296Ssam goto bad; 90610296Ssam } 90726448Slepreau if (listen(data, 1) < 0) 90810296Ssam perror("ftp: listen"); 90911651Ssam if (sendport) { 91011651Ssam a = (char *)&data_addr.sin_addr; 91111651Ssam p = (char *)&data_addr.sin_port; 91210296Ssam #define UC(b) (((int)b)&0xff) 91311651Ssam result = 91411651Ssam command("PORT %d,%d,%d,%d,%d,%d", 91511651Ssam UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 91611651Ssam UC(p[0]), UC(p[1])); 91711651Ssam if (result == ERROR && sendport == -1) { 91811651Ssam sendport = 0; 91926048Sminshall tmpno = 1; 92011651Ssam goto noport; 92111651Ssam } 92211651Ssam return (result != COMPLETE); 92311651Ssam } 92426448Slepreau if (tmpno) 92526048Sminshall sendport = 1; 92611651Ssam return (0); 92710296Ssam bad: 92810296Ssam (void) close(data), data = -1; 92926448Slepreau if (tmpno) 93026048Sminshall sendport = 1; 93110296Ssam return (1); 93210296Ssam } 93310296Ssam 93410296Ssam FILE * 93510296Ssam dataconn(mode) 93610296Ssam char *mode; 93710296Ssam { 93810296Ssam struct sockaddr_in from; 93910296Ssam int s, fromlen = sizeof (from); 94010296Ssam 941*26496Sminshall s = accept(data, (struct sockaddr *) &from, &fromlen); 94210296Ssam if (s < 0) { 94310296Ssam perror("ftp: accept"); 94410296Ssam (void) close(data), data = -1; 94510296Ssam return (NULL); 94610296Ssam } 94710296Ssam (void) close(data); 94810296Ssam data = s; 94910296Ssam return (fdopen(data, mode)); 95010296Ssam } 95110296Ssam 95226048Sminshall ptransfer(direction, bytes, t0, t1, local, remote) 95326048Sminshall char *direction, *local, *remote; 95411651Ssam long bytes; 95510296Ssam struct timeval *t0, *t1; 95610296Ssam { 95710296Ssam struct timeval td; 95816437Sleres float s, bs; 95910296Ssam 96010296Ssam tvsub(&td, t1, t0); 96116437Sleres s = td.tv_sec + (td.tv_usec / 1000000.); 96210296Ssam #define nz(x) ((x) == 0 ? 1 : (x)) 96316437Sleres bs = bytes / nz(s); 96426448Slepreau if (local && *local != '-') 96526048Sminshall printf("local: %s ", local); 96626448Slepreau if (remote) 96726048Sminshall printf("remote: %s\n", remote); 96816437Sleres printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 96916437Sleres bytes, direction, s, bs / 1024.); 97010296Ssam } 97110296Ssam 972*26496Sminshall /*tvadd(tsum, t0) 97310296Ssam struct timeval *tsum, *t0; 97410296Ssam { 97510296Ssam 97610296Ssam tsum->tv_sec += t0->tv_sec; 97710296Ssam tsum->tv_usec += t0->tv_usec; 97810296Ssam if (tsum->tv_usec > 1000000) 97910296Ssam tsum->tv_sec++, tsum->tv_usec -= 1000000; 980*26496Sminshall } */ 98110296Ssam 98210296Ssam tvsub(tdiff, t1, t0) 98310296Ssam struct timeval *tdiff, *t1, *t0; 98410296Ssam { 98510296Ssam 98610296Ssam tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 98710296Ssam tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 98810296Ssam if (tdiff->tv_usec < 0) 98910296Ssam tdiff->tv_sec--, tdiff->tv_usec += 1000000; 99010296Ssam } 99126048Sminshall 99226048Sminshall psabort() 99326048Sminshall { 99426048Sminshall extern int abrtflag; 99526048Sminshall 99626048Sminshall abrtflag++; 99726048Sminshall } 99826048Sminshall 99926048Sminshall pswitch(flag) 100026048Sminshall int flag; 100126048Sminshall { 100226048Sminshall extern int proxy, abrtflag; 100326048Sminshall int (*oldintr)(); 100426048Sminshall static struct comvars { 100526048Sminshall int connect; 100626048Sminshall char name[32]; 100726048Sminshall struct sockaddr_in mctl; 100826048Sminshall struct sockaddr_in hctl; 100926048Sminshall FILE *in; 101026048Sminshall FILE *out; 101126048Sminshall int tflag; 101226048Sminshall int tpe; 101326048Sminshall int cpnd; 101426048Sminshall int sunqe; 101526048Sminshall int runqe; 101626048Sminshall int mcse; 101726048Sminshall int ntflg; 101826048Sminshall char nti[17]; 101926048Sminshall char nto[17]; 102026048Sminshall int mapflg; 102126048Sminshall char mi[MAXPATHLEN]; 102226048Sminshall char mo[MAXPATHLEN]; 102326048Sminshall } proxstruct, tmpstruct; 102426048Sminshall struct comvars *ip, *op; 102526048Sminshall 102626048Sminshall abrtflag = 0; 102726048Sminshall oldintr = signal(SIGINT, psabort); 102826048Sminshall if (flag) { 102926448Slepreau if (proxy) 103026048Sminshall return; 103126048Sminshall ip = &tmpstruct; 103226048Sminshall op = &proxstruct; 103326048Sminshall proxy++; 103426048Sminshall } 103526048Sminshall else { 103626448Slepreau if (!proxy) 103726048Sminshall return; 103826048Sminshall ip = &proxstruct; 103926048Sminshall op = &tmpstruct; 104026048Sminshall proxy = 0; 104126048Sminshall } 104226048Sminshall ip->connect = connected; 104326048Sminshall connected = op->connect; 1044*26496Sminshall (void) strncpy(ip->name, hostname, 31); 104526048Sminshall (ip->name)[strlen(ip->name)] = '\0'; 104626048Sminshall hostname = op->name; 104726048Sminshall ip->hctl = hisctladdr; 104826048Sminshall hisctladdr = op->hctl; 104926048Sminshall ip->mctl = myctladdr; 105026048Sminshall myctladdr = op->mctl; 105126048Sminshall ip->in = cin; 105226048Sminshall cin = op->in; 105326048Sminshall ip->out = cout; 105426048Sminshall cout = op->out; 105526048Sminshall ip->tflag = telflag; 105626048Sminshall telflag = op->tflag; 105726048Sminshall ip->tpe = type; 105826048Sminshall type = op->tpe; 105926448Slepreau if (!type) 106026048Sminshall type = 1; 106126048Sminshall ip->cpnd = cpend; 106226048Sminshall cpend = op->cpnd; 106326048Sminshall ip->sunqe = sunique; 106426048Sminshall sunique = op->sunqe; 106526048Sminshall ip->runqe = runique; 106626048Sminshall runique = op->runqe; 106726048Sminshall ip->mcse = mcase; 106826048Sminshall mcase = op->mcse; 106926048Sminshall ip->ntflg = ntflag; 107026048Sminshall ntflag = op->ntflg; 1071*26496Sminshall (void) strncpy(ip->nti, ntin, 16); 107226048Sminshall (ip->nti)[strlen(ip->nti)] = '\0'; 1073*26496Sminshall (void) strcpy(ntin, op->nti); 1074*26496Sminshall (void) strncpy(ip->nto, ntout, 16); 107526048Sminshall (ip->nto)[strlen(ip->nto)] = '\0'; 1076*26496Sminshall (void) strcpy(ntout, op->nto); 107726048Sminshall ip->mapflg = mapflag; 107826048Sminshall mapflag = op->mapflg; 1079*26496Sminshall (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 108026048Sminshall (ip->mi)[strlen(ip->mi)] = '\0'; 1081*26496Sminshall (void) strcpy(mapin, op->mi); 1082*26496Sminshall (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 108326048Sminshall (ip->mo)[strlen(ip->mo)] = '\0'; 1084*26496Sminshall (void) strcpy(mapout, op->mo); 108526048Sminshall (void) signal(SIGINT, oldintr); 108626048Sminshall if (abrtflag) { 108726048Sminshall abrtflag = 0; 108826048Sminshall (*oldintr)(); 108926448Slepreau } 109026048Sminshall } 109126048Sminshall 109226048Sminshall jmp_buf ptabort; 109326048Sminshall int ptabflg; 109426048Sminshall 109526048Sminshall abortpt() 109626048Sminshall { 109726048Sminshall printf("\n"); 1098*26496Sminshall (void) fflush(stdout); 109926048Sminshall ptabflg++; 110026048Sminshall mflag = 0; 110126048Sminshall abrtflag = 0; 110226048Sminshall longjmp(ptabort, 1); 110326048Sminshall } 110426048Sminshall 110526048Sminshall proxtrans(cmd, local, remote) 110626048Sminshall char *cmd, *local, *remote; 110726048Sminshall { 110826048Sminshall int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0; 110926048Sminshall extern jmp_buf ptabort; 111026048Sminshall char *cmd2; 1111*26496Sminshall struct fd_set mask; 111226048Sminshall 111326448Slepreau if (strcmp(cmd, "RETR")) 111426048Sminshall cmd2 = "RETR"; 111526448Slepreau else 111626048Sminshall cmd2 = runique ? "STOU" : "STOR"; 111726048Sminshall if (command("PASV") != COMPLETE) { 111826048Sminshall printf("proxy server does not support third part transfers.\n"); 111926048Sminshall return; 112026048Sminshall } 112126048Sminshall tmptype = type; 112226048Sminshall pswitch(0); 112326048Sminshall if (!connected) { 112426048Sminshall printf("No primary connection\n"); 112526048Sminshall pswitch(1); 112626048Sminshall code = -1; 112726048Sminshall return; 112826048Sminshall } 112926048Sminshall if (type != tmptype) { 113026048Sminshall oldtype = type; 113126048Sminshall switch (tmptype) { 113226048Sminshall case TYPE_A: 113326048Sminshall setascii(); 113426048Sminshall break; 113526048Sminshall case TYPE_I: 113626048Sminshall setbinary(); 113726048Sminshall break; 113826048Sminshall case TYPE_E: 113926048Sminshall setebcdic(); 114026048Sminshall break; 114126048Sminshall case TYPE_L: 114226048Sminshall settenex(); 114326048Sminshall break; 114426048Sminshall } 114526048Sminshall } 114626048Sminshall if (command("PORT %s", pasv) != COMPLETE) { 114726048Sminshall switch (oldtype) { 114826048Sminshall case 0: 114926048Sminshall break; 115026048Sminshall case TYPE_A: 115126048Sminshall setascii(); 115226048Sminshall break; 115326048Sminshall case TYPE_I: 115426048Sminshall setbinary(); 115526048Sminshall break; 115626048Sminshall case TYPE_E: 115726048Sminshall setebcdic(); 115826048Sminshall break; 115926048Sminshall case TYPE_L: 116026048Sminshall settenex(); 116126048Sminshall break; 116226048Sminshall } 116326048Sminshall pswitch(1); 116426048Sminshall return; 116526048Sminshall } 116626448Slepreau if (setjmp(ptabort)) 116726048Sminshall goto abort; 116826048Sminshall oldintr = signal(SIGINT, abortpt); 116926048Sminshall if (command("%s %s", cmd, remote) != PRELIM) { 117026048Sminshall (void) signal(SIGINT, oldintr); 117126048Sminshall switch (oldtype) { 117226048Sminshall case 0: 117326048Sminshall break; 117426048Sminshall case TYPE_A: 117526048Sminshall setascii(); 117626048Sminshall break; 117726048Sminshall case TYPE_I: 117826048Sminshall setbinary(); 117926048Sminshall break; 118026048Sminshall case TYPE_E: 118126048Sminshall setebcdic(); 118226048Sminshall break; 118326048Sminshall case TYPE_L: 118426048Sminshall settenex(); 118526048Sminshall break; 118626048Sminshall } 118726048Sminshall pswitch(1); 118826048Sminshall return; 118926048Sminshall } 119026048Sminshall sleep(2); 119126048Sminshall pswitch(1); 119226048Sminshall secndflag++; 119326448Slepreau if (command("%s %s", cmd2, local) != PRELIM) 119426048Sminshall goto abort; 119526048Sminshall ptflag++; 119626048Sminshall (void) getreply(0); 119726048Sminshall pswitch(0); 119826048Sminshall (void) getreply(0); 119926048Sminshall (void) signal(SIGINT, oldintr); 120026048Sminshall switch (oldtype) { 120126048Sminshall case 0: 120226048Sminshall break; 120326048Sminshall case TYPE_A: 120426048Sminshall setascii(); 120526048Sminshall break; 120626048Sminshall case TYPE_I: 120726048Sminshall setbinary(); 120826048Sminshall break; 120926048Sminshall case TYPE_E: 121026048Sminshall setebcdic(); 121126048Sminshall break; 121226048Sminshall case TYPE_L: 121326048Sminshall settenex(); 121426048Sminshall break; 121526048Sminshall } 121626048Sminshall pswitch(1); 121726048Sminshall ptflag = 0; 121826048Sminshall printf("local: %s remote: %s\n", local, remote); 121926048Sminshall return; 122026048Sminshall abort: 122126048Sminshall (void) signal(SIGINT, SIG_IGN); 122226048Sminshall ptflag = 0; 122326448Slepreau if (strcmp(cmd, "RETR") && !proxy) 122426048Sminshall pswitch(1); 122526448Slepreau else if (!strcmp(cmd, "RETR") && proxy) 122626048Sminshall pswitch(0); 122726048Sminshall if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 122826048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 122926048Sminshall pswitch(0); 123026048Sminshall switch (oldtype) { 123126048Sminshall case 0: 123226048Sminshall break; 123326048Sminshall case TYPE_A: 123426048Sminshall setascii(); 123526048Sminshall break; 123626048Sminshall case TYPE_I: 123726048Sminshall setbinary(); 123826048Sminshall break; 123926048Sminshall case TYPE_E: 124026048Sminshall setebcdic(); 124126048Sminshall break; 124226048Sminshall case TYPE_L: 124326048Sminshall settenex(); 124426048Sminshall break; 124526048Sminshall } 124626048Sminshall if (cpend && telflag) { 124726048Sminshall char msg[2]; 124826048Sminshall 124926048Sminshall fprintf(cout,"%c%c",IAC,IP); 125026048Sminshall (void) fflush(cout); 125126048Sminshall *msg = IAC; 125226048Sminshall *(msg+1) = DM; 125326448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 125426048Sminshall perror("abort"); 125526048Sminshall } 125626048Sminshall if (cpend) { 125726048Sminshall fprintf(cout,"ABOR\r\n"); 125826048Sminshall (void) fflush(cout); 1259*26496Sminshall FD_ZERO((char *) &mask); 1260*26496Sminshall FD_SET(fileno(cin), &mask); 1261*26496Sminshall if (empty(mask,10) < 0) { 126226048Sminshall perror("abort"); 126326448Slepreau if (ptabflg) 126426048Sminshall code = -1; 126526048Sminshall lostpeer(); 126626048Sminshall } 126726048Sminshall (void) getreply(0); 126826048Sminshall (void) getreply(0); 126926048Sminshall } 127026048Sminshall } 127126048Sminshall pswitch(1); 127226448Slepreau if (ptabflg) 127326048Sminshall code = -1; 127426048Sminshall (void) signal(SIGINT, oldintr); 127526048Sminshall return; 127626048Sminshall } 127726048Sminshall if (cpend && telflag) { 127826048Sminshall char msg[2]; 127926048Sminshall 128026048Sminshall fprintf(cout,"%c%c",IAC,IP); 128126048Sminshall (void) fflush(cout); 128226048Sminshall *msg = IAC; 128326048Sminshall *(msg+1) = DM; 128426448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 128526048Sminshall perror("abort"); 128626048Sminshall } 128726048Sminshall if (cpend) { 128826048Sminshall fprintf(cout,"ABOR\r\n"); 128926048Sminshall (void) fflush(cout); 1290*26496Sminshall FD_ZERO((char *) &mask); 1291*26496Sminshall FD_SET(fileno(cin), &mask); 1292*26496Sminshall if ((empty(mask,10)) < 0) { 129326048Sminshall perror("abort"); 129426448Slepreau if (ptabflg) 129526048Sminshall code = -1; 129626048Sminshall lostpeer(); 129726048Sminshall } 129826048Sminshall (void) getreply(0); 129926048Sminshall (void) getreply(0); 130026048Sminshall } 130126048Sminshall pswitch(!proxy); 130226048Sminshall if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 130326048Sminshall if (command("%s %s", cmd2, local) != PRELIM) { 130426048Sminshall pswitch(0); 130526048Sminshall switch (oldtype) { 130626048Sminshall case 0: 130726048Sminshall break; 130826048Sminshall case TYPE_A: 130926048Sminshall setascii(); 131026048Sminshall break; 131126048Sminshall case TYPE_I: 131226048Sminshall setbinary(); 131326048Sminshall break; 131426048Sminshall case TYPE_E: 131526048Sminshall setebcdic(); 131626048Sminshall break; 131726048Sminshall case TYPE_L: 131826048Sminshall settenex(); 131926048Sminshall break; 132026048Sminshall } 132126048Sminshall if (cpend && telflag) { 132226048Sminshall char msg[2]; 132326048Sminshall 132426048Sminshall fprintf(cout,"%c%c",IAC,IP); 132526048Sminshall (void) fflush(cout); 132626048Sminshall *msg = IAC; 132726048Sminshall *(msg+1) = DM; 132826448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 132926048Sminshall perror("abort"); 133026048Sminshall } 133126048Sminshall if (cpend) { 133226048Sminshall fprintf(cout,"ABOR\r\n"); 133326048Sminshall (void) fflush(cout); 1334*26496Sminshall FD_ZERO((char *) &mask); 1335*26496Sminshall FD_SET(fileno(cin), &mask); 1336*26496Sminshall if (empty(mask,10) < 0) { 133726048Sminshall perror("abort"); 133826448Slepreau if (ptabflg) 133926048Sminshall code = -1; 134026048Sminshall lostpeer(); 134126048Sminshall } 134226048Sminshall (void) getreply(0); 134326048Sminshall (void) getreply(0); 134426048Sminshall } 134526048Sminshall pswitch(1); 134626448Slepreau if (ptabflg) 134726048Sminshall code = -1; 134826048Sminshall (void) signal(SIGINT, oldintr); 134926048Sminshall return; 135026048Sminshall } 135126048Sminshall } 135226048Sminshall if (cpend && telflag) { 135326048Sminshall char msg[2]; 135426048Sminshall 135526048Sminshall fprintf(cout,"%c%c",IAC,IP); 135626048Sminshall (void) fflush(cout); 135726048Sminshall *msg = IAC; 135826048Sminshall *(msg+1) = DM; 135926448Slepreau if (send(fileno(cout),msg,2,MSG_OOB) != 2) 136026048Sminshall perror("abort"); 136126048Sminshall } 136226048Sminshall if (cpend) { 136326048Sminshall fprintf(cout,"ABOR\r\n"); 136426048Sminshall (void) fflush(cout); 1365*26496Sminshall FD_ZERO((char *) &mask); 1366*26496Sminshall FD_SET(fileno(cin), &mask); 1367*26496Sminshall if (empty(mask,10) < 0) { 136826048Sminshall perror("abort"); 136926448Slepreau if (ptabflg) 137026048Sminshall code = -1; 137126048Sminshall lostpeer(); 137226048Sminshall } 137326048Sminshall (void) getreply(0); 137426048Sminshall (void) getreply(0); 137526048Sminshall } 137626048Sminshall pswitch(!proxy); 137726048Sminshall if (cpend) { 1378*26496Sminshall FD_ZERO((char *) &mask); 1379*26496Sminshall FD_SET(fileno(cin), &mask); 1380*26496Sminshall if (empty(mask,10) < 0) { 138126048Sminshall perror("abort"); 138226448Slepreau if (ptabflg) 138326048Sminshall code = -1; 138426048Sminshall lostpeer(); 138526048Sminshall } 138626048Sminshall (void) getreply(0); 138726048Sminshall (void) getreply(0); 138826048Sminshall } 138926448Slepreau if (proxy) 139026048Sminshall pswitch(0); 139126048Sminshall switch (oldtype) { 139226048Sminshall case 0: 139326048Sminshall break; 139426048Sminshall case TYPE_A: 139526048Sminshall setascii(); 139626048Sminshall break; 139726048Sminshall case TYPE_I: 139826048Sminshall setbinary(); 139926048Sminshall break; 140026048Sminshall case TYPE_E: 140126048Sminshall setebcdic(); 140226048Sminshall break; 140326048Sminshall case TYPE_L: 140426048Sminshall settenex(); 140526048Sminshall break; 140626048Sminshall } 140726048Sminshall pswitch(1); 140826448Slepreau if (ptabflg) 140926048Sminshall code = -1; 141026048Sminshall (void) signal(SIGINT, oldintr); 141126048Sminshall } 141226048Sminshall 141326048Sminshall reset() 141426048Sminshall { 1415*26496Sminshall struct fd_set mask; 1416*26496Sminshall int nfnd = 1; 141726048Sminshall 1418*26496Sminshall FD_ZERO((char *) &mask); 1419*26496Sminshall while (nfnd) { 1420*26496Sminshall FD_SET(fileno(cin), &mask); 1421*26496Sminshall if ((nfnd = empty(mask,0)) < 0) { 142226048Sminshall perror("reset"); 142326048Sminshall code = -1; 142426048Sminshall lostpeer(); 142526048Sminshall } 1426*26496Sminshall else { 142726048Sminshall (void) getreply(0); 1428*26496Sminshall } 142926048Sminshall } 143026048Sminshall } 143126048Sminshall 143226048Sminshall char * 143326048Sminshall gunique(local) 143426048Sminshall char *local; 143526048Sminshall { 143626048Sminshall static char new[MAXPATHLEN]; 143726048Sminshall char *cp = rindex(local, '/'); 143826048Sminshall int d, count=0; 143926048Sminshall char ext = '1'; 144026048Sminshall 144126448Slepreau if (cp) 144226048Sminshall *cp = '\0'; 144326048Sminshall d = access(cp ? local : ".", 2); 144426448Slepreau if (cp) 144526048Sminshall *cp = '/'; 144626048Sminshall if (d < 0) { 144726048Sminshall perror(local); 144826048Sminshall return((char *) 0); 144926048Sminshall } 145026048Sminshall (void) strcpy(new, local); 145126048Sminshall cp = new + strlen(new); 145226048Sminshall *cp++ = '.'; 145326048Sminshall while (!d) { 145426048Sminshall if (++count == 100) { 145526048Sminshall printf("runique: can't find unique file name.\n"); 145626048Sminshall return((char *) 0); 145726048Sminshall } 145826048Sminshall *cp++ = ext; 145926048Sminshall *cp = '\0'; 146026448Slepreau if (ext == '9') 146126048Sminshall ext = '0'; 146226448Slepreau else 146326048Sminshall ext++; 146426448Slepreau if ((d = access(new, 0)) < 0) 146526048Sminshall break; 146626448Slepreau if (ext != '0') 146726048Sminshall cp--; 146826448Slepreau else if (*(cp - 2) == '.') 146926048Sminshall *(cp - 1) = '1'; 147026048Sminshall else { 147126048Sminshall *(cp - 2) = *(cp - 2) + 1; 147226048Sminshall cp--; 147326048Sminshall } 147426048Sminshall } 147526048Sminshall return(new); 147626048Sminshall } 1477