]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/analyze/analyze.c
Merge pull request #13207 from keszybz/symbolic-exit-code-names
[thirdparty/systemd.git] / src / analyze / analyze.c
index b7545c08e291ed374f8d9c90afcadf6b34369b8f..45e41fedee2b9dc33ee06e90a7f8ee1ea286c863 100644 (file)
@@ -24,6 +24,7 @@
 #include "conf-files.h"
 #include "copy.h"
 #include "def.h"
+#include "exit-status.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-table.h"
@@ -1080,7 +1081,7 @@ static int analyze_blame(int argc, char *argv[], void *userdata) {
         if (n <= 0)
                 return n;
 
-        table = table_new("TIME", "UNIT");
+        table = table_new("time", "unit");
         if (!table)
                 return log_oom();
 
@@ -1637,6 +1638,48 @@ 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;
 
@@ -1733,7 +1776,7 @@ static int dump_timespan(int argc, char *argv[], void *userdata) {
                         return r;
                 }
 
-                table = table_new("NAME", "VALUE");
+                table = table_new("name", "value");
                 if (!table)
                         return log_oom();
 
@@ -1805,7 +1848,7 @@ static int test_timestamp_one(const char *p) {
                 return r;
         }
 
-        table = table_new("NAME", "VALUE");
+        table = table_new("name", "value");
         if (!table)
                 return log_oom();
 
@@ -1859,11 +1902,13 @@ static int test_timestamp_one(const char *p) {
         if (r < 0)
                 return r;
 
-        r = table_add_cell_stringf(table, &cell, "@%"PRI_USEC"%s%0*"PRI_USEC"",
-                                   usec / USEC_PER_SEC,
-                                   usec % USEC_PER_SEC ? "." : "",
-                                   usec % USEC_PER_SEC ? 6 : 0,
-                                   usec % USEC_PER_SEC);
+        if (usec % USEC_PER_SEC == 0)
+                r = table_add_cell_stringf(table, &cell, "@%"PRI_USEC,
+                                           usec / USEC_PER_SEC);
+        else
+                r = table_add_cell_stringf(table, &cell, "@%"PRI_USEC".%06"PRI_USEC"",
+                                           usec / USEC_PER_SEC,
+                                           usec % USEC_PER_SEC);
         if (r < 0)
                 return r;
 
@@ -1912,7 +1957,7 @@ static int test_calendar_one(usec_t n, const char *p) {
         if (r < 0)
                 return log_error_errno(r, "Failed to format calendar specification '%s': %m", p);
 
-        table = table_new("NAME", "VALUE");
+        table = table_new("name", "value");
         if (!table)
                 return log_oom();
 
@@ -2124,7 +2169,7 @@ static int do_security(int argc, char *argv[], void *userdata) {
 }
 
 static int help(int argc, char *argv[], void *userdata) {
-        _cleanup_free_ char *link = NULL;
+        _cleanup_free_ char *link = NULL, *dot_link = NULL;
         int r;
 
         (void) pager_open(arg_pager_flags);
@@ -2133,6 +2178,11 @@ static int help(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return log_oom();
 
+        /* Not using terminal_urlify_man() for this, since we don't want the "man page" text suffix in this case. */
+        r = terminal_urlify("man:dot(1)", "dot(1)", &dot_link);
+        if (r < 0)
+                return log_oom();
+
         printf("%s [OPTIONS...] {COMMAND} ...\n\n"
                "Profile systemd, show unit dependencies, check unit files.\n\n"
                "  -h --help                Show this help\n"
@@ -2157,12 +2207,13 @@ static int help(int argc, char *argv[], void *userdata) {
                "  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 man:dot(1) format\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"
@@ -2173,6 +2224,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "  security [UNIT...]       Analyze security of unit\n"
                "\nSee the %s for details.\n"
                , program_invocation_short_name
+               , dot_link
                , link
         );
 
@@ -2366,6 +2418,7 @@ static int run(int argc, char *argv[]) {
                 { "dump",              VERB_ANY, 1,        0,            dump                   },
                 { "cat-config",        2,        VERB_ANY, 0,            cat_config             },
                 { "unit-paths",        1,        1,        0,            dump_unit_paths        },
+                { "exit-codes",        VERB_ANY, VERB_ANY, 0,            dump_exit_codes        },
                 { "syscall-filter",    VERB_ANY, VERB_ANY, 0,            dump_syscall_filters   },
                 { "condition",         2,        VERB_ANY, 0,            do_condition           },
                 { "verify",            2,        VERB_ANY, 0,            do_verify              },