diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml
index acbe54a140..2175c48fa2 100644
--- a/man/systemd-detect-virt.xml
+++ b/man/systemd-detect-virt.xml
@@ -230,6 +230,12 @@
technology identifier.
+
+
+
+ Output all currently known and detectable container and VM environments.
+
+
diff --git a/src/basic/string-table.h b/src/basic/string-table.h
index a39206fb94..92825c4d79 100644
--- a/src/basic/string-table.h
+++ b/src/basic/string-table.h
@@ -102,3 +102,18 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static)
+
+#define DUMP_STRING_TABLE(name,type,max) \
+ do { \
+ type _k; \
+ flockfile(stdout); \
+ for (_k = 0; _k < (max); _k++) { \
+ const char *_t; \
+ _t = name##_to_string(_k); \
+ if (!_t) \
+ continue; \
+ fputs_unlocked(_t, stdout); \
+ fputc_unlocked('\n', stdout); \
+ } \
+ funlockfile(stdout); \
+ } while(false)
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index e255206228..2933a449db 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -217,7 +217,7 @@ static int parse_argv(int argc, char *argv[]) {
case 'o':
if (arg_output) {
- log_error("cannot set output more than once");
+ log_error("Cannot set output more than once.");
return -EINVAL;
}
@@ -241,7 +241,7 @@ static int parse_argv(int argc, char *argv[]) {
case 'F':
if (arg_field) {
- log_error("cannot use --field/-F more than once");
+ log_error("Cannot use --field/-F more than once.");
return -EINVAL;
}
arg_field = optarg;
diff --git a/src/detect-virt/detect-virt.c b/src/detect-virt/detect-virt.c
index 3fbcdf5556..197e526b05 100644
--- a/src/detect-virt/detect-virt.c
+++ b/src/detect-virt/detect-virt.c
@@ -10,6 +10,7 @@
#include
#include
+#include "string-table.h"
#include "util.h"
#include "virt.h"
@@ -32,6 +33,7 @@ static void help(void) {
" -r --chroot Detect whether we are run in a chroot() environment\n"
" --private-users Only detect whether we are running in a user namespace\n"
" -q --quiet Don't output anything, just set return value\n"
+ " --list List all known and detectable types of virtualization\n"
, program_invocation_short_name);
}
@@ -40,6 +42,7 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_PRIVATE_USERS,
+ ARG_LIST,
};
static const struct option options[] = {
@@ -50,6 +53,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "chroot", no_argument, NULL, 'r' },
{ "private-users", no_argument, NULL, ARG_PRIVATE_USERS },
{ "quiet", no_argument, NULL, 'q' },
+ { "list", no_argument, NULL, ARG_LIST },
{}
};
@@ -89,6 +93,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_mode = ONLY_CHROOT;
break;
+ case ARG_LIST:
+ DUMP_STRING_TABLE(virtualization, int, _VIRTUALIZATION_MAX);
+ return 0;
+
case '?':
return -EINVAL;
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index aa59489cff..92cf2eb122 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -58,11 +58,12 @@
#include "rlimit-util.h"
#include "set.h"
#include "sigbus.h"
+#include "string-table.h"
#include "strv.h"
#include "syslog-util.h"
#include "terminal-util.h"
-#include "udev.h"
#include "udev-util.h"
+#include "udev.h"
#include "unit-name.h"
#include "user-util.h"
@@ -509,6 +510,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output format '%s'.", optarg);
diff --git a/src/login/loginctl.c b/src/login/loginctl.c
index f73d2f0a75..8cea282988 100644
--- a/src/login/loginctl.c
+++ b/src/login/loginctl.c
@@ -29,6 +29,7 @@
#include "sigbus.h"
#include "signal-util.h"
#include "spawn-polkit-agent.h"
+#include "string-table.h"
#include "strv.h"
#include "sysfs-show.h"
#include "terminal-util.h"
@@ -1441,6 +1442,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
@@ -1465,6 +1471,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 's':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c
index 54860bd1a5..eb68eb192b 100644
--- a/src/machine/machinectl.c
+++ b/src/machine/machinectl.c
@@ -46,6 +46,7 @@
#include "signal-util.h"
#include "spawn-polkit-agent.h"
#include "stdio-util.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "unit-name.h"
@@ -2859,6 +2860,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
@@ -2879,6 +2885,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 's':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
@@ -2913,6 +2924,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_VERIFY:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(import_verify, ImportVerify, _IMPORT_VERIFY_MAX);
+ return 0;
+ }
+
arg_verify = import_verify_from_string(optarg);
if (arg_verify < 0) {
log_error("Failed to parse --verify= setting: %s", optarg);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index b5d9de8da0..762747686a 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -90,6 +90,7 @@
#include "socket-util.h"
#include "stat-util.h"
#include "stdio-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
@@ -916,7 +917,10 @@ static int parse_argv(int argc, char *argv[]) {
if (!optarg)
arg_volatile_mode = VOLATILE_YES;
- else {
+ else if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(volatile_mode, VolatileMode, _VOLATILE_MODE_MAX);
+ return 0;
+ } else {
VolatileMode m;
m = volatile_mode_from_string(optarg);
@@ -1024,6 +1028,11 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_KILL_SIGNAL:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
arg_kill_signal = signal_from_string(optarg);
if (arg_kill_signal < 0) {
log_error("Cannot parse signal: %s", optarg);
@@ -1153,6 +1162,11 @@ static int parse_argv(int argc, char *argv[]) {
char *name;
int rl;
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(rlimit, int, _RLIMIT_MAX);
+ return 0;
+ }
+
eq = strchr(optarg, '=');
if (!eq) {
log_error("--rlimit= expects an '=' assignment.");
diff --git a/src/resolve/resolvectl.c b/src/resolve/resolvectl.c
index 10665a7e04..26b3a811ad 100644
--- a/src/resolve/resolvectl.c
+++ b/src/resolve/resolvectl.c
@@ -27,6 +27,7 @@
#include "resolvectl.h"
#include "resolved-def.h"
#include "resolved-dns-packet.h"
+#include "string-table.h"
#include "strv.h"
#include "terminal-util.h"
#include "verbs.h"
@@ -2232,29 +2233,17 @@ static void help_protocol_types(void) {
}
static void help_dns_types(void) {
- const char *t;
- int i;
-
if (arg_legend)
puts("Known DNS RR types:");
- for (i = 0; i < _DNS_TYPE_MAX; i++) {
- t = dns_type_to_string(i);
- if (t)
- puts(t);
- }
+
+ DUMP_STRING_TABLE(dns_type, int, _DNS_TYPE_MAX);
}
static void help_dns_classes(void) {
- const char *t;
- int i;
-
if (arg_legend)
puts("Known DNS RR classes:");
- for (i = 0; i < _DNS_CLASS_MAX; i++) {
- t = dns_class_to_string(i);
- if (t)
- puts(t);
- }
+
+ DUMP_STRING_TABLE(dns_class, int, _DNS_CLASS_MAX);
}
static void compat_help(void) {
diff --git a/src/shared/volatile-util.c b/src/shared/volatile-util.c
index d70d5856d3..a20f0b43f4 100644
--- a/src/shared/volatile-util.c
+++ b/src/shared/volatile-util.c
@@ -11,27 +11,10 @@
#include "macro.h"
#include "parse-util.h"
#include "proc-cmdline.h"
+#include "string-table.h"
#include "string-util.h"
#include "volatile-util.h"
-VolatileMode volatile_mode_from_string(const char *s) {
- int b;
-
- if (isempty(s))
- return _VOLATILE_MODE_INVALID;
-
- b = parse_boolean(s);
- if (b > 0)
- return VOLATILE_YES;
- if (b == 0)
- return VOLATILE_NO;
-
- if (streq(s, "state"))
- return VOLATILE_STATE;
-
- return _VOLATILE_MODE_INVALID;
-}
-
int query_volatile_mode(VolatileMode *ret) {
_cleanup_free_ char *mode = NULL;
VolatileMode m = VOLATILE_NO;
@@ -56,3 +39,11 @@ finish:
*ret = m;
return r;
}
+
+static const char* const volatile_mode_table[_VOLATILE_MODE_MAX] = {
+ [VOLATILE_NO] = "no",
+ [VOLATILE_YES] = "yes",
+ [VOLATILE_STATE] = "state",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(volatile_mode, VolatileMode, VOLATILE_YES);
diff --git a/src/shared/volatile-util.h b/src/shared/volatile-util.h
index b275bff176..4312c97a99 100644
--- a/src/shared/volatile-util.h
+++ b/src/shared/volatile-util.h
@@ -16,5 +16,6 @@ typedef enum VolatileMode {
} VolatileMode;
VolatileMode volatile_mode_from_string(const char *s);
+const char* volatile_mode_to_string(VolatileMode m);
int query_volatile_mode(VolatileMode *ret);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index a8ca47b3ad..fcc6c08492 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -7199,81 +7199,64 @@ static void runlevel_help(void) {
}
static void help_types(void) {
- int i;
-
if (!arg_no_legend)
puts("Available unit types:");
- for (i = 0; i < _UNIT_TYPE_MAX; i++)
- puts(unit_type_to_string(i));
+
+ DUMP_STRING_TABLE(unit_type, UnitType, _UNIT_TYPE_MAX);
}
static void help_states(void) {
- int i;
-
if (!arg_no_legend)
puts("Available unit load states:");
- for (i = 0; i < _UNIT_LOAD_STATE_MAX; i++)
- puts(unit_load_state_to_string(i));
+ DUMP_STRING_TABLE(unit_load_state, UnitLoadState, _UNIT_LOAD_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable unit active states:");
- for (i = 0; i < _UNIT_ACTIVE_STATE_MAX; i++)
- puts(unit_active_state_to_string(i));
+ DUMP_STRING_TABLE(unit_active_state, UnitActiveState, _UNIT_ACTIVE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable automount unit substates:");
- for (i = 0; i < _AUTOMOUNT_STATE_MAX; i++)
- puts(automount_state_to_string(i));
+ DUMP_STRING_TABLE(automount_state, AutomountState, _AUTOMOUNT_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable device unit substates:");
- for (i = 0; i < _DEVICE_STATE_MAX; i++)
- puts(device_state_to_string(i));
+ DUMP_STRING_TABLE(device_state, DeviceState, _DEVICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable mount unit substates:");
- for (i = 0; i < _MOUNT_STATE_MAX; i++)
- puts(mount_state_to_string(i));
+ DUMP_STRING_TABLE(mount_state, MountState, _MOUNT_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable path unit substates:");
- for (i = 0; i < _PATH_STATE_MAX; i++)
- puts(path_state_to_string(i));
+ DUMP_STRING_TABLE(path_state, PathState, _PATH_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable scope unit substates:");
- for (i = 0; i < _SCOPE_STATE_MAX; i++)
- puts(scope_state_to_string(i));
+ DUMP_STRING_TABLE(scope_state, ScopeState, _SCOPE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable service unit substates:");
- for (i = 0; i < _SERVICE_STATE_MAX; i++)
- puts(service_state_to_string(i));
+ DUMP_STRING_TABLE(service_state, ServiceState, _SERVICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable slice unit substates:");
- for (i = 0; i < _SLICE_STATE_MAX; i++)
- puts(slice_state_to_string(i));
+ DUMP_STRING_TABLE(slice_state, SliceState, _SLICE_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable socket unit substates:");
- for (i = 0; i < _SOCKET_STATE_MAX; i++)
- puts(socket_state_to_string(i));
+ DUMP_STRING_TABLE(socket_state, SocketState, _SOCKET_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable swap unit substates:");
- for (i = 0; i < _SWAP_STATE_MAX; i++)
- puts(swap_state_to_string(i));
+ DUMP_STRING_TABLE(swap_state, SwapState, _SWAP_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable target unit substates:");
- for (i = 0; i < _TARGET_STATE_MAX; i++)
- puts(target_state_to_string(i));
+ DUMP_STRING_TABLE(target_state, TargetState, _TARGET_STATE_MAX);
if (!arg_no_legend)
puts("\nAvailable timer unit substates:");
- for (i = 0; i < _TIMER_STATE_MAX; i++)
- puts(timer_state_to_string(i));
+ DUMP_STRING_TABLE(timer_state, TimerState, _TIMER_STATE_MAX);
}
static int systemctl_parse_argv(int argc, char *argv[]) {
@@ -7569,6 +7552,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case 's':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(signal, int, _NSIG);
+ return 0;
+ }
+
arg_signal = signal_from_string(optarg);
if (arg_signal < 0) {
log_error("Failed to parse signal string %s.", optarg);
@@ -7602,6 +7590,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case 'o':
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(output_mode, OutputMode, _OUTPUT_MODE_MAX);
+ return 0;
+ }
+
arg_output = output_mode_from_string(optarg);
if (arg_output < 0) {
log_error("Unknown output '%s'.", optarg);
@@ -7659,6 +7652,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case ARG_PRESET_MODE:
+ if (streq(optarg, "help")) {
+ DUMP_STRING_TABLE(unit_file_preset_mode, UnitFilePresetMode, _UNIT_FILE_PRESET_MAX);
+ return 0;
+ }
arg_preset_mode = unit_file_preset_mode_from_string(optarg);
if (arg_preset_mode < 0) {