From nobody Thu Jul 23 10:00:45 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4h5RTB3jYkz6lW0l for ; Thu, 23 Jul 2026 10:00:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4h5RT96gz2z3W6S for ; Thu, 23 Jul 2026 10:00:45 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1784800845; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=XuKQEexekD369HPo31RTXmg2P49hUaKuIPsFVn6jLFA=; b=V1O0Tbq75rj56ASZ52XrT1TR1eeB+5gK0BJOaywTg5eGqOfRtm8jQw2i/t73pZm9QmHFk9 sgHc/wMtDS2Nxg/6uMFqZ8Kn3j9hviHBoYHM8/GICTvbVPK3sPPFCFYM9R7cURjCBDK9L6 HYiCILPhVvHU7tNsH4MMgMsKL8A4zwr80fukivfFcx7gSte+01w+G9ZUgkREUf2tQsjVWs MlLKmzM7l70yuiBkD4LArx25TIhTVlRXHZ8VfZTCnDYXhJ68rFrL3Zl2eo7LeT2DW4O/W2 71E3eetGq1YHxlTCIYhFz2TL6Nf/+v01wuL7409erLHNEzkbXluhrd9vEqvrJQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1784800845; a=rsa-sha256; cv=none; b=Dx8xDFqMce+6zsRiD+TlLpSqAPRUJQq8cbUujvwso6c8J+RtBCqG9vPER/X0tPXp9tOo1W NwZBp3bdP8JQbXXIJNc3jyPwBHPawfjB60W0pBZJO0Tl5DRCcbCyOZGBFA+e/lZM9i3V8X b5Bosigqx3iQBdJbCfYlrlN3o2Ai7Tbr7jCLWmX37B9aa40ZhCGGSeBB0/lQJsnRCw4Zv8 yGmNL7vUbLlbA+AGtGn4xdwFQIxQpuDPSIuBIstCOUWdtxMv5AuMWBQa+bulX/oULGS4Y2 ay3okfL4+U5qCrkOaMlBrQb5kN0qd5OFSCit4CD87vJtfxdw+suXARBzvtY6lw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1784800845; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=XuKQEexekD369HPo31RTXmg2P49hUaKuIPsFVn6jLFA=; b=xJCuOrKfo8cOdoDZ1X2CkOXbPRRsfdPkDhfpJLUXS6C5msI+LSEFIm5gKe3+Ng8qi83Px1 4qUIKYh+SvlUhJhHVlv8MlKJOBJu9hRtL3kU/tkifyWmghvTu4/CyRK8lOYbq+cpKGjJSb zvO3XJdTy7GWE7jK0j1yzazfK+oSHAOhEEXbpWGBHonRSkOfHZEMc5Erfo/efe2z8xLIKN 3+F3GVp0znyNr1hPwrJ7DOFLxjqs1ANVl6immaIMLtoHDuyKlLcu5y6Z46MHsblnYYDr0P 92RoK2ja9qaUW0tu5s26jZ0BA3X7NhNvDJR1mPR//lN+YMHDeST0/h1AhZckBQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h5RT95RlWz10bZ for ; Thu, 23 Jul 2026 10:00:45 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3bb3d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 23 Jul 2026 10:00:45 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Olivier Certner Subject: git: 58a0b5d61996 - stable/14 - netstat(1): '-w': Banners to appear before a new statistics line, not after List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: olce X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 58a0b5d619962966408bb05a34b5ecb9e7fd4807 Auto-Submitted: auto-generated Date: Thu, 23 Jul 2026 10:00:45 +0000 Message-Id: <6a61e64d.3bb3d.330606d1@gitrepo.freebsd.org> The branch stable/14 has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=58a0b5d619962966408bb05a34b5ecb9e7fd4807 commit 58a0b5d619962966408bb05a34b5ecb9e7fd4807 Author: Olivier Certner AuthorDate: 2026-04-02 19:13:02 +0000 Commit: Olivier Certner CommitDate: 2026-07-23 09:59:06 +0000 netstat(1): '-w': Banners to appear before a new statistics line, not after Recurring banners except the first are printed just after the latest interval's statistics line, giving the false impression that the latter are omitted. It is also better to print a new banner only if it is going to be followed by a new line of statistics, in case netstat(1) is interrupted or we have reached the number of iterations specified by '-q'. Fix this by pushing printing these banners inside the loop producing statistics lines, after having waited for the next interval. The first banner is printed before the loop, as we want it to be printed immediately at launch, even if at this point we do not have statistics to display (we have to wait for an interval to compute these, as they are based on a difference). While here, remove the 'goto' spaghetti by putting banner printing into its own private function and using a proper infinite loop in sidewaysintpr(). While here, document the why of the 21 statistics line span between two banners. While here, check for the number of output lines of statistics once such a line has effectively been printed. This allows to remove the internal incrementation performed when reading '-w''s argument, which was a hack to compensate the misplaced check. While here, in the manual page, simplify the description of the '-w' mode and mention that passing 0 to '-q' means "no count limit". Reviewed by: glebius Fixes: 84c1edcbad7d ("Rewrite netstat/if.c to use ...") Fixes: bf10ffe1d3a9 ("Add a new option, -q howmany, ...") MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D56227 (cherry picked from commit 31749859525b2b79634dc7c066c3563be5b1e3fd) --- usr.bin/netstat/if.c | 146 +++++++++++++++++++++++++++------------------- usr.bin/netstat/main.c | 2 - usr.bin/netstat/netstat.1 | 22 +++---- 3 files changed, 93 insertions(+), 77 deletions(-) diff --git a/usr.bin/netstat/if.c b/usr.bin/netstat/if.c index 2d6e04422ed1..10d9fb09b403 100644 --- a/usr.bin/netstat/if.c +++ b/usr.bin/netstat/if.c @@ -374,7 +374,7 @@ intpr(void (*pfunc)(char *), int af) u_int npkt_len = 8, nbyte_len = 10, nerr_len = 5; if (interval) - return sidewaysintpr(); + return (sidewaysintpr()); if (getifaddrs(&ifap) != 0) err(EX_OSERR, "getifaddrs"); @@ -630,6 +630,21 @@ catchalarm(int signo __unused) signalled = true; } +static void +running_stats_banner(void) +{ + xo_emit("{T:/%17s} {T:/%14s} {T:/%16s}\n", "input", + interface != NULL ? interface : "(Total)", "output"); + xo_emit("{T:/%10s} {T:/%5s} {T:/%5s} {T:/%10s} {T:/%10s} {T:/%5s} " + "{T:/%10s} {T:/%5s}", + "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes", + "colls"); + if (dflag) + xo_emit(" {T:/%5.5s}", "drops"); + xo_emit("\n"); + xo_flush(); +} + /* * Print a running summary of interface statistics. * Repeat display every interval seconds, showing statistics @@ -653,71 +668,82 @@ sidewaysintpr(void) interval_it.it_interval.tv_usec = 0; interval_it.it_value = interval_it.it_interval; setitimer(ITIMER_REAL, &interval_it, NULL); + xo_open_list("interface-statistics"); -banner: - xo_emit("{T:/%17s} {T:/%14s} {T:/%16s}\n", "input", - interface != NULL ? interface : "(Total)", "output"); - xo_emit("{T:/%10s} {T:/%5s} {T:/%5s} {T:/%10s} {T:/%10s} {T:/%5s} " - "{T:/%10s} {T:/%5s}", - "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes", - "colls"); - if (dflag) - xo_emit(" {T:/%5.5s}", "drops"); - xo_emit("\n"); - xo_flush(); + /* + * We print the first banner right away, even if we'll have to wait for + * the specified interval to get the first statistics line. Next + * banners will be printed only when the next statistics line is + * available. + */ + running_stats_banner(); + /* Number of written statistics line since latest banner. */ line = 0; -loop: - if ((noutputs != 0) && (--noutputs == 0)) { - xo_close_list("interface-statistics"); - return; - } - oldmask = sigblock(sigmask(SIGALRM)); - while (!signalled) - sigpause(0); - signalled = false; - sigsetmask(oldmask); - line++; - - fill_iftot(new); - - xo_open_instance("stats"); - show_stat("lu", 10, "received-packets", - new->ift_ip - old->ift_ip, 1, 1); - show_stat("lu", 5, "received-errors", - new->ift_ie - old->ift_ie, 1, 1); - show_stat("lu", 5, "dropped-packets", - new->ift_id - old->ift_id, 1, 1); - show_stat("lu", 10, "received-bytes", - new->ift_ib - old->ift_ib, 1, 0); - show_stat("lu", 10, "sent-packets", - new->ift_op - old->ift_op, 1, 1); - show_stat("lu", 5, "send-errors", - new->ift_oe - old->ift_oe, 1, 1); - show_stat("lu", 10, "sent-bytes", - new->ift_ob - old->ift_ob, 1, 0); - show_stat("NRSlu", 5, "collisions", - new->ift_co - old->ift_co, 1, 1); - if (dflag) - show_stat("LSlu", 5, "dropped-packets", - new->ift_od - old->ift_od, 1, 1); - xo_close_instance("stats"); - xo_emit("\n"); - xo_flush(); + for (;;) { + /* Wait for next interval. */ + oldmask = sigblock(sigmask(SIGALRM)); + while (!signalled) + sigpause(0); + signalled = false; + sigsetmask(oldmask); - if (new == &ift[0]) { - new = &ift[1]; - old = &ift[0]; - } else { - new = &ift[0]; - old = &ift[1]; - } + fill_iftot(new); - if (line == 21) - goto banner; - else - goto loop; + /* + * We want that, on a 24-line display, when the previous banner + * reaches exactly the top of the screen, a new banner is + * printed before the next statistics line. This ensures that + * at least one banner is visible on screen at all time + * (provided the screen has at least 24 lines). Since the + * banner takes 2 lines, and the last screen line is occupied by + * the cursor, it's after having written 21 statistics lines + * that we must output the banner. + */ + if (line == 21) { + running_stats_banner(); + line = 0; + } + ++line; + + xo_open_instance("stats"); + show_stat("lu", 10, "received-packets", + new->ift_ip - old->ift_ip, 1, 1); + show_stat("lu", 5, "received-errors", + new->ift_ie - old->ift_ie, 1, 1); + show_stat("lu", 5, "dropped-packets", + new->ift_id - old->ift_id, 1, 1); + show_stat("lu", 10, "received-bytes", + new->ift_ib - old->ift_ib, 1, 0); + show_stat("lu", 10, "sent-packets", + new->ift_op - old->ift_op, 1, 1); + show_stat("lu", 5, "send-errors", + new->ift_oe - old->ift_oe, 1, 1); + show_stat("lu", 10, "sent-bytes", + new->ift_ob - old->ift_ob, 1, 0); + show_stat("NRSlu", 5, "collisions", + new->ift_co - old->ift_co, 1, 1); + if (dflag) + show_stat("LSlu", 5, "dropped-packets", + new->ift_od - old->ift_od, 1, 1); + xo_close_instance("stats"); + xo_emit("\n"); + xo_flush(); + + if ((noutputs != 0) && (--noutputs == 0)) { + xo_close_list("interface-statistics"); + return; + } + + if (new == &ift[0]) { + new = &ift[1]; + old = &ift[0]; + } else { + new = &ift[0]; + old = &ift[1]; + } + } /* NOTREACHED */ } diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c index a60d951c8d39..5828029ba7eb 100644 --- a/usr.bin/netstat/main.c +++ b/usr.bin/netstat/main.c @@ -399,8 +399,6 @@ main(int argc, char *argv[]) break; case 'q': noutputs = atoi(optarg); - if (noutputs != 0) - noutputs++; break; case 'r': rflag = 1; diff --git a/usr.bin/netstat/netstat.1 b/usr.bin/netstat/netstat.1 index 9b476e6825e6..06179dd197c9 100644 --- a/usr.bin/netstat/netstat.1 +++ b/usr.bin/netstat/netstat.1 @@ -27,7 +27,7 @@ .\" .\" @(#)netstat.1 8.8 (Berkeley) 4/18/94 .\" -.Dd April 30, 2025 +.Dd April 3, 2026 .Dt NETSTAT 1 .Os .Sh NAME @@ -357,23 +357,14 @@ See At intervals of .Ar wait seconds, display the information regarding packet traffic on all -configured network interfaces or a single -.Ar interface . +configured network interfaces, or a single +.Ar interface +if +.Fl I +is specified. .Pp -When -.Nm -is invoked with the -.Fl w -option and a -.Ar wait -interval argument, it displays a running count of statistics related to -network interfaces. An obsolescent version of this option used a numeric parameter with no option, and is currently supported for backward compatibility. -By default, this display summarizes information for all interfaces. -Information for a specific interface may be displayed with the -.Fl I Ar interface -option. .Bl -tag -width indent .It Fl I Ar interface Only show information regarding @@ -400,6 +391,7 @@ See Exit after .Ar howmany outputs. +A value of zero indicates no limit, and is the default. .It Fl j Ar jail Run inside a jail. See