X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/98c50518c04eefe9ebf5c1593074a759374f0747..f59b664716fca2bd38e085ad28391c267b319794:/usr/src/usr.bin/ftp/ftp.c diff --git a/usr/src/usr.bin/ftp/ftp.c b/usr/src/usr.bin/ftp/ftp.c index 5c47733e60..9f76af4b5a 100644 --- a/usr/src/usr.bin/ftp/ftp.c +++ b/usr/src/usr.bin/ftp/ftp.c @@ -1,19 +1,30 @@ /* - * Copyright (c) 1985 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. + * Copyright (c) 1985, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint -static char sccsid[] = "@(#)ftp.c 5.8 (Berkeley) %G%"; -#endif not lint - -#include "ftp_var.h" +static char sccsid[] = "@(#)ftp.c 5.29 (Berkeley) %G%"; +#endif /* not lint */ +#include #include #include #include #include +#include #include #include @@ -26,14 +37,16 @@ static char sccsid[] = "@(#)ftp.c 5.8 (Berkeley) %G%"; #include #include +#include "ftp_var.h" + struct sockaddr_in hisctladdr; struct sockaddr_in data_addr; int data = -1; -int telflag = 0; int abrtflag = 0; int ptflag = 0; int connected; struct sockaddr_in myctladdr; +uid_t getuid(); FILE *cin, *cout; FILE *dataconn(); @@ -44,27 +57,26 @@ hookup(host, port) int port; { register struct hostent *hp = 0; - int s,len,oldverbose; + int s,len; static char hostnamebuf[80]; - char msg[2]; bzero((char *)&hisctladdr, sizeof (hisctladdr)); hisctladdr.sin_addr.s_addr = inet_addr(host); if (hisctladdr.sin_addr.s_addr != -1) { hisctladdr.sin_family = AF_INET; - (void) strcpy(hostnamebuf, host); - } - else { + (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); + } else { hp = gethostbyname(host); if (hp == NULL) { - printf("%s: unknown host\n", host); + fprintf(stderr, "ftp: %s: ", host); + herror((char *)NULL); code = -1; return((char *) 0); } hisctladdr.sin_family = hp->h_addrtype; bcopy(hp->h_addr_list[0], (caddr_t)&hisctladdr.sin_addr, hp->h_length); - (void) strcpy(hostnamebuf, hp->h_name); + (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); } hostname = hostnamebuf; s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); @@ -74,19 +86,26 @@ hookup(host, port) return (0); } hisctladdr.sin_port = port; - while (connect(s, (caddr_t)&hisctladdr, sizeof (hisctladdr)) < 0) { + while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { if (hp && hp->h_addr_list[1]) { int oerrno = errno; fprintf(stderr, "ftp: connect to address %s: ", inet_ntoa(hisctladdr.sin_addr)); errno = oerrno; - perror(0); + perror((char *) 0); hp->h_addr_list++; bcopy(hp->h_addr_list[0], (caddr_t)&hisctladdr.sin_addr, hp->h_length); - fprintf(stderr, "Trying %s...\n", + fprintf(stdout, "Trying %s...\n", inet_ntoa(hisctladdr.sin_addr)); + (void) close(s); + s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + if (s < 0) { + perror("ftp: socket"); + code = -1; + return (0); + } continue; } perror("ftp: connect"); @@ -104,42 +123,36 @@ hookup(host, port) if (cin == NULL || cout == NULL) { fprintf(stderr, "ftp: fdopen failed.\n"); if (cin) - fclose(cin); + (void) fclose(cin); if (cout) - fclose(cout); + (void) fclose(cout); code = -1; goto bad; } if (verbose) printf("Connected to %s.\n", hostname); - if (getreply(0) != 2) { /* read startup message from server */ + if (getreply(0) > 2) { /* read startup message from server */ if (cin) - fclose(cin); + (void) fclose(cin); if (cout) - fclose(cout); + (void) fclose(cout); code = -1; goto bad; } +#ifdef SO_OOBINLINE + { + int on = 1; -/* test to see if server command parser understands TELNET SYNC command */ + if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) + < 0 && debug) { + perror("ftp: setsockopt"); + } + } +#endif SO_OOBINLINE - fprintf(cout,"%c%c",IAC,NOP); - (void) fflush(cout); - *msg = IAC; - *(msg+1) = DM; - if (send(s,msg,2,MSG_OOB) != 2) - perror("sync"); - oldverbose = verbose; - if (!debug) - verbose = -1; - if (command("NOOP") == COMPLETE) - telflag = 1; - else - telflag = 0; - verbose = oldverbose; return (hostname); bad: - close(s); + (void) close(s); return ((char *)0); } @@ -152,11 +165,10 @@ login(host) user = pass = acct = 0; if (ruserpass(host, &user, &pass, &acct) < 0) { - disconnect(); code = -1; return(0); } - if (user == NULL) { + while (user == NULL) { char *myname = getlogin(); if (myname == NULL) { @@ -165,7 +177,10 @@ login(host) if (pp != NULL) myname = pp->pw_name; } - printf("Name (%s:%s): ", host, myname); + if (myname) + printf("Name (%s:%s): ", host, myname); + else + printf("Name (%s): ", host); (void) fgets(tmp, sizeof(tmp) - 1, stdin); tmp[strlen(tmp) - 1] = '\0'; if (*tmp == '\0') @@ -194,7 +209,7 @@ login(host) return(1); for (n = 0; n < macnum; ++n) { if (!strcmp("init", macros[n].mac_name)) { - strcpy(line, "$init"); + (void) strcpy(line, "$init"); makeargv(); domacro(margc, margv); break; @@ -214,16 +229,20 @@ cmdabort() longjmp(ptabort,1); } -/*VARARGS 1*/ +/*VARARGS1*/ command(fmt, args) char *fmt; { int r, (*oldintr)(), cmdabort(); + char *xxx = "XXX"; abrtflag = 0; if (debug) { printf("---> "); - _doprnt(fmt, &args, stdout); + if (strncmp(fmt, "PASS", 4) == 0) + _doprnt(fmt, (int *)&xxx, stdout); + else + _doprnt(fmt, &args, stdout); printf("\n"); (void) fflush(stdout); } @@ -244,6 +263,8 @@ command(fmt, args) return(r); } +char reply_string[BUFSIZ]; /* last line of previous reply */ + #include getreply(expecteof) @@ -251,6 +272,7 @@ getreply(expecteof) { register int c, n; register int dig; + register char *cp; int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); int pflag = 0; char *pt = pasv; @@ -258,7 +280,27 @@ getreply(expecteof) oldintr = signal(SIGINT,cmdabort); for (;;) { dig = n = code = 0; + cp = reply_string; while ((c = getc(cin)) != '\n') { + if (c == IAC) { /* handle telnet commands */ + switch (c = getc(cin)) { + case WILL: + case WONT: + c = getc(cin); + fprintf(cout, "%c%c%c",IAC,DONT,c); + (void) fflush(cout); + break; + case DO: + case DONT: + c = getc(cin); + fprintf(cout, "%c%c%c",IAC,WONT,c); + (void) fflush(cout); + break; + default: + break; + } + continue; + } dig++; if (c == EOF) { if (expecteof) { @@ -270,16 +312,16 @@ getreply(expecteof) if (verbose) { printf("421 Service not available, remote server has closed connection\n"); (void) fflush(stdout); - code = 421; - return(4); } + code = 421; + return(4); } if (c != '\r' && (verbose > 0 || (verbose > -1 && n == '5' && dig > 4))) { if (proxflag && (dig == 1 || dig == 5 && verbose == 0)) printf("%s:",hostname); - putchar(c); + (void) putchar(c); } if (dig < 4 && isdigit(c)) code = code * 10 + (c - '0'); @@ -302,9 +344,11 @@ getreply(expecteof) } if (n == 0) n = c; + if (cp < &reply_string[sizeof(reply_string) - 1]) + *cp++ = c; } if (verbose > 0 || verbose > -1 && n == '5') { - putchar(c); + (void) putchar(c); (void) fflush (stdout); } if (continuation && code != originalcode) { @@ -312,6 +356,7 @@ getreply(expecteof) originalcode = code; continue; } + *cp = '\0'; if (n != '1') cpend = 0; (void) signal(SIGINT,oldintr); @@ -324,16 +369,14 @@ getreply(expecteof) } empty(mask, sec) - long mask; + struct fd_set *mask; int sec; { struct timeval t; t.tv_sec = (long) sec; t.tv_usec = 0; - if (select(20, &mask, 0, 0, &t) < 0) - return(-1); - return (mask); + return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); } jmp_buf sendabort; @@ -348,25 +391,38 @@ abortsend() longjmp(sendabort, 1); } -sendrequest(cmd, local, remote) +#define HASHBYTES 1024 + +sendrequest(cmd, local, remote, printnames) char *cmd, *local, *remote; + int printnames; { FILE *fin, *dout = 0, *popen(); int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); int abortsend(); - char buf[BUFSIZ]; - long bytes = 0, hashbytes = sizeof (buf); + char buf[BUFSIZ], *bufp; + long bytes = 0, hashbytes = HASHBYTES; register int c, d; struct stat st; struct timeval start, stop; + char *mode; + if (verbose && printnames) { + if (local && *local != '-') + printf("local: %s ", local); + if (remote) + printf("remote: %s\n", remote); + } if (proxy) { proxtrans(cmd, local, remote); return; } + if (curtype != type) + changetype(type, 0); closefunc = NULL; oldintr = NULL; oldintp = NULL; + mode = "w"; if (setjmp(sendabort)) { while (cpend) { (void) getreply(0); @@ -407,8 +463,9 @@ sendrequest(cmd, local, remote) closefunc = fclose; if (fstat(fileno(fin), &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG) { - fprintf(stderr, "%s: not a plain file.\n", local); + fprintf(stdout, "%s: not a plain file.\n", local); (void) signal(SIGINT, oldintr); + fclose(fin); code = -1; return; } @@ -418,15 +475,20 @@ sendrequest(cmd, local, remote) if (oldintp) (void) signal(SIGPIPE, oldintp); code = -1; + if (closefunc != NULL) + (*closefunc)(fin); return; } if (setjmp(sendabort)) goto abort; + if (remote) { if (command("%s %s", cmd, remote) != PRELIM) { (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); + if (closefunc != NULL) + (*closefunc)(fin); return; } } else @@ -434,79 +496,101 @@ sendrequest(cmd, local, remote) (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); + if (closefunc != NULL) + (*closefunc)(fin); return; } - dout = dataconn("w"); + dout = dataconn(mode); if (dout == NULL) goto abort; - gettimeofday(&start, (struct timezone *)0); + (void) gettimeofday(&start, (struct timezone *)0); + oldintp = signal(SIGPIPE, SIG_IGN); switch (type) { case TYPE_I: case TYPE_L: errno = d = 0; - while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { - if ((d = write(fileno (dout), buf, c)) < 0) - break; + while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { bytes += c; + for (bufp = buf; c > 0; c -= d, bufp += d) + if ((d = write(fileno(dout), bufp, c)) <= 0) + break; + for (bufp = buf; c > 0; c -= d, bufp += d) + if ((d = write(fileno(dout), bufp, c)) <= 0) + break; if (hash) { - putchar('#'); - fflush(stdout); + while (bytes >= hashbytes) { + (void) putchar('#'); + hashbytes += HASHBYTES; + } + (void) fflush(stdout); } } if (hash && bytes > 0) { - putchar('\n'); - fflush(stdout); + if (bytes < HASHBYTES) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); } if (c < 0) perror(local); - if (d < 0) - perror("netout"); + if (d <= 0) { + if (d == 0) + fprintf(stderr, "netout: write returned 0?\n"); + else if (errno != EPIPE) + perror("netout"); + bytes = -1; + } break; case TYPE_A: while ((c = getc(fin)) != EOF) { if (c == '\n') { while (hash && (bytes >= hashbytes)) { - putchar('#'); - fflush(stdout); - hashbytes += sizeof (buf); + (void) putchar('#'); + (void) fflush(stdout); + hashbytes += HASHBYTES; } if (ferror(dout)) break; - putc('\r', dout); + (void) putc('\r', dout); bytes++; } - putc(c, dout); + (void) putc(c, dout); bytes++; /* if (c == '\r') { */ - /* putc('\0', dout); /* this violates rfc */ + /* (void) putc('\0', dout); /* this violates rfc */ /* bytes++; */ /* } */ } if (hash) { if (bytes < hashbytes) - putchar('#'); - putchar('\n'); - fflush(stdout); + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); } if (ferror(fin)) perror(local); - if (ferror(dout)) - perror("netout"); + if (ferror(dout)) { + if (errno != EPIPE) + perror("netout"); + bytes = -1; + } break; } - gettimeofday(&stop, (struct timezone *)0); + (void) gettimeofday(&stop, (struct timezone *)0); if (closefunc != NULL) (*closefunc)(fin); (void) fclose(dout); (void) getreply(0); (void) signal(SIGINT, oldintr); - if (bytes > 0 && verbose) - ptransfer("sent", bytes, &start, &stop, local, remote); + if (oldintp) + (void) signal(SIGPIPE, oldintp); + if (bytes > 0) + ptransfer("sent", bytes, &start, &stop); return; abort: - gettimeofday(&stop, (struct timezone *)0); + (void) gettimeofday(&stop, (struct timezone *)0); (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); @@ -524,8 +608,8 @@ abort: code = -1; if (closefunc != NULL && fin != NULL) (*closefunc)(fin); - if (bytes > 0 && verbose) - ptransfer("sent", bytes, &start, &stop, local, remote); + if (bytes > 0) + ptransfer("sent", bytes, &start, &stop); } jmp_buf recvabort; @@ -540,25 +624,37 @@ abortrecv() longjmp(recvabort, 1); } -recvrequest(cmd, local, remote, mode) +recvrequest(cmd, local, remote, mode, printnames) char *cmd, *local, *remote, *mode; { FILE *fout, *din = 0, *popen(); int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); - int abortrecv(), oldverbose, oldtype = 0, tcrflag; - char buf[BUFSIZ], *gunique(); - long bytes = 0, hashbytes = sizeof (buf), mask; + int abortrecv(), is_retr, tcrflag, nfnd; + char *bufp, *gunique(), msg; + static char *buf; + static int bufsize; + long bytes = 0, hashbytes = HASHBYTES; + struct fd_set mask; register int c, d; struct timeval start, stop; + struct stat st; + extern char *malloc(); - if (proxy && strcmp(cmd,"RETR") == 0) { + is_retr = strcmp(cmd, "RETR") == 0; + if (is_retr && verbose && printnames) { + if (local && *local != '-') + printf("local: %s ", local); + if (remote) + printf("remote: %s\n", remote); + } + if (proxy && is_retr) { proxtrans(cmd, local, remote); return; } closefunc = NULL; oldintr = NULL; oldintp = NULL; - tcrflag = !crflag && !strcmp(cmd, "RETR"); + tcrflag = !crflag && is_retr; if (setjmp(recvabort)) { while (cpend) { (void) getreply(0); @@ -595,7 +691,7 @@ recvrequest(cmd, local, remote, mode) return; } if (!runique && errno == EACCES && - chmod(local,0600) < 0) { + chmod(local, 0600) < 0) { perror(local); (void) signal(SIGINT, oldintr); code = -1; @@ -614,6 +710,11 @@ recvrequest(cmd, local, remote, mode) return; } } + if (!is_retr) { + if (curtype != TYPE_A) + changetype(TYPE_A, 0); + } else if (curtype != type) + changetype(type, 0); if (initconn()) { (void) signal(SIGINT, oldintr); code = -1; @@ -621,54 +722,17 @@ recvrequest(cmd, local, remote, mode) } if (setjmp(recvabort)) goto abort; - if (strcmp(cmd, "RETR") && type != TYPE_A) { - oldtype = type; - oldverbose = verbose; - if (!debug) - verbose = 0; - setascii(); - verbose = oldverbose; - } + if (is_retr && restart_point && + command("REST %ld", (long) restart_point) != CONTINUE) + return; if (remote) { if (command("%s %s", cmd, remote) != PRELIM) { (void) signal(SIGINT, oldintr); - if (oldtype) { - if (!debug) - verbose = 0; - switch (oldtype) { - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } - verbose = oldverbose; - } return; } } else { if (command("%s", cmd) != PRELIM) { (void) signal(SIGINT, oldintr); - if (oldtype) { - if (!debug) - verbose = 0; - switch (oldtype) { - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } - verbose = oldverbose; - } return; } } @@ -685,8 +749,7 @@ recvrequest(cmd, local, remote, mode) goto abort; } closefunc = pclose; - } - else { + } else { fout = fopen(local, mode); if (fout == NULL) { perror(local); @@ -694,146 +757,155 @@ recvrequest(cmd, local, remote, mode) } closefunc = fclose; } - gettimeofday(&start, (struct timezone *)0); - switch (type) { + if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) + st.st_blksize = BUFSIZ; + if (st.st_blksize > bufsize) { + if (buf) + (void) free(buf); + buf = malloc(st.st_blksize); + if (buf == NULL) { + perror("malloc"); + bufsize = 0; + bufsize = 0; + goto abort; + } + bufsize = st.st_blksize; + } + (void) gettimeofday(&start, (struct timezone *)0); + switch (curtype) { case TYPE_I: case TYPE_L: errno = d = 0; - while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { - if ((d = write(fileno(fout), buf, c)) < 0) + while ((c = read(fileno(din), buf, bufsize)) > 0) { + if ((d = write(fileno(fout), buf, c)) != c) break; bytes += c; if (hash) { - putchar('#'); - fflush(stdout); + while (bytes >= hashbytes) { + (void) putchar('#'); + hashbytes += HASHBYTES; + } + (void) fflush(stdout); } } if (hash && bytes > 0) { - putchar('\n'); - fflush(stdout); + if (bytes < HASHBYTES) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } + if (c < 0) { + if (errno != EPIPE) + perror("netin"); + bytes = -1; + } + if (d < c) { + if (d < 0) + perror(local); + else + fprintf(stderr, "%s: short write\n", local); } - if (c < 0) - perror("netin"); - if (d < 0) - perror(local); break; case TYPE_A: while ((c = getc(din)) != EOF) { - if (c == '\r') { + while (c == '\r') { while (hash && (bytes >= hashbytes)) { - putchar('#'); - fflush(stdout); - hashbytes += sizeof (buf); + (void) putchar('#'); + (void) fflush(stdout); + hashbytes += HASHBYTES; } bytes++; if ((c = getc(din)) != '\n' || tcrflag) { - if (ferror (fout)) - break; - putc ('\r', fout); + if (ferror(fout)) + goto break2; + (void) putc('\r', fout); + if (c == '\0') { + bytes++; + goto contin2; + } + if (c == EOF) + goto contin2; + } + if (c == EOF) + goto contin2; } - /*if (c == '\0') { - bytes++; - continue; - }*/ } - putc (c, fout); + (void) putc(c, fout); bytes++; + contin2: ; } +break2: if (hash) { if (bytes < hashbytes) - putchar('#'); - putchar('\n'); - fflush(stdout); + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); } - if (ferror (din)) - perror ("netin"); - if (ferror (fout)) - perror (local); + if (ferror(din)) { + if (errno != EPIPE) + perror("netin"); + bytes = -1; + } + if (ferror(fout)) + perror(local); break; } if (closefunc != NULL) (*closefunc)(fout); - signal(SIGINT, oldintr); + (void) signal(SIGINT, oldintr); if (oldintp) (void) signal(SIGPIPE, oldintp); - gettimeofday(&stop, (struct timezone *)0); + (void) gettimeofday(&stop, (struct timezone *)0); (void) fclose(din); (void) getreply(0); - if (bytes > 0 && verbose) - ptransfer("received", bytes, &start, &stop, local, remote); - if (oldtype) { - if (!debug) - verbose = 0; - switch (oldtype) { - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } - verbose = oldverbose; - } + if (bytes > 0 && is_retr) + ptransfer("received", bytes, &start, &stop); return; abort: -/* if server command parser understands TELNET commands, abort using */ -/* recommended IP,SYNC sequence */ +/* abort using RFC959 recommended IP,SYNC sequence */ - gettimeofday(&stop, (struct timezone *)0); + (void) gettimeofday(&stop, (struct timezone *)0); if (oldintp) (void) signal(SIGPIPE, oldintr); (void) signal(SIGINT,SIG_IGN); - if (oldtype) { - if (!debug) - verbose = 0; - switch (oldtype) { - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } - verbose = oldverbose; - } if (!cpend) { code = -1; (void) signal(SIGINT,oldintr); return; } - if (telflag) { - char msg[2]; - fprintf(cout,"%c%c",IAC,IP); - (void) fflush(cout); - *msg = IAC; - *(msg+1) = DM; - if (send(fileno(cout),msg,2,MSG_OOB) != 2) - perror("abort"); + fprintf(cout,"%c%c",IAC,IP); + (void) fflush(cout); + msg = IAC; +/* send IAC in urgent mode instead of DM because UNIX places oob mark */ +/* after urgent byte rather than before as now is protocol */ + if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { + perror("abort"); } - fprintf(cout,"ABOR\r\n"); + fprintf(cout,"%cABOR\r\n",DM); (void) fflush(cout); - mask = (1 << fileno(cin)) | (din ? (1 << fileno(din)) : 0); - if ((mask = empty(mask,10)) < 0) { - perror("abort"); + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if (din) { + FD_SET(fileno(din), &mask); + } + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } code = -1; lostpeer(); } - if (din && mask & (1 << fileno(din))) - while ((c = read(fileno(din), buf, sizeof (buf))) > 0) + if (din && FD_ISSET(fileno(din), &mask)) { + while ((c = read(fileno(din), buf, bufsize)) > 0) ; - if ((c = getreply(0)) == ERROR) { /* needed for nic style abort */ + } + if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ if (data >= 0) { - close(data); + (void) close(data); data = -1; } (void) getreply(0); @@ -848,8 +920,8 @@ abort: (*closefunc)(fout); if (din) (void) fclose(din); - if (bytes > 0 && verbose) - ptransfer("received", bytes, &start, &stop, local, remote); + if (bytes > 0) + ptransfer("received", bytes, &start, &stop); (void) signal(SIGINT,oldintr); } @@ -858,7 +930,7 @@ abort: * before we send the command, otherwise the * server's connect may fail. */ -static int sendport = -1; +int sendport = -1; initconn() { @@ -880,16 +952,16 @@ noport: return (1); } if (!sendport) - if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { - perror("ftp: setsockopt (resuse address)"); + if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { + perror("ftp: setsockopt (reuse address)"); goto bad; } - if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) { + if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { perror("ftp: bind"); goto bad; } if (options & SO_DEBUG && - setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) + setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) perror("ftp: setsockopt (ignored)"); len = sizeof (data_addr); if (getsockname(data, (char *)&data_addr, &len) < 0) { @@ -930,7 +1002,7 @@ dataconn(mode) struct sockaddr_in from; int s, fromlen = sizeof (from); - s = accept(data, &from, &fromlen, 0); + s = accept(data, (struct sockaddr *) &from, &fromlen); if (s < 0) { perror("ftp: accept"); (void) close(data), data = -1; @@ -941,27 +1013,25 @@ dataconn(mode) return (fdopen(data, mode)); } -ptransfer(direction, bytes, t0, t1, local, remote) - char *direction, *local, *remote; +ptransfer(direction, bytes, t0, t1) + char *direction; long bytes; struct timeval *t0, *t1; { struct timeval td; float s, bs; - tvsub(&td, t1, t0); - s = td.tv_sec + (td.tv_usec / 1000000.); + if (verbose) { + tvsub(&td, t1, t0); + s = td.tv_sec + (td.tv_usec / 1000000.); #define nz(x) ((x) == 0 ? 1 : (x)) - bs = bytes / nz(s); - if (local && *local != '-') - printf("local: %s ", local); - if (remote) - printf("remote: %s\n", remote); - printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", - bytes, direction, s, bs / 1024.); + bs = bytes / nz(s); + printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", + bytes, direction, s, bs / 1024.); + } } -tvadd(tsum, t0) +/*tvadd(tsum, t0) struct timeval *tsum, *t0; { @@ -969,7 +1039,7 @@ tvadd(tsum, t0) tsum->tv_usec += t0->tv_usec; if (tsum->tv_usec > 1000000) tsum->tv_sec++, tsum->tv_usec -= 1000000; -} +} */ tvsub(tdiff, t1, t0) struct timeval *tdiff, *t1, *t0; @@ -995,13 +1065,13 @@ pswitch(flag) int (*oldintr)(); static struct comvars { int connect; - char name[32]; + char name[MAXHOSTNAMELEN]; struct sockaddr_in mctl; struct sockaddr_in hctl; FILE *in; FILE *out; - int tflag; int tpe; + int curtpe; int cpnd; int sunqe; int runqe; @@ -1012,7 +1082,7 @@ pswitch(flag) int mapflg; char mi[MAXPATHLEN]; char mo[MAXPATHLEN]; - } proxstruct, tmpstruct; + } proxstruct, tmpstruct; struct comvars *ip, *op; abrtflag = 0; @@ -1023,8 +1093,7 @@ pswitch(flag) ip = &tmpstruct; op = &proxstruct; proxy++; - } - else { + } else { if (!proxy) return; ip = &proxstruct; @@ -1033,8 +1102,11 @@ pswitch(flag) } ip->connect = connected; connected = op->connect; - strncpy(ip->name, hostname, 31); - (ip->name)[strlen(ip->name)] = '\0'; + if (hostname) { + (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); + ip->name[strlen(ip->name)] = '\0'; + } else + ip->name[0] = 0; hostname = op->name; ip->hctl = hisctladdr; hisctladdr = op->hctl; @@ -1044,12 +1116,10 @@ pswitch(flag) cin = op->in; ip->out = cout; cout = op->out; - ip->tflag = telflag; - telflag = op->tflag; ip->tpe = type; type = op->tpe; - if (!type) - type = 1; + ip->curtpe = curtype; + curtype = op->curtpe; ip->cpnd = cpend; cpend = op->cpnd; ip->sunqe = sunique; @@ -1060,20 +1130,20 @@ pswitch(flag) mcase = op->mcse; ip->ntflg = ntflag; ntflag = op->ntflg; - strncpy(ip->nti, ntin, 16); + (void) strncpy(ip->nti, ntin, 16); (ip->nti)[strlen(ip->nti)] = '\0'; - strcpy(ntin, op->nti); - strncpy(ip->nto, ntout, 16); + (void) strcpy(ntin, op->nti); + (void) strncpy(ip->nto, ntout, 16); (ip->nto)[strlen(ip->nto)] = '\0'; - strcpy(ntout, op->nto); + (void) strcpy(ntout, op->nto); ip->mapflg = mapflag; mapflag = op->mapflg; - strncpy(ip->mi, mapin, MAXPATHLEN - 1); + (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); (ip->mi)[strlen(ip->mi)] = '\0'; - strcpy(mapin, op->mi); - strncpy(ip->mo, mapout, MAXPATHLEN - 1); + (void) strcpy(mapin, op->mi); + (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); (ip->mo)[strlen(ip->mo)] = '\0'; - strcpy(mapout, op->mo); + (void) strcpy(mapout, op->mo); (void) signal(SIGINT, oldintr); if (abrtflag) { abrtflag = 0; @@ -1087,7 +1157,7 @@ int ptabflg; abortpt() { printf("\n"); - fflush(stdout); + (void) fflush(stdout); ptabflg++; mflag = 0; abrtflag = 0; @@ -1097,20 +1167,27 @@ abortpt() proxtrans(cmd, local, remote) char *cmd, *local, *remote; { - int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0; + int (*oldintr)(), abortpt(), prox_type, secndflag = 0, nfnd; extern jmp_buf ptabort; char *cmd2; - long mask; + struct fd_set mask; if (strcmp(cmd, "RETR")) cmd2 = "RETR"; else cmd2 = runique ? "STOU" : "STOR"; + if ((prox_type = type) == 0) { + if (unix_server && unix_proxy) + prox_type = TYPE_I; + else + prox_type = TYPE_A; + } + if (curtype != prox_type) + changetype(prox_type, 1); if (command("PASV") != COMPLETE) { - printf("proxy server does not support third part transfers.\n"); + printf("proxy server does not support third party transfers.\n"); return; } - tmptype = type; pswitch(0); if (!connected) { printf("No primary connection\n"); @@ -1118,40 +1195,9 @@ proxtrans(cmd, local, remote) code = -1; return; } - if (type != tmptype) { - oldtype = type; - switch (tmptype) { - case TYPE_A: - setascii(); - break; - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } - } + if (curtype != prox_type) + changetype(prox_type, 1); if (command("PORT %s", pasv) != COMPLETE) { - switch (oldtype) { - case 0: - break; - case TYPE_A: - setascii(); - break; - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } pswitch(1); return; } @@ -1160,22 +1206,6 @@ proxtrans(cmd, local, remote) oldintr = signal(SIGINT, abortpt); if (command("%s %s", cmd, remote) != PRELIM) { (void) signal(SIGINT, oldintr); - switch (oldtype) { - case 0: - break; - case TYPE_A: - setascii(); - break; - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } pswitch(1); return; } @@ -1189,22 +1219,6 @@ proxtrans(cmd, local, remote) pswitch(0); (void) getreply(0); (void) signal(SIGINT, oldintr); - switch (oldtype) { - case 0: - break; - case TYPE_A: - setascii(); - break; - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } pswitch(1); ptflag = 0; printf("local: %s remote: %s\n", local, remote); @@ -1219,23 +1233,7 @@ abort: if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ if (command("%s %s", cmd2, local) != PRELIM) { pswitch(0); - switch (oldtype) { - case 0: - break; - case TYPE_A: - setascii(); - break; - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } - if (cpend && telflag) { + if (cpend) { char msg[2]; fprintf(cout,"%c%c",IAC,IP); @@ -1244,13 +1242,14 @@ abort: *(msg+1) = DM; if (send(fileno(cout),msg,2,MSG_OOB) != 2) perror("abort"); - } - if (cpend) { fprintf(cout,"ABOR\r\n"); (void) fflush(cout); - mask = 1 << fileno(cin); - if ((mask = empty(mask,10)) < 0) { - perror("abort"); + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } if (ptabflg) code = -1; lostpeer(); @@ -1265,7 +1264,7 @@ abort: (void) signal(SIGINT, oldintr); return; } - if (cpend && telflag) { + if (cpend) { char msg[2]; fprintf(cout,"%c%c",IAC,IP); @@ -1274,13 +1273,14 @@ abort: *(msg+1) = DM; if (send(fileno(cout),msg,2,MSG_OOB) != 2) perror("abort"); - } - if (cpend) { fprintf(cout,"ABOR\r\n"); (void) fflush(cout); - mask = 1 << fileno(cin); - if ((mask = empty(mask,10)) < 0) { - perror("abort"); + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } if (ptabflg) code = -1; lostpeer(); @@ -1292,23 +1292,7 @@ abort: if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ if (command("%s %s", cmd2, local) != PRELIM) { pswitch(0); - switch (oldtype) { - case 0: - break; - case TYPE_A: - setascii(); - break; - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } - if (cpend && telflag) { + if (cpend) { char msg[2]; fprintf(cout,"%c%c",IAC,IP); @@ -1317,13 +1301,14 @@ abort: *(msg+1) = DM; if (send(fileno(cout),msg,2,MSG_OOB) != 2) perror("abort"); - } - if (cpend) { fprintf(cout,"ABOR\r\n"); (void) fflush(cout); - mask = 1 << fileno(cin); - if ((mask = empty(mask,10)) < 0) { - perror("abort"); + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } if (ptabflg) code = -1; lostpeer(); @@ -1338,7 +1323,7 @@ abort: return; } } - if (cpend && telflag) { + if (cpend) { char msg[2]; fprintf(cout,"%c%c",IAC,IP); @@ -1347,13 +1332,14 @@ abort: *(msg+1) = DM; if (send(fileno(cout),msg,2,MSG_OOB) != 2) perror("abort"); - } - if (cpend) { fprintf(cout,"ABOR\r\n"); (void) fflush(cout); - mask = 1 << fileno(cin); - if ((mask = empty(mask,10)) < 0) { - perror("abort"); + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } if (ptabflg) code = -1; lostpeer(); @@ -1363,9 +1349,12 @@ abort: } pswitch(!proxy); if (cpend) { - mask = 1 << fileno(cin); - if ((mask = empty(mask,10)) < 0) { - perror("abort"); + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask,10)) <= 0) { + if (nfnd < 0) { + perror("abort"); + } if (ptabflg) code = -1; lostpeer(); @@ -1375,22 +1364,6 @@ abort: } if (proxy) pswitch(0); - switch (oldtype) { - case 0: - break; - case TYPE_A: - setascii(); - break; - case TYPE_I: - setbinary(); - break; - case TYPE_E: - setebcdic(); - break; - case TYPE_L: - settenex(); - break; - } pswitch(1); if (ptabflg) code = -1; @@ -1399,17 +1372,20 @@ abort: reset() { - long mask; + struct fd_set mask; + int nfnd = 1; - mask = 1 << fileno(cin); - while (mask > 0) { - if ((mask = empty(mask,0)) < 0) { + FD_ZERO(&mask); + while (nfnd > 0) { + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask,0)) < 0) { perror("reset"); code = -1; lostpeer(); } - if (mask > 0) + else if (nfnd) { (void) getreply(0); + } } }