From c106ca54bb6c182bb1c5ce3f95e924afa9690d0f Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sat, 4 Aug 2007 15:09:31 +0000 Subject: [PATCH] Sync with NetBSD: - 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 | 14 +- contrib/tnftp/extern.h | 3 +- contrib/tnftp/fetch.c | 81 ++++++----- contrib/tnftp/ftp.1 | 69 +++++++--- contrib/tnftp/ftp.c | 258 ++++++++++++++++-------------------- contrib/tnftp/ftp_var.h | 4 +- contrib/tnftp/main.c | 6 +- contrib/tnftp/progressbar.c | 6 +- contrib/tnftp/util.c | 39 +++--- contrib/tnftp/version.h | 4 +- 10 files changed, 253 insertions(+), 231 deletions(-) diff --git a/contrib/tnftp/cmds.c b/contrib/tnftp/cmds.c index 554b17ade2..241fd1dbec 100644 --- a/contrib/tnftp/cmds.c +++ b/contrib/tnftp/cmds.c @@ -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. @@ -103,7 +103,7 @@ #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); } diff --git a/contrib/tnftp/extern.h b/contrib/tnftp/extern.h index 628384ccb9..ee7d9f66f9 100644 --- a/contrib/tnftp/extern.h +++ b/contrib/tnftp/extern.h @@ -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); diff --git a/contrib/tnftp/fetch.c b/contrib/tnftp/fetch.c index 0b66024555..7954277d8f 100644 --- a/contrib/tnftp/fetch.c +++ b/contrib/tnftp/fetch.c @@ -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 #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): * ://[[:]@][:][/] * 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 is surrounded by `[' and ']', it's parsed as an - * IPv6 address (as per RFC 2732). - * - * XXX: this is not totally RFC 1738 compliant; will have the + * XXX: this is not totally RFC3986 compliant; 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; diff --git a/contrib/tnftp/ftp.1 b/contrib/tnftp/ftp.1 index ea2a50dda4..4f99f2b578 100644 --- a/contrib/tnftp/ftp.1 +++ b/contrib/tnftp/ftp.1 @@ -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 diff --git a/contrib/tnftp/ftp.c b/contrib/tnftp/ftp.c index b6cc64f124..aa44ff45f3 100644 --- a/contrib/tnftp/ftp.c +++ b/contrib/tnftp/ftp.c @@ -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); diff --git a/contrib/tnftp/ftp_var.h b/contrib/tnftp/ftp_var.h index 0997376df4..990420ead3 100644 --- a/contrib/tnftp/ftp_var.h +++ b/contrib/tnftp/ftp_var.h @@ -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 diff --git a/contrib/tnftp/main.c b/contrib/tnftp/main.c index c7740debe8..8805c368e5 100644 --- a/contrib/tnftp/main.c +++ b/contrib/tnftp/main.c @@ -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 #include #include +#include #include #include @@ -147,6 +148,7 @@ main(int volatile argc, char **volatile argv) size_t len; socklen_t slen; + tzset(); setlocale(LC_ALL, ""); setprogname(argv[0]); diff --git a/contrib/tnftp/progressbar.c b/contrib/tnftp/progressbar.c index 34d3cc6b28..b9345cfadd 100644 --- a/contrib/tnftp/progressbar.c +++ b/contrib/tnftp/progressbar.c @@ -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 #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 */ diff --git a/contrib/tnftp/util.c b/contrib/tnftp/util.c index 6162fbc5f3..05f0167a1d 100644 --- a/contrib/tnftp/util.c +++ b/contrib/tnftp/util.c @@ -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 #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 */ diff --git a/contrib/tnftp/version.h b/contrib/tnftp/version.h index b9937b32b9..83243fe5bb 100644 --- a/contrib/tnftp/version.h +++ b/contrib/tnftp/version.h @@ -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 -- 2.41.0