diff options
Diffstat (limited to 'src/coredump/coredumpctl.c')
-rw-r--r-- | src/coredump/coredumpctl.c | 100 |
1 files changed, 58 insertions, 42 deletions
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index 99d07c14fb..fbee242962 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -15,22 +15,26 @@ #include "bus-error.h" #include "bus-util.h" #include "compress.h" +#include "def.h" #include "fd-util.h" -#include "fileio.h" #include "fs-util.h" #include "journal-internal.h" #include "journal-util.h" #include "log.h" #include "macro.h" +#include "main-func.h" #include "pager.h" #include "parse-util.h" #include "path-util.h" +#include "pretty-print.h" #include "process-util.h" +#include "rlimit-util.h" #include "sigbus.h" #include "signal-util.h" #include "string-util.h" #include "strv.h" #include "terminal-util.h" +#include "tmpfile-util.h" #include "user-util.h" #include "util.h" #include "verbs.h" @@ -41,10 +45,10 @@ static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY; static const char* arg_field = NULL; static const char *arg_debugger = NULL; static const char *arg_directory = NULL; -static bool arg_no_pager = false; +static PagerFlags arg_pager_flags = 0; static int arg_no_legend = false; static int arg_one = false; -static FILE* arg_output = NULL; +static const char* arg_output = NULL; static bool arg_reverse = false; static bool arg_quiet = false; @@ -135,6 +139,13 @@ static int acquire_journal(sd_journal **ret, char **matches) { } static int help(void) { + _cleanup_free_ char *link = NULL; + int r; + + r = terminal_urlify_man("coredumpctl", "1", &link); + if (r < 0) + return log_oom(); + printf("%s [OPTIONS...]\n\n" "List or retrieve coredumps from the journal.\n\n" "Flags:\n" @@ -156,7 +167,10 @@ static int help(void) { " info [MATCHES...] Show detailed information about one or more coredumps\n" " dump [MATCHES...] Print first matching coredump to stdout\n" " debug [MATCHES...] Start a debugger for the first matching coredump\n" - , program_invocation_short_name); + "\nSee the %s for details.\n" + , program_invocation_short_name + , link + ); return 0; } @@ -199,7 +213,7 @@ static int parse_argv(int argc, char *argv[]) { return version(); case ARG_NO_PAGER: - arg_no_pager = true; + arg_pager_flags |= PAGER_DISABLE; break; case ARG_NO_LEGEND: @@ -211,34 +225,29 @@ static int parse_argv(int argc, char *argv[]) { break; case 'o': - if (arg_output) { - log_error("Cannot set output more than once."); - return -EINVAL; - } - - arg_output = fopen(optarg, "we"); - if (!arg_output) - return log_error_errno(errno, "writing to '%s': %m", optarg); + if (arg_output) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot set output more than once."); + arg_output = optarg; break; case 'S': r = parse_timestamp(optarg, &arg_since); if (r < 0) - return log_error_errno(r, "Failed to parse timestamp: %s", optarg); + return log_error_errno(r, "Failed to parse timestamp '%s': %m", optarg); break; case 'U': r = parse_timestamp(optarg, &arg_until); if (r < 0) - return log_error_errno(r, "Failed to parse timestamp: %s", optarg); + return log_error_errno(r, "Failed to parse timestamp '%s': %m", optarg); break; case 'F': - if (arg_field) { - log_error("Cannot use --field/-F more than once."); - return -EINVAL; - } + if (arg_field) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Cannot use --field/-F more than once."); arg_field = optarg; break; @@ -266,10 +275,9 @@ static int parse_argv(int argc, char *argv[]) { } if (arg_since != USEC_INFINITY && arg_until != USEC_INFINITY && - arg_since > arg_until) { - log_error("--since= must be before --until=."); - return -EINVAL; - } + arg_since > arg_until) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "--since= must be before --until=."); return 1; } @@ -617,10 +625,9 @@ static int focus(sd_journal *j) { r = sd_journal_previous(j); if (r < 0) return log_error_errno(r, "Failed to search journal: %m"); - if (r == 0) { - log_error("No match found."); - return -ESRCH; - } + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), + "No match found."); return r; } @@ -647,14 +654,15 @@ static int dump_list(int argc, char **argv, void *userdata) { if (r < 0) return r; - (void) pager_open(arg_no_pager, false); + (void) pager_open(arg_pager_flags); /* The coredumps are likely to compressed, and for just * listing them we don't need to decompress them, so let's * pick a fairly low data threshold here */ sd_journal_set_data_threshold(j, 4096); - if (arg_one) { + /* "info" without pattern implies "-1" */ + if (arg_one || (verb_is_info && argc == 1)) { r = focus(j); if (r < 0) return r; @@ -788,7 +796,8 @@ static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp) */ if (!file) { if (on_tty()) - return log_error_errno(ENOTTY, "Refusing to dump core to tty" + return log_error_errno(SYNTHETIC_ERRNO(ENOTTY), + "Refusing to dump core to tty" " (use shell redirection or specify --output)."); file = stdout; } @@ -858,6 +867,7 @@ error: static int dump_core(int argc, char **argv, void *userdata) { _cleanup_(sd_journal_closep) sd_journal *j = NULL; + _cleanup_fclose_ FILE *f = NULL; int r; if (arg_field) { @@ -873,9 +883,15 @@ static int dump_core(int argc, char **argv, void *userdata) { if (r < 0) return r; - print_info(arg_output ? stdout : stderr, j, false); + if (arg_output) { + f = fopen(arg_output, "we"); + if (!f) + return log_error_errno(errno, "Failed to open \"%s\" for writing: %m", arg_output); + } - r = save_core(j, arg_output, NULL, NULL); + print_info(f ? stdout : stderr, j, false); + + r = save_core(j, f, NULL, NULL); if (r < 0) return r; @@ -952,7 +968,7 @@ static int run_debug(int argc, char **argv, void *userdata) { fork_name = strjoina("(", arg_debugger, ")"); - r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid); + r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid); if (r < 0) goto finish; if (r == 0) { @@ -976,7 +992,7 @@ finish: } static int check_units_active(void) { - _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; @@ -1049,16 +1065,19 @@ static int coredumpctl_main(int argc, char *argv[]) { return dispatch_verb(argc, argv, verbs, NULL); } -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { int r, units_active; setlocale(LC_ALL, ""); log_parse_environment(); log_open(); + /* The journal merging logic potentially needs a lot of fds. */ + (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE); + r = parse_argv(argc, argv); if (r <= 0) - goto end; + return r; sigbus_install(); @@ -1071,10 +1090,7 @@ int main(int argc, char *argv[]) { ansi_highlight_red(), units_active, units_active == 1 ? "unit is running" : "units are running", ansi_normal()); -end: - pager_close(); - - safe_fclose(arg_output); - - return r >= 0 ? r : EXIT_FAILURE; + return r; } + +DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run); |