git: 7b35b4d19630 - main - sockstat: add libxo support
- Reply: Phil Shafer : "Re: git: 7b35b4d19630 - main - sockstat: add libxo support"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 30 Jul 2025 20:27:43 UTC
The branch main has been updated by asomers:
URL: https://cgit.FreeBSD.org/src/commit/?id=7b35b4d196309baf579571e1c1a433a4000d74c9
commit 7b35b4d196309baf579571e1c1a433a4000d74c9
Author: Damin Rido <rido@freebsd.org>
AuthorDate: 2025-07-16 17:20:15 +0000
Commit: Alan Somers <asomers@FreeBSD.org>
CommitDate: 2025-07-30 20:27:14 +0000
sockstat: add libxo support
Sponsored by: Google, LLC (GSoC 2025)
MFC after: 2 weeks
Reviewed by: asomers
Pull Request: https://github.com/freebsd/freebsd-src/pull/1770
Relnotes: yes
---
usr.bin/sockstat/Makefile | 2 +-
usr.bin/sockstat/sockstat.1 | 17 +-
usr.bin/sockstat/sockstat.c | 467 +++++++++++++++++++++++++++-----------------
3 files changed, 306 insertions(+), 180 deletions(-)
diff --git a/usr.bin/sockstat/Makefile b/usr.bin/sockstat/Makefile
index 188432dfc27e..7254511f21c6 100644
--- a/usr.bin/sockstat/Makefile
+++ b/usr.bin/sockstat/Makefile
@@ -2,7 +2,7 @@
PROG= sockstat
-LIBADD= jail
+LIBADD= jail xo
.if ${MK_CASPER} != "no"
LIBADD+= casper
diff --git a/usr.bin/sockstat/sockstat.1 b/usr.bin/sockstat/sockstat.1
index 4832a09764fd..091911cd0879 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 June 30, 2025
+.Dd July 17, 2025
.Dt SOCKSTAT 1
.Os
.Sh NAME
@@ -33,6 +33,7 @@
.Nd list open sockets
.Sh SYNOPSIS
.Nm
+.Op Fl -libxo
.Op Fl 46ACcfIiLlnqSsUuvw
.Op Fl j Ar jail
.Op Fl p Ar ports
@@ -46,6 +47,13 @@ domain sockets.
.Pp
The following options are available:
.Bl -tag -width Fl
+.It Fl -libxo
+Generate output via
+.Xr libxo 3
+in a selection of different human and machine readable formats.
+See
+.Xr xo_options 7
+for details on command line arguments.
.It Fl 4
Show
.Dv AF_INET
@@ -229,6 +237,11 @@ Show TCP IPv6 sockets which are listening and connected (default):
.Bd -literal -offset indent
$ sockstat -6 -P tcp
.Ed
+.Pp
+Show all sockets in JSON format with neat alignment:
+.Bd -literal -offset indent
+$ sockstat --libxo json,pretty
+.Ed
.Sh SEE ALSO
.Xr fstat 1 ,
.Xr netstat 1 ,
@@ -237,6 +250,8 @@ $ sockstat -6 -P tcp
.Xr inet 4 ,
.Xr inet6 4 ,
.Xr protocols 5
+.Xr libxo 3 ,
+.Xr xo_options 7
.Sh HISTORY
The
.Nm
diff --git a/usr.bin/sockstat/sockstat.c b/usr.bin/sockstat/sockstat.c
index d0540c54a1aa..7355eaa272a0 100644
--- a/usr.bin/sockstat/sockstat.c
+++ b/usr.bin/sockstat/sockstat.c
@@ -55,7 +55,6 @@
#include <capsicum_helpers.h>
#include <ctype.h>
-#include <err.h>
#include <errno.h>
#include <inttypes.h>
#include <jail.h>
@@ -67,6 +66,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <libxo/xo.h>
#include <libcasper.h>
#include <casper/cap_net.h>
@@ -74,6 +74,7 @@
#include <casper/cap_pwd.h>
#include <casper/cap_sysctl.h>
+#define SOCKSTAT_XO_VERSION "1"
#define sstosin(ss) ((struct sockaddr_in *)(ss))
#define sstosin6(ss) ((struct sockaddr_in6 *)(ss))
#define sstosun(ss) ((struct sockaddr_un *)(ss))
@@ -197,7 +198,7 @@ static bool
_check_ksize(size_t received_size, size_t expected_size, const char *struct_name)
{
if (received_size != expected_size) {
- warnx("%s size mismatch: expected %zd, received %zd",
+ xo_warnx("%s size mismatch: expected %zd, received %zd",
struct_name, expected_size, received_size);
return false;
}
@@ -209,7 +210,7 @@ static void
_enforce_ksize(size_t received_size, size_t expected_size, const char *struct_name)
{
if (received_size != expected_size) {
- errx(1, "fatal: struct %s size mismatch: expected %zd, received %zd",
+ xo_errx(1, "fatal: struct %s size mismatch: expected %zd, received %zd",
struct_name, expected_size, received_size);
}
}
@@ -227,7 +228,7 @@ get_proto_type(const char *proto)
else
pent = getprotobyname(proto);
if (pent == NULL) {
- warn("cap_getprotobyname");
+ xo_warn("cap_getprotobyname");
return (-1);
}
return (pent->p_proto);
@@ -248,7 +249,7 @@ init_protos(int num)
}
if ((protos = malloc(sizeof(int) * proto_count)) == NULL)
- err(1, "malloc");
+ xo_err(1, "malloc");
numprotos = proto_count;
}
@@ -282,17 +283,17 @@ parse_ports(const char *portspec)
if (ports == NULL)
if ((ports = calloc(65536 / INT_BIT, sizeof(int))) == NULL)
- err(1, "calloc()");
+ xo_err(1, "calloc()");
p = portspec;
while (*p != '\0') {
if (!isdigit(*p))
- errx(1, "syntax error in port range");
+ xo_errx(1, "syntax error in port range");
for (q = p; *q != '\0' && isdigit(*q); ++q)
/* nothing */ ;
for (port = 0; p < q; ++p)
port = port * 10 + digittoint(*p);
if (port < 0 || port > 65535)
- errx(1, "invalid port number");
+ xo_errx(1, "invalid port number");
SET_PORT(port);
switch (*p) {
case '-':
@@ -310,7 +311,7 @@ parse_ports(const char *portspec)
for (end = 0; p < q; ++p)
end = end * 10 + digittoint(*p);
if (end < port || end > 65535)
- errx(1, "invalid port number");
+ xo_errx(1, "invalid port number");
while (port++ < end)
SET_PORT(port);
if (*p == ',')
@@ -395,15 +396,15 @@ gather_sctp(void)
varname = "net.inet.sctp.assoclist";
if (cap_sysctlbyname(capsysctl, varname, 0, &len, 0, 0) < 0) {
if (errno != ENOENT)
- err(1, "cap_sysctlbyname()");
+ xo_err(1, "cap_sysctlbyname()");
return;
}
if ((buf = (char *)malloc(len)) == NULL) {
- err(1, "malloc()");
+ xo_err(1, "malloc()");
return;
}
if (cap_sysctlbyname(capsysctl, varname, buf, &len, 0, 0) < 0) {
- err(1, "cap_sysctlbyname()");
+ xo_err(1, "cap_sysctlbyname()");
free(buf);
return;
}
@@ -411,7 +412,7 @@ gather_sctp(void)
offset = sizeof(struct xsctp_inpcb);
while ((offset < len) && (xinpcb->last == 0)) {
if ((sock = calloc(1, sizeof *sock)) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
sock->socket = xinpcb->socket;
sock->proto = IPPROTO_SCTP;
sock->protoname = "sctp";
@@ -439,7 +440,7 @@ gather_sctp(void)
if (xladdr->last == 1)
break;
if ((laddr = calloc(1, sizeof(struct addr))) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
switch (xladdr->address.sa.sa_family) {
case AF_INET:
#define __IN_IS_ADDR_LOOPBACK(pina) \
@@ -461,7 +462,7 @@ gather_sctp(void)
htons(xinpcb->local_port));
break;
default:
- errx(1, "address family %d not supported",
+ xo_errx(1, "address family %d not supported",
xladdr->address.sa.sa_family);
}
laddr->next = NULL;
@@ -474,7 +475,7 @@ gather_sctp(void)
if (sock->laddr == NULL) {
if ((sock->laddr =
calloc(1, sizeof(struct addr))) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
sock->laddr->address.ss_family = sock->family;
if (sock->family == AF_INET)
sock->laddr->address.ss_len =
@@ -485,7 +486,7 @@ gather_sctp(void)
local_all_loopback = 0;
}
if ((sock->faddr = calloc(1, sizeof(struct addr))) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
sock->faddr->address.ss_family = sock->family;
if (sock->family == AF_INET)
sock->faddr->address.ss_len =
@@ -512,7 +513,7 @@ gather_sctp(void)
no_stcb = 0;
if (opt_c) {
if ((sock = calloc(1, sizeof *sock)) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
sock->socket = xinpcb->socket;
sock->proto = IPPROTO_SCTP;
sock->protoname = "sctp";
@@ -542,7 +543,7 @@ gather_sctp(void)
continue;
laddr = calloc(1, sizeof(struct addr));
if (laddr == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
switch (xladdr->address.sa.sa_family) {
case AF_INET:
#define __IN_IS_ADDR_LOOPBACK(pina) \
@@ -564,7 +565,7 @@ gather_sctp(void)
htons(xstcb->local_port));
break;
default:
- errx(1,
+ xo_errx(1,
"address family %d not supported",
xladdr->address.sa.sa_family);
}
@@ -587,7 +588,7 @@ gather_sctp(void)
continue;
faddr = calloc(1, sizeof(struct addr));
if (faddr == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
switch (xraddr->address.sa.sa_family) {
case AF_INET:
#define __IN_IS_ADDR_LOOPBACK(pina) \
@@ -609,7 +610,7 @@ gather_sctp(void)
htons(xstcb->remote_port));
break;
default:
- errx(1,
+ xo_errx(1,
"address family %d not supported",
xraddr->address.sa.sa_family);
}
@@ -673,7 +674,7 @@ gather_inet(int proto)
protoname = "div";
break;
default:
- errx(1, "protocol %d not supported", proto);
+ xo_errx(1, "protocol %d not supported", proto);
}
buf = NULL;
@@ -682,7 +683,7 @@ gather_inet(int proto)
do {
for (;;) {
if ((buf = realloc(buf, bufsize)) == NULL)
- err(1, "realloc()");
+ xo_err(1, "realloc()");
len = bufsize;
if (cap_sysctlbyname(capsysctl, varname, buf, &len,
NULL, 0) == 0)
@@ -690,7 +691,7 @@ gather_inet(int proto)
if (errno == ENOENT)
goto out;
if (errno != ENOMEM || len != bufsize)
- err(1, "cap_sysctlbyname()");
+ xo_err(1, "cap_sysctlbyname()");
bufsize *= 2;
}
xig = (struct xinpgen *)buf;
@@ -701,7 +702,7 @@ gather_inet(int proto)
} while (xig->xig_gen != exig->xig_gen && retry--);
if (xig->xig_gen != exig->xig_gen && opt_v)
- warnx("warning: data may be inconsistent");
+ xo_warnx("warning: data may be inconsistent");
for (;;) {
xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
@@ -722,7 +723,7 @@ gather_inet(int proto)
goto out;
break;
default:
- errx(1, "protocol %d not supported", proto);
+ xo_errx(1, "protocol %d not supported", proto);
}
so = &xip->xi_socket;
if ((xip->inp_vflag & vflag) == 0)
@@ -748,15 +749,15 @@ gather_inet(int proto)
continue;
} else {
if (opt_v)
- warnx("invalid vflag 0x%x", xip->inp_vflag);
+ xo_warnx("invalid vflag 0x%x", xip->inp_vflag);
continue;
}
if ((sock = calloc(1, sizeof(*sock))) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
if ((laddr = calloc(1, sizeof *laddr)) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
if ((faddr = calloc(1, sizeof *faddr)) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
sock->socket = so->xso_so;
sock->pcb = so->so_pcb;
sock->splice_socket = so->so_splice_so;
@@ -822,7 +823,9 @@ gather_unix(int proto)
break;
case SOCK_SEQPACKET:
varname = "net.local.seqpacket.pcblist";
- protoname = "seqpac";
+ protoname = (xo_get_style(NULL) == XO_STYLE_TEXT)
+ ? "seqpac"
+ : "seqpacket";
break;
default:
abort();
@@ -833,13 +836,13 @@ gather_unix(int proto)
do {
for (;;) {
if ((buf = realloc(buf, bufsize)) == NULL)
- err(1, "realloc()");
+ xo_err(1, "realloc()");
len = bufsize;
if (cap_sysctlbyname(capsysctl, varname, buf, &len,
NULL, 0) == 0)
break;
if (errno != ENOMEM || len != bufsize)
- err(1, "cap_sysctlbyname()");
+ xo_err(1, "cap_sysctlbyname()");
bufsize *= 2;
}
xug = (struct xunpgen *)buf;
@@ -851,7 +854,7 @@ gather_unix(int proto)
} while (xug->xug_gen != exug->xug_gen && retry--);
if (xug->xug_gen != exug->xug_gen && opt_v)
- warnx("warning: data may be inconsistent");
+ xo_warnx("warning: data may be inconsistent");
for (;;) {
xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len);
@@ -864,11 +867,11 @@ gather_unix(int proto)
(xup->unp_conn != 0 && !opt_c))
continue;
if ((sock = calloc(1, sizeof(*sock))) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
if ((laddr = calloc(1, sizeof *laddr)) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
if ((faddr = calloc(1, sizeof *faddr)) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
sock->socket = xup->xu_socket.xso_so;
sock->pcb = xup->xu_unpp;
sock->proto = proto;
@@ -899,21 +902,21 @@ getfiles(void)
olen = len = sizeof(*xfiles);
if ((xfiles = malloc(len)) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
while (cap_sysctlbyname(capsysctl, "kern.file", xfiles, &len, 0, 0)
== -1) {
if (errno != ENOMEM || len != olen)
- err(1, "cap_sysctlbyname()");
+ xo_err(1, "cap_sysctlbyname()");
olen = len *= 2;
if ((xfiles = realloc(xfiles, len)) == NULL)
- err(1, "realloc()");
+ xo_err(1, "realloc()");
}
if (len > 0)
enforce_ksize(xfiles->xf_size, struct xfile);
nfiles = len / sizeof(*xfiles);
if ((files = malloc(nfiles * sizeof(struct file))) == NULL)
- err(1, "malloc()");
+ xo_err(1, "malloc()");
for (int i = 0; i < nfiles; i++) {
files[i].xf_data = xfiles[i].xf_data;
@@ -932,6 +935,7 @@ formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize)
struct sockaddr_un *sun;
char addrstr[NI_MAXHOST] = { '\0', '\0' };
int error, off, port = 0;
+ const bool is_text_style = (xo_get_style(NULL) == XO_STYLE_TEXT);
switch (ss->ss_family) {
case AF_INET:
@@ -947,6 +951,11 @@ formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize)
case AF_UNIX:
sun = sstosun(ss);
off = (int)((char *)&sun->sun_path - (char *)sun);
+ if (!is_text_style) {
+ xo_emit("{:path/%.*s}", sun->sun_len - off,
+ sun->sun_path);
+ return 0;
+ }
return snprintf(buf, bufsize, "%.*s",
sun->sun_len - off, sun->sun_path);
}
@@ -954,7 +963,12 @@ formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize)
error = cap_getnameinfo(capnet, sstosa(ss), ss->ss_len,
addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
if (error)
- errx(1, "cap_getnameinfo()");
+ xo_errx(1, "cap_getnameinfo()");
+ }
+ if (!is_text_style) {
+ xo_emit("{:address/%s}", addrstr);
+ xo_emit("{:port/%d}", port);
+ return 0;
}
if (port == 0)
return snprintf(buf, bufsize, "%s:*", addrstr);
@@ -977,7 +991,7 @@ getprocname(pid_t pid)
== -1) {
/* Do not warn if the process exits before we get its name. */
if (errno != ESRCH)
- warn("cap_sysctl()");
+ xo_warn("cap_sysctl()");
return ("??");
}
return (proc.ki_comm);
@@ -999,7 +1013,7 @@ getprocjid(pid_t pid)
== -1) {
/* Do not warn if the process exits before we get its jid. */
if (errno != ESRCH)
- warn("cap_sysctl()");
+ xo_warn("cap_sysctl()");
return (-1);
}
return (proc.ki_jid);
@@ -1099,13 +1113,15 @@ format_unix_faddr(struct addr *faddr, char *buf, size_t bufsize) {
#define SAFESIZE (buf == NULL ? 0 : bufsize - pos)
size_t pos = 0;
- /* Remote peer we connect(2) to, if any. */
+ const bool is_text_style = (xo_get_style(NULL) == XO_STYLE_TEXT);
if (faddr->conn != 0) {
+ /* Remote peer we connect(2) to, if any. */
struct sock *p;
- pos += strlcpy(SAFEBUF, "-> ", SAFESIZE);
+ if (is_text_style)
+ pos += strlcpy(SAFEBUF, "-> ", SAFESIZE);
p = RB_FIND(pcbs_t, &pcbs,
&(struct sock){ .pcb = faddr->conn });
- if (__predict_false(p == NULL)) {
+ if (__predict_false(p == NULL) && is_text_style) {
/* XXGL: can this happen at all? */
pos += snprintf(SAFEBUF, SAFESIZE, "??");
} else if (p->laddr->address.ss_len == 0) {
@@ -1114,34 +1130,52 @@ format_unix_faddr(struct addr *faddr, char *buf, size_t bufsize) {
&(struct file){ .xf_data =
p->socket });
if (f != NULL) {
- pos += snprintf(SAFEBUF, SAFESIZE, "[%lu %d]",
- (u_long)f->xf_pid, f->xf_fd);
+ if (is_text_style) {
+ pos += snprintf(SAFEBUF, SAFESIZE,
+ "[%lu %d]", (u_long)f->xf_pid,
+ f->xf_fd);
+ } else {
+ xo_open_list("connections");
+ xo_open_instance("connections");
+ xo_emit("{:pid/%lu}", (u_long)f->xf_pid);
+ xo_emit("{:fd/%d}", f->xf_fd);
+ xo_close_instance("connections");
+ xo_close_list("connections");
+ }
}
} else
pos += formataddr(&p->laddr->address,
SAFEBUF, SAFESIZE);
- }
- /* Remote peer(s) connect(2)ed to us, if any. */
- if (faddr->firstref != 0) {
+ } else if (faddr->firstref != 0) {
+ /* Remote peer(s) connect(2)ed to us, if any. */
struct sock *p;
struct file *f;
kvaddr_t ref = faddr->firstref;
bool fref = true;
- pos += snprintf(SAFEBUF, SAFESIZE, " <- ");
-
+ if (is_text_style)
+ pos += snprintf(SAFEBUF, SAFESIZE, " <- ");
+ xo_open_list("connections");
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);
+ if (is_text_style) {
+ pos += snprintf(SAFEBUF, SAFESIZE,
+ "%s[%lu %d]", fref ? "" : ",",
+ (u_long)f->xf_pid, f->xf_fd);
+ } else {
+ xo_open_instance("connections");
+ xo_emit("{:pid/%lu}", (u_long)f->xf_pid);
+ xo_emit("{:fd/%d}", f->xf_fd);
+ xo_close_instance("connections");
+ }
}
ref = p->faddr->nextref;
fref = false;
}
+ xo_close_list("connections");
}
return pos;
}
@@ -1183,7 +1217,7 @@ calculate_sock_column_widths(struct col_widths *cw, struct sock *s)
while (laddr != NULL || faddr != NULL) {
if (opt_w && s->family == AF_UNIX) {
if ((laddr == NULL) || (faddr == NULL))
- errx(1, "laddr = %p or faddr = %p is NULL",
+ xo_errx(1, "laddr = %p or faddr = %p is NULL",
(void *)laddr, (void *)faddr);
if (laddr->address.ss_len > 0)
len = formataddr(&laddr->address, NULL, 0);
@@ -1298,6 +1332,7 @@ calculate_column_widths(struct col_widths *cw)
struct sock *s;
struct passwd *pwd;
+ cap_setpassent(cappwd, 1);
for (xf = files, n = 0; n < nfiles; ++n, ++xf) {
if (xf->xf_data == 0)
continue;
@@ -1345,65 +1380,104 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize)
laddr = s->laddr;
faddr = s->faddr;
first = true;
+ const bool is_text_style = (xo_get_style(NULL) == XO_STYLE_TEXT);
snprintf(buf, bufsize, "%s%s%s",
s->protoname,
s->vflag & INP_IPV4 ? "4" : "",
s->vflag & INP_IPV6 ? "6" : "");
- printf(" %-*s", cw->proto, buf);
+ xo_emit(" {:proto/%-*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",
+ xo_errx(1, "laddr = %p or faddr = %p is NULL",
(void *)laddr, (void *)faddr);
- if (laddr->address.ss_len > 0)
+ if (laddr->address.ss_len > 0) {
+ xo_open_container("local");
formataddr(&laddr->address, buf, bufsize);
- else if (laddr->address.ss_len == 0 && faddr->conn == 0)
- strlcpy(buf, "(not connected)", bufsize);
- else
- strlcpy(buf, "??", bufsize);
- printf(" %-*.*s", cw->local_addr, cw->local_addr, buf);
- if (format_unix_faddr(faddr, buf, bufsize) == 0)
- strlcpy(buf, "??", bufsize);
- printf(" %-*.*s", cw->foreign_addr,
- cw->foreign_addr, buf);
+ if (is_text_style) {
+ xo_emit(" {:/%-*.*s}", cw->local_addr,
+ cw->local_addr, buf);
+ }
+ xo_close_container("local");
+ } else if (laddr->address.ss_len == 0 &&
+ faddr->conn == 0 && is_text_style) {
+ xo_emit(" {:/%-*.*s}", cw->local_addr,
+ cw->local_addr, "(not connected)");
+ } else if (is_text_style) {
+ xo_emit(" {:/%-*.*s}", cw->local_addr,
+ cw->local_addr, "??");
+ }
+ if (faddr->conn != 0 || faddr->firstref != 0) {
+ xo_open_container("foreign");
+ int len = format_unix_faddr(faddr, buf,
+ bufsize);
+ if (len == 0 && is_text_style)
+ xo_emit(" {:/%-*s}",
+ cw->foreign_addr, "??");
+ else if (is_text_style)
+ xo_emit(" {:/%-*.*s}", cw->foreign_addr,
+ cw->foreign_addr, buf);
+ xo_close_container("foreign");
+ } else if (is_text_style)
+ xo_emit(" {:/%-*s}", cw->foreign_addr, "??");
} else {
- if (laddr != NULL)
+ if (laddr != NULL) {
+ xo_open_container("local");
formataddr(&laddr->address, buf, bufsize);
- else
- strlcpy(buf, "??", bufsize);
- printf(" %-*.*s", cw->local_addr, cw->local_addr, buf);
- if (faddr != NULL)
+ if (is_text_style) {
+ xo_emit(" {:/%-*.*s}", cw->local_addr,
+ cw->local_addr, buf);
+ }
+ xo_close_container("local");
+ } else if (is_text_style)
+ xo_emit(" {:/%-*.*s}", cw->local_addr,
+ cw->local_addr, "??");
+ if (faddr != NULL) {
+ xo_open_container("foreign");
formataddr(&faddr->address, buf, bufsize);
- else
- strlcpy(buf, "??", bufsize);
- printf(" %-*.*s", cw->foreign_addr,
- cw->foreign_addr, buf);
+ if (is_text_style) {
+ xo_emit(" {:/%-*.*s}", cw->foreign_addr,
+ cw->foreign_addr, buf);
+ }
+ xo_close_container("foreign");
+ } else if (is_text_style) {
+ xo_emit(" {:/%-*.*s}", cw->foreign_addr,
+ cw->foreign_addr, "??");
+ }
+ }
+ if (opt_A) {
+ snprintf(buf, bufsize, "%#*" PRIx64,
+ cw->pcb_kva, s->pcb);
+ xo_emit(" {:pcb-kva/%s}", buf);
}
- if (opt_A)
- printf(" %#*" PRIx64, cw->pcb_kva, s->pcb);
if (opt_f)
- printf(" %*d", cw->fib, s->fibnum);
+ xo_emit(" {:fib/%*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)
+ if (sp != NULL) {
+ xo_open_container("splice");
formataddr(&sp->laddr->address,
buf, bufsize);
- else
+ xo_close_container("splice");
+ } else if (is_text_style)
strlcpy(buf, "??", bufsize);
- } else
+ } else if (is_text_style)
strlcpy(buf, "??", bufsize);
- printf(" %-*s", cw->splice_address, buf);
+ if (is_text_style)
+ xo_emit(" {:/%-*s}", cw->splice_address, buf);
}
if (opt_i) {
if (s->proto == IPPROTO_TCP || s->proto == IPPROTO_UDP)
- printf(" %*" PRIu64, cw->inp_gencnt,
+ {
+ snprintf(buf, bufsize, "%" PRIu64,
s->inp_gencnt);
- else
- printf(" %*s", cw->inp_gencnt, "??");
+ xo_emit(" {:id/%*s}", cw->inp_gencnt, buf);
+ } else if (is_text_style)
+ xo_emit(" {:/%*s}", cw->inp_gencnt, "??");
}
if (opt_U) {
if (faddr != NULL &&
@@ -1414,10 +1488,10 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize)
(s->proto == IPPROTO_TCP &&
s->state != TCPS_CLOSED &&
s->state != TCPS_LISTEN))) {
- printf(" %*u", cw->encaps,
+ xo_emit(" {:encaps/%*u}", cw->encaps,
ntohs(faddr->encaps_port));
- } else
- printf(" %*s", cw->encaps, "??");
+ } else if (is_text_style)
+ xo_emit(" {:/%*s}", cw->encaps, "??");
}
if (opt_s) {
if (faddr != NULL &&
@@ -1425,10 +1499,10 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize)
s->state != SCTP_CLOSED &&
s->state != SCTP_BOUND &&
s->state != SCTP_LISTEN) {
- printf(" %-*s", cw->path_state,
+ xo_emit(" {:path-state/%-*s}", cw->path_state,
sctp_path_state(faddr->state));
- } else
- printf(" %-*s", cw->path_state, "??");
+ } else if (is_text_style)
+ xo_emit(" {:/%-*s}", cw->path_state, "??");
}
if (first) {
if (opt_s) {
@@ -1436,47 +1510,52 @@ display_sock(struct sock *s, struct col_widths *cw, char *buf, size_t bufsize)
s->proto == IPPROTO_TCP) {
switch (s->proto) {
case IPPROTO_SCTP:
- printf(" %-*s", cw->conn_state,
- sctp_conn_state(s->state));
+ xo_emit(" {:path-state/%-*s}",
+ cw->path_state,
+ sctp_path_state(
+ faddr->state));
break;
case IPPROTO_TCP:
if (s->state >= 0 &&
s->state < TCP_NSTATES)
- printf(" %-*s",
- cw->conn_state,
- tcpstates[s->state]);
- else
- printf(" %-*s",
- cw->conn_state, "??");
+ xo_emit(" {:conn-state/%-*s}",
+ cw->conn_state,
+ tcpstates[s->state]);
+ else if (is_text_style)
+ xo_emit(" {:/%-*s}",
+ cw->conn_state, "??");
break;
}
- } else
- printf(" %-*s", cw->conn_state, "??");
+ } else if (is_text_style)
+ xo_emit(" {:/%-*s}",
+ cw->conn_state, "??");
}
if (opt_S) {
if (s->proto == IPPROTO_TCP)
- printf(" %-*s", cw->stack, s->stack);
- else
- printf(" %-*s", cw->stack, "??");
+ xo_emit(" {:stack/%-*s}",
+ cw->stack, s->stack);
+ else if (is_text_style)
+ xo_emit(" {:/%-*s}",
+ cw->stack, "??");
}
if (opt_C) {
if (s->proto == IPPROTO_TCP)
- printf(" %-*s", cw->cc, s->cc);
- else
- printf(" %-*s", cw->cc, "??");
+ xo_emit(" {:cc/%-*s}", cw->cc, s->cc);
+ else if (is_text_style)
+ xo_emit(" {:/%-*s}", cw->cc, "??");
}
}
if (laddr != NULL)
laddr = laddr->next;
if (faddr != NULL)
faddr = faddr->next;
- if (laddr != NULL || faddr != NULL)
- printf("%-*s %-*s %-*s %-*s %-*s", cw->user, "",
- cw->command, "", cw->pid, "", cw->fd, "",
- cw->proto, "");
+ if (is_text_style && (laddr != NULL || faddr != NULL))
+ xo_emit("{:/%-*s} {:/%-*s} {:/%*s} {:/%*s}",
+ cw->user, "??", cw->command, "??",
+ cw->pid, "??", cw->fd, "??");
first = false;
}
- printf("\n");
+ xo_emit("\n");
}
static void
@@ -1490,56 +1569,63 @@ display(void)
const size_t bufsize = 512;
void *buf;
if ((buf = (char *)malloc(bufsize)) == NULL) {
- err(1, "malloc()");
+ xo_err(1, "malloc()");
return;
}
- cw = (struct col_widths) {
- .user = strlen("USER"),
- .command = 10,
- .pid = strlen("PID"),
- .fd = strlen("FD"),
- .proto = strlen("PROTO"),
- .local_addr = opt_w ? strlen("LOCAL ADDRESS") : 21,
- .foreign_addr = opt_w ? strlen("FOREIGN ADDRESS") : 21,
- .pcb_kva = 18,
- .fib = strlen("FIB"),
- .splice_address = strlen("SPLICE ADDRESS"),
- .inp_gencnt = strlen("ID"),
- .encaps = strlen("ENCAPS"),
- .path_state = strlen("PATH STATE"),
- .conn_state = strlen("CONN STATE"),
- .stack = strlen("STACK"),
- .cc = strlen("CC"),
- };
- calculate_column_widths(&cw);
+ if (xo_get_style(NULL) == XO_STYLE_TEXT) {
+ cw = (struct col_widths) {
+ .user = strlen("USER"),
+ .command = 10,
+ .pid = strlen("PID"),
+ .fd = strlen("FD"),
+ .proto = strlen("PROTO"),
+ .local_addr = opt_w ? strlen("LOCAL ADDRESS") : 21,
+ .foreign_addr = opt_w ? strlen("FOREIGN ADDRESS") : 21,
+ .pcb_kva = 18,
+ .fib = strlen("FIB"),
+ .splice_address = strlen("SPLICE ADDRESS"),
+ .inp_gencnt = strlen("ID"),
+ .encaps = strlen("ENCAPS"),
+ .path_state = strlen("PATH STATE"),
+ .conn_state = strlen("CONN STATE"),
+ .stack = strlen("STACK"),
+ .cc = strlen("CC"),
+ };
+ calculate_column_widths(&cw);
+ } else
+ memset(&cw, 0, sizeof(cw));
+ xo_set_version(SOCKSTAT_XO_VERSION);
+ xo_open_container("sockstat");
+ xo_open_list("socket");
if (!opt_q) {
- 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");
+ xo_emit("{T:/%-*s} {T:/%-*s} {T:/%*s} {T:/%*s} {T:/%-*s} "
+ "{T:/%-*s} {T:/%-*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(" %-*s", cw.pcb_kva, "PCB KVA");
+ xo_emit(" {T:/%-*s}", cw.pcb_kva, "PCB KVA");
if (opt_f)
/* RT_MAXFIBS is 65535. */
- printf(" %*s", cw.fib, "FIB");
+ xo_emit(" {T:/%*s}", cw.fib, "FIB");
if (opt_I)
- printf(" %-*s", cw.splice_address, "SPLICE ADDRESS");
+ xo_emit(" {T:/%-*s}", cw.splice_address,
+ "SPLICE ADDRESS");
if (opt_i)
- printf(" %*s", cw.inp_gencnt, "ID");
+ xo_emit(" {T:/%*s}", cw.inp_gencnt, "ID");
if (opt_U)
- printf(" %*s", cw.encaps, "ENCAPS");
+ xo_emit(" {T:/%*s}", cw.encaps, "ENCAPS");
if (opt_s) {
- printf(" %-*s", cw.path_state, "PATH STATE");
- printf(" %-*s", cw.conn_state, "CONN STATE");
+ xo_emit(" {T:/%-*s}", cw.path_state, "PATH STATE");
+ xo_emit(" {T:/%-*s}", cw.conn_state, "CONN STATE");
}
if (opt_S)
- printf(" %-*s", cw.stack, "STACK");
+ xo_emit(" {T:/%-*s}", cw.stack, "STACK");
if (opt_C)
- printf(" %-*s", cw.cc, "CC");
- printf("\n");
+ xo_emit(" {T:/%-*s}", cw.cc, "CC");
+ xo_emit("\n");
}
cap_setpassent(cappwd, 1);
for (xf = files, n = 0; n < nfiles; ++n, ++xf) {
@@ -1550,17 +1636,24 @@ display(void)
s = RB_FIND(socks_t, &socks,
&(struct sock){ .socket = xf->xf_data});
if (s != NULL && check_ports(s)) {
+ xo_open_instance("socket");
s->shown = 1;
if (opt_n ||
(pwd = cap_getpwuid(cappwd, xf->xf_uid)) == NULL)
- printf("%-*lu", cw.user, (u_long)xf->xf_uid);
+ xo_emit("{:user/%-*lu}", cw.user,
+ (u_long)xf->xf_uid);
+ else
+ xo_emit("{:user/%-*s}", cw.user, pwd->pw_name);
+ if (xo_get_style(NULL) == XO_STYLE_TEXT)
+ xo_emit(" {:/%-*.10s}", cw.command,
+ getprocname(xf->xf_pid));
else
- 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);
+ xo_emit(" {:command/%-*s}", cw.command,
+ getprocname(xf->xf_pid));
+ xo_emit(" {:pid/%*lu}", cw.pid, (u_long)xf->xf_pid);
+ xo_emit(" {:fd/%*d}", cw.fd, xf->xf_fd);
display_sock(s, &cw, buf, bufsize);
+ xo_close_instance("socket");
}
}
if (opt_j >= 0)
@@ -1568,20 +1661,33 @@ display(void)
SLIST_FOREACH(s, &nosocks, socket_list) {
if (!check_ports(s))
continue;
- printf("%-*s %-*s %*s %*s", cw.user, "??", cw.command, "??",
- cw.pid, "??", cw.fd, "??");
+ xo_open_instance("socket");
+ if (xo_get_style(NULL) == XO_STYLE_TEXT)
+ xo_emit("{:/%-*s} {:/%-*s} {:/%*s} {:/%*s}",
+ cw.user, "??", cw.command, "??",
+ cw.pid, "??", cw.fd, "??");
display_sock(s, &cw, buf, bufsize);
+ xo_close_instance("socket");
}
RB_FOREACH(s, socks_t, &socks) {
if (s->shown)
continue;
if (!check_ports(s))
continue;
- printf("%-*s %-*s %*s %*s", cw.user, "??", cw.command, "??",
- cw.pid, "??", cw.fd, "??");
+ xo_open_instance("socket");
+ if (xo_get_style(NULL) == XO_STYLE_TEXT)
+ xo_emit("{:/%-*s} {:/%-*s} {:/%*s} {:/%*s}",
+ cw.user, "??", cw.command, "??",
+ cw.pid, "??", cw.fd, "??");
display_sock(s, &cw, buf, bufsize);
+ xo_close_instance("socket");
}
+ xo_close_list("socket");
+ xo_close_container("sockstat");
*** 103 LINES SKIPPED ***