Sync with NetBSD:
authorPeter Avalos <pavalos@dragonflybsd.org>
Sat, 4 Aug 2007 15:09:31 +0000 (15:09 +0000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Sat, 4 Aug 2007 15:09:31 +0000 (15:09 +0000)
- Fix up display of interrupted prompts.

- Modify parse_url() to consistently strip the leading `/' off ftp URLs.

- Display times in RFC2822.

- Enforce restriction that (http) proxied URL fetchs don't support
being restarted.

contrib/tnftp/cmds.c
contrib/tnftp/extern.h
contrib/tnftp/fetch.c
contrib/tnftp/ftp.1
contrib/tnftp/ftp.c
contrib/tnftp/ftp_var.h
contrib/tnftp/main.c
contrib/tnftp/progressbar.c
contrib/tnftp/util.c
contrib/tnftp/version.h

index 554b17a..241fd1d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: cmds.c,v 1.121 2007/04/18 01:39:04 lukem Exp $ */
+/*     $NetBSD: cmds.c,v 1.123 2007/05/24 05:05:18 lukem Exp $ */
 
 /*-
  * Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
 #if 0
 static char sccsid[] = "@(#)cmds.c     8.6 (Berkeley) 10/9/94";
 #else
-__RCSID("$NetBSD: cmds.c,v 1.121 2007/04/18 01:39:04 lukem Exp $");
+__RCSID("$NetBSD: cmds.c,v 1.123 2007/05/24 05:05:18 lukem Exp $");
 #endif
 #endif /* not lint */
 
@@ -754,8 +754,9 @@ mget(int argc, char *argv[])
 void
 fget(int argc, char *argv[])
 {
-       char    *buf, *mode;
+       char    *mode;
        FILE    *fp;
+       char    buf[MAXPATHLEN];
 
        if (argc != 2) {
                UPRINTF("usage: %s localfile\n", argv[0]);
@@ -773,9 +774,7 @@ fget(int argc, char *argv[])
        argv[0] = "get";
        mode = restart_point ? "r+" : "w";
 
-       for (;
-           (buf = fparseln(fp, NULL, NULL, "\0\0\0", 0)) != NULL;
-           free(buf)) {
+       while (getline(fp, buf, sizeof(buf), NULL) >= 0) {
                if (buf[0] == '\0')
                        continue;
                argv[1] = buf;
@@ -2496,7 +2495,8 @@ modtime(int argc, char *argv[])
        }
        mtime = remotemodtime(argv[1], 1);
        if (mtime != -1)
-               fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime)));
+               fprintf(ttyout, "%s\t%s", argv[1],
+                   rfc2822time(localtime(&mtime)));
        code = (mtime > 0);
 }
 
index 628384c..ee7d9f6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: extern.h,v 1.71 2007/04/18 01:39:04 lukem Exp $        */
+/*     $NetBSD: extern.h,v 1.72 2007/05/24 05:05:18 lukem Exp $        */
 
 /*-
  * Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
@@ -195,6 +195,7 @@ void        removedir(int, char **);
 void   renamefile(int, char **);
 void   reset(int, char **);
 void   restart(int, char **);
+const char *rfc2822time(const struct tm *);
 void   rmthelp(int, char **);
 void   rmtstatus(int, char **);
 char   *rprompt(void);
index 0b66024..7954277 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: fetch.c,v 1.175 2007/04/17 05:52:03 lukem Exp $        */
+/*     $NetBSD: fetch.c,v 1.180 2007/06/05 00:31:20 lukem Exp $        */
 
 /*-
  * Copyright (c) 1997-2007 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: fetch.c,v 1.175 2007/04/17 05:52:03 lukem Exp $");
+__RCSID("$NetBSD: fetch.c,v 1.180 2007/06/05 00:31:20 lukem Exp $");
 #endif /* not lint */
 
 /*
@@ -286,7 +286,7 @@ url_decode(char *url)
 
 
 /*
- * Parse URL of form:
+ * Parse URL of form (per RFC3986):
  *     <type>://[<user>[:<password>]@]<host>[:<port>][/<path>]
  * Returns -1 if a parse error occurred, otherwise 0.
  * It's the caller's responsibility to url_decode() the returned
@@ -296,12 +296,9 @@ url_decode(char *url)
  * malloc(3)ed strings of the relevant section, and port to
  * the number given, or ftpport if ftp://, or httpport if http://.
  *
- * If <host> is surrounded by `[' and ']', it's parsed as an
- * IPv6 address (as per RFC 2732).
- *
- * XXX: this is not totally RFC 1738 compliant; <path> will have the
+ * XXX: this is not totally RFC3986 compliant; <path> will have the
  * leading `/' unless it's an ftp:// URL, as this makes things easier
- * for file:// and http:// URLs. ftp:// URLs have the `/' between the
+ * for file:// and http:// URLs.  ftp:// URLs have the `/' between the
  * host and the URL-path removed, but any additional leading slashes
  * in the URL-path are retained (because they imply that we should
  * later do "CWD" with a null argument).
@@ -309,11 +306,14 @@ url_decode(char *url)
  * Examples:
  *      input URL                       output path
  *      ---------                       -----------
- *     "ftp://host"                    NULL
- *     "http://host/"                  NULL
+ *     "http://host"                   "/"
+ *     "http://host/"                  "/"
+ *     "http://host/path"              "/path"
  *     "file://host/dir/file"          "dir/file"
+ *     "ftp://host"                    ""
  *     "ftp://host/"                   ""
- *     "ftp://host//"                  NULL
+ *     "ftp://host//"                  "/"
+ *     "ftp://host/dir/file"           "dir/file"
  *     "ftp://host//dir/file"          "/dir/file"
  */
 static int
@@ -398,7 +398,7 @@ parse_url(const char *url, const char *desc, url_t *type,
 #ifdef INET6
                        /*
                         * Check if thost is an encoded IPv6 address, as per
-                        * RFC 2732:
+                        * RFC3986:
                         *      `[' ipv6-address ']'
                         */
        if (*thost == '[') {
@@ -424,8 +424,8 @@ parse_url(const char *url, const char *desc, url_t *type,
                        cp = NULL;
        } else
 #endif /* INET6 */
-           if ((cp = strchr(thost, ':')) != NULL)
-               *cp++ =  '\0';
+               if ((cp = strchr(thost, ':')) != NULL)
+                       *cp++ =  '\0';
        *host = thost;
 
                        /* look for [:port] */
@@ -444,8 +444,12 @@ parse_url(const char *url, const char *desc, url_t *type,
 
        if (tport != NULL)
                *port = ftp_strdup(tport);
-       if (*path == NULL)
-               *path = ftp_strdup("/");
+       if (*path == NULL) {
+               const char *emptypath = "/";
+               if (*type == FTP_URL_T) /* skip first / for ftp URLs */
+                       emptypath++;
+               *path = ftp_strdup(emptypath);
+       }
 
        DPRINTF("parse_url: user `%s' pass `%s' host %s port %s(%d) "
            "path `%s'\n",
@@ -485,7 +489,8 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
        static char             *xferbuf;
        const char              *cp, *token;
        char                    *ep;
-       char                    *volatile buf;
+       char                    buf[FTPBUFLEN];
+       const char              *errormsg;
        char                    *volatile savefile;
        char                    *volatile auth;
        char                    *volatile location;
@@ -505,7 +510,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
        closefunc = NULL;
        fin = fout = NULL;
        s = -1;
-       buf = savefile = NULL;
+       savefile = NULL;
        auth = location = message = NULL;
        ischunked = isproxy = hcode = 0;
        rval = 1;
@@ -646,6 +651,11 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
                        }
 
                        if (isproxy) {
+                               if (restart_point) {
+                                       warnx("Can't restart via proxy URL `%s'",
+                                           proxyenv);
+                                       goto cleanup_fetch_url;
+                               }
                                if (parse_url(proxyenv, "proxy URL", &purltype,
                                    &puser, &ppass, &phost, &pport, &portnum,
                                    &ppath) == -1)
@@ -822,8 +832,11 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
                }
 
                                /* Read the response */
-               if ((buf = fparseln(fin, &len, NULL, "\0\0\0", 0)) == NULL) {
-                       warn("Receiving HTTP reply");
+               len = getline(fin, buf, sizeof(buf), &errormsg);
+               if (len < 0) {
+                       if (*errormsg == '\n')
+                               errormsg++;
+                       warnx("Receiving HTTP reply: %s", errormsg);
                        goto cleanup_fetch_url;
                }
                while (len > 0 && (ISLWS(buf[len-1])))
@@ -843,10 +856,11 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
 
                                /* Read the rest of the header. */
                while (1) {
-                       FREEPTR(buf);
-                       if ((buf = fparseln(fin, &len, NULL, "\0\0\0", 0))
-                           == NULL) {
-                               warn("Receiving HTTP reply");
+                       len = getline(fin, buf, sizeof(buf), &errormsg);
+                       if (len < 0) {
+                               if (*errormsg == '\n')
+                                       errormsg++;
+                               warnx("Receiving HTTP reply: %s", errormsg);
                                goto cleanup_fetch_url;
                        }
                        while (len > 0 && (ISLWS(buf[len-1])))
@@ -920,11 +934,12 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
                                struct tm parsed;
                                char *t;
 
-                                                       /* RFC 1123 */
+                               memset(&parsed, 0, sizeof(parsed));
+                                                       /* RFC1123 */
                                if ((t = strptime(cp,
                                                "%a, %d %b %Y %H:%M:%S GMT",
                                                &parsed))
-                                                       /* RFC 850 */
+                                                       /* RFC0850 */
                                    || (t = strptime(cp,
                                                "%a, %d-%b-%y %H:%M:%S GMT",
                                                &parsed))
@@ -939,7 +954,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
                                        if (ftp_debug && mtime != -1) {
                                                fprintf(ttyout,
                                                    "parsed date as: %s",
-                                                   ctime(&mtime));
+                                               rfc2822time(localtime(&mtime)));
                                        }
 #endif
                                }
@@ -978,7 +993,6 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
 
                }
                                /* finished parsing header */
-               FREEPTR(buf);
 
                switch (hcode) {
                case 200:
@@ -1239,7 +1253,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
                if (utimes(savefile, tval) == -1) {
                        fprintf(ttyout,
                            "Can't change modification time to %s",
-                           asctime(localtime(&mtime)));
+                           rfc2822time(localtime(&mtime)));
                }
        }
        if (bytes > 0)
@@ -1278,7 +1292,6 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
        if (ppass != NULL)
                memset(ppass, 0, strlen(ppass));
        FREEPTR(ppass);
-       FREEPTR(buf);
        FREEPTR(auth);
        FREEPTR(location);
        FREEPTR(message);
@@ -1480,12 +1493,12 @@ fetch_ftp(const char *url)
                 * directories in one step.
                 *
                 * If we are dealing with an `ftp://host/path' URL
-                * (urltype is FTP_URL_T), then RFC 1738 says we need to
+                * (urltype is FTP_URL_T), then RFC3986 says we need to
                 * send a separate CWD command for each unescaped "/"
                 * in the path, and we have to interpret %hex escaping
                 * *after* we find the slashes.  It's possible to get
                 * empty components here, (from multiple adjacent
-                * slashes in the path) and RFC 1738 says that we should
+                * slashes in the path) and RFC3986 says that we should
                 * still do `CWD ' (with a null argument) in such cases.
                 *
                 * Many ftp servers don't support `CWD ', so if there's an
@@ -1557,8 +1570,8 @@ fetch_ftp(const char *url)
                                                fprintf(stderr,
 "\n"
 "ftp: The `CWD ' command (without a directory), which is required by\n"
-"     RFC 1738 to support the empty directory in the URL pathname (`//'),\n"
-"     conflicts with the server's conformance to RFC 959.\n"
+"     RFC3986 to support the empty directory in the URL pathname (`//'),\n"
+"     conflicts with the server's conformance to RFC0959.\n"
 "     Try the same URL without the `//' in the URL pathname.\n"
 "\n");
                                        goto cleanup_fetch_ftp;
index ea2a50d..4f99f2b 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $NetBSD: ftp.1,v 1.115 2007/04/17 05:52:03 lukem Exp $
+.\"    $NetBSD: ftp.1,v 1.119 2007/07/18 06:40:01 lukem Exp $
 .\"
 .\" Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -64,7 +64,7 @@
 .\"
 .\"    @(#)ftp.1       8.3 (Berkeley) 10/9/94
 .\"
-.Dd April 16, 2007
+.Dd July 18, 2007
 .Dt FTP 1
 .Os
 .Sh NAME
@@ -356,7 +356,7 @@ is awaiting commands from the user the prompt
 is provided to the user.
 The following commands are recognized
 by
-.Nm ftp  :
+.Nm ftp :
 .Bl -tag -width Ic
 .It Ic \&! Op Ar command Op Ar args
 Invoke an interactive shell on the local machine.
@@ -787,7 +787,9 @@ The default (and only supported)
 mode is
 .Dq stream .
 .It Ic modtime Ar remote-file
-Show the last modification time of the file on the remote machine.
+Show the last modification time of the file on the remote machine, in
+.Li RFC2822
+format.
 .It Ic more Ar file
 A synonym for
 .Ic page .
@@ -1007,7 +1009,7 @@ traffic.
 servers are required to support the
 .Dv PASV
 command by
-.Li RFC 1123 ,
+.Li RFC1123 ,
 some do not.)
 .It Ic pdir Op Ar remote-path
 Perform
@@ -1622,7 +1624,7 @@ ascii or binary (respectively).
 The default transfer type is binary.
 .Pp
 In order to be compliant with
-.Li RFC 1738 ,
+.Li RFC3986 ,
 .Nm
 interprets the
 .Ar path
@@ -1675,7 +1677,7 @@ Any
 .Sq Li \&% Ns Ar XX
 codes
 (per
-.Li RFC 1738 )
+.Li RFC3986 )
 within the path components are decoded, with
 .Ar XX
 representing a character code in hexadecimal.
@@ -1800,6 +1802,26 @@ is in the URL, use them for the first attempt to authenticate.
 A local URL, copied from
 .Pa / Ns Ar path
 on the local host.
+.\" about:
+.It Xo
+.Sm off
+.Li about:
+.Ar topic
+.Sm on
+.Xc
+Display information regarding
+.Ar topic ;
+no file is retrieved for this auto-fetched element.
+Supported values include:
+.Bl -tag -width "about:version"
+.It Li about:ftp
+Information about
+.Nm ftp .
+.It Li about:version
+The version of
+.Nm ftp .
+Useful to provide when reporting problems.
+.El
 .El
 .Pp
 Unless noted otherwise above, and
@@ -2320,7 +2342,7 @@ URL characters are required in the username or password
 or
 .Sq / ) ,
 encode them with
-.Li RFC 1738
+.Li RFC3986
 .Sq Li \&% Ns Ar XX
 encoding.
 .Pp
@@ -2363,16 +2385,27 @@ for an example of how to make this automatic.
 .Xr ftpd 8
 .Sh STANDARDS
 .Nm
-attempts to be compliant with
-.Li RFC 959 ,
-.Li RFC 1123 ,
-.Li RFC 1738 ,
-.Li RFC 2068 ,
-.Li RFC 2389 ,
-.Li RFC 2428 ,
-.Li RFC 2732 ,
-and
-.Cm draft-ietf-ftpext-mlst-11 .
+attempts to be compliant with:
+.Bl -tag -offset indent -width 8n
+.It Li RFC0959
+.Em File Transfer Protocol
+.It Li RFC1123
+.Em Requirements for Internet Hosts - Application and Support
+.It Li RFC1635
+.Em How to Use Anonymous FTP
+.It Li RFC2389
+.Em Feature negotiation mechanism for the File Transfer Protocol
+.It Li RFC2428
+.Em FTP Extensions for IPv6 and NATs
+.It Li RFC2616
+.Em Hypertext Transfer Protocol -- HTTP/1.1
+.It Li RFC2822
+.Em Internet Message Format
+.It Li RFC3659
+.Em Extensions to FTP
+.It Li RFC3986
+.Em Uniform Resource Identifier (URI)
+.El
 .Sh HISTORY
 The
 .Nm
index b6cc64f..aa44ff4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ftp.c,v 1.148 2007/04/18 01:50:45 lukem Exp $  */
+/*     $NetBSD: ftp.c,v 1.152 2007/07/22 05:02:50 lukem Exp $  */
 
 /*-
  * Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
@@ -99,7 +99,7 @@
 #if 0
 static char sccsid[] = "@(#)ftp.c      8.6 (Berkeley) 10/27/94";
 #else
-__RCSID("$NetBSD: ftp.c,v 1.148 2007/04/18 01:50:45 lukem Exp $");
+__RCSID("$NetBSD: ftp.c,v 1.152 2007/07/22 05:02:50 lukem Exp $");
 #endif
 #endif /* not lint */
 
@@ -146,12 +146,12 @@ struct sockinet {
                struct sockaddr_in6 su_sin6;
 #endif
        } si_su;
-#if !HAVE_SOCKADDR_SA_LEN
+#if !defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
        int     si_len;
 #endif
 };
 
-#if !HAVE_SOCKADDR_SA_LEN
+#if !defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
 # define su_len                si_len
 #else
 # define su_len                si_su.su_sin.sin_len
@@ -567,20 +567,104 @@ abortxfer(int notused)
        siglongjmp(xferabort, 1);
 }
 
+/*
+ * Read data from infd & write to outfd, using buf/bufsize as the temporary
+ * buffer, dealing with short writes.
+ * If rate_limit != 0, rate-limit the transfer.
+ * If hash_interval != 0, fputc('c', ttyout) every hash_interval bytes.
+ * Updates global variables: bytes.
+ * Returns 0 if ok, 1 if there was a read error, 2 if there was a write error.
+ * In the case of error, errno contains the appropriate error code.
+ */
+static int
+copy_bytes(int infd, int outfd, char *buf, size_t bufsize,
+       int rate_limit, int hash_interval)
+{
+       volatile off_t  hashc;
+       ssize_t         inc, outc;
+       char            *bufp;
+       struct timeval  tvthen, tvnow, tvdiff;
+       off_t           bufrem, bufchunk;
+       int             serr;
+
+       hashc = hash_interval;
+       if (rate_limit)
+               bufchunk = rate_limit;
+       else
+               bufchunk = bufsize;
+
+       while (1) {
+               if (rate_limit) {
+                       (void)gettimeofday(&tvthen, NULL);
+               }
+               errno = 0;
+               inc = outc = 0;
+                                       /* copy bufchunk at a time */
+               bufrem = bufchunk;
+               while (bufrem > 0) {
+                       inc = read(infd, buf, MIN(bufsize, bufrem));
+                       if (inc <= 0)
+                               goto copy_done;
+                       bytes += inc;
+                       bufrem -= inc;
+                       bufp = buf;
+                       while (inc > 0) {
+                               outc = write(outfd, bufp, inc);
+                               if (outc < 0)
+                                       goto copy_done;
+                               inc -= outc;
+                               bufp += outc;
+                       }
+                       if (hash_interval) {
+                               while (bytes >= hashc) {
+                                       (void)putc('#', ttyout);
+                                       hashc += hash_interval;
+                               }
+                               (void)fflush(ttyout);
+                       }
+               }
+               if (rate_limit) {       /* rate limited; wait if necessary */
+                       while (1) {
+                               (void)gettimeofday(&tvnow, NULL);
+                               timersub(&tvnow, &tvthen, &tvdiff);
+                               if (tvdiff.tv_sec > 0)
+                                       break;
+                               usleep(1000000 - tvdiff.tv_usec);
+                       }
+               }
+       }
+
+ copy_done:
+       serr = errno;
+       if (hash_interval && bytes > 0) {
+               if (bytes < hash_interval)
+                       (void)putc('#', ttyout);
+               (void)putc('\n', ttyout);
+               (void)fflush(ttyout);
+       }
+       errno = serr;
+       if (inc == -1)
+               return 1;
+       if (outc == -1)
+               return 2;
+
+       return 0;
+}
+
 void
 sendrequest(const char *cmd, const char *local, const char *remote,
            int printnames)
 {
        struct stat st;
-       int c, d;
+       int c;
        FILE *volatile fin;
        FILE *volatile dout;
        int (*volatile closefunc)(FILE *);
        sigfunc volatile oldintr;
        sigfunc volatile oldintp;
        off_t volatile hashbytes;
+       int hash_interval;
        char *volatile lmode;
-       char *bufp;
        static size_t bufsize;
        static char *buf;
        int oprogress;
@@ -693,79 +777,17 @@ sendrequest(const char *cmd, const char *local, const char *remote,
 
        progressmeter(-1);
        oldintp = xsignal(SIGPIPE, SIG_IGN);
+       hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0;
 
        switch (curtype) {
 
        case TYPE_I:
        case TYPE_L:
-               if (rate_put) {         /* rate limited */
-                       while (1) {
-                               struct timeval then, now, td;
-                               off_t bufrem;
-
-                               (void)gettimeofday(&then, NULL);
-                               errno = c = d = 0;
-                               bufrem = rate_put;
-                               while (bufrem > 0) {
-                                       if ((c = read(fileno(fin), buf,
-                                           MIN(bufsize, bufrem))) <= 0)
-                                               goto senddone;
-                                       bytes += c;
-                                       bufrem -= c;
-                                       for (bufp = buf; c > 0;
-                                           c -= d, bufp += d)
-                                               if ((d = write(fileno(dout),
-                                                   bufp, c)) <= 0)
-                                                       break;
-                                       if (d < 0)
-                                               goto senddone;
-                                       if (hash &&
-                                           (!progress || filesize < 0) ) {
-                                               while (bytes >= hashbytes) {
-                                                       (void)putc('#', ttyout);
-                                                       hashbytes += mark;
-                                               }
-                                               (void)fflush(ttyout);
-                                       }
-                               }
-                               while (1) {
-                                       (void)gettimeofday(&now, NULL);
-                                       timersub(&now, &then, &td);
-                                       if (td.tv_sec > 0)
-                                               break;
-                                       usleep(1000000 - td.tv_usec);
-                               }
-                       }
-               } else {                /* simpler/faster; no rate limit */
-                       while (1) {
-                               errno = c = d = 0;
-                               if ((c = read(fileno(fin), buf, bufsize)) <= 0)
-                                       goto senddone;
-                               bytes += c;
-                               for (bufp = buf; c > 0; c -= d, bufp += d)
-                                       if ((d = write(fileno(dout), bufp, c))
-                                           <= 0)
-                                               break;
-                               if (d < 0)
-                                       goto senddone;
-                               if (hash && (!progress || filesize < 0) ) {
-                                       while (bytes >= hashbytes) {
-                                               (void)putc('#', ttyout);
-                                               hashbytes += mark;
-                                       }
-                                       (void)fflush(ttyout);
-                               }
-                       }
-               }
- senddone:
-               if (hash && (!progress || filesize < 0) && bytes > 0) {
-                       if (bytes < mark)
-                               (void)putc('#', ttyout);
-                       (void)putc('\n', ttyout);
-               }
-               if (c < 0)
+               c = copy_bytes(fileno(fin), fileno(dout), buf, bufsize,
+                              rate_put, hash_interval);
+               if (c == 1) {
                        warn("Reading `%s'", local);
-               if (d < 0) {
+               } else if (c == 2) {
                        if (errno != EPIPE)
                                warn("Writing to network");
                        bytes = -1;
@@ -775,8 +797,7 @@ sendrequest(const char *cmd, const char *local, const char *remote,
        case TYPE_A:
                while ((c = getc(fin)) != EOF) {
                        if (c == '\n') {
-                               while (hash && (!progress || filesize < 0) &&
-                                   (bytes >= hashbytes)) {
+                               while (hash_interval && bytes >= hashbytes) {
                                        (void)putc('#', ttyout);
                                        (void)fflush(ttyout);
                                        hashbytes += mark;
@@ -788,14 +809,14 @@ sendrequest(const char *cmd, const char *local, const char *remote,
                        }
                        (void)putc(c, dout);
                        bytes++;
-#if 0  /* this violates RFC */
+#if 0  /* this violates RFC0959 */
                        if (c == '\r') {
                                (void)putc('\0', dout);
                                bytes++;
                        }
 #endif
                }
-               if (hash && (!progress || filesize < 0)) {
+               if (hash_interval) {
                        if (bytes < hashbytes)
                                (void)putc('#', ttyout);
                        (void)putc('\n', ttyout);
@@ -876,6 +897,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
        static size_t bufsize;
        static char *buf;
        off_t volatile hashbytes;
+       int hash_interval;
        struct stat st;
        time_t mtime;
        struct timeval tval[2];
@@ -1015,6 +1037,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
        }
 
        progressmeter(-1);
+       hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0;
 
        switch (curtype) {
 
@@ -1025,73 +1048,14 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
                        warn("Can't seek to restart `%s'", local);
                        goto cleanuprecv;
                }
-               if (rate_get) {         /* rate limiting */
-                       while (1) {
-                               struct timeval then, now, td;
-                               off_t bufrem;
-
-                               (void)gettimeofday(&then, NULL);
-                               errno = c = d = 0;
-                               for (bufrem = rate_get; bufrem > 0; ) {
-                                       if ((c = read(fileno(din), buf,
-                                           MIN(bufsize, bufrem))) <= 0)
-                                               goto recvdone;
-                                       bytes += c;
-                                       bufrem -=c;
-                                       if ((d = write(fileno(fout), buf, c))
-                                           != c)
-                                               goto recvdone;
-                                       if (hash &&
-                                           (!progress || filesize < 0)) {
-                                               while (bytes >= hashbytes) {
-                                                       (void)putc('#', ttyout);
-                                                       hashbytes += mark;
-                                               }
-                                               (void)fflush(ttyout);
-                                       }
-                               }
-                                       /* sleep until time is up */
-                               while (1) {
-                                       (void)gettimeofday(&now, NULL);
-                                       timersub(&now, &then, &td);
-                                       if (td.tv_sec > 0)
-                                               break;
-                                       usleep(1000000 - td.tv_usec);
-                               }
-                       }
-               } else {                /* faster code (no limiting) */
-                       while (1) {
-                               errno = c = d = 0;
-                               if ((c = read(fileno(din), buf, bufsize)) <= 0)
-                                       goto recvdone;
-                               bytes += c;
-                               if ((d = write(fileno(fout), buf, c)) != c)
-                                       goto recvdone;
-                               if (hash && (!progress || filesize < 0)) {
-                                       while (bytes >= hashbytes) {
-                                               (void)putc('#', ttyout);
-                                               hashbytes += mark;
-                                       }
-                                       (void)fflush(ttyout);
-                               }
-                       }
-               }
- recvdone:
-               if (hash && (!progress || filesize < 0) && bytes > 0) {
-                       if (bytes < mark)
-                               (void)putc('#', ttyout);
-                       (void)putc('\n', ttyout);
-               }
-               if (c < 0) {
+               c = copy_bytes(fileno(din), fileno(fout), buf, bufsize,
+                              rate_get, hash_interval);
+               if (c == 1) {
                        if (errno != EPIPE)
                                warn("Reading from network");
                        bytes = -1;
-               }
-               if (d < c) {
-                       if (d < 0)
-                               warn("Writing `%s'", local);
-                       else
-                               warnx("Writing `%s': short write", local);
+               } else if (c == 2) {
+                       warn("Writing `%s'", local);
                }
                break;
 
@@ -1118,8 +1082,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
                        if (c == '\n')
                                bare_lfs++;
                        while (c == '\r') {
-                               while (hash && (!progress || filesize < 0) &&
-                                   (bytes >= hashbytes)) {
+                               while (hash_interval && bytes >= hashbytes) {
                                        (void)putc('#', ttyout);
                                        (void)fflush(ttyout);
                                        hashbytes += mark;
@@ -1142,7 +1105,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
        contin2:        ;
                }
  break2:
-               if (hash && (!progress || filesize < 0)) {
+               if (hash_interval) {
                        if (bytes < hashbytes)
                                (void)putc('#', ttyout);
                        (void)putc('\n', ttyout);
@@ -1183,7 +1146,8 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
                                if (utimes(local, tval) == -1) {
                                        fprintf(ttyout,
                                "Can't change modification time on %s to %s",
-                                           local, asctime(localtime(&mtime)));
+                                           local,
+                                           rfc2822time(localtime(&mtime)));
                                }
                        }
                }
@@ -1192,7 +1156,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
 
  abort:
                        /*
-                        * abort using RFC 959 recommended IP,SYNC sequence
+                        * abort using RFC0959 recommended IP,SYNC sequence
                         */
        if (! sigsetjmp(xferabort, 1)) {
                        /* this is the first call */
@@ -2150,7 +2114,7 @@ ai_unmapped(struct addrinfo *ai)
        sin.sin_port = sin6->sin6_port;
 
        ai->ai_family = AF_INET;
-#if HAVE_SOCKADDR_SA_LEN
+#if defined(HAVE_STRUCT_SOCKADDR_SA_LEN)
        sin.sin_len = len;
 #endif
        memcpy(ai->ai_addr, &sin, len);
index 0997376..990420e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: ftp_var.h,v 1.74 2007/04/17 05:52:03 lukem Exp $       */
+/*     $NetBSD: ftp_var.h,v 1.75 2007/07/22 05:02:50 lukem Exp $       */
 
 /*-
  * Copyright (c) 1996-2007 The NetBSD Foundation, Inc.
@@ -328,7 +328,7 @@ extern      struct option   optiontab[];
 #define        FREEPTR(x)      if ((x) != NULL) { free(x); (x) = NULL; }
 
 #ifdef BSD4_4
-# define HAVE_SOCKADDR_SA_LEN  1
+# define HAVE_STRUCT_SOCKADDR_SA_LEN   1
 #endif
 
 #ifdef NO_LONG_LONG
index c7740de..8805c36 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: main.c,v 1.104 2007/04/17 05:52:03 lukem Exp $ */
+/*     $NetBSD: main.c,v 1.105 2007/05/22 05:16:48 lukem Exp $ */
 
 /*-
  * Copyright (c) 1996-2005 The NetBSD Foundation, Inc.
@@ -104,7 +104,7 @@ __COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\n\
 #if 0
 static char sccsid[] = "@(#)main.c     8.6 (Berkeley) 10/9/94";
 #else
-__RCSID("$NetBSD: main.c,v 1.104 2007/04/17 05:52:03 lukem Exp $");
+__RCSID("$NetBSD: main.c,v 1.105 2007/05/22 05:16:48 lukem Exp $");
 #endif
 #endif /* not lint */
 
@@ -123,6 +123,7 @@ __RCSID("$NetBSD: main.c,v 1.104 2007/04/17 05:52:03 lukem Exp $");
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 #include <locale.h>
 
@@ -147,6 +148,7 @@ main(int volatile argc, char **volatile argv)
        size_t len;
        socklen_t slen;
 
+       tzset();
        setlocale(LC_ALL, "");
        setprogname(argv[0]);
 
index 34d3cc6..b9345cf 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: progressbar.c,v 1.15 2007/04/17 05:52:03 lukem Exp $   */
+/*     $NetBSD: progressbar.c,v 1.17 2007/05/05 18:09:24 martin Exp $  */
 
 /*-
  * Copyright (c) 1997-2007 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: progressbar.c,v 1.15 2007/04/17 05:52:03 lukem Exp $");
+__RCSID("$NetBSD: progressbar.c,v 1.17 2007/05/05 18:09:24 martin Exp $");
 #endif /* not lint */
 
 /*
@@ -93,7 +93,7 @@ updateprogressmeter(int dummy)
 /*
  * List of order of magnitude suffixes, per IEC 60027-2.
  */
-static const char const *suffixes[] = {
+static const char * const suffixes[] = {
        "",     /* 2^0  (byte) */
        "KiB",  /* 2^10 Kibibyte */
        "MiB",  /* 2^20 Mebibyte */
index 6162fbc..05f0167 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: util.c,v 1.138 2007/04/17 05:52:04 lukem Exp $ */
+/*     $NetBSD: util.c,v 1.143 2007/05/24 05:05:19 lukem Exp $ */
 
 /*-
  * Copyright (c) 1997-2007 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: util.c,v 1.138 2007/04/17 05:52:04 lukem Exp $");
+__RCSID("$NetBSD: util.c,v 1.143 2007/05/24 05:05:19 lukem Exp $");
 #endif /* not lint */
 
 /*
@@ -175,7 +175,7 @@ parse_feat(const char *line)
 
                        /*
                         * work-around broken ProFTPd servers that can't
-                        * even obey RFC 2389.
+                        * even obey RFC2389.
                         */
        while (*line && isspace((int)*line))
                line++;
@@ -399,7 +399,7 @@ ftp_login(const char *host, const char *luser, const char *lpass)
         */
        if (anonftp) {
                FREEPTR(user);
-               user = ftp_strdup("anonymous"); /* as per RFC 1635 */
+               user = ftp_strdup("anonymous"); /* as per RFC1635 */
                FREEPTR(pass);
                pass = ftp_strdup(getoptionvalue("anonpass"));
        }
@@ -717,7 +717,6 @@ remotemodtime(const char *file, int noisy)
        if (r == COMPLETE) {
                struct tm timebuf;
                char *timestr, *frac;
-               int yy, mo, day, hour, min, sec;
 
                /*
                 * time-val = 14DIGIT [ "." 1*DIGIT ]
@@ -749,20 +748,13 @@ remotemodtime(const char *file, int noisy)
                        timestr[1] = '0';
                        fprintf(ttyout, "Converted to `%s'\n", timestr);
                }
+               memset(&timebuf, 0, sizeof(timebuf));
                if (strlen(timestr) != 14 ||
-                   sscanf(timestr, "%04d%02d%02d%02d%02d%02d",
-                       &yy, &mo, &day, &hour, &min, &sec) != 6) {
+                   (strptime(timestr, "%Y%m%d%H%M%S", &timebuf) == NULL)) {
  bad_parse_time:
                        fprintf(ttyout, "Can't parse time `%s'.\n", timestr);
                        goto cleanup_parse_time;
                }
-               memset(&timebuf, 0, sizeof(timebuf));
-               timebuf.tm_sec = sec;
-               timebuf.tm_min = min;
-               timebuf.tm_hour = hour;
-               timebuf.tm_mday = day;
-               timebuf.tm_mon = mo - 1;
-               timebuf.tm_year = yy - TM_YEAR_BASE;
                timebuf.tm_isdst = -1;
                rtime = timegm(&timebuf);
                if (rtime == -1) {
@@ -771,7 +763,9 @@ remotemodtime(const char *file, int noisy)
                        else
                                goto cleanup_parse_time;
                } else
-                       DPRINTF("parsed date as: %s", ctime(&rtime));
+                       DPRINTF("parsed date `%s' as " LLF ", %s",
+                           timestr, (LLT)rtime,
+                           rfc2822time(localtime(&rtime)));
        } else {
                if (r == ERROR && code == 500 && features[FEAT_MDTM] == -1)
                        features[FEAT_MDTM] = 0;
@@ -787,6 +781,21 @@ remotemodtime(const char *file, int noisy)
        return (rtime);
 }
 
+/*
+ * Format tm in an RFC2822 compatible manner, with a trailing \n.
+ * Returns a pointer to a static string containing the result.
+ */
+const char *
+rfc2822time(const struct tm *tm)
+{
+       static char result[50];
+
+       if (strftime(result, sizeof(result),
+           "%a, %d %b %Y %H:%M:%S %z\n", tm) == 0)
+               errx(1, "Can't convert RFC2822 time: buffer too small");
+       return result;
+}
+
 /*
  * Update global `localcwd', which contains the state of the local cwd
  */
index b9937b3..83243fe 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: version.h,v 1.63 2007/04/18 01:39:04 lukem Exp $       */
+/*     $NetBSD: version.h,v 1.68 2007/06/05 00:31:20 lukem Exp $       */
 /*-
  * Copyright (c) 1999-2007 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -40,5 +40,5 @@
 #endif
 
 #ifndef FTP_VERSION
-#define        FTP_VERSION     "20070418"
+#define        FTP_VERSION     "20070605"
 #endif