The new option --columns (short: -c) allows to select columns to be displayed. Note that this doesn't affect the order in which columns are displayed.
Reported-by: Yoann P. <yoann.p.pub...@gmail.com> Signed-off-by: Stefano Brivio <sbri...@redhat.com> --- man/man8/ss.8 | 5 +++++ misc/ss.c | 62 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/man/man8/ss.8 b/man/man8/ss.8 index 7a6572b17364..c987dec6bcd7 100644 --- a/man/man8/ss.8 +++ b/man/man8/ss.8 @@ -24,6 +24,11 @@ Output version information. .B \-H, \-\-no-header Suppress header line. .TP +.B \-c COLS, \-\-columns=COLS +Only display selected columns, separated by commas. The following column names +are understood: netid, state, local, lport, peer, pport, ext. This does not +define the order of columns. +.TP .B \-n, \-\-numeric Do not try to resolve service names. .TP diff --git a/misc/ss.c b/misc/ss.c index c3f61ef66258..91be3c6db151 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -132,6 +132,7 @@ enum col_align { struct column { const enum col_align align; + const char *optname; const char *header; const char *ldelim; int disabled; @@ -140,15 +141,15 @@ struct column { }; static struct column columns[] = { - { ALIGN_LEFT, "Netid", "", 0, 0, 0 }, - { ALIGN_LEFT, "State", " ", 0, 0, 0 }, - { ALIGN_LEFT, "Recv-Q", " ", 0, 0, 0 }, - { ALIGN_LEFT, "Send-Q", " ", 0, 0, 0 }, - { ALIGN_RIGHT, "Local Address:", " ", 0, 0, 0 }, - { ALIGN_LEFT, "Port", "", 0, 0, 0 }, - { ALIGN_RIGHT, "Peer Address:", " ", 0, 0, 0 }, - { ALIGN_LEFT, "Port", "", 0, 0, 0 }, - { ALIGN_LEFT, "", "", 0, 0, 0 }, + { ALIGN_LEFT, "netid", "Netid", "", 0, 0, 0 }, + { ALIGN_LEFT, "state", "State", " ", 0, 0, 0 }, + { ALIGN_LEFT, "recvq", "Recv-Q", " ", 0, 0, 0 }, + { ALIGN_LEFT, "sendq", "Send-Q", " ", 0, 0, 0 }, + { ALIGN_RIGHT, "local", "Local Address:", " ", 0, 0, 0 }, + { ALIGN_LEFT, "lport", "Port", "", 0, 0, 0 }, + { ALIGN_RIGHT, "peer", "Peer Address:", " ", 0, 0, 0 }, + { ALIGN_LEFT, "pport", "Port", "", 0, 0, 0 }, + { ALIGN_LEFT, "ext", "", "", 0, 0, 0 }, }; static struct column *current_field = columns; @@ -1073,6 +1074,11 @@ static int field_is_last(struct column *f) return f - columns == COL_MAX - 1; } +static int field_is_valid(struct column *f) +{ + return f >= columns && f - columns < COL_MAX; +} + static void field_next(void) { field_flush(current_field); @@ -4666,6 +4672,8 @@ static void _usage(FILE *dest) "\n" " -K, --kill forcibly close sockets, display what was closed\n" " -H, --no-header Suppress header line\n" +" -c, --columns=COLS display only COLS columns\n" +" COLS := {netid|state|local|lport|peer|pport|ext}[,COLS]\n" "\n" " -A, --query=QUERY, --socket=QUERY\n" " QUERY := {all|inet|tcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink|vsock_stream|vsock_dgram|tipc}[,QUERY]\n" @@ -4785,6 +4793,7 @@ static const struct option long_opts[] = { { "tipcinfo", 0, 0, OPT_TIPCINFO}, { "kill", 0, 0, 'K' }, { "no-header", 0, 0, 'H' }, + { "columns", 1, 0, 'c' }, { 0 } }; @@ -4800,7 +4809,7 @@ int main(int argc, char *argv[]) int state_filter = 0; while ((ch = getopt_long(argc, argv, - "dhaletuwxnro460spbEf:miA:D:F:vVzZN:KHS", + "dhaletuwxnro460spbEf:miA:D:F:vVzZN:KHc:S", long_opts, NULL)) != EOF) { switch (ch) { case 'n': @@ -4966,6 +4975,39 @@ int main(int argc, char *argv[]) case 'H': show_header = 0; break; + case 'c': + { + struct column *f; + char *p, *p1; + + if (!optarg) { + fprintf(stderr, "ss: No columns given.\n"); + usage(); + } + + for (f = columns; field_is_valid(f); f++) + f->disabled = 1; + + p = optarg; + do { + p1 = strchr(p, ','); + if (p1) + *p1 = 0; + for (f = columns; field_is_valid(f); f++) { + if (!strcmp(f->optname, p)) { + f->disabled = 0; + break; + } + } + if (!field_is_valid(f)) { + fprintf(stderr, "ss: No column %s\n", + p); + usage(); + } + p = p1 + 1; + } while (p1); + break; + } case 'h': help(); case '?': -- 2.19.1