mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-03-10 00:58:20 +03:00
Merge pull request #14562 from yuwata/table-strv
introduce TABLE_STRV and use it in networkctl and resolvectl
This commit is contained in:
commit
98f44b97bb
@ -730,19 +730,26 @@ char **strv_sort(char **l) {
|
||||
return l;
|
||||
}
|
||||
|
||||
bool strv_equal(char * const *a, char * const *b) {
|
||||
int strv_compare(char * const *a, char * const *b) {
|
||||
int r;
|
||||
|
||||
if (strv_isempty(a))
|
||||
return strv_isempty(b);
|
||||
if (strv_isempty(a)) {
|
||||
if (strv_isempty(b))
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strv_isempty(b))
|
||||
return false;
|
||||
return 1;
|
||||
|
||||
for ( ; *a || *b; ++a, ++b)
|
||||
if (!streq_ptr(*a, *b))
|
||||
return false;
|
||||
for ( ; *a || *b; ++a, ++b) {
|
||||
r = strcmp_ptr(*a, *b);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void strv_print(char * const *l) {
|
||||
|
@ -51,7 +51,10 @@ char **strv_remove(char **l, const char *s);
|
||||
char **strv_uniq(char **l);
|
||||
bool strv_is_uniq(char * const *l);
|
||||
|
||||
bool strv_equal(char * const *a, char * const *b);
|
||||
int strv_compare(char * const *a, char * const *b);
|
||||
static inline bool strv_equal(char * const *a, char * const *b) {
|
||||
return strv_compare(a, b) == 0;
|
||||
}
|
||||
|
||||
#define strv_contains(l, s) (!!strv_find((l), (s)))
|
||||
|
||||
|
@ -742,29 +742,41 @@ static int get_gateway_description(
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
static int dump_list(Table *table, const char *prefix, char * const *l) {
|
||||
int r;
|
||||
|
||||
if (strv_isempty(l))
|
||||
return 0;
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, prefix,
|
||||
TABLE_STRV, l);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_gateways(
|
||||
sd_netlink *rtnl,
|
||||
sd_hwdb *hwdb,
|
||||
Table *table,
|
||||
int ifindex) {
|
||||
_cleanup_free_ struct local_address *local = NULL;
|
||||
_cleanup_strv_free_ char **buf = NULL;
|
||||
int r, n, i;
|
||||
|
||||
assert(rtnl);
|
||||
assert(table);
|
||||
|
||||
n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local);
|
||||
if (n < 0)
|
||||
if (n <= 0)
|
||||
return n;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
_cleanup_free_ char *gateway = NULL, *description = NULL, *with_description = NULL;
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, i == 0 ? "Gateway:" : "");
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
char name[IF_NAMESIZE+1];
|
||||
|
||||
r = in_addr_to_string(local[i].family, &local[i].address, &gateway);
|
||||
if (r < 0)
|
||||
@ -772,28 +784,24 @@ static int dump_gateways(
|
||||
|
||||
r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Could not get description of gateway: %m");
|
||||
log_debug_errno(r, "Could not get description of gateway, ignoring: %m");
|
||||
|
||||
if (description) {
|
||||
with_description = strjoin(gateway, " (", description, ")");
|
||||
if (!with_description)
|
||||
return -ENOMEM;
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
/* Show interface name for the entry if we show
|
||||
* entries for all interfaces */
|
||||
if (ifindex <= 0) {
|
||||
char name[IF_NAMESIZE+1];
|
||||
|
||||
r = table_add_cell_stringf(table, NULL, "%s on %s", with_description ?: gateway,
|
||||
format_ifname_full(local[i].ifindex, name, FORMAT_IFNAME_IFINDEX_WITH_PERCENT));
|
||||
} else
|
||||
r = table_add_cell(table, NULL, TABLE_STRING, with_description ?: gateway);
|
||||
/* Show interface name for the entry if we show entries for all interfaces */
|
||||
r = strv_extendf(&buf, "%s%s%s",
|
||||
with_description ?: gateway,
|
||||
ifindex <= 0 ? " on " : "",
|
||||
ifindex <= 0 ? format_ifname_full(local[i].ifindex, name, FORMAT_IFNAME_IFINDEX_WITH_PERCENT) : "");
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return dump_list(table, "Gateway:", buf);
|
||||
}
|
||||
|
||||
static int dump_addresses(
|
||||
@ -803,25 +811,21 @@ static int dump_addresses(
|
||||
|
||||
_cleanup_free_ struct local_address *local = NULL;
|
||||
_cleanup_free_ char *dhcp4_address = NULL;
|
||||
_cleanup_strv_free_ char **buf = NULL;
|
||||
int r, n, i;
|
||||
|
||||
assert(rtnl);
|
||||
assert(table);
|
||||
|
||||
n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local);
|
||||
if (n < 0)
|
||||
if (n <= 0)
|
||||
return n;
|
||||
|
||||
(void) sd_network_link_get_dhcp4_address(ifindex, &dhcp4_address);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
_cleanup_free_ char *pretty = NULL;
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, i == 0 ? "Address:" : "");
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
char name[IF_NAMESIZE+1];
|
||||
|
||||
r = in_addr_to_string(local[i].family, &local[i].address, &pretty);
|
||||
if (r < 0)
|
||||
@ -836,18 +840,15 @@ static int dump_addresses(
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (ifindex <= 0) {
|
||||
char name[IF_NAMESIZE+1];
|
||||
|
||||
r = table_add_cell_stringf(table, NULL, "%s on %s", pretty,
|
||||
format_ifname_full(local[i].ifindex, name, FORMAT_IFNAME_IFINDEX_WITH_PERCENT));
|
||||
} else
|
||||
r = table_add_cell(table, NULL, TABLE_STRING, pretty);
|
||||
r = strv_extendf(&buf, "%s%s%s",
|
||||
pretty,
|
||||
ifindex <= 0 ? " on " : "",
|
||||
ifindex <= 0 ? format_ifname_full(local[i].ifindex, name, FORMAT_IFNAME_IFINDEX_WITH_PERCENT) : "");
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return dump_list(table, "Address:", buf);
|
||||
}
|
||||
|
||||
static int dump_address_labels(sd_netlink *rtnl) {
|
||||
@ -997,8 +998,9 @@ static int next_lldp_neighbor(FILE *f, sd_lldp_neighbor **ret) {
|
||||
}
|
||||
|
||||
static int dump_lldp_neighbors(Table *table, const char *prefix, int ifindex) {
|
||||
_cleanup_strv_free_ char **buf = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int r, c = 0;
|
||||
int r;
|
||||
|
||||
assert(table);
|
||||
assert(prefix);
|
||||
@ -1020,29 +1022,21 @@ static int dump_lldp_neighbors(Table *table, const char *prefix, int ifindex) {
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, c == 0 ? prefix : "");
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
(void) sd_lldp_neighbor_get_system_name(n, &system_name);
|
||||
(void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id);
|
||||
(void) sd_lldp_neighbor_get_port_description(n, &port_description);
|
||||
|
||||
r = table_add_cell_stringf(table, NULL,
|
||||
"%s on port %s%s%s%s",
|
||||
strna(system_name), strna(port_id),
|
||||
isempty(port_description) ? "" : " (",
|
||||
strempty(port_description),
|
||||
isempty(port_description) ? "" : ")");
|
||||
r = strv_extendf(&buf, "%s on port %s%s%s%s",
|
||||
strna(system_name),
|
||||
strna(port_id),
|
||||
isempty(port_description) ? "" : " (",
|
||||
strempty(port_description),
|
||||
isempty(port_description) ? "" : ")");
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
c++;
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return c;
|
||||
return dump_list(table, prefix, buf);
|
||||
}
|
||||
|
||||
static int dump_ifindexes(Table *table, const char *prefix, const int *ifindexes) {
|
||||
@ -1066,25 +1060,6 @@ static int dump_ifindexes(Table *table, const char *prefix, const int *ifindexes
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_list(Table *table, const char *prefix, char **l) {
|
||||
char **i;
|
||||
int r;
|
||||
|
||||
if (strv_isempty(l))
|
||||
return 0;
|
||||
|
||||
STRV_FOREACH(i, l) {
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, i == l ? prefix : "",
|
||||
TABLE_STRING, *i);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DUMP_STATS_ONE(name, val_name) \
|
||||
r = table_add_many(table, \
|
||||
TABLE_EMPTY, \
|
||||
@ -1197,7 +1172,6 @@ static int link_status_one(
|
||||
_cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
TableCell *cell;
|
||||
char **p;
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
@ -1282,20 +1256,9 @@ static int link_status_one(
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
STRV_FOREACH(p, info->alternative_names) {
|
||||
if (p == info->alternative_names)
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, "Alternative Names:",
|
||||
TABLE_STRING, *p);
|
||||
else
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, *p);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
r = dump_list(table, "Alternative Names:", info->alternative_names);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (path) {
|
||||
r = table_add_many(table,
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "bus-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "escape.h"
|
||||
#include "format-table.h"
|
||||
#include "format-util.h"
|
||||
#include "gcrypt-util.h"
|
||||
#include "main-func.h"
|
||||
@ -984,6 +985,7 @@ static int verb_tlsa(int argc, char **argv, void *userdata) {
|
||||
static int show_statistics(int argc, char **argv, void *userdata) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
sd_bus *bus = userdata;
|
||||
uint64_t n_current_transactions, n_total_transactions,
|
||||
cache_size, n_cache_hit, n_cache_miss,
|
||||
@ -1025,14 +1027,6 @@ static int show_statistics(int argc, char **argv, void *userdata) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
printf("%sTransactions%s\n"
|
||||
"Current Transactions: %" PRIu64 "\n"
|
||||
" Total Transactions: %" PRIu64 "\n",
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
n_current_transactions,
|
||||
n_total_transactions);
|
||||
|
||||
reply = sd_bus_message_unref(reply);
|
||||
|
||||
r = sd_bus_get_property(bus,
|
||||
@ -1053,16 +1047,6 @@ static int show_statistics(int argc, char **argv, void *userdata) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
printf("\n%sCache%s\n"
|
||||
" Current Cache Size: %" PRIu64 "\n"
|
||||
" Cache Hits: %" PRIu64 "\n"
|
||||
" Cache Misses: %" PRIu64 "\n",
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
cache_size,
|
||||
n_cache_hit,
|
||||
n_cache_miss);
|
||||
|
||||
reply = sd_bus_message_unref(reply);
|
||||
|
||||
r = sd_bus_get_property(bus,
|
||||
@ -1084,17 +1068,53 @@ static int show_statistics(int argc, char **argv, void *userdata) {
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
printf("\n%sDNSSEC Verdicts%s\n"
|
||||
" Secure: %" PRIu64 "\n"
|
||||
" Insecure: %" PRIu64 "\n"
|
||||
" Bogus: %" PRIu64 "\n"
|
||||
" Indeterminate: %" PRIu64 "\n",
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
n_dnssec_secure,
|
||||
n_dnssec_insecure,
|
||||
n_dnssec_bogus,
|
||||
n_dnssec_indeterminate);
|
||||
table = table_new("key", "value");
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
table_set_header(table, false);
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, "Transactions",
|
||||
TABLE_SET_COLOR, ansi_highlight(),
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, "Current Transactions:",
|
||||
TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_UINT64, n_current_transactions,
|
||||
TABLE_STRING, "Total Transactions:",
|
||||
TABLE_UINT64, n_total_transactions,
|
||||
TABLE_EMPTY, TABLE_EMPTY,
|
||||
TABLE_STRING, "Cache",
|
||||
TABLE_SET_COLOR, ansi_highlight(),
|
||||
TABLE_SET_ALIGN_PERCENT, 0,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, "Current Cache Size:",
|
||||
TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_UINT64, cache_size,
|
||||
TABLE_STRING, "Cache Hits:",
|
||||
TABLE_UINT64, n_cache_hit,
|
||||
TABLE_STRING, "Cache Misses:",
|
||||
TABLE_UINT64, n_cache_miss,
|
||||
TABLE_EMPTY, TABLE_EMPTY,
|
||||
TABLE_STRING, "DNSSEC Verdicts",
|
||||
TABLE_SET_COLOR, ansi_highlight(),
|
||||
TABLE_SET_ALIGN_PERCENT, 0,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, "Secure:",
|
||||
TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_UINT64, n_dnssec_secure,
|
||||
TABLE_STRING, "Insecure:",
|
||||
TABLE_UINT64, n_dnssec_insecure,
|
||||
TABLE_STRING, "Bogus:",
|
||||
TABLE_UINT64, n_dnssec_bogus,
|
||||
TABLE_STRING, "Indeterminate:",
|
||||
TABLE_UINT64, n_dnssec_indeterminate);
|
||||
if (r < 0)
|
||||
table_log_add_error(r);
|
||||
|
||||
r = table_print(table, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to print table: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1365,6 +1385,21 @@ static void link_info_clear(struct link_info *p) {
|
||||
strv_free(p->ntas);
|
||||
}
|
||||
|
||||
static int dump_list(Table *table, const char *prefix, char * const *l) {
|
||||
int r;
|
||||
|
||||
if (strv_isempty(l))
|
||||
return 0;
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, prefix,
|
||||
TABLE_STRV, l);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode mode, bool *empty_line) {
|
||||
static const struct bus_properties_map property_map[] = {
|
||||
{ "ScopesMask", "t", NULL, offsetof(struct link_info, scopes_mask) },
|
||||
@ -1383,9 +1418,9 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
_cleanup_(link_info_clear) struct link_info link_info = {};
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
char ifi[DECIMAL_STR_MAX(int)], ifname[IF_NAMESIZE + 1] = "";
|
||||
char **i;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
@ -1471,49 +1506,80 @@ static int status_ifindex(sd_bus *bus, int ifindex, const char *name, StatusMode
|
||||
printf("%sLink %i (%s)%s\n",
|
||||
ansi_highlight(), ifindex, name, ansi_normal());
|
||||
|
||||
table = table_new("key", "value");
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
table_set_header(table, false);
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, "Current Scopes:",
|
||||
TABLE_SET_ALIGN_PERCENT, 100);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
if (link_info.scopes_mask == 0)
|
||||
printf(" Current Scopes: none\n");
|
||||
else
|
||||
printf(" Current Scopes:%s%s%s%s%s\n",
|
||||
link_info.scopes_mask & SD_RESOLVED_DNS ? " DNS" : "",
|
||||
link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
|
||||
link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
|
||||
link_info.scopes_mask & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4" : "",
|
||||
link_info.scopes_mask & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6" : "");
|
||||
r = table_add_cell(table, NULL, TABLE_STRING, "none");
|
||||
else {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
size_t len;
|
||||
|
||||
printf("DefaultRoute setting: %s\n"
|
||||
" LLMNR setting: %s\n"
|
||||
"MulticastDNS setting: %s\n"
|
||||
" DNSOverTLS setting: %s\n"
|
||||
" DNSSEC setting: %s\n"
|
||||
" DNSSEC supported: %s\n",
|
||||
yes_no(link_info.default_route),
|
||||
strna(link_info.llmnr),
|
||||
strna(link_info.mdns),
|
||||
strna(link_info.dns_over_tls),
|
||||
strna(link_info.dnssec),
|
||||
yes_no(link_info.dnssec_supported));
|
||||
if (asprintf(&buf, "%s%s%s%s%s",
|
||||
link_info.scopes_mask & SD_RESOLVED_DNS ? "DNS " : "",
|
||||
link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV4 ? "LLMNR/IPv4 " : "",
|
||||
link_info.scopes_mask & SD_RESOLVED_LLMNR_IPV6 ? "LLMNR/IPv6 " : "",
|
||||
link_info.scopes_mask & SD_RESOLVED_MDNS_IPV4 ? "mDNS/IPv4 " : "",
|
||||
link_info.scopes_mask & SD_RESOLVED_MDNS_IPV6 ? "mDNS/IPv6 " : "") < 0)
|
||||
return log_oom();
|
||||
|
||||
if (link_info.current_dns)
|
||||
printf(" Current DNS Server: %s\n", link_info.current_dns);
|
||||
len = strlen(buf);
|
||||
assert(len > 0);
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
STRV_FOREACH(i, link_info.dns) {
|
||||
printf(" %s %s\n",
|
||||
i == link_info.dns ? "DNS Servers:" : " ",
|
||||
*i);
|
||||
r = table_add_cell(table, NULL, TABLE_STRING, buf);
|
||||
}
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, "DefaultRoute setting:",
|
||||
TABLE_BOOLEAN, link_info.default_route,
|
||||
TABLE_STRING, "LLMNR setting:",
|
||||
TABLE_STRING, strna(link_info.llmnr),
|
||||
TABLE_STRING, "MulticastDNS setting:",
|
||||
TABLE_STRING, strna(link_info.mdns),
|
||||
TABLE_STRING, "DNSOverTLS setting:",
|
||||
TABLE_STRING, strna(link_info.dns_over_tls),
|
||||
TABLE_STRING, "DNSSEC setting:",
|
||||
TABLE_STRING, strna(link_info.dnssec),
|
||||
TABLE_STRING, "DNSSEC supported:",
|
||||
TABLE_BOOLEAN, link_info.dnssec_supported);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
if (link_info.current_dns) {
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, "Current DNS Server:",
|
||||
TABLE_STRING, link_info.current_dns);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, link_info.domains) {
|
||||
printf(" %s %s\n",
|
||||
i == link_info.domains ? "DNS Domain:" : " ",
|
||||
*i);
|
||||
}
|
||||
r = dump_list(table, "DNS Servers:", link_info.dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(i, link_info.ntas) {
|
||||
printf(" %s %s\n",
|
||||
i == link_info.ntas ? "DNSSEC NTA:" : " ",
|
||||
*i);
|
||||
}
|
||||
r = dump_list(table, "DNS Domain:", link_info.domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dump_list(table, "DNSSEC NTA:", link_info.ntas);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = table_print(table, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to print table: %m");
|
||||
|
||||
if (empty_line)
|
||||
*empty_line = true;
|
||||
@ -1653,7 +1719,7 @@ static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
_cleanup_(global_info_clear) struct global_info global_info = {};
|
||||
char **i;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
@ -1711,44 +1777,55 @@ static int status_global(sd_bus *bus, StatusMode mode, bool *empty_line) {
|
||||
|
||||
printf("%sGlobal%s\n", ansi_highlight(), ansi_normal());
|
||||
|
||||
printf(" LLMNR setting: %s\n"
|
||||
"MulticastDNS setting: %s\n"
|
||||
" DNSOverTLS setting: %s\n"
|
||||
" DNSSEC setting: %s\n"
|
||||
" DNSSEC supported: %s\n",
|
||||
strna(global_info.llmnr),
|
||||
strna(global_info.mdns),
|
||||
strna(global_info.dns_over_tls),
|
||||
strna(global_info.dnssec),
|
||||
yes_no(global_info.dnssec_supported));
|
||||
table = table_new("key", "value");
|
||||
if (!table)
|
||||
return log_oom();
|
||||
|
||||
if (global_info.current_dns)
|
||||
printf(" Current DNS Server: %s\n", global_info.current_dns);
|
||||
table_set_header(table, false);
|
||||
|
||||
STRV_FOREACH(i, global_info.dns) {
|
||||
printf(" %s %s\n",
|
||||
i == global_info.dns ? "DNS Servers:" : " ",
|
||||
*i);
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, "LLMNR setting:",
|
||||
TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_STRING, strna(global_info.llmnr),
|
||||
TABLE_STRING, "MulticastDNS setting:",
|
||||
TABLE_STRING, strna(global_info.mdns),
|
||||
TABLE_STRING, "DNSOverTLS setting:",
|
||||
TABLE_STRING, strna(global_info.dns_over_tls),
|
||||
TABLE_STRING, "DNSSEC setting:",
|
||||
TABLE_STRING, strna(global_info.dnssec),
|
||||
TABLE_STRING, "DNSSEC supported:",
|
||||
TABLE_BOOLEAN, global_info.dnssec_supported);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
|
||||
if (global_info.current_dns) {
|
||||
r = table_add_many(table,
|
||||
TABLE_STRING, "Current DNS Server:",
|
||||
TABLE_STRING, global_info.current_dns);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, global_info.fallback_dns) {
|
||||
printf("%s %s\n",
|
||||
i == global_info.fallback_dns ? "Fallback DNS Servers:" : " ",
|
||||
*i);
|
||||
}
|
||||
r = dump_list(table, "DNS Servers:", global_info.dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(i, global_info.domains) {
|
||||
printf(" %s %s\n",
|
||||
i == global_info.domains ? "DNS Domain:" : " ",
|
||||
*i);
|
||||
}
|
||||
r = dump_list(table, "Fallback DNS Servers:", global_info.fallback_dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dump_list(table, "DNS Domain:", global_info.domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
strv_sort(global_info.ntas);
|
||||
STRV_FOREACH(i, global_info.ntas) {
|
||||
printf(" %s %s\n",
|
||||
i == global_info.ntas ? "DNSSEC NTA:" : " ",
|
||||
*i);
|
||||
}
|
||||
r = dump_list(table, "DNSSEC NTA:", global_info.ntas);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = table_print(table, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to print table: %m");
|
||||
|
||||
*empty_line = true;
|
||||
|
||||
|
@ -80,6 +80,7 @@ typedef struct TableData {
|
||||
usec_t timespan;
|
||||
uint64_t size;
|
||||
char string[0];
|
||||
char **strv;
|
||||
int int_val;
|
||||
int8_t int8;
|
||||
int16_t int16;
|
||||
@ -207,6 +208,9 @@ static TableData *table_data_free(TableData *d) {
|
||||
free(d->formatted);
|
||||
free(d->url);
|
||||
|
||||
if (d->type == TABLE_STRV)
|
||||
strv_free(d->strv);
|
||||
|
||||
return mfree(d);
|
||||
}
|
||||
|
||||
@ -242,6 +246,9 @@ static size_t table_data_size(TableDataType type, const void *data) {
|
||||
case TABLE_PATH:
|
||||
return strlen(data) + 1;
|
||||
|
||||
case TABLE_STRV:
|
||||
return sizeof(char **);
|
||||
|
||||
case TABLE_BOOLEAN:
|
||||
return sizeof(bool);
|
||||
|
||||
@ -344,8 +351,8 @@ static TableData *table_data_new(
|
||||
unsigned align_percent,
|
||||
unsigned ellipsize_percent) {
|
||||
|
||||
_cleanup_free_ TableData *d = NULL;
|
||||
size_t data_size;
|
||||
TableData *d;
|
||||
|
||||
data_size = table_data_size(type, data);
|
||||
|
||||
@ -360,9 +367,15 @@ static TableData *table_data_new(
|
||||
d->weight = weight;
|
||||
d->align_percent = align_percent;
|
||||
d->ellipsize_percent = ellipsize_percent;
|
||||
memcpy_safe(d->data, data, data_size);
|
||||
|
||||
return d;
|
||||
if (type == TABLE_STRV) {
|
||||
d->strv = strv_copy(data);
|
||||
if (!d->strv)
|
||||
return NULL;
|
||||
} else
|
||||
memcpy_safe(d->data, data, data_size);
|
||||
|
||||
return TAKE_PTR(d);
|
||||
}
|
||||
|
||||
int table_add_cell_full(
|
||||
@ -778,6 +791,10 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
|
||||
data = va_arg(ap, const char *);
|
||||
break;
|
||||
|
||||
case TABLE_STRV:
|
||||
data = va_arg(ap, char * const *);
|
||||
break;
|
||||
|
||||
case TABLE_BOOLEAN:
|
||||
buffer.b = va_arg(ap, int);
|
||||
data = &buffer.b;
|
||||
@ -1055,6 +1072,9 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t
|
||||
case TABLE_PATH:
|
||||
return path_compare(a->string, b->string);
|
||||
|
||||
case TABLE_STRV:
|
||||
return strv_compare(a->strv, b->strv);
|
||||
|
||||
case TABLE_BOOLEAN:
|
||||
if (!a->boolean && b->boolean)
|
||||
return -1;
|
||||
@ -1185,6 +1205,17 @@ static const char *table_data_format(Table *t, TableData *d) {
|
||||
|
||||
return d->string;
|
||||
|
||||
case TABLE_STRV: {
|
||||
char *p;
|
||||
|
||||
p = strv_join(d->strv, "\n");
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
d->formatted = p;
|
||||
break;
|
||||
}
|
||||
|
||||
case TABLE_BOOLEAN:
|
||||
return yes_no(d->boolean);
|
||||
|
||||
@ -2054,6 +2085,9 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) {
|
||||
case TABLE_PATH:
|
||||
return json_variant_new_string(ret, d->string);
|
||||
|
||||
case TABLE_STRV:
|
||||
return json_variant_new_array_strv(ret, d->strv);
|
||||
|
||||
case TABLE_BOOLEAN:
|
||||
return json_variant_new_boolean(ret, d->boolean);
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
typedef enum TableDataType {
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING,
|
||||
TABLE_STRV,
|
||||
TABLE_PATH,
|
||||
TABLE_BOOLEAN,
|
||||
TABLE_TIMESTAMP,
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "format-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
|
||||
static void test_issue_9549(void) {
|
||||
@ -143,6 +144,118 @@ static void test_multiline(void) {
|
||||
formatted = mfree(formatted);
|
||||
}
|
||||
|
||||
static void test_strv(void) {
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
_cleanup_free_ char *formatted = NULL;
|
||||
|
||||
assert_se(table = table_new("foo", "bar"));
|
||||
|
||||
assert_se(table_set_align_percent(table, TABLE_HEADER_CELL(1), 100) >= 0);
|
||||
|
||||
assert_se(table_add_many(table,
|
||||
TABLE_STRV, STRV_MAKE("three", "different", "lines"),
|
||||
TABLE_STRV, STRV_MAKE("two", "lines")) >= 0);
|
||||
|
||||
table_set_cell_height_max(table, 1);
|
||||
assert_se(table_format(table, &formatted) >= 0);
|
||||
fputs(formatted, stdout);
|
||||
assert_se(streq(formatted,
|
||||
"FOO BAR\n"
|
||||
"three… two…\n"));
|
||||
formatted = mfree(formatted);
|
||||
|
||||
table_set_cell_height_max(table, 2);
|
||||
assert_se(table_format(table, &formatted) >= 0);
|
||||
fputs(formatted, stdout);
|
||||
assert_se(streq(formatted,
|
||||
"FOO BAR\n"
|
||||
"three two\n"
|
||||
"different… lines\n"));
|
||||
formatted = mfree(formatted);
|
||||
|
||||
table_set_cell_height_max(table, 3);
|
||||
assert_se(table_format(table, &formatted) >= 0);
|
||||
fputs(formatted, stdout);
|
||||
assert_se(streq(formatted,
|
||||
"FOO BAR\n"
|
||||
"three two\n"
|
||||
"different lines\n"
|
||||
"lines \n"));
|
||||
formatted = mfree(formatted);
|
||||
|
||||
table_set_cell_height_max(table, (size_t) -1);
|
||||
assert_se(table_format(table, &formatted) >= 0);
|
||||
fputs(formatted, stdout);
|
||||
assert_se(streq(formatted,
|
||||
"FOO BAR\n"
|
||||
"three two\n"
|
||||
"different lines\n"
|
||||
"lines \n"));
|
||||
formatted = mfree(formatted);
|
||||
|
||||
assert_se(table_add_many(table,
|
||||
TABLE_STRING, "short",
|
||||
TABLE_STRV, STRV_MAKE("a", "pair")) >= 0);
|
||||
|
||||
assert_se(table_add_many(table,
|
||||
TABLE_STRV, STRV_MAKE("short2"),
|
||||
TABLE_STRV, STRV_MAKE("a", "four", "line", "cell")) >= 0);
|
||||
|
||||
table_set_cell_height_max(table, 1);
|
||||
assert_se(table_format(table, &formatted) >= 0);
|
||||
fputs(formatted, stdout);
|
||||
assert_se(streq(formatted,
|
||||
"FOO BAR\n"
|
||||
"three… two…\n"
|
||||
"short a…\n"
|
||||
"short2 a…\n"));
|
||||
formatted = mfree(formatted);
|
||||
|
||||
table_set_cell_height_max(table, 2);
|
||||
assert_se(table_format(table, &formatted) >= 0);
|
||||
fputs(formatted, stdout);
|
||||
assert_se(streq(formatted,
|
||||
"FOO BAR\n"
|
||||
"three two\n"
|
||||
"different… lines\n"
|
||||
"short a\n"
|
||||
" pair\n"
|
||||
"short2 a\n"
|
||||
" four…\n"));
|
||||
formatted = mfree(formatted);
|
||||
|
||||
table_set_cell_height_max(table, 3);
|
||||
assert_se(table_format(table, &formatted) >= 0);
|
||||
fputs(formatted, stdout);
|
||||
assert_se(streq(formatted,
|
||||
"FOO BAR\n"
|
||||
"three two\n"
|
||||
"different lines\n"
|
||||
"lines \n"
|
||||
"short a\n"
|
||||
" pair\n"
|
||||
"short2 a\n"
|
||||
" four\n"
|
||||
" line…\n"));
|
||||
formatted = mfree(formatted);
|
||||
|
||||
table_set_cell_height_max(table, (size_t) -1);
|
||||
assert_se(table_format(table, &formatted) >= 0);
|
||||
fputs(formatted, stdout);
|
||||
assert_se(streq(formatted,
|
||||
"FOO BAR\n"
|
||||
"three two\n"
|
||||
"different lines\n"
|
||||
"lines \n"
|
||||
"short a\n"
|
||||
" pair\n"
|
||||
"short2 a\n"
|
||||
" four\n"
|
||||
" line\n"
|
||||
" cell\n"));
|
||||
formatted = mfree(formatted);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
_cleanup_(table_unrefp) Table *t = NULL;
|
||||
@ -285,6 +398,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
test_issue_9549();
|
||||
test_multiline();
|
||||
test_strv();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -711,27 +711,33 @@ static void test_strv_push(void) {
|
||||
assert_se(streq_ptr(a[3], NULL));
|
||||
}
|
||||
|
||||
static void test_strv_equal(void) {
|
||||
static void test_strv_compare(void) {
|
||||
_cleanup_strv_free_ char **a = NULL;
|
||||
_cleanup_strv_free_ char **b = NULL;
|
||||
_cleanup_strv_free_ char **c = NULL;
|
||||
_cleanup_strv_free_ char **d = NULL;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
a = strv_new("one", "two", "three");
|
||||
assert_se(a);
|
||||
b = strv_new("one", "two", "three");
|
||||
assert_se(a);
|
||||
assert_se(b);
|
||||
c = strv_new("one", "two", "three", "four");
|
||||
assert_se(a);
|
||||
assert_se(c);
|
||||
d = strv_new(NULL);
|
||||
assert_se(d);
|
||||
|
||||
assert_se(strv_equal(a, a));
|
||||
assert_se(strv_equal(a, b));
|
||||
assert_se(strv_equal(NULL, NULL));
|
||||
assert_se(strv_compare(a, a) == 0);
|
||||
assert_se(strv_compare(a, b) == 0);
|
||||
assert_se(strv_compare(d, d) == 0);
|
||||
assert_se(strv_compare(d, NULL) == 0);
|
||||
assert_se(strv_compare(NULL, NULL) == 0);
|
||||
|
||||
assert_se(!strv_equal(a, c));
|
||||
assert_se(!strv_equal(b, c));
|
||||
assert_se(!strv_equal(b, NULL));
|
||||
assert_se(strv_compare(a, c) < 0);
|
||||
assert_se(strv_compare(b, c) < 0);
|
||||
assert_se(strv_compare(b, d) == 1);
|
||||
assert_se(strv_compare(b, NULL) == 1);
|
||||
}
|
||||
|
||||
static void test_strv_is_uniq(void) {
|
||||
@ -990,7 +996,7 @@ int main(int argc, char *argv[]) {
|
||||
test_strv_insert();
|
||||
test_strv_push_prepend();
|
||||
test_strv_push();
|
||||
test_strv_equal();
|
||||
test_strv_compare();
|
||||
test_strv_is_uniq();
|
||||
test_strv_reverse();
|
||||
test_strv_shell_escape();
|
||||
|
Loading…
x
Reference in New Issue
Block a user