]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/analyze/analyze.c
analyze: deprecate the commands moved to systemctl
[thirdparty/systemd.git] / src / analyze / analyze.c
index 45e41fedee2b9dc33ee06e90a7f8ee1ea286c863..991e61de7e7ff99a90fbc4bd60205379717ed85f 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <getopt.h>
 #include <inttypes.h>
-#include <locale.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -85,6 +84,7 @@ static bool arg_man = true;
 static bool arg_generators = false;
 static const char *arg_root = NULL;
 static unsigned arg_iterations = 1;
+static usec_t arg_base_time = USEC_INFINITY;
 
 STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep);
 STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep);
@@ -1546,6 +1546,53 @@ static int get_or_set_log_target(int argc, char *argv[], void *userdata) {
         return (argc == 1) ? get_log_target(argc, argv, userdata) : set_log_target(argc, argv, userdata);
 }
 
+static bool strv_fnmatch_strv_or_empty(char* const* patterns, char **strv, int flags) {
+        char **s;
+        STRV_FOREACH(s, strv)
+                if (strv_fnmatch_or_empty(patterns, *s, flags))
+                        return true;
+
+        return false;
+}
+
+static int do_unit_files(int argc, char *argv[], void *userdata) {
+        _cleanup_(lookup_paths_free) LookupPaths lp = {};
+        _cleanup_hashmap_free_ Hashmap *unit_ids = NULL;
+        _cleanup_hashmap_free_ Hashmap *unit_names = NULL;
+        char **patterns = strv_skip(argv, 1);
+        Iterator i;
+        const char *k, *dst;
+        char **v;
+        int r;
+
+        r = lookup_paths_init(&lp, arg_scope, 0, NULL);
+        if (r < 0)
+                return log_error_errno(r, "lookup_paths_init() failed: %m");
+
+        r = unit_file_build_name_map(&lp, NULL, &unit_ids, &unit_names, NULL);
+        if (r < 0)
+                return log_error_errno(r, "unit_file_build_name_map() failed: %m");
+
+        HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) {
+                if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) &&
+                    !strv_fnmatch_or_empty(patterns, dst, FNM_NOESCAPE))
+                        continue;
+
+                printf("ids: %s → %s\n", k, dst);
+        }
+
+        HASHMAP_FOREACH_KEY(v, k, unit_names, i) {
+                if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) &&
+                    !strv_fnmatch_strv_or_empty(patterns, v, FNM_NOESCAPE))
+                        continue;
+
+                _cleanup_free_ char *j = strv_join(v, ", ");
+                printf("aliases: %s ← %s\n", k, j);
+        }
+
+        return 0;
+}
+
 static int dump_unit_paths(int argc, char *argv[], void *userdata) {
         _cleanup_(lookup_paths_free) LookupPaths paths = {};
         int r;
@@ -1561,6 +1608,52 @@ static int dump_unit_paths(int argc, char *argv[], void *userdata) {
         return 0;
 }
 
+static int dump_exit_status(int argc, char *argv[], void *userdata) {
+        _cleanup_(table_unrefp) Table *table = NULL;
+        int r;
+
+        table = table_new("name", "status", "class");
+        if (!table)
+                return log_oom();
+
+        r = table_set_align_percent(table, table_get_cell(table, 0, 1), 100);
+        if (r < 0)
+                return log_error_errno(r, "Failed to right-align status: %m");
+
+        if (strv_isempty(strv_skip(argv, 1)))
+                for (size_t i = 0; i < ELEMENTSOF(exit_status_mappings); i++) {
+                        if (!exit_status_mappings[i].name)
+                                continue;
+
+                        r = table_add_many(table,
+                                           TABLE_STRING, exit_status_mappings[i].name,
+                                           TABLE_INT, (int) i,
+                                           TABLE_STRING, exit_status_class(i));
+                        if (r < 0)
+                                return r;
+                }
+        else
+                for (int i = 1; i < argc; i++) {
+                        int status;
+
+                        status = exit_status_from_string(argv[i]);
+                        if (status < 0)
+                                return log_error_errno(r, "Invalid exit status \"%s\": %m", argv[i]);
+
+                        assert(status >= 0 && (size_t) status < ELEMENTSOF(exit_status_mappings));
+                        r = table_add_many(table,
+                                           TABLE_STRING, exit_status_mappings[status].name ?: "-",
+                                           TABLE_INT, status,
+                                           TABLE_STRING, exit_status_class(status) ?: "-");
+                        if (r < 0)
+                                return r;
+                }
+
+        (void) pager_open(arg_pager_flags);
+
+        return table_print(table, NULL);
+}
+
 #if HAVE_SECCOMP
 
 static int load_kernel_syscalls(Set **ret) {
@@ -1620,7 +1713,7 @@ static void kernel_syscalls_remove(Set *s, const SyscallFilterSet *set) {
                 if (syscall[0] == '@')
                         continue;
 
-                (void) set_remove(s, syscall);
+                free(set_remove(s, syscall));
         }
 }
 
@@ -1638,48 +1731,6 @@ static void dump_syscall_filter(const SyscallFilterSet *set) {
                 printf("    %s%s%s\n", syscall[0] == '@' ? ansi_underline() : "", syscall, ansi_normal());
 }
 
-static int dump_exit_codes(int argc, char *argv[], void *userdata) {
-        _cleanup_(table_unrefp) Table *table = NULL;
-        int r;
-
-        table = table_new("name", "code", "class");
-        if (!table)
-                return log_oom();
-
-        if (strv_isempty(strv_skip(argv, 1)))
-                for (size_t i = 0; i < ELEMENTSOF(exit_status_mappings); i++) {
-                        if (!exit_status_mappings[i].name)
-                                continue;
-
-                        r = table_add_many(table,
-                                           TABLE_STRING, exit_status_mappings[i].name,
-                                           TABLE_UINT, i,
-                                           TABLE_STRING, exit_status_class(i));
-                        if (r < 0)
-                                return r;
-                }
-        else
-                for (int i = 1; i < argc; i++) {
-                        int code;
-
-                        code = exit_status_from_string(argv[i]);
-                        if (code < 0)
-                                return log_error_errno(r, "Invalid exit code \"%s\": %m", argv[i]);
-
-                        assert(code >= 0 && (size_t) code < ELEMENTSOF(exit_status_mappings));
-                        r = table_add_many(table,
-                                           TABLE_STRING, exit_status_mappings[code].name ?: "-",
-                                           TABLE_UINT, code,
-                                           TABLE_STRING, exit_status_class(code) ?: "-");
-                        if (r < 0)
-                                return r;
-                }
-
-        (void) pager_open(arg_pager_flags);
-
-        return table_print(table, NULL);
-}
-
 static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
         bool first = true;
 
@@ -1706,15 +1757,21 @@ static int dump_syscall_filters(int argc, char *argv[], void *userdata) {
                         fflush(stdout);
                         log_notice_errno(k, "# Not showing unlisted system calls, couldn't retrieve kernel system call list: %m");
                 } else if (!set_isempty(kernel)) {
-                        const char *syscall;
-                        Iterator j;
+                        _cleanup_free_ char **l = NULL;
+                        char **syscall;
 
                         printf("\n"
                                "# %sUnlisted System Calls%s (supported by the local kernel, but not included in any of the groups listed above):\n",
                                ansi_highlight(), ansi_normal());
 
-                        SET_FOREACH(syscall, kernel, j)
-                                printf("#   %s\n", syscall);
+                        l = set_get_strv(kernel);
+                        if (!l)
+                                return log_oom();
+
+                        strv_sort(l);
+
+                        STRV_FOREACH(syscall, l)
+                                printf("#   %s\n", *syscall);
                 }
         } else {
                 char **name;
@@ -2080,7 +2137,10 @@ static int test_calendar(int argc, char *argv[], void *userdata) {
         char **p;
         usec_t n;
 
-        n = now(CLOCK_REALTIME); /* We want to use the same "base" for all expressions */
+        if (arg_base_time != USEC_INFINITY)
+                n = arg_base_time;
+        else
+                n = now(CLOCK_REALTIME); /* We want to use the same "base" for all expressions */
 
         STRV_FOREACH(p, strv_skip(argv, 1)) {
                 r = test_calendar_one(n, *p);
@@ -2106,8 +2166,8 @@ static int service_watchdogs(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return log_error_errno(r, "Failed to create bus connection: %m");
 
-        /* get ServiceWatchdogs */
         if (argc == 1) {
+                /* get ServiceWatchdogs */
                 r = sd_bus_get_property_trivial(
                                 bus,
                                 "org.freedesktop.systemd1",
@@ -2122,28 +2182,25 @@ static int service_watchdogs(int argc, char *argv[], void *userdata) {
 
                 printf("%s\n", yes_no(!!b));
 
-                return 0;
-        }
+        } else {
+                /* set ServiceWatchdogs */
+                b = parse_boolean(argv[1]);
+                if (b < 0)
+                        return log_error_errno(b, "Failed to parse service-watchdogs argument: %m");
 
-        /* set ServiceWatchdogs */
-        b = parse_boolean(argv[1]);
-        if (b < 0) {
-                log_error("Failed to parse service-watchdogs argument.");
-                return -EINVAL;
+                r = sd_bus_set_property(
+                                bus,
+                                "org.freedesktop.systemd1",
+                                "/org/freedesktop/systemd1",
+                                "org.freedesktop.systemd1.Manager",
+                                "ServiceWatchdogs",
+                                &error,
+                                "b",
+                                b);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r));
         }
 
-        r = sd_bus_set_property(
-                        bus,
-                        "org.freedesktop.systemd1",
-                        "/org/freedesktop/systemd1",
-                        "org.freedesktop.systemd1.Manager",
-                        "ServiceWatchdogs",
-                        &error,
-                        "b",
-                        b);
-        if (r < 0)
-                return log_error_errno(r, "Failed to set service-watchdog state: %s", bus_error_message(&error, r));
-
         return 0;
 }
 
@@ -2183,8 +2240,27 @@ static int help(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return log_oom();
 
-        printf("%s [OPTIONS...] {COMMAND} ...\n\n"
-               "Profile systemd, show unit dependencies, check unit files.\n\n"
+        printf("%s [OPTIONS...] COMMAND ...\n\n"
+               "%sProfile systemd, show unit dependencies, check unit files.%s\n"
+               "\nCommands:\n"
+               "  [time]                   Print time required to boot the machine\n"
+               "  blame                    Print list of running units ordered by time to init\n"
+               "  critical-chain [UNIT...] Print a tree of the time critical chain of units\n"
+               "  plot                     Output SVG graphic showing service initialization\n"
+               "  dot [UNIT...]            Output dependency graph in %s format\n"
+               "  dump                     Output state serialization of service manager\n"
+               "  cat-config               Show configuration file and drop-ins\n"
+               "  unit-files               List files and symlinks for units\n"
+               "  unit-paths               List load directories for units\n"
+               "  exit-status [STATUS...]  List exit status definitions\n"
+               "  syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
+               "  condition CONDITION...   Evaluate conditions and asserts\n"
+               "  verify FILE...           Check unit files for correctness\n"
+               "  calendar SPEC...         Validate repetitive calendar time events\n"
+               "  timestamp TIMESTAMP...   Validate a timestamp\n"
+               "  timespan SPAN...         Validate a time span\n"
+               "  security [UNIT...]       Analyze security of unit\n"
+               "\nOptions:\n"
                "  -h --help                Show this help\n"
                "     --version             Show package version\n"
                "     --no-pager            Do not pipe output into a pager\n"
@@ -2202,28 +2278,11 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --man[=BOOL]          Do [not] check for existence of man pages\n"
                "     --generators[=BOOL]   Do [not] run unit generators (requires privileges)\n"
                "     --iterations=N        Show the specified number of iterations\n"
-               "\nCommands:\n"
-               "  time                     Print time spent in the kernel\n"
-               "  blame                    Print list of running units ordered by time to init\n"
-               "  critical-chain [UNIT...] Print a tree of the time critical chain of units\n"
-               "  plot                     Output SVG graphic showing service initialization\n"
-               "  dot [UNIT...]            Output dependency graph in %s format\n"
-               "  log-level [LEVEL]        Get/set logging threshold for manager\n"
-               "  log-target [TARGET]      Get/set logging target for manager\n"
-               "  dump                     Output state serialization of service manager\n"
-               "  cat-config               Show configuration file and drop-ins\n"
-               "  unit-paths               List load directories for units\n"
-               "  exit-codes               List exit code definitions\n"
-               "  syscall-filter [NAME...] Print list of syscalls in seccomp filter\n"
-               "  condition CONDITION...   Evaluate conditions and asserts\n"
-               "  verify FILE...           Check unit files for correctness\n"
-               "  service-watchdogs [BOOL] Get/set service watchdog state\n"
-               "  calendar SPEC...         Validate repetitive calendar time events\n"
-               "  timestamp TIMESTAMP...   Validate a timestamp\n"
-               "  timespan SPAN...         Validate a time span\n"
-               "  security [UNIT...]       Analyze security of unit\n"
+               "     --base-time=TIMESTAMP Calculate calendar times relative to specified time\n"
                "\nSee the %s for details.\n"
                , program_invocation_short_name
+               , ansi_highlight()
+               , ansi_normal()
                , dot_link
                , link
         );
@@ -2250,6 +2309,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_MAN,
                 ARG_GENERATORS,
                 ARG_ITERATIONS,
+                ARG_BASE_TIME,
         };
 
         static const struct option options[] = {
@@ -2270,6 +2330,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "host",         required_argument, NULL, 'H'                  },
                 { "machine",      required_argument, NULL, 'M'                  },
                 { "iterations",   required_argument, NULL, ARG_ITERATIONS       },
+                { "base-time",    required_argument, NULL, ARG_BASE_TIME        },
                 {}
         };
 
@@ -2376,6 +2437,13 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_BASE_TIME:
+                        r = parse_timestamp(optarg, &arg_base_time);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to parse --base-time= parameter: %s", optarg);
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -2408,24 +2476,25 @@ static int run(int argc, char *argv[]) {
                 { "critical-chain",    VERB_ANY, VERB_ANY, 0,            analyze_critical_chain },
                 { "plot",              VERB_ANY, 1,        0,            analyze_plot           },
                 { "dot",               VERB_ANY, VERB_ANY, 0,            dot                    },
+                /* The following seven verbs are deprecated */
                 { "log-level",         VERB_ANY, 2,        0,            get_or_set_log_level   },
                 { "log-target",        VERB_ANY, 2,        0,            get_or_set_log_target  },
-                /* The following four verbs are deprecated aliases */
                 { "set-log-level",     2,        2,        0,            set_log_level          },
                 { "get-log-level",     VERB_ANY, 1,        0,            get_log_level          },
                 { "set-log-target",    2,        2,        0,            set_log_target         },
                 { "get-log-target",    VERB_ANY, 1,        0,            get_log_target         },
+                { "service-watchdogs", VERB_ANY, 2,        0,            service_watchdogs      },
                 { "dump",              VERB_ANY, 1,        0,            dump                   },
                 { "cat-config",        2,        VERB_ANY, 0,            cat_config             },
+                { "unit-files",        VERB_ANY, VERB_ANY, 0,            do_unit_files          },
                 { "unit-paths",        1,        1,        0,            dump_unit_paths        },
-                { "exit-codes",        VERB_ANY, VERB_ANY, 0,            dump_exit_codes        },
+                { "exit-status",       VERB_ANY, VERB_ANY, 0,            dump_exit_status       },
                 { "syscall-filter",    VERB_ANY, VERB_ANY, 0,            dump_syscall_filters   },
                 { "condition",         2,        VERB_ANY, 0,            do_condition           },
                 { "verify",            2,        VERB_ANY, 0,            do_verify              },
                 { "calendar",          2,        VERB_ANY, 0,            test_calendar          },
                 { "timestamp",         2,        VERB_ANY, 0,            test_timestamp         },
                 { "timespan",          2,        VERB_ANY, 0,            dump_timespan          },
-                { "service-watchdogs", VERB_ANY, 2,        0,            service_watchdogs      },
                 { "security",          VERB_ANY, VERB_ANY, 0,            do_security            },
                 {}
         };