From owner-svn-src-all@freebsd.org Tue Oct 9 10:49:21 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 6B9DF10C96B8; Tue, 9 Oct 2018 10:49:21 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 1E0758233A; Tue, 9 Oct 2018 10:49:21 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 18A8211065; Tue, 9 Oct 2018 10:49:21 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w99AnLXs001418; Tue, 9 Oct 2018 10:49:21 GMT (envelope-from des@FreeBSD.org) Received: (from des@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w99AnJib001412; Tue, 9 Oct 2018 10:49:19 GMT (envelope-from des@FreeBSD.org) Message-Id: <201810091049.w99AnJib001412@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: des set sender to des@FreeBSD.org using -f From: =?UTF-8?Q?Dag-Erling_Sm=c3=b8rgrav?= Date: Tue, 9 Oct 2018 10:49:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r339250 - in stable/11: lib/libfetch usr.bin/fetch X-SVN-Group: stable-11 X-SVN-Commit-Author: des X-SVN-Commit-Paths: in stable/11: lib/libfetch usr.bin/fetch X-SVN-Commit-Revision: 339250 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Oct 2018 10:49:21 -0000 Author: des Date: Tue Oct 9 10:49:19 2018 New Revision: 339250 URL: https://svnweb.freebsd.org/changeset/base/339250 Log: MFH (r314778): use reallocarray(3) for extra bounds checks MFH (r333306): fix typo in man page MFH (r333571, r333572): preserve if-modified-since across redirects MFH (r334317): simplify the DEBUG macro MFH (r334319): style bug roundup MFH (r334326): fix netrc file location logic, improve netrcfd handling MFH (r338572): fix end-of-transfer statistics, improve no-tty display PR: 202424, 224426, 228017 Modified: stable/11/lib/libfetch/common.c stable/11/lib/libfetch/common.h stable/11/lib/libfetch/fetch.c stable/11/lib/libfetch/ftp.c stable/11/lib/libfetch/http.c stable/11/usr.bin/fetch/fetch.1 stable/11/usr.bin/fetch/fetch.c Directory Properties: stable/11/ (props changed) Modified: stable/11/lib/libfetch/common.c ============================================================================== --- stable/11/lib/libfetch/common.c Tue Oct 9 07:22:14 2018 (r339249) +++ stable/11/lib/libfetch/common.c Tue Oct 9 10:49:19 2018 (r339250) @@ -345,7 +345,7 @@ fetch_connect(const char *host, int port, int af, int conn_t *conn = NULL; int err = 0, sd = -1; - DEBUG(fprintf(stderr, "---> %s:%d\n", host, port)); + DEBUGF("---> %s:%d\n", host, port); /* resolve server address */ if (verbose) @@ -1156,7 +1156,7 @@ fetch_getln(conn_t *conn) } while (c != '\n'); conn->buf[conn->buflen] = '\0'; - DEBUG(fprintf(stderr, "<<< %s", conn->buf)); + DEBUGF("<<< %s", conn->buf); return (0); } @@ -1261,7 +1261,7 @@ fetch_putln(conn_t *conn, const char *str, size_t len) struct iovec iov[2]; int ret; - DEBUG(fprintf(stderr, ">>> %s\n", str)); + DEBUGF(">>> %s\n", str); iov[0].iov_base = __DECONST(char *, str); iov[0].iov_len = len; iov[1].iov_base = __DECONST(char *, ENDL); @@ -1323,7 +1323,7 @@ fetch_add_entry(struct url_ent **p, int *size, int *le } if (*len >= *size - 1) { - tmp = realloc(*p, (*size * 2 + 1) * sizeof(**p)); + tmp = reallocarray(*p, *size * 2 + 1, sizeof(**p)); if (tmp == NULL) { errno = ENOMEM; fetch_syserr(); @@ -1359,19 +1359,20 @@ fetch_read_word(FILE *f) static int fetch_netrc_open(void) { - const char *p; + struct passwd *pwd; char fn[PATH_MAX]; + const char *p; + int fd, serrno; if ((p = getenv("NETRC")) != NULL) { + DEBUGF("NETRC=%s\n", p); if (snprintf(fn, sizeof(fn), "%s", p) >= (int)sizeof(fn)) { fetch_info("$NETRC specifies a file name " "longer than PATH_MAX"); return (-1); } } else { - if ((p = getenv("HOME")) != NULL) { - struct passwd *pwd; - + if ((p = getenv("HOME")) == NULL) { if ((pwd = getpwuid(getuid())) == NULL || (p = pwd->pw_dir) == NULL) return (-1); @@ -1380,7 +1381,12 @@ fetch_netrc_open(void) return (-1); } - return (open(fn, O_RDONLY)); + if ((fd = open(fn, O_RDONLY)) < 0) { + serrno = errno; + DEBUGF("%s: %s\n", fn, strerror(serrno)); + errno = serrno; + } + return (fd); } /* @@ -1390,24 +1396,32 @@ int fetch_netrc_auth(struct url *url) { const char *word; + int serrno; FILE *f; - if (url->netrcfd == -2) + if (url->netrcfd < 0) url->netrcfd = fetch_netrc_open(); if (url->netrcfd < 0) return (-1); - if ((f = fdopen(url->netrcfd, "r")) == NULL) + if ((f = fdopen(url->netrcfd, "r")) == NULL) { + serrno = errno; + DEBUGF("fdopen(netrcfd): %s", strerror(errno)); + close(url->netrcfd); + url->netrcfd = -1; + errno = serrno; return (-1); + } rewind(f); + DEBUGF("searching netrc for %s\n", url->host); while ((word = fetch_read_word(f)) != NULL) { if (strcmp(word, "default") == 0) { - DEBUG(fetch_info("Using default .netrc settings")); + DEBUGF("using default netrc settings\n"); break; } if (strcmp(word, "machine") == 0 && (word = fetch_read_word(f)) != NULL && strcasecmp(word, url->host) == 0) { - DEBUG(fetch_info("Using .netrc settings for %s", word)); + DEBUGF("using netrc settings for %s\n", word); break; } } @@ -1439,9 +1453,13 @@ fetch_netrc_auth(struct url *url) } } fclose(f); + url->netrcfd = -1; return (0); - ferr: +ferr: + serrno = errno; fclose(f); + url->netrcfd = -1; + errno = serrno; return (-1); } Modified: stable/11/lib/libfetch/common.h ============================================================================== --- stable/11/lib/libfetch/common.h Tue Oct 9 07:22:14 2018 (r339249) +++ stable/11/lib/libfetch/common.h Tue Oct 9 10:49:19 2018 (r339250) @@ -102,9 +102,16 @@ int fetch_no_proxy_match(const char *); #define url_seterr(n) fetch_seterr(url_errlist, n) #ifndef NDEBUG -#define DEBUG(x) do { if (fetchDebug) { x; } } while (0) +#define DEBUGF(...) \ + do { \ + if (fetchDebug) \ + fprintf(stderr, __VA_ARGS__); \ + } while (0) #else -#define DEBUG(x) do { } while (0) +#define DEBUGF(...) \ + do { \ + /* nothing */ \ + } while (0) #endif /* Modified: stable/11/lib/libfetch/fetch.c ============================================================================== --- stable/11/lib/libfetch/fetch.c Tue Oct 9 07:22:14 2018 (r339249) +++ stable/11/lib/libfetch/fetch.c Tue Oct 9 10:49:19 2018 (r339250) @@ -270,6 +270,7 @@ fetchMakeURL(const char *scheme, const char *host, int fetch_syserr(); return (NULL); } + u->netrcfd = -1; if ((u->doc = strdup(doc ? doc : "/")) == NULL) { fetch_syserr(); @@ -284,7 +285,6 @@ fetchMakeURL(const char *scheme, const char *host, int seturl(pwd); #undef seturl u->port = port; - u->netrcfd = -2; return (u); } @@ -350,7 +350,7 @@ fetchParseURL(const char *URL) fetch_syserr(); return (NULL); } - u->netrcfd = -2; + u->netrcfd = -1; /* scheme name */ if ((p = strstr(URL, ":/"))) { @@ -442,15 +442,14 @@ nohost: goto ouch; } - DEBUG(fprintf(stderr, - "scheme: \"%s\"\n" - "user: \"%s\"\n" - "password: \"%s\"\n" - "host: \"%s\"\n" - "port: \"%d\"\n" - "document: \"%s\"\n", - u->scheme, u->user, u->pwd, - u->host, u->port, u->doc)); + DEBUGF("scheme: \"%s\"\n" + "user: \"%s\"\n" + "password: \"%s\"\n" + "host: \"%s\"\n" + "port: \"%d\"\n" + "document: \"%s\"\n", + u->scheme, u->user, u->pwd, + u->host, u->port, u->doc); return (u); Modified: stable/11/lib/libfetch/ftp.c ============================================================================== --- stable/11/lib/libfetch/ftp.c Tue Oct 9 07:22:14 2018 (r339249) +++ stable/11/lib/libfetch/ftp.c Tue Oct 9 10:49:19 2018 (r339250) @@ -257,7 +257,7 @@ ftp_pwd(conn_t *conn, char *pwd, size_t pwdlen) return (FTP_PROTOCOL_ERROR); *dst = '\0'; #if 0 - DEBUG(fprintf(stderr, "pwd: [%s]\n", pwd)); + DEBUGF("pwd: [%s]\n", pwd); #endif return (FTP_OK); } @@ -289,8 +289,8 @@ ftp_cwd(conn_t *conn, const char *file) if (pwd[i] != file[i]) break; #if 0 - DEBUG(fprintf(stderr, "have: [%.*s|%s]\n", i, pwd, pwd + i)); - DEBUG(fprintf(stderr, "want: [%.*s|%s]\n", i, file, file + i)); + DEBUGF("have: [%.*s|%s]\n", i, pwd, pwd + i); + DEBUGF("want: [%.*s|%s]\n", i, file, file + i); #endif /* Keep going up a dir until we have a matching prefix. */ if (pwd[i] == '\0' && (file[i - 1] == '/' || file[i] == '/')) @@ -431,7 +431,7 @@ ftp_stat(conn_t *conn, const char *file, struct url_st } if (us->size == 0) us->size = -1; - DEBUG(fprintf(stderr, "size: [%lld]\n", (long long)us->size)); + DEBUGF("size: [%lld]\n", (long long)us->size); e = ftp_cmd(conn, "MDTM %.*s", filenamelen, filename); if (e != FTP_FILE_STATUS) { @@ -466,10 +466,9 @@ ftp_stat(conn_t *conn, const char *file, struct url_st t = time(NULL); us->mtime = t; us->atime = t; - DEBUG(fprintf(stderr, - "last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n", + DEBUGF("last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec)); + tm.tm_hour, tm.tm_min, tm.tm_sec); return (0); } @@ -583,7 +582,7 @@ ftp_closefn(void *v) fetch_close(io->dconn); io->dir = -1; io->dconn = NULL; - DEBUG(fprintf(stderr, "Waiting for final status\n")); + DEBUGF("Waiting for final status\n"); r = ftp_chkerr(io->cconn); if (io->cconn == cached_connection && io->cconn->ref == 1) cached_connection = NULL; @@ -913,7 +912,8 @@ ftp_authenticate(conn_t *conn, struct url *url, struct fetch_netrc_auth(url); user = url->user; if (*user == '\0') - user = getenv("FTP_LOGIN"); + if ((user = getenv("FTP_LOGIN")) != NULL) + DEBUGF("FTP_LOGIN=%s\n", user); if (user == NULL || *user == '\0') user = FTP_ANONYMOUS_USER; if (purl && url->port == fetch_default_port(url->scheme)) @@ -927,7 +927,8 @@ ftp_authenticate(conn_t *conn, struct url *url, struct if (e == FTP_NEED_PASSWORD) { pwd = url->pwd; if (*pwd == '\0') - pwd = getenv("FTP_PASSWORD"); + if ((pwd = getenv("FTP_PASSWORD")) != NULL) + DEBUGF("FTP_PASSWORD=%s\n", pwd); if (pwd == NULL || *pwd == '\0') { if ((logname = getlogin()) == NULL) logname = FTP_ANONYMOUS_USER; Modified: stable/11/lib/libfetch/http.c ============================================================================== --- stable/11/lib/libfetch/http.c Tue Oct 9 07:22:14 2018 (r339249) +++ stable/11/lib/libfetch/http.c Tue Oct 9 10:49:19 2018 (r339250) @@ -778,9 +778,9 @@ http_parse_authenticate(const char *cp, http_auth_chal goto out; } init_http_auth_challenge(cs->challenges[cs->count]); - if (!strcasecmp(key, "basic")) { + if (strcasecmp(key, "basic") == 0) { cs->challenges[cs->count]->scheme = HTTPAS_BASIC; - } else if (!strcasecmp(key, "digest")) { + } else if (strcasecmp(key, "digest") == 0) { cs->challenges[cs->count]->scheme = HTTPAS_DIGEST; } else { cs->challenges[cs->count]->scheme = HTTPAS_UNKNOWN; @@ -809,25 +809,27 @@ http_parse_authenticate(const char *cp, http_auth_chal if (lex != HTTPHL_WORD && lex != HTTPHL_STRING) goto out; - if (!strcasecmp(key, "realm")) + if (strcasecmp(key, "realm") == 0) { cs->challenges[cs->count]->realm = - strdup(value); - else if (!strcasecmp(key, "qop")) + strdup(value); + } else if (strcasecmp(key, "qop") == 0) { cs->challenges[cs->count]->qop = - strdup(value); - else if (!strcasecmp(key, "nonce")) + strdup(value); + } else if (strcasecmp(key, "nonce") == 0) { cs->challenges[cs->count]->nonce = - strdup(value); - else if (!strcasecmp(key, "opaque")) + strdup(value); + } else if (strcasecmp(key, "opaque") == 0) { cs->challenges[cs->count]->opaque = - strdup(value); - else if (!strcasecmp(key, "algorithm")) + strdup(value); + } else if (strcasecmp(key, "algorithm") == 0) { cs->challenges[cs->count]->algo = - strdup(value); - else if (!strcasecmp(key, "stale")) + strdup(value); + } else if (strcasecmp(key, "stale") == 0) { cs->challenges[cs->count]->stale = - strcasecmp(value, "no"); - /* Else ignore unknown attributes */ + strcasecmp(value, "no"); + } else { + /* ignore unknown attributes */ + } /* Comma or Next challenge or End */ lex = http_header_lex(&cp, key); @@ -889,10 +891,9 @@ http_parse_mtime(const char *p, time_t *mtime) setlocale(LC_TIME, locale); if (r == NULL) return (-1); - DEBUG(fprintf(stderr, "last modified: [%04d-%02d-%02d " - "%02d:%02d:%02d]\n", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec)); + DEBUGF("last modified: [%04d-%02d-%02d %02d:%02d:%02d]\n", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); *mtime = timegm(&tm); return (0); } @@ -909,8 +910,7 @@ http_parse_length(const char *p, off_t *length) len = len * 10 + (*p - '0'); if (*p) return (-1); - DEBUG(fprintf(stderr, "content length: [%lld]\n", - (long long)len)); + DEBUGF("content length: [%lld]\n", (long long)len); *length = len; return (0); } @@ -944,12 +944,11 @@ http_parse_range(const char *p, off_t *offset, off_t * if (*p || len < last - first + 1) return (-1); if (first == -1) { - DEBUG(fprintf(stderr, "content range: [*/%lld]\n", - (long long)len)); + DEBUGF("content range: [*/%lld]\n", (long long)len); *length = 0; } else { - DEBUG(fprintf(stderr, "content range: [%lld-%lld/%lld]\n", - (long long)first, (long long)last, (long long)len)); + DEBUGF("content range: [%lld-%lld/%lld]\n", + (long long)first, (long long)last, (long long)len); *length = last - first + 1; } *offset = first; @@ -1185,9 +1184,10 @@ DigestCalcResponse( OUT HASHHEX Response /* request-digest or response-digest */ ) { -/* DEBUG(fprintf(stderr, - "Calc: HA1[%s] Nonce[%s] qop[%s] method[%s] URI[%s]\n", - HA1, pszNonce, pszQop, pszMethod, pszDigestUri));*/ +#if 0 + DEBUGF("Calc: HA1[%s] Nonce[%s] qop[%s] method[%s] URI[%s]\n", + HA1, pszNonce, pszQop, pszMethod, pszDigestUri); +#endif MD5_CTX Md5Ctx; HASH HA2; HASH RespHash; @@ -1255,15 +1255,15 @@ http_digest_auth(conn_t *conn, const char *hdr, http_a char *options = NULL; if (!c->realm || !c->nonce) { - DEBUG(fprintf(stderr, "realm/nonce not set in challenge\n")); + DEBUGF("realm/nonce not set in challenge\n"); return(-1); } if (!c->algo) c->algo = strdup(""); if (asprintf(&options, "%s%s%s%s", - *c->algo? ",algorithm=" : "", c->algo, - c->opaque? ",opaque=" : "", c->opaque?c->opaque:"")== -1) + *c->algo? ",algorithm=" : "", c->algo, + c->opaque? ",opaque=" : "", c->opaque?c->opaque:"") < 0) return (-1); if (!c->qop) { @@ -1280,7 +1280,7 @@ http_digest_auth(conn_t *conn, const char *hdr, http_a HASHHEX HA1; DigestCalcHA1(c->algo, parms->user, c->realm, parms->password, c->nonce, cnonce, HA1); - DEBUG(fprintf(stderr, "HA1: [%s]\n", HA1)); + DEBUGF("HA1: [%s]\n", HA1); HASHHEX digest; DigestCalcResponse(HA1, c->nonce, noncecount, cnonce, c->qop, "GET", url->doc, "", digest); @@ -1312,8 +1312,8 @@ http_basic_auth(conn_t *conn, const char *hdr, const c char *upw, *auth; int r; - DEBUG(fprintf(stderr, "basic: usr: [%s]\n", usr)); - DEBUG(fprintf(stderr, "basic: pwd: [%s]\n", pwd)); + DEBUGF("basic: usr: [%s]\n", usr); + DEBUGF("basic: pwd: [%s]\n", pwd); if (asprintf(&upw, "%s:%s", usr, pwd) == -1) return (-1); auth = http_base64(upw); @@ -1338,7 +1338,7 @@ http_authorize(conn_t *conn, const char *hdr, http_aut /* If user or pass are null we're not happy */ if (!parms->user || !parms->password) { - DEBUG(fprintf(stderr, "NULL usr or pass\n")); + DEBUGF("NULL usr or pass\n"); return (-1); } @@ -1349,10 +1349,9 @@ http_authorize(conn_t *conn, const char *hdr, http_aut } /* Error if "Digest" was specified and there is no Digest challenge */ - if (!digest && (parms->scheme && - !strcasecmp(parms->scheme, "digest"))) { - DEBUG(fprintf(stderr, - "Digest auth in env, not supported by peer\n")); + if (!digest && + (parms->scheme && strcasecmp(parms->scheme, "digest") == 0)) { + DEBUGF("Digest auth in env, not supported by peer\n"); return (-1); } /* @@ -1360,7 +1359,8 @@ http_authorize(conn_t *conn, const char *hdr, http_aut * challenge, do the basic thing. Don't need a challenge for this, * so no need to check basic!=NULL */ - if (!digest || (parms->scheme && !strcasecmp(parms->scheme,"basic"))) + if (!digest || + (parms->scheme && strcasecmp(parms->scheme, "basic") == 0)) return (http_basic_auth(conn,hdr,parms->user,parms->password)); /* Else, prefer digest. We just checked that it's not NULL */ @@ -1852,26 +1852,29 @@ http_request_body(struct url *URL, const char *op, str if (new) free(new); if (verbose) - fetch_info("%d redirect to %s", conn->err, p); + fetch_info("%d redirect to %s", + conn->err, p); if (*p == '/') /* absolute path */ - new = fetchMakeURL(url->scheme, url->host, url->port, p, - url->user, url->pwd); + new = fetchMakeURL(url->scheme, url->host, + url->port, p, url->user, url->pwd); else new = fetchParseURL(p); if (new == NULL) { /* XXX should set an error code */ - DEBUG(fprintf(stderr, "failed to parse new URL\n")); + DEBUGF("failed to parse new URL\n"); goto ouch; } /* Only copy credentials if the host matches */ - if (!strcmp(new->host, url->host) && !*new->user && !*new->pwd) { + if (strcmp(new->host, url->host) == 0 && + !*new->user && !*new->pwd) { strcpy(new->user, url->user); strcpy(new->pwd, url->pwd); } new->offset = url->offset; new->length = url->length; + new->ims_time = url->ims_time; break; case hdr_transfer_encoding: /* XXX weak test*/ @@ -1906,7 +1909,7 @@ http_request_body(struct url *URL, const char *op, str (conn->err == HTTP_NEED_PROXY_AUTH && !proxy_challenges.valid)) { /* 401/7 but no www/proxy-authenticate ?? */ - DEBUG(fprintf(stderr, "401/7 and no auth header\n")); + DEBUGF("%03d without auth header\n", conn->err); goto ouch; } fetch_close(conn); @@ -1941,7 +1944,7 @@ http_request_body(struct url *URL, const char *op, str fetch_close(conn); conn = NULL; if (!new) { - DEBUG(fprintf(stderr, "redirect with no new location\n")); + DEBUGF("redirect with no new location\n"); break; } if (url != URL) @@ -1955,10 +1958,9 @@ http_request_body(struct url *URL, const char *op, str goto ouch; } - DEBUG(fprintf(stderr, "offset %lld, length %lld," - " size %lld, clength %lld\n", - (long long)offset, (long long)length, - (long long)size, (long long)clength)); + DEBUGF("offset %lld, length %lld, size %lld, clength %lld\n", + (long long)offset, (long long)length, + (long long)size, (long long)clength); if (conn->err == HTTP_NOT_MODIFIED) { http_seterr(HTTP_NOT_MODIFIED); Modified: stable/11/usr.bin/fetch/fetch.1 ============================================================================== --- stable/11/usr.bin/fetch/fetch.1 Tue Oct 9 07:22:14 2018 (r339249) +++ stable/11/usr.bin/fetch/fetch.1 Tue Oct 9 10:49:19 2018 (r339250) @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 18, 2016 +.Dd May 6, 2018 .Dt FETCH 1 .Os .Sh NAME @@ -241,7 +241,7 @@ certificate presented by the server. .It Fl -no-verify-peer [SSL] Do not verify the peer certificate against trusted CAs. -.It Fl o Ar file , Fl output= Ns Ar file +.It Fl o Ar file , Fl -output= Ns Ar file Set the output file name to .Ar file . By default, a ``pathname'' is extracted from the specified URI, and Modified: stable/11/usr.bin/fetch/fetch.c ============================================================================== --- stable/11/usr.bin/fetch/fetch.c Tue Oct 9 07:22:14 2018 (r339249) +++ stable/11/usr.bin/fetch/fetch.c Tue Oct 9 10:49:19 2018 (r339250) @@ -85,6 +85,7 @@ static int t_flag; /*! -t: workaround TCP bug */ static int U_flag; /* -U: do not use high ports */ static int v_level = 1; /* -v: verbosity level */ static int v_tty; /* stdout is a tty */ +static int v_progress; /* whether to display progress */ static pid_t pgrp; /* our process group */ static long w_secs; /* -w: retry delay */ static int family = PF_UNSPEC; /* -[46]: address family to use */ @@ -199,12 +200,33 @@ struct xferstat { }; /* + * Format a number of seconds as either XXdYYh, XXhYYm, XXmYYs, or XXs + * depending on its magnitude + */ +static void +stat_seconds(char *str, size_t strsz, long seconds) +{ + + if (seconds > 86400) + snprintf(str, strsz, "%02ldd%02ldh", + seconds / 86400, (seconds % 86400) / 3600); + else if (seconds > 3600) + snprintf(str, strsz, "%02ldh%02ldm", + seconds / 3600, (seconds % 3600) / 60); + else if (seconds > 60) + snprintf(str, strsz, "%02ldm%02lds", + seconds / 60, seconds % 60); + else + snprintf(str, strsz, " %02lds", + seconds); +} + +/* * Compute and display ETA */ -static const char * -stat_eta(struct xferstat *xs) +static void +stat_eta(char *str, size_t strsz, const struct xferstat *xs) { - static char str[16]; long elapsed, eta; off_t received, expected; @@ -212,55 +234,47 @@ stat_eta(struct xferstat *xs) received = xs->rcvd - xs->offset; expected = xs->size - xs->rcvd; eta = (long)((double)elapsed * expected / received); - if (eta > 3600) - snprintf(str, sizeof str, "%02ldh%02ldm", - eta / 3600, (eta % 3600) / 60); - else if (eta > 0) - snprintf(str, sizeof str, "%02ldm%02lds", - eta / 60, eta % 60); + if (eta > 0) + stat_seconds(str, strsz, eta); else - snprintf(str, sizeof str, "%02ldm%02lds", - elapsed / 60, elapsed % 60); - return (str); + stat_seconds(str, strsz, elapsed); } /* * Format a number as "xxxx YB" where Y is ' ', 'k', 'M'... */ static const char *prefixes = " kMGTP"; -static const char * -stat_bytes(off_t bytes) +static void +stat_bytes(char *str, size_t strsz, off_t bytes) { - static char str[16]; const char *prefix = prefixes; while (bytes > 9999 && prefix[1] != '\0') { bytes /= 1024; prefix++; } - snprintf(str, sizeof str, "%4jd %cB", (intmax_t)bytes, *prefix); - return (str); + snprintf(str, strsz, "%4ju %cB", (uintmax_t)bytes, *prefix); } /* * Compute and display transfer rate */ -static const char * -stat_bps(struct xferstat *xs) +static void +stat_bps(char *str, size_t strsz, struct xferstat *xs) { - static char str[16]; + char bytes[16]; double delta, bps; - delta = (xs->last.tv_sec + (xs->last.tv_usec / 1.e6)) - - (xs->last2.tv_sec + (xs->last2.tv_usec / 1.e6)); + delta = ((double)xs->last.tv_sec + (xs->last.tv_usec / 1.e6)) + - ((double)xs->last2.tv_sec + (xs->last2.tv_usec / 1.e6)); if (delta == 0.0) { - snprintf(str, sizeof str, "?? Bps"); + snprintf(str, strsz, "?? Bps"); } else { bps = (xs->rcvd - xs->lastrcvd) / delta; - snprintf(str, sizeof str, "%sps", stat_bytes((off_t)bps)); + stat_bytes(bytes, sizeof bytes, (off_t)bps); + snprintf(str, strsz, "%sps", bytes); } - return (str); } /* @@ -269,11 +283,12 @@ stat_bps(struct xferstat *xs) static void stat_display(struct xferstat *xs, int force) { + char bytes[16], bps[16], eta[16]; struct timeval now; int ctty_pgrp; /* check if we're the foreground process */ - if (ioctl(STDERR_FILENO, TIOCGPGRP, &ctty_pgrp) == -1 || + if (ioctl(STDERR_FILENO, TIOCGPGRP, &ctty_pgrp) != 0 || (pid_t)ctty_pgrp != pgrp) return; @@ -284,26 +299,31 @@ stat_display(struct xferstat *xs, int force) xs->last = now; fprintf(stderr, "\r%-46.46s", xs->name); - if (xs->size <= 0) { - setproctitle("%s [%s]", xs->name, stat_bytes(xs->rcvd)); - fprintf(stderr, " %s", stat_bytes(xs->rcvd)); + if (xs->rcvd >= xs->size) { + stat_bytes(bytes, sizeof bytes, xs->rcvd); + setproctitle("%s [%s]", xs->name, bytes); + fprintf(stderr, " %s", bytes); } else { + stat_bytes(bytes, sizeof bytes, xs->size); setproctitle("%s [%d%% of %s]", xs->name, (int)((100.0 * xs->rcvd) / xs->size), - stat_bytes(xs->size)); + bytes); fprintf(stderr, "%3d%% of %s", (int)((100.0 * xs->rcvd) / xs->size), - stat_bytes(xs->size)); + bytes); } if (force == 2) { xs->lastrcvd = xs->offset; xs->last2 = xs->start; } - fprintf(stderr, " %s", stat_bps(xs)); + stat_bps(bps, sizeof bps, xs); + fprintf(stderr, " %s", bps); if ((xs->size > 0 && xs->rcvd > 0 && xs->last.tv_sec >= xs->start.tv_sec + 3) || - force == 2) - fprintf(stderr, " %s", stat_eta(xs)); + force == 2) { + stat_eta(eta, sizeof eta, xs); + fprintf(stderr, " %s", eta); + } xs->lastrcvd = xs->rcvd; } @@ -313,14 +333,16 @@ stat_display(struct xferstat *xs, int force) static void stat_start(struct xferstat *xs, const char *name, off_t size, off_t offset) { + + memset(xs, 0, sizeof *xs); snprintf(xs->name, sizeof xs->name, "%s", name); gettimeofday(&xs->start, NULL); - xs->last.tv_sec = xs->last.tv_usec = 0; + xs->last2 = xs->last = xs->start; xs->size = size; xs->offset = offset; xs->rcvd = offset; xs->lastrcvd = offset; - if (v_tty && v_level > 0) + if (v_progress) stat_display(xs, 1); else if (v_level > 0) fprintf(stderr, "%-46s", xs->name); @@ -332,8 +354,9 @@ stat_start(struct xferstat *xs, const char *name, off_ static void stat_update(struct xferstat *xs, off_t rcvd) { + xs->rcvd = rcvd; - if (v_tty && v_level > 0) + if (v_progress) stat_display(xs, 0); } @@ -343,13 +366,17 @@ stat_update(struct xferstat *xs, off_t rcvd) static void stat_end(struct xferstat *xs) { + char bytes[16], bps[16], eta[16]; + gettimeofday(&xs->last, NULL); - if (v_tty && v_level > 0) { + if (v_progress) { stat_display(xs, 2); putc('\n', stderr); } else if (v_level > 0) { - fprintf(stderr, " %s %s\n", - stat_bytes(xs->size), stat_bps(xs)); + stat_bytes(bytes, sizeof bytes, xs->rcvd); + stat_bps(bps, sizeof bps, xs); + stat_eta(eta, sizeof eta, xs); + fprintf(stderr, " %s %s %s\n", bytes, bps, eta); } } @@ -552,9 +579,10 @@ fetch(char *URL, const char *path) goto signal; if (f == NULL) { warnx("%s: %s", URL, fetchLastErrString); - if (i_flag && strcmp(url->scheme, SCHEME_HTTP) == 0 - && fetchLastErrCode == FETCH_OK - && strcmp(fetchLastErrString, "Not Modified") == 0) { + if (i_flag && (strcmp(url->scheme, SCHEME_HTTP) == 0 || + strcmp(url->scheme, SCHEME_HTTPS) == 0) && + fetchLastErrCode == FETCH_OK && + strcmp(fetchLastErrString, "Not Modified") == 0) { /* HTTP Not Modified Response, return OK. */ r = 0; goto done; @@ -1109,7 +1137,8 @@ main(int argc, char *argv[]) /* check if output is to a tty (for progress report) */ v_tty = isatty(STDERR_FILENO); - if (v_tty) + v_progress = v_tty && v_level > 0; + if (v_progress) pgrp = getpgrp(); r = 0;