From 5ce97d33d098d225a6480179293d0b02da6dde41 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 14 Mar 2018 17:46:34 +0900 Subject: [PATCH] coredumpctl: use dispatch_verb() --- src/coredump/coredumpctl.c | 200 ++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 105 deletions(-) diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index a4cc9c1db3d..2795f5b675f 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -51,18 +51,11 @@ #include "terminal-util.h" #include "user-util.h" #include "util.h" +#include "verbs.h" #define SHORT_BUS_CALL_TIMEOUT_USEC (3 * USEC_PER_SEC) static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY; - -static enum { - ACTION_NONE, - ACTION_INFO, - ACTION_LIST, - ACTION_DUMP, - ACTION_GDB, -} arg_action = ACTION_LIST; static const char* arg_field = NULL; static const char *arg_directory = NULL; static bool arg_no_pager = false; @@ -70,7 +63,6 @@ static int arg_no_legend = false; static int arg_one = false; static FILE* arg_output = NULL; static bool arg_reverse = false; -static char** arg_matches = NULL; static bool arg_quiet = false; static int add_match(sd_journal *j, const char *match) { @@ -102,7 +94,7 @@ static int add_match(sd_journal *j, const char *match) { return 0; } -static int add_matches(sd_journal *j) { +static int add_matches(sd_journal *j, char **matches) { char **match; int r; @@ -114,7 +106,7 @@ static int add_matches(sd_journal *j) { if (r < 0) return log_error_errno(r, "Failed to add match \"%s\": %m", "MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR); - STRV_FOREACH(match, arg_matches) { + STRV_FOREACH(match, matches) { r = add_match(j, *match); if (r < 0) return r; @@ -123,7 +115,44 @@ static int add_matches(sd_journal *j) { return 0; } -static void help(void) { +static int acquire_journal(sd_journal **ret, char **matches) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; + int r; + + assert(ret); + + if (arg_directory) { + r = sd_journal_open_directory(&j, arg_directory, 0); + if (r < 0) + return log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory); + } else { + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + if (r < 0) + return log_error_errno(r, "Failed to open journal: %m"); + } + + r = journal_access_check_and_warn(j, arg_quiet, true); + if (r < 0) + return r; + + r = add_matches(j, matches); + if (r < 0) + return r; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *filter; + + filter = journal_make_match_string(j); + log_debug("Journal filter: %s", filter); + } + + *ret = j; + j = NULL; + + return 0; +} + +static int help(void) { printf("%s [OPTIONS...]\n\n" "List or retrieve coredumps from the journal.\n\n" "Flags:\n" @@ -145,6 +174,8 @@ static void help(void) { " dump [MATCHES...] Print first matching coredump to stdout\n" " gdb [MATCHES...] Start gdb for the first matching coredump\n" , program_invocation_short_name); + + return 0; } static int parse_argv(int argc, char *argv[]) { @@ -177,12 +208,9 @@ static int parse_argv(int argc, char *argv[]) { while ((c = getopt_long(argc, argv, "ho:F:1D:rS:U:q", options, NULL)) >= 0) switch(c) { case 'h': - arg_action = ACTION_NONE; - help(); - return 0; + return help(); case ARG_VERSION: - arg_action = ACTION_NONE; return version(); case ARG_NO_PAGER: @@ -254,31 +282,7 @@ static int parse_argv(int argc, char *argv[]) { return -EINVAL; } - if (optind < argc) { - const char *cmd = argv[optind++]; - if (streq(cmd, "list")) - arg_action = ACTION_LIST; - else if (streq(cmd, "dump")) - arg_action = ACTION_DUMP; - else if (streq(cmd, "gdb")) - arg_action = ACTION_GDB; - else if (streq(cmd, "info")) - arg_action = ACTION_INFO; - else { - log_error("Unknown action '%s'", cmd); - return -EINVAL; - } - } - - if (arg_field && arg_action != ACTION_LIST) { - log_error("Option --field/-F only makes sense with list"); - return -EINVAL; - } - - if (optind < argc) - arg_matches = argv + optind; - - return 0; + return 1; } static int retrieve(const void *data, @@ -631,10 +635,10 @@ static int focus(sd_journal *j) { return r; } -static int print_entry(sd_journal *j, unsigned n_found) { +static int print_entry(sd_journal *j, unsigned n_found, bool verb_is_info) { assert(j); - if (arg_action == ACTION_INFO) + if (verb_is_info) return print_info(stdout, j, n_found); else if (arg_field) return print_field(stdout, j); @@ -642,11 +646,19 @@ static int print_entry(sd_journal *j, unsigned n_found) { return print_list(stdout, j, n_found); } -static int dump_list(sd_journal *j) { +static int dump_list(int argc, char **argv, void *userdata) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; unsigned n_found = 0; + bool verb_is_info; int r; - assert(j); + verb_is_info = (argc >= 1 && streq(argv[0], "info")); + + r = acquire_journal(&j, argv + 1); + if (r < 0) + return r; + + pager_open(arg_no_pager, false); /* The coredumps are likely to compressed, and for just * listing them we don't need to decompress them, so let's @@ -658,7 +670,7 @@ static int dump_list(sd_journal *j) { if (r < 0) return r; - return print_entry(j, 0); + return print_entry(j, 0, verb_is_info); } else { if (arg_since != USEC_INFINITY && !arg_reverse) r = sd_journal_seek_realtime_usec(j, arg_since); @@ -703,7 +715,7 @@ static int dump_list(sd_journal *j) { continue; } - r = print_entry(j, n_found++); + r = print_entry(j, n_found++, verb_is_info); if (r < 0) return r; } @@ -856,10 +868,18 @@ error: return r; } -static int dump_core(sd_journal* j) { +static int dump_core(int argc, char **argv, void *userdata) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; int r; - assert(j); + if (arg_field) { + log_error("Option --field/-F only makes sense with list"); + return -EINVAL; + } + + r = acquire_journal(&j, argv + 1); + if (r < 0) + return r; r = focus(j); if (r < 0) @@ -878,7 +898,8 @@ static int dump_core(sd_journal* j) { return 0; } -static int run_gdb(sd_journal *j) { +static int run_gdb(int argc, char **argv, void *userdata) { + _cleanup_(sd_journal_closep) sd_journal *j = NULL; _cleanup_free_ char *exe = NULL, *path = NULL; bool unlink_path = false; const char *data; @@ -886,7 +907,14 @@ static int run_gdb(sd_journal *j) { pid_t pid; int r; - assert(j); + if (arg_field) { + log_error("Option --field/-F only makes sense with list"); + return -EINVAL; + } + + r = acquire_journal(&j, argv + 1); + if (r < 0) + return r; r = focus(j); if (r < 0) @@ -1007,73 +1035,35 @@ static int check_units_active(void) { return c; } +static int coredumpctl_main(int argc, char *argv[]) { + + static const Verb verbs[] = { + { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, dump_list }, + { "info", VERB_ANY, VERB_ANY, 0, dump_list }, + { "dump", VERB_ANY, VERB_ANY, 0, dump_core }, + { "gdb", VERB_ANY, VERB_ANY, 0, run_gdb }, + {} + }; + + return dispatch_verb(argc, argv, verbs, NULL); +} + int main(int argc, char *argv[]) { - _cleanup_(sd_journal_closep) sd_journal*j = NULL; - int r = 0, units_active; + int r, units_active; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); r = parse_argv(argc, argv); - if (r < 0) - goto end; - - if (arg_action == ACTION_NONE) + if (r <= 0) goto end; sigbus_install(); - if (arg_directory) { - r = sd_journal_open_directory(&j, arg_directory, 0); - if (r < 0) { - log_error_errno(r, "Failed to open journals in directory: %s: %m", arg_directory); - goto end; - } - } else { - r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); - if (r < 0) { - log_error_errno(r, "Failed to open journal: %m"); - goto end; - } - } - - r = journal_access_check_and_warn(j, arg_quiet, true); - if (r < 0) - goto end; - - r = add_matches(j); - if (r < 0) - goto end; - - if (DEBUG_LOGGING) { - _cleanup_free_ char *filter; - - filter = journal_make_match_string(j); - log_debug("Journal filter: %s", filter); - } - units_active = check_units_active(); /* error is treated the same as 0 */ - switch(arg_action) { - - case ACTION_LIST: - case ACTION_INFO: - pager_open(arg_no_pager, false); - r = dump_list(j); - break; - - case ACTION_DUMP: - r = dump_core(j); - break; - - case ACTION_GDB: - r = run_gdb(j); - break; - - default: - assert_not_reached("Shouldn't be here"); - } + r = coredumpctl_main(argc, argv); if (units_active > 0) printf("%s-- Notice: %d systemd-coredump@.service %s, output may be incomplete.%s\n",