format-table: make UID/GID/PID fields first class citizens + add signal cell type
This way we can display invalid UIDs/GIDs/PIDs as n/a while still storing them as is. Also, let's add a new cell type for unix signal, that is stored as integer, but displayed as signal name string.
This commit is contained in:
@@ -20,11 +20,14 @@
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "sort-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strxcpyx.h"
|
||||
#include "terminal-util.h"
|
||||
#include "time-util.h"
|
||||
#include "user-util.h"
|
||||
#include "utf8.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -100,6 +103,9 @@ typedef struct TableData {
|
||||
int ifindex;
|
||||
union in_addr_union address;
|
||||
sd_id128_t id128;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
pid_t pid;
|
||||
/* … add more here as we start supporting more cell data types … */
|
||||
};
|
||||
} TableData;
|
||||
@@ -284,6 +290,7 @@ static size_t table_data_size(TableDataType type, const void *data) {
|
||||
case TABLE_UINT:
|
||||
case TABLE_PERCENT:
|
||||
case TABLE_IFINDEX:
|
||||
case TABLE_SIGNAL:
|
||||
return sizeof(int);
|
||||
|
||||
case TABLE_IN_ADDR:
|
||||
@@ -296,6 +303,13 @@ static size_t table_data_size(TableDataType type, const void *data) {
|
||||
case TABLE_ID128:
|
||||
return sizeof(sd_id128_t);
|
||||
|
||||
case TABLE_UID:
|
||||
return sizeof(uid_t);
|
||||
case TABLE_GID:
|
||||
return sizeof(gid_t);
|
||||
case TABLE_PID:
|
||||
return sizeof(pid_t);
|
||||
|
||||
default:
|
||||
assert_not_reached("Uh? Unexpected cell type");
|
||||
}
|
||||
@@ -801,6 +815,9 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
|
||||
bool b;
|
||||
union in_addr_union address;
|
||||
sd_id128_t id128;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
pid_t pid;
|
||||
} buffer;
|
||||
|
||||
switch (type) {
|
||||
@@ -840,6 +857,7 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
|
||||
break;
|
||||
|
||||
case TABLE_INT:
|
||||
case TABLE_SIGNAL:
|
||||
buffer.int_val = va_arg(ap, int);
|
||||
data = &buffer.int_val;
|
||||
break;
|
||||
@@ -931,6 +949,21 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
|
||||
data = &buffer.id128;
|
||||
break;
|
||||
|
||||
case TABLE_UID:
|
||||
buffer.uid = va_arg(ap, uid_t);
|
||||
data = &buffer.uid;
|
||||
break;
|
||||
|
||||
case TABLE_GID:
|
||||
buffer.gid = va_arg(ap, gid_t);
|
||||
data = &buffer.gid;
|
||||
break;
|
||||
|
||||
case TABLE_PID:
|
||||
buffer.pid = va_arg(ap, pid_t);
|
||||
data = &buffer.pid;
|
||||
break;
|
||||
|
||||
case TABLE_SET_MINIMUM_WIDTH: {
|
||||
size_t w = va_arg(ap, size_t);
|
||||
|
||||
@@ -1189,6 +1222,7 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t
|
||||
return CMP(a->size, b->size);
|
||||
|
||||
case TABLE_INT:
|
||||
case TABLE_SIGNAL:
|
||||
return CMP(a->int_val, b->int_val);
|
||||
|
||||
case TABLE_INT8:
|
||||
@@ -1234,6 +1268,15 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t
|
||||
case TABLE_ID128:
|
||||
return memcmp(&a->id128, &b->id128, sizeof(sd_id128_t));
|
||||
|
||||
case TABLE_UID:
|
||||
return CMP(a->uid, b->uid);
|
||||
|
||||
case TABLE_GID:
|
||||
return CMP(a->gid, b->gid);
|
||||
|
||||
case TABLE_PID:
|
||||
return CMP(a->pid, b->pid);
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
@@ -1618,6 +1661,67 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_UID: {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
if (!uid_is_valid(d->uid))
|
||||
return "n/a";
|
||||
|
||||
p = new(char, DECIMAL_STR_WIDTH(d->uid) + 1);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
sprintf(p, UID_FMT, d->uid);
|
||||
d->formatted = TAKE_PTR(p);
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_GID: {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
if (!gid_is_valid(d->gid))
|
||||
return "n/a";
|
||||
|
||||
p = new(char, DECIMAL_STR_WIDTH(d->gid) + 1);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
sprintf(p, GID_FMT, d->gid);
|
||||
d->formatted = TAKE_PTR(p);
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_PID: {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
if (!pid_is_valid(d->pid))
|
||||
return "n/a";
|
||||
|
||||
p = new(char, DECIMAL_STR_WIDTH(d->pid) + 1);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
sprintf(p, PID_FMT, d->pid);
|
||||
d->formatted = TAKE_PTR(p);
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_SIGNAL: {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
const char *suffix;
|
||||
|
||||
suffix = signal_to_string(d->int_val);
|
||||
if (!suffix)
|
||||
return "n/a";
|
||||
|
||||
p = strjoin("SIG", suffix);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
d->formatted = TAKE_PTR(p);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert_not_reached("Unexpected type?");
|
||||
}
|
||||
@@ -2392,6 +2496,30 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) {
|
||||
return json_variant_new_string(ret, id128_to_uuid_string(d->id128, buf));
|
||||
}
|
||||
|
||||
case TABLE_UID:
|
||||
if (!uid_is_valid(d->uid))
|
||||
return json_variant_new_null(ret);
|
||||
|
||||
return json_variant_new_integer(ret, d->uid);
|
||||
|
||||
case TABLE_GID:
|
||||
if (!gid_is_valid(d->gid))
|
||||
return json_variant_new_null(ret);
|
||||
|
||||
return json_variant_new_integer(ret, d->gid);
|
||||
|
||||
case TABLE_PID:
|
||||
if (!pid_is_valid(d->pid))
|
||||
return json_variant_new_null(ret);
|
||||
|
||||
return json_variant_new_integer(ret, d->pid);
|
||||
|
||||
case TABLE_SIGNAL:
|
||||
if (!SIGNAL_VALID(d->int_val))
|
||||
return json_variant_new_null(ret);
|
||||
|
||||
return json_variant_new_integer(ret, d->int_val);
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,10 @@ typedef enum TableDataType {
|
||||
TABLE_IN6_ADDR, /* Takes a union in_addr_union (or a struct in6_addr) */
|
||||
TABLE_ID128,
|
||||
TABLE_UUID,
|
||||
TABLE_UID,
|
||||
TABLE_GID,
|
||||
TABLE_PID,
|
||||
TABLE_SIGNAL,
|
||||
_TABLE_DATA_TYPE_MAX,
|
||||
|
||||
/* The following are not really data types, but commands for table_add_cell_many() to make changes to
|
||||
@@ -57,16 +61,6 @@ typedef enum TableDataType {
|
||||
_TABLE_DATA_TYPE_INVALID = -1,
|
||||
} TableDataType;
|
||||
|
||||
/* PIDs are just 32bit signed integers on Linux */
|
||||
#define TABLE_PID TABLE_INT32
|
||||
assert_cc(sizeof(pid_t) == sizeof(int32_t));
|
||||
|
||||
/* UIDs/GIDs are just 32bit unsigned integers on Linux */
|
||||
#define TABLE_UID TABLE_UINT32
|
||||
#define TABLE_GID TABLE_UINT32
|
||||
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
|
||||
assert_cc(sizeof(gid_t) == sizeof(uint32_t));
|
||||
|
||||
typedef struct Table Table;
|
||||
typedef struct TableCell TableCell;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user