Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Jun 2025 15:59:32 GMT
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 0726c6574f88 - main - sockstat: Add automatic column sizing and remove -w option
Message-ID:  <202506271559.55RFxWdm024724@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by asomers:

URL: https://cgit.FreeBSD.org/src/commit/?id=0726c6574f889507e5030173bf4c82c80911394d

commit 0726c6574f889507e5030173bf4c82c80911394d
Author:     Damin Rido <rido@FreeBSD.com>
AuthorDate: 2025-06-12 09:12:49 +0000
Commit:     Alan Somers <asomers@FreeBSD.org>
CommitDate: 2025-06-27 15:54:41 +0000

    sockstat: Add automatic column sizing and remove -w option
    
    Refactor sockstat to dynamically size table columns based on content.
    This eliminates the need for the -w option, which is now ignored
    for backwards compatibility.
    
    Numeric columns are now right-aligned for improved readability;
    previously, they were left-aligned.
    
    Unknown fields are now consistently shown as "??" instead of a mix
    of "", "?", and "?" for output uniformity.
    
    Sponsored by:   Google, LLC (GSoC 2025)
    MFC after:      2 weeks
    Reviewed by:    asomers
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1720
---
 usr.bin/sockstat/sockstat.1 |   6 +-
 usr.bin/sockstat/sockstat.c | 622 +++++++++++++++++++++++++++-----------------
 2 files changed, 392 insertions(+), 236 deletions(-)

diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1
index b13c6afdd9c0..da658e33e542 100644
--- a/usr.bin/sockstat/sockstat.1
+++ b/usr.bin/sockstat/sockstat.1
@@ -25,7 +25,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd February 6, 2025
+.Dd June 27, 2025
 .Dt SOCKSTAT 1
 .Os
 .Sh NAME
@@ -33,7 +33,7 @@
 .Nd list open sockets
 .Sh SYNOPSIS
 .Nm
-.Op Fl 46ACcfIiLlnqSsUuvw
+.Op Fl 46ACcfIiLlnqSsUuv
 .Op Fl j Ar jail
 .Op Fl p Ar ports
 .Op Fl P Ar protocols
@@ -119,8 +119,6 @@ Show
 sockets.
 .It Fl v
 Verbose mode.
-.It Fl w
-Use wider field size for displaying addresses.
 .El
 .Pp
 If neither
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c
index e1a52c57b3d1..52243910a31c 100644
--- a/usr.bin/sockstat/sockstat.c
+++ b/usr.bin/sockstat/sockstat.c
@@ -97,7 +97,6 @@ static bool	 opt_s;		/* Show protocol state if applicable */
 static bool	 opt_U;		/* Show remote UDP encapsulation port number */
 static bool	 opt_u;		/* Show Unix domain sockets */
 static u_int	 opt_v;		/* Verbose mode */
-static bool	 opt_w;		/* Wide print area for addresses */
 
 /*
  * Default protocols to use if no -P was defined.
@@ -193,20 +192,6 @@ static cap_channel_t *capnetdb;
 static cap_channel_t *capsysctl;
 static cap_channel_t *cappwd;
 
-static int
-xprintf(const char *fmt, ...)
-{
-	va_list ap;
-	int len;
-
-	va_start(ap, fmt);
-	len = vprintf(fmt, ap);
-	va_end(ap);
-	if (len < 0)
-		err(1, "printf()");
-	return (len);
-}
-
 static bool
 _check_ksize(size_t received_size, size_t expected_size, const char *struct_name)
 {
@@ -941,7 +926,7 @@ getfiles(void)
 }
 
 static int
-printaddr(struct sockaddr_storage *ss)
+formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize)
 {
 	struct sockaddr_un *sun;
 	char addrstr[NI_MAXHOST] = { '\0', '\0' };
@@ -961,18 +946,18 @@ printaddr(struct sockaddr_storage *ss)
 	case AF_UNIX:
 		sun = sstosun(ss);
 		off = (int)((char *)&sun->sun_path - (char *)sun);
-		return (xprintf("%.*s", sun->sun_len - off, sun->sun_path));
+		return snprintf(buf, bufsize, "%.*s",
+				sun->sun_len - off, sun->sun_path);
 	}
 	if (addrstr[0] == '\0') {
 		error = cap_getnameinfo(capnet, sstosa(ss), ss->ss_len,
-		    addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
+			addrstr, sizeof(addrstr), buf, bufsize, NI_NUMERICHOST);
 		if (error)
 			errx(1, "cap_getnameinfo()");
 	}
 	if (port == 0)
-		return xprintf("%s:*", addrstr);
-	else
-		return xprintf("%s:%d", addrstr, port);
+		return snprintf(buf, bufsize, "%s:*", addrstr);
+	return snprintf(buf, bufsize, "%s:%d", addrstr, port);
 }
 
 static const char *
@@ -1107,235 +1092,408 @@ sctp_path_state(int state)
 	}
 }
 
+static int
+format_unix_faddr(struct addr *faddr, char *buf, size_t bufsize) {
+	#define SAFEBUF  (buf == NULL ? NULL : buf + pos)
+	#define SAFESIZE (buf == NULL ? 0 : bufsize - pos)
+
+	size_t pos = 0;
+	/* Remote peer we connect(2) to, if any. */
+	if (faddr->conn != 0) {
+		struct sock *p;
+		pos += strlcpy(buf, "-> ", bufsize);
+		p = RB_FIND(pcbs_t, &pcbs,
+			&(struct sock){ .pcb = faddr->conn });
+		if (__predict_false(p == NULL)) {
+			/* XXGL: can this happen at all? */
+			pos += snprintf(SAFEBUF, SAFESIZE, "??");
+		} else if (p->laddr->address.ss_len == 0) {
+			struct file *f;
+			f = RB_FIND(files_t, &ftree,
+				&(struct file){ .xf_data =
+				p->socket });
+			if (f != NULL) {
+				pos += snprintf(SAFEBUF, SAFESIZE, "[%lu %d]",
+					(u_long)f->xf_pid, f->xf_fd);
+			}
+		} else
+			pos += formataddr(&p->laddr->address,
+				SAFEBUF, SAFESIZE);
+	}
+	/* Remote peer(s) connect(2)ed to us, if any. */
+	if (faddr->firstref != 0) {
+		struct sock *p;
+		struct file *f;
+		kvaddr_t ref = faddr->firstref;
+		bool fref = true;
+
+		pos += snprintf(SAFEBUF, SAFESIZE, " <- ");
+
+		while ((p = RB_FIND(pcbs_t, &pcbs,
+			&(struct sock){ .pcb = ref })) != 0) {
+			f = RB_FIND(files_t, &ftree,
+				&(struct file){ .xf_data =
+				p->socket });
+			if (f != NULL) {
+				pos += snprintf(SAFEBUF, SAFESIZE,
+					"%s[%lu %d]", fref ? "" : ",",
+					(u_long)f->xf_pid, f->xf_fd);
+			}
+			ref = p->faddr->nextref;
+			fref = false;
+		}
+	}
+	return pos;
+}
+
+struct col_widths {
+	int user;
+	int command;
+	int pid;
+	int fd;
+	int proto;
+	int local_addr;
+	int foreign_addr;
+	int pcb_kva;
+	int fib;
+	int splice_address;
+	int inp_gencnt;
+	int encaps;
+	int path_state;
+	int conn_state;
+	int stack;
+	int cc;
+};
+
 static void
-displaysock(struct sock *s, int pos)
+calculate_sock_column_widths(struct col_widths *cw, struct sock *s)
 {
-	int first, offset;
 	struct addr *laddr, *faddr;
-
-	while (pos < 30)
-		pos += xprintf(" ");
-	pos += xprintf("%s", s->protoname);
-	if (s->vflag & INP_IPV4)
-		pos += xprintf("4");
-	if (s->vflag & INP_IPV6)
-		pos += xprintf("6");
-	if (s->vflag & (INP_IPV4 | INP_IPV6))
-		pos += xprintf(" ");
+	bool first = true;
+	int len = 0;
 	laddr = s->laddr;
 	faddr = s->faddr;
-	first = 1;
+	first = true;
+
+	len = strlen(s->protoname);
+	if (s->vflag & (INP_IPV4 | INP_IPV6))
+		len += 1;
+	if (laddr != NULL && faddr != NULL && s->family == AF_UNIX &&
+		laddr->address.ss_len == 0 && faddr->conn == 0)
+		len += strlen(" (not connected)");
+	cw->proto = MAX(cw->proto, len);
+
 	while (laddr != NULL || faddr != NULL) {
-		offset = 37;
-		while (pos < offset)
-			pos += xprintf(" ");
-		switch (s->family) {
-		case AF_INET:
-		case AF_INET6:
-			if (laddr != NULL)
-				pos += printaddr(&laddr->address);
-			offset += opt_w ? 46 : 22;
-			do
-				pos += xprintf(" ");
-			while (pos < offset);
-			if (faddr != NULL)
-				pos += printaddr(&faddr->address);
-			offset += opt_w ? 46 : 22;
-			break;
-		case AF_UNIX:
+		if (s->family == AF_UNIX) {
 			if ((laddr == NULL) || (faddr == NULL))
 				errx(1, "laddr = %p or faddr = %p is NULL",
-				    (void *)laddr, (void *)faddr);
-			if (laddr->address.ss_len == 0 && faddr->conn == 0) {
-				pos += xprintf("(not connected)");
-				offset += opt_w ? 92 : 44;
-				break;
-			}
-			/* Local bind(2) address, if any. */
+					(void *)laddr, (void *)faddr);
 			if (laddr->address.ss_len > 0)
-				pos += printaddr(&laddr->address);
-			/* Remote peer we connect(2) to, if any. */
-			if (faddr->conn != 0) {
-				struct sock *p;
-
-				pos += xprintf("%s-> ",
-				    laddr->address.ss_len > 0 ? " " : "");
-				p = RB_FIND(pcbs_t, &pcbs,
-				    &(struct sock){ .pcb = faddr->conn });
-				if (__predict_false(p == NULL)) {
-					/* XXGL: can this happen at all? */
-					pos += xprintf("??");
-				}  else if (p->laddr->address.ss_len == 0) {
-					struct file *f;
-
-					f = RB_FIND(files_t, &ftree,
-					    &(struct file){ .xf_data =
-					    p->socket });
-					if (f != NULL) {
-						pos += xprintf("[%lu %d]",
-						    (u_long)f->xf_pid,
-						    f->xf_fd);
-					}
-				} else
-					pos += printaddr(&p->laddr->address);
+				len = formataddr(&laddr->address, NULL, 0);
+			cw->local_addr = MAX(cw->local_addr, len);
+			len = format_unix_faddr(faddr, NULL, 0);
+			cw->foreign_addr = MAX(cw->foreign_addr, len);
+		} else {
+			if (laddr != NULL) {
+				len = formataddr(&laddr->address, NULL, 0);
+				cw->local_addr = MAX(cw->local_addr, len);
 			}
-			/* Remote peer(s) connect(2)ed to us, if any. */
-			if (faddr->firstref != 0) {
-				struct sock *p;
-				struct file *f;
-				kvaddr_t ref = faddr->firstref;
-				bool fref = true;
-
-				pos += xprintf(" <- ");
-
-				while ((p = RB_FIND(pcbs_t, &pcbs,
-				    &(struct sock){ .pcb = ref })) != 0) {
-					f = RB_FIND(files_t, &ftree,
-					    &(struct file){ .xf_data =
-					    p->socket });
-					if (f != NULL) {
-						pos += xprintf("%s[%lu %d]",
-						    fref ? "" : ",",
-						    (u_long)f->xf_pid,
-						    f->xf_fd);
-					}
-					ref = p->faddr->nextref;
-					fref = false;
-				}
+			if (faddr != NULL) {
+				len = formataddr(&faddr->address, NULL, 0);
+				cw->foreign_addr = MAX(cw->foreign_addr, len);
 			}
-			offset += opt_w ? 92 : 44;
-			break;
-		default:
-			abort();
-		}
-		while (pos < offset)
-			pos += xprintf(" ");
-		if (opt_A) {
-			pos += xprintf("0x%16lx", s->pcb);
-			offset += 18;
 		}
 		if (opt_f) {
-			pos += xprintf("%d", s->fibnum);
-			offset += 7;
+			len = snprintf(NULL, 0, "%d", s->fibnum);
+			cw->fib = MAX(cw->fib, len);
 		}
 		if (opt_I) {
 			if (s->splice_socket != 0) {
 				struct sock *sp;
 
 				sp = RB_FIND(socks_t, &socks, &(struct sock)
-				    { .socket = s->splice_socket });
+					{ .socket = s->splice_socket });
 				if (sp != NULL) {
-					do
-						pos += xprintf(" ");
-					while (pos < offset);
-					pos += printaddr(&sp->laddr->address);
-				} else {
-					do
-						pos += xprintf(" ");
-					while (pos < offset);
-					pos += xprintf("??");
-					offset += opt_w ? 46 : 22;
+					len = formataddr(&sp->laddr->address,
+						 NULL, 0);
+					cw->splice_address = MAX(
+						cw->splice_address, len);
 				}
 			}
-			offset += opt_w ? 46 : 22;
 		}
 		if (opt_i) {
-			if (s->proto == IPPROTO_TCP ||
-			    s->proto == IPPROTO_UDP) {
-				do
-					pos += xprintf(" ");
-				while (pos < offset);
-				pos += xprintf("%" PRIu64, s->inp_gencnt);
+			if (s->proto == IPPROTO_TCP || s->proto == IPPROTO_UDP)
+			{
+				len = snprintf(NULL, 0,
+					"%" PRIu64, s->inp_gencnt);
+				cw->inp_gencnt = MAX(cw->inp_gencnt, len);
 			}
-			offset += 9;
 		}
 		if (opt_U) {
 			if (faddr != NULL &&
-			    ((s->proto == IPPROTO_SCTP &&
-			      s->state != SCTP_CLOSED &&
-			      s->state != SCTP_BOUND &&
-			      s->state != SCTP_LISTEN) ||
-			     (s->proto == IPPROTO_TCP &&
-			      s->state != TCPS_CLOSED &&
-			      s->state != TCPS_LISTEN))) {
-				do
-					pos += xprintf(" ");
-				while (pos < offset);
-				pos += xprintf("%u",
-				    ntohs(faddr->encaps_port));
+				((s->proto == IPPROTO_SCTP &&
+					s->state != SCTP_CLOSED &&
+					s->state != SCTP_BOUND &&
+					s->state != SCTP_LISTEN) ||
+					(s->proto == IPPROTO_TCP &&
+					s->state != TCPS_CLOSED &&
+					s->state != TCPS_LISTEN))) {
+				len = snprintf(NULL, 0, "%u",
+					ntohs(faddr->encaps_port));
+				cw->encaps = MAX(cw->encaps, len);
 			}
-			offset += 7;
 		}
 		if (opt_s) {
 			if (faddr != NULL &&
-			    s->proto == IPPROTO_SCTP &&
-			    s->state != SCTP_CLOSED &&
-			    s->state != SCTP_BOUND &&
-			    s->state != SCTP_LISTEN) {
-				do
-					pos += xprintf(" ");
-				while (pos < offset);
-				pos += xprintf("%s",
-				    sctp_path_state(faddr->state));
+				s->proto == IPPROTO_SCTP &&
+				s->state != SCTP_CLOSED &&
+				s->state != SCTP_BOUND &&
+				s->state != SCTP_LISTEN) {
+				len = strlen(sctp_path_state(faddr->state));
+				cw->path_state = MAX(cw->path_state, len);
 			}
-			offset += 13;
+		}
+		if (first) {
+			if (opt_s) {
+				if (s->proto == IPPROTO_SCTP ||
+					s->proto == IPPROTO_TCP) {
+					switch (s->proto) {
+					case IPPROTO_SCTP:
+						len = strlen(
+						    sctp_conn_state(s->state));
+						cw->conn_state = MAX(
+							cw->conn_state, len);
+						break;
+					case IPPROTO_TCP:
+						if (s->state >= 0 &&
+						    s->state < TCP_NSTATES) {
+						    len = strlen(
+							tcpstates[s->state]);
+						    cw->conn_state = MAX(
+							cw->conn_state, len);
+						}
+						break;
+					}
+				}
+			}
+			if (opt_S && s->proto == IPPROTO_TCP) {
+				len = strlen(s->stack);
+				cw->stack = MAX(cw->stack, len);
+			}
+			if (opt_C && s->proto == IPPROTO_TCP) {
+				len = strlen(s->cc);
+				cw->cc = MAX(cw->cc, len);
+			}
+		}
+		if (laddr != NULL)
+			laddr = laddr->next;
+		if (faddr != NULL)
+			faddr = faddr->next;
+		first = false;
+	}
+}
+
+static void
+calculate_column_widths(struct col_widths *cw)
+{
+	cw->user = 4;
+	cw->command = 10;
+	cw->pid = 3;
+	cw->fd = 2;
+	cw->proto = 5;
+	cw->local_addr = 13;
+	cw->foreign_addr = 15;
+	cw->pcb_kva = 18;
+	cw->fib = 3;
+	cw->splice_address = 14;
+	cw->inp_gencnt = 2;
+	cw->encaps = 6;
+	cw->path_state = 10;
+	cw->conn_state = 10;
+	cw->stack = 5;
+	cw->cc = 2;
+
+	int n, len;
+	struct file *xf;
+	struct sock *s;
+	struct passwd *pwd;
+
+	for (xf = files, n = 0; n < nfiles; ++n, ++xf) {
+		if (xf->xf_data == 0)
+			continue;
+		if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid))
+			continue;
+		s = RB_FIND(socks_t, &socks,
+			&(struct sock){ .socket = xf->xf_data});
+		if (s == NULL || (!check_ports(s)))
+			continue;
+		s->shown = 1;
+		if (opt_n ||
+			(pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL)
+			len = snprintf(NULL, 0, "%lu", (u_long)xf->xf_uid);
+		else
+			len = snprintf(NULL, 0, "%s", pwd->pw_name);
+		cw->user = MAX(cw->user, len);
+		len = snprintf(NULL, 0, "%lu", (u_long)xf->xf_pid);
+		cw->pid = MAX(cw->pid, len);
+		len = snprintf(NULL, 0, "%d", xf->xf_fd);
+		cw->fd = MAX(cw->fd, len);
+
+		calculate_sock_column_widths(cw, s);
+	}
+	if (opt_j >= 0)
+		return;
+	SLIST_FOREACH(s, &nosocks, socket_list) {
+		if (!check_ports(s))
+			continue;
+		calculate_sock_column_widths(cw, s);
+	}
+	RB_FOREACH(s, socks_t, &socks) {
+		if (s->shown)
+			continue;
+		if (!check_ports(s))
+			continue;
+		calculate_sock_column_widths(cw, s);
+	}
+}
+
+static void
+display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize)
+{
+	struct addr *laddr, *faddr;
+	bool first;
+	laddr = s->laddr;
+	faddr = s->faddr;
+	first = true;
+
+	snprintf(buf, bufsize, "%s%s%s%s",
+		s->protoname,
+		s->vflag & INP_IPV4 ? "4" : "",
+		s->vflag & INP_IPV6 ? "6" : "",
+		(laddr != NULL && faddr != NULL &&
+		s->family == AF_UNIX && laddr->address.ss_len == 0 &&
+		faddr->conn == 0) ? " (not connected)" : "");
+	printf(" %-*s", cw->proto, buf);
+	while (laddr != NULL || faddr != NULL) {
+		if (s->family == AF_UNIX) {
+			if ((laddr == NULL) || (faddr == NULL))
+				errx(1, "laddr = %p or faddr = %p is NULL",
+					(void *)laddr, (void *)faddr);
+			if (laddr->address.ss_len > 0)
+				formataddr(&laddr->address, buf, bufsize);
+			else
+				strlcpy(buf, "??", bufsize);
+			printf(" %-*s", cw->local_addr, buf);
+			if (format_unix_faddr(faddr, buf, bufsize) == 0)
+				strlcpy(buf, "??", bufsize);
+			printf(" %-*s", cw->foreign_addr, buf);
+		} else {
+			if (laddr != NULL)
+				formataddr(&laddr->address, buf, bufsize);
+			else
+				strlcpy(buf, "??", bufsize);
+			printf(" %-*s", cw->local_addr, buf);
+			if (faddr != NULL)
+				formataddr(&faddr->address, buf, bufsize);
+			else
+				strlcpy(buf, "??", bufsize);
+			printf(" %-*s", cw->foreign_addr, buf);
+		}
+		if (opt_A)
+			printf(" %#*" PRIx64, cw->pcb_kva, s->pcb);
+		if (opt_f)
+			printf(" %*d", cw->fib, s->fibnum);
+		if (opt_I) {
+			if (s->splice_socket != 0) {
+				struct sock *sp;
+				sp = RB_FIND(socks_t, &socks, &(struct sock)
+					{ .socket = s->splice_socket });
+				if (sp != NULL)
+					formataddr(&sp->laddr->address,
+								buf, bufsize);
+			} else
+				strlcpy(buf, "??", bufsize);
+			printf(" %-*s", cw->splice_address, buf);
+		}
+		if (opt_i) {
+			if (s->proto == IPPROTO_TCP || s->proto == IPPROTO_UDP)
+				printf(" %*" PRIu64, cw->inp_gencnt,
+					s->inp_gencnt);
+			else
+				printf(" %*s", cw->inp_gencnt, "??");
+		}
+		if (opt_U) {
+			if (faddr != NULL &&
+				((s->proto == IPPROTO_SCTP &&
+					s->state != SCTP_CLOSED &&
+					s->state != SCTP_BOUND &&
+					s->state != SCTP_LISTEN) ||
+					(s->proto == IPPROTO_TCP &&
+					s->state != TCPS_CLOSED &&
+					s->state != TCPS_LISTEN))) {
+				printf(" %*u", cw->encaps,
+					ntohs(faddr->encaps_port));
+			} else
+				printf(" %*s", cw->encaps, "??");
+		}
+		if (opt_s) {
+			if (faddr != NULL &&
+				s->proto == IPPROTO_SCTP &&
+				s->state != SCTP_CLOSED &&
+				s->state != SCTP_BOUND &&
+				s->state != SCTP_LISTEN) {
+				printf(" %-*s", cw->path_state,
+					sctp_path_state(faddr->state));
+			} else
+				printf(" %-*s", cw->path_state, "??");
 		}
 		if (first) {
 			if (opt_s) {
 				if (s->proto == IPPROTO_SCTP ||
 				    s->proto == IPPROTO_TCP) {
-					do
-						pos += xprintf(" ");
-					while (pos < offset);
 					switch (s->proto) {
 					case IPPROTO_SCTP:
-						pos += xprintf("%s",
+						printf(" %-*s", cw->conn_state,
 						    sctp_conn_state(s->state));
 						break;
 					case IPPROTO_TCP:
 						if (s->state >= 0 &&
-						    s->state < TCP_NSTATES)
-							pos += xprintf("%s",
-							    tcpstates[s->state]);
+							s->state < TCP_NSTATES)
+							printf(" %-*s",
+							cw->conn_state,
+							tcpstates[s->state]);
 						else
-							pos += xprintf("?");
+							printf(" %-*s",
+							cw->conn_state, "??");
 						break;
 					}
-				}
-				offset += 13;
+				} else
+					printf(" %-*s", cw->conn_state, "??");
 			}
 			if (opt_S) {
-				if (s->proto == IPPROTO_TCP) {
-					do
-						pos += xprintf(" ");
-					while (pos < offset);
-					pos += xprintf("%.*s",
-					    TCP_FUNCTION_NAME_LEN_MAX,
-					    s->stack);
-				}
-				offset += TCP_FUNCTION_NAME_LEN_MAX + 1;
+				if (s->proto == IPPROTO_TCP)
+					printf(" %-*s", cw->stack, s->stack);
+				else
+					printf(" %-*s", cw->stack, "??");
 			}
 			if (opt_C) {
-				if (s->proto == IPPROTO_TCP) {
-					do
-						pos += xprintf(" ");
-					while (pos < offset);
-					xprintf("%.*s", TCP_CA_NAME_MAX, s->cc);
-				}
-				offset += TCP_CA_NAME_MAX + 1;
+				if (s->proto == IPPROTO_TCP)
+					printf(" %-*s", cw->cc, s->cc);
+				else
+					printf(" %-*s", cw->cc, "??");
 			}
 		}
 		if (laddr != NULL)
 			laddr = laddr->next;
 		if (faddr != NULL)
 			faddr = faddr->next;
-		if ((laddr != NULL) || (faddr != NULL)) {
-			xprintf("\n");
-			pos = 0;
-		}
-		first = 0;
+		if (laddr != NULL || faddr != NULL)
+			printf("%-*s %-*s %-*s %-*s %-*s", cw->user, "",
+				cw->command, "", cw->pid, "", cw->fd, "",
+				cw->proto, "");
+		first = false;
 	}
-	xprintf("\n");
+	printf("\n");
 }
 
 static void
@@ -1344,33 +1502,41 @@ display(void)
 	struct passwd *pwd;
 	struct file *xf;
 	struct sock *s;
-	int n, pos;
+	int n;
+	struct col_widths cw;
+	const size_t bufsize = 512;
+	void *buf;
+	if ((buf = (char *)malloc(bufsize)) == NULL) {
+		err(1, "malloc()");
+		return;
+	}
+	calculate_column_widths(&cw);
 
 	if (!opt_q) {
-		printf("%-8s %-10s %-5s %-3s %-6s %-*s %-*s",
-		    "USER", "COMMAND", "PID", "FD", "PROTO",
-		    opt_w ? 45 : 21, "LOCAL ADDRESS",
-		    opt_w ? 45 : 21, "FOREIGN ADDRESS");
+		printf("%-*s %-*s %*s %*s %-*s %-*s %-*s",
+				cw.user, "USER", cw.command, "COMMAND",
+				cw.pid, "PID", cw.fd, "FD", cw.proto, "PROTO",
+				cw.local_addr, "LOCAL ADDRESS",
+				cw.foreign_addr,"FOREIGN ADDRESS");
 		if (opt_A)
-			printf(" %-18s", "PCB KVA");
+			printf(" %-*s", cw.pcb_kva, "PCB KVA");
 		if (opt_f)
 			/* RT_MAXFIBS is 65535. */
-			printf(" %-6s", "FIB");
+			printf(" %*s", cw.fib, "FIB");
 		if (opt_I)
-			printf(" %-*s", opt_w ? 45 : 21, "SPLICE ADDRESS");
+			printf(" %-*s", cw.splice_address, "SPLICE ADDRESS");
 		if (opt_i)
-			printf(" %-8s", "ID");
+			printf(" %*s", cw.inp_gencnt, "ID");
 		if (opt_U)
-			printf(" %-6s", "ENCAPS");
+			printf(" %*s", cw.encaps, "ENCAPS");
 		if (opt_s) {
-			printf(" %-12s", "PATH STATE");
-			printf(" %-12s", "CONN STATE");
+			printf(" %-*s", cw.path_state, "PATH STATE");
+			printf(" %-*s", cw.conn_state, "CONN STATE");
 		}
 		if (opt_S)
-			printf(" %-*.*s", TCP_FUNCTION_NAME_LEN_MAX,
-			    TCP_FUNCTION_NAME_LEN_MAX, "STACK");
+			printf(" %-*s", cw.stack, "STACK");
 		if (opt_C)
-			printf(" %-.*s", TCP_CA_NAME_MAX, "CC");
+			printf(" %-*s", cw.cc, "CC");
 		printf("\n");
 	}
 	cap_setpassent(cappwd, 1);
@@ -1380,28 +1546,19 @@ display(void)
 		if (opt_j >= 0 && opt_j != getprocjid(xf->xf_pid))
 			continue;
 		s = RB_FIND(socks_t, &socks,
-		    &(struct sock){ .socket = xf->xf_data});
+			&(struct sock){ .socket = xf->xf_data});
 		if (s != NULL && check_ports(s)) {
 			s->shown = 1;
-			pos = 0;
 			if (opt_n ||
 			    (pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL)
-				pos += xprintf("%lu", (u_long)xf->xf_uid);
+				printf("%-*lu", cw.user, (u_long)xf->xf_uid);
 			else
-				pos += xprintf("%s", pwd->pw_name);
-			do
-				pos += xprintf(" ");
-			while (pos < 9);
-			pos += xprintf("%.10s", getprocname(xf->xf_pid));
-			do
-				pos += xprintf(" ");
-			while (pos < 20);
-			pos += xprintf("%5lu", (u_long)xf->xf_pid);
-			do
-				pos += xprintf(" ");
-			while (pos < 26);
-			pos += xprintf("%-3d", xf->xf_fd);
-			displaysock(s, pos);
+				printf("%-*s", cw.user, pwd->pw_name);
+			printf(" %-*.*s", cw.command, cw.command,
+				getprocname(xf->xf_pid));
+			printf(" %*lu", cw.pid, (u_long)xf->xf_pid);
+			printf(" %*d", cw.fd, xf->xf_fd);
+			display_sock(s, &cw, buf, bufsize);
 		}
 	}
 	if (opt_j >= 0)
@@ -1409,19 +1566,20 @@ display(void)
 	SLIST_FOREACH(s, &nosocks, socket_list) {
 		if (!check_ports(s))
 			continue;
-		pos = xprintf("%-8s %-10s %-5s %-3s",
-		    "?", "?", "?", "?");
-		displaysock(s, pos);
+		printf("%-*s %-*s %*s %*s", cw.user, "??", cw.command, "??",
+			cw.pid, "??", cw.fd, "??");
+		display_sock(s, &cw, buf, bufsize);
 	}
 	RB_FOREACH(s, socks_t, &socks) {
 		if (s->shown)
 			continue;
 		if (!check_ports(s))
 			continue;
-		pos = xprintf("%-8s %-10s %-5s %-3s",
-		    "?", "?", "?", "?");
-		displaysock(s, pos);
+		printf("%-*s %-*s %*s %*s", cw.user, "??", cw.command, "??",
+			cw.pid, "??", cw.fd, "??");
+		display_sock(s, &cw, buf, bufsize);
 	}
+	free(buf);
 }
 
 static int
@@ -1484,7 +1642,7 @@ static void
 usage(void)
 {
 	errx(1,
-    "usage: sockstat [-46ACcfIiLlnqSsUuvw] [-j jid] [-p ports] [-P protocols]");
+    "usage: sockstat [-46ACcfIiLlnqSsUuv] [-j jid] [-p ports] [-P protocols]");
 }
 
 int
@@ -1563,7 +1721,7 @@ main(int argc, char *argv[])
 			++opt_v;
 			break;
 		case 'w':
-			opt_w = true;
+			/* left for backward compatibility. */
 			break;
 		default:
 			usage();



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506271559.55RFxWdm024724>