new file organization
[unix-history] / usr / src / usr.bin / ftp / ftp.c
index c5cbd50..ae2b804 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)ftp.c      4.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)ftp.c      4.9 (Berkeley) %G%";
 #endif
 
 #include <sys/param.h>
 #endif
 
 #include <sys/param.h>
@@ -8,6 +8,7 @@ static char sccsid[] = "@(#)ftp.c       4.3 (Berkeley) %G%";
 #include <sys/socket.h>
 
 #include <netinet/in.h>
 #include <sys/socket.h>
 
 #include <netinet/in.h>
+#include <arpa/ftp.h>
 
 #include <stdio.h>
 #include <signal.h>
 
 #include <stdio.h>
 #include <signal.h>
@@ -15,7 +16,6 @@ static char sccsid[] = "@(#)ftp.c     4.3 (Berkeley) %G%";
 #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;
@@ -33,14 +33,11 @@ hookup(host, port)
        int port;
 {
        register struct hostent *hp;
        int port;
 {
        register struct hostent *hp;
-       int s;
+       int s, len;
 
        bzero((char *)&hisctladdr, sizeof (hisctladdr));
        hp = gethostbyname(host);
 
        bzero((char *)&hisctladdr, sizeof (hisctladdr));
        hp = gethostbyname(host);
-       if (hp) {
-               hisctladdr.sin_family = hp->h_addrtype;
-               hostname = hp->h_name;
-       } else {
+       if (hp == NULL) {
                static struct hostent def;
                static struct in_addr defaddr;
                static char namebuf[128];
                static struct hostent def;
                static struct in_addr defaddr;
                static char namebuf[128];
@@ -60,6 +57,8 @@ hookup(host, port)
                def.h_aliases = 0;
                hp = &def;
        }
                def.h_aliases = 0;
                hp = &def;
        }
+       hostname = hp->h_name;
+       hisctladdr.sin_family = hp->h_addrtype;
        s = socket(hp->h_addrtype, SOCK_STREAM, 0, 0);
        if (s < 0) {
                perror("ftp: socket");
        s = socket(hp->h_addrtype, SOCK_STREAM, 0, 0);
        if (s < 0) {
                perror("ftp: socket");
@@ -75,8 +74,9 @@ hookup(host, port)
                perror("ftp: connect");
                goto bad;
        }
                perror("ftp: connect");
                goto bad;
        }
-       if (socketaddr(s, &myctladdr) < 0) {
-               perror("ftp: socketaddr");
+       len = sizeof (myctladdr);
+       if (getsockname(s, (char *)&myctladdr, &len) < 0) {
+               perror("ftp: getsockname");
                goto bad;
        }
        cin = fdopen(s, "r");
                goto bad;
        }
        cin = fdopen(s, "r");
@@ -173,8 +173,10 @@ getreply(expecteof)
                        if (n == 0)
                                n = c;
                }
                        if (n == 0)
                                n = c;
                }
-               if (verbose || n == '5')
+               if (verbose || n == '5') {
                        putchar(c);
                        putchar(c);
+                       (void) fflush (stdout);
+               }
                if (continuation && code != originalcode) {
                        if (originalcode == 0)
                                originalcode = code;
                if (continuation && code != originalcode) {
                        if (originalcode == 0)
                                originalcode = code;
@@ -188,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)
@@ -213,10 +215,10 @@ 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, c;
+       long bytes = 0, hashbytes = sizeof (buf);
+       register int c, d;
        struct stat st;
        struct timeval start, stop;
        struct stat st;
        struct timeval start, stop;
-       extern int errno;
 
        closefunc = NULL;
        if (setjmp(sendabort))
 
        closefunc = NULL;
        if (setjmp(sendabort))
@@ -260,21 +262,34 @@ sendrequest(cmd, local, remote)
 
        case TYPE_I:
        case TYPE_L:
 
        case TYPE_I:
        case TYPE_L:
-               errno = 0;
+               errno = d = 0;
                while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) {
                while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) {
-                       if (write(fileno (dout), buf, c) < 0)
+                       if ((d = write(fileno (dout), buf, c)) < 0)
                                break;
                        bytes += c;
                                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);
-               else if (errno)
+               if (d < 0)
                        perror("netout");
                break;
 
        case TYPE_A:
                while ((c = getc(fin)) != EOF) {
                        if (c == '\n') {
                        perror("netout");
                break;
 
        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);
@@ -287,9 +302,15 @@ sendrequest(cmd, local, remote)
                                bytes++;
                        }
                }
                                bytes++;
                        }
                }
+               if (hash) {
+                       if (bytes < hashbytes)
+                               putchar('#');
+                       putchar('\n');
+                       fflush(stdout);
+               }
                if (ferror(fin))
                        perror(local);
                if (ferror(fin))
                        perror(local);
-               else if (ferror(dout))
+               if (ferror(dout))
                        perror("netout");
                break;
        }
                        perror("netout");
                break;
        }
@@ -319,15 +340,15 @@ 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();
+       int (*closefunc)(), pclose(), fclose(), (*oldintr)();
        char buf[BUFSIZ];
        char buf[BUFSIZ];
-       int (*closefunc)(), pclose(), fclose(), (*oldintr)(), c;
-       register int bytes = 0;
+       long bytes = 0, hashbytes = sizeof (buf);
+       register int c, d;
        struct timeval start, stop;
        struct timeval start, stop;
-       extern int errno;
 
        closefunc = NULL;
        if (setjmp(recvabort))
 
        closefunc = NULL;
        if (setjmp(recvabort))
@@ -360,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) {
@@ -375,21 +396,34 @@ recvrequest(cmd, local, remote)
 
        case TYPE_I:
        case TYPE_L:
 
        case TYPE_I:
        case TYPE_L:
-               errno = 0;
+               errno = d = 0;
                while ((c = read(fileno(din), buf, sizeof (buf))) > 0) {
                while ((c = read(fileno(din), buf, sizeof (buf))) > 0) {
-                       if (write(fileno(fout), buf, c) < 0)
+                       if ((d = write(fileno(fout), buf, c)) < 0)
                                break;
                        bytes += c;
                                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");
-               if (errno)
+               if (d < 0)
                        perror(local);
                break;
 
        case TYPE_A:
                while ((c = getc(din)) != EOF) {
                        if (c == '\r') {
                        perror(local);
                break;
 
        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))
@@ -404,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))
@@ -433,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;
 initconn()
 {
        register char *p, *a;
-       int result;
+       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;
@@ -452,22 +503,30 @@ initconn()
        if (options & SO_DEBUG &&
            setsockopt(data, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
                perror("ftp: setsockopt (ignored)");
        if (options & SO_DEBUG &&
            setsockopt(data, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
                perror("ftp: setsockopt (ignored)");
-       if (socketaddr(data, &data_addr) < 0) {
-               perror("ftp: socketaddr");
+       len = sizeof (data_addr);
+       if (getsockname(data, (char *)&data_addr, &len) < 0) {
+               perror("ftp: getsockname");
                goto bad;
        }
        if (listen(data, 1) < 0) {
                perror("ftp: listen");
                goto bad;
        }
                goto bad;
        }
        if (listen(data, 1) < 0) {
                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);
@@ -488,24 +547,27 @@ dataconn(mode)
        }
        (void) close(data);
        data = s;
        }
        (void) close(data);
        data = s;
+       if (*mode == 'w' && linger)
+               (void) setsockopt(s, SOL_SOCKET, SO_LINGER, &linger,
+                   sizeof (linger));
        return (fdopen(data, mode));
 }
 
 ptransfer(direction, bytes, t0, t1)
        char *direction;
        return (fdopen(data, mode));
 }
 
 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;
+       long ms;
+       float bs;
 
        tvsub(&td, t1, t0);
        ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
 #define        nz(x)   ((x) == 0 ? 1 : (x))
 
        tvsub(&td, t1, t0);
        ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
 #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 * NBBY * 1000) / (float) nz(ms)) / NBBY;
+       printf("%ld bytes %s in %d.%02d seconds (%.2g Kbytes/s)\n",
+               bytes, direction, td.tv_sec, td.tv_usec / 10000, bs / 1024.);
 }
 
 tvadd(tsum, t0)
 }
 
 tvadd(tsum, t0)