Simplified math in ptransfer() to avoid destroying bits (and somethings
[unix-history] / usr / src / usr.bin / ftp / ftp.c
index 413c34d..6f3ed61 100644 (file)
@@ -1,21 +1,21 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)ftp.c      4.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)ftp.c      4.12 (Berkeley) %G%";
 #endif
 
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #endif
 
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <sys/time.h>
 
 #include <netinet/in.h>
 
 #include <netinet/in.h>
+#include <arpa/ftp.h>
 
 #include <stdio.h>
 #include <signal.h>
 
 #include <stdio.h>
 #include <signal.h>
-#include <time.h>
 #include <errno.h>
 #include <netdb.h>
 
 #include <errno.h>
 #include <netdb.h>
 
-#include "ftp.h"
 #include "ftp_var.h"
 
 struct sockaddr_in hisctladdr;
 #include "ftp_var.h"
 
 struct sockaddr_in hisctladdr;
@@ -190,7 +190,7 @@ getreply(expecteof)
 empty(f)
        FILE *f;
 {
 empty(f)
        FILE *f;
 {
-       int mask;
+       long mask;
        struct timeval t;
 
        if (f->_cnt > 0)
        struct timeval t;
 
        if (f->_cnt > 0)
@@ -215,7 +215,7 @@ sendrequest(cmd, local, remote)
        FILE *fin, *dout, *popen();
        int (*closefunc)(), pclose(), fclose(), (*oldintr)();
        char buf[BUFSIZ];
        FILE *fin, *dout, *popen();
        int (*closefunc)(), pclose(), fclose(), (*oldintr)();
        char buf[BUFSIZ];
-       register int bytes = 0;
+       long bytes = 0, hashbytes = sizeof (buf);
        register int c, d;
        struct stat st;
        struct timeval start, stop;
        register int c, d;
        struct stat st;
        struct timeval start, stop;
@@ -267,6 +267,14 @@ sendrequest(cmd, local, remote)
                        if ((d = write(fileno (dout), buf, c)) < 0)
                                break;
                        bytes += c;
                        if ((d = write(fileno (dout), buf, c)) < 0)
                                break;
                        bytes += c;
+                       if (hash) {
+                               putchar('#');
+                               fflush(stdout);
+                       }
+               }
+               if (hash && bytes > 0) {
+                       putchar('\n');
+                       fflush(stdout);
                }
                if (c < 0)
                        perror(local);
                }
                if (c < 0)
                        perror(local);
@@ -277,6 +285,11 @@ sendrequest(cmd, local, remote)
        case TYPE_A:
                while ((c = getc(fin)) != EOF) {
                        if (c == '\n') {
        case TYPE_A:
                while ((c = getc(fin)) != EOF) {
                        if (c == '\n') {
+                               while (hash && (bytes >= hashbytes)) {
+                                       putchar('#');
+                                       fflush(stdout);
+                                       hashbytes += sizeof (buf);
+                               }
                                if (ferror(dout))
                                        break;
                                putc('\r', dout);
                                if (ferror(dout))
                                        break;
                                putc('\r', dout);
@@ -289,6 +302,12 @@ sendrequest(cmd, local, remote)
                                bytes++;
                        }
                }
                                bytes++;
                        }
                }
+               if (hash) {
+                       if (bytes < hashbytes)
+                               putchar('#');
+                       putchar('\n');
+                       fflush(stdout);
+               }
                if (ferror(fin))
                        perror(local);
                if (ferror(dout))
                if (ferror(fin))
                        perror(local);
                if (ferror(dout))
@@ -321,13 +340,13 @@ abortrecv()
        longjmp(recvabort, 1);
 }
 
        longjmp(recvabort, 1);
 }
 
-recvrequest(cmd, local, remote)
-       char *cmd, *local, *remote;
+recvrequest(cmd, local, remote, mode)
+       char *cmd, *local, *remote, *mode;
 {
        FILE *fout, *din, *popen();
 {
        FILE *fout, *din, *popen();
-       char buf[BUFSIZ];
        int (*closefunc)(), pclose(), fclose(), (*oldintr)();
        int (*closefunc)(), pclose(), fclose(), (*oldintr)();
-       register int bytes = 0;
+       char buf[BUFSIZ];
+       long bytes = 0, hashbytes = sizeof (buf);
        register int c, d;
        struct timeval start, stop;
 
        register int c, d;
        struct timeval start, stop;
 
@@ -362,7 +381,7 @@ recvrequest(cmd, local, remote)
                fout = popen(local + 1, "w");
                closefunc = pclose;
        } else {
                fout = popen(local + 1, "w");
                closefunc = pclose;
        } else {
-               fout = fopen(local, "w");
+               fout = fopen(local, mode);
                closefunc = fclose;
        }
        if (fout == NULL) {
                closefunc = fclose;
        }
        if (fout == NULL) {
@@ -382,6 +401,14 @@ recvrequest(cmd, local, remote)
                        if ((d = write(fileno(fout), buf, c)) < 0)
                                break;
                        bytes += c;
                        if ((d = write(fileno(fout), buf, c)) < 0)
                                break;
                        bytes += c;
+                       if (hash) {
+                               putchar('#');
+                               fflush(stdout);
+                       }
+               }
+               if (hash && bytes > 0) {
+                       putchar('\n');
+                       fflush(stdout);
                }
                if (c < 0)
                        perror("netin");
                }
                if (c < 0)
                        perror("netin");
@@ -392,6 +419,11 @@ recvrequest(cmd, local, remote)
        case TYPE_A:
                while ((c = getc(din)) != EOF) {
                        if (c == '\r') {
        case TYPE_A:
                while ((c = getc(din)) != EOF) {
                        if (c == '\r') {
+                               while (hash && (bytes >= hashbytes)) {
+                                       putchar('#');
+                                       fflush(stdout);
+                                       hashbytes += sizeof (buf);
+                               }
                                bytes++;
                                if ((c = getc(din)) != '\n') {
                                        if (ferror (fout))
                                bytes++;
                                if ((c = getc(din)) != '\n') {
                                        if (ferror (fout))
@@ -406,6 +438,12 @@ recvrequest(cmd, local, remote)
                        putc (c, fout);
                        bytes++;
                }
                        putc (c, fout);
                        bytes++;
                }
+               if (hash) {
+                       if (bytes < hashbytes)
+                               putchar('#');
+                       putchar('\n');
+                       fflush(stdout);
+               }
                if (ferror (din))
                        perror ("netin");
                if (ferror (fout))
                if (ferror (din))
                        perror ("netin");
                if (ferror (fout))
@@ -435,18 +473,29 @@ bad:
  * before we send the command, otherwise the
  * server's connect may fail.
  */
  * before we send the command, otherwise the
  * server's connect may fail.
  */
+static int sendport = -1;
+
 initconn()
 {
        register char *p, *a;
        int result, len;
 
 initconn()
 {
        register char *p, *a;
        int result, len;
 
+noport:
        data_addr = myctladdr;
        data_addr = myctladdr;
-       data_addr.sin_port = 0;         /* let system pick one */
+       if (sendport)
+               data_addr.sin_port = 0; /* let system pick one */ 
+       if (data != -1)
+               (void) close (data);
        data = socket(AF_INET, SOCK_STREAM, 0, 0);
        if (data < 0) {
                perror("ftp: socket");
                return (1);
        }
        data = socket(AF_INET, SOCK_STREAM, 0, 0);
        if (data < 0) {
                perror("ftp: socket");
                return (1);
        }
+       if (!sendport)
+               if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) {
+                       perror("ftp: setsockopt (resuse address)");
+                       goto bad;
+               }
        if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) {
                perror("ftp: bind");
                goto bad;
        if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) {
                perror("ftp: bind");
                goto bad;
@@ -463,14 +512,21 @@ initconn()
                perror("ftp: listen");
                goto bad;
        }
                perror("ftp: listen");
                goto bad;
        }
-       a = (char *)&data_addr.sin_addr;
-       p = (char *)&data_addr.sin_port;
+       if (sendport) {
+               a = (char *)&data_addr.sin_addr;
+               p = (char *)&data_addr.sin_port;
 #define        UC(b)   (((int)b)&0xff)
 #define        UC(b)   (((int)b)&0xff)
-       result =
-           command("PORT %d,%d,%d,%d,%d,%d",
-             UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
-             UC(p[0]), UC(p[1]));
-       return (result != COMPLETE);
+               result =
+                   command("PORT %d,%d,%d,%d,%d,%d",
+                     UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
+                     UC(p[0]), UC(p[1]));
+               if (result == ERROR && sendport == -1) {
+                       sendport = 0;
+                       goto noport;
+               }
+               return (result != COMPLETE);
+       }
+       return (0);
 bad:
        (void) close(data), data = -1;
        return (1);
 bad:
        (void) close(data), data = -1;
        return (1);
@@ -496,19 +552,18 @@ dataconn(mode)
 
 ptransfer(direction, bytes, t0, t1)
        char *direction;
 
 ptransfer(direction, bytes, t0, t1)
        char *direction;
-       int bytes;
+       long bytes;
        struct timeval *t0, *t1;
 {
        struct timeval td;
        struct timeval *t0, *t1;
 {
        struct timeval td;
-       int ms, bs;
+       float s, bs;
 
        tvsub(&td, t1, t0);
 
        tvsub(&td, t1, t0);
-       ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
+       s = td.tv_sec + (td.tv_usec / 1000000.);
 #define        nz(x)   ((x) == 0 ? 1 : (x))
 #define        nz(x)   ((x) == 0 ? 1 : (x))
-       bs = ((bytes * NBBY * 1000) / nz(ms)) / NBBY;
-       printf("%d bytes %s in %d.%02d seconds (%d.%01d Kbytes/s)\n",
-               bytes, direction, td.tv_sec, td.tv_usec / 10000,
-               bs / 1024, (((bs % 1024) * 10) + 1023) / 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)