chiark / gitweb /
journalctl: static variables immediately configured via command line arguments should...
[elogind.git] / src / journal / coredumpctl.c
index 2bc9021022bbfbfba56cd2c16d4accc3d8920de0..756e793a4fed14bea20771f5e38ed7a8248fae44 100644 (file)
@@ -26,8 +26,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "systemd/sd-journal.h"
-
+#include "sd-journal.h"
 #include "build.h"
 #include "set.h"
 #include "util.h"
@@ -38,6 +37,7 @@
 #include "journal-internal.h"
 #include "copy.h"
 #include "compress.h"
+#include "sigbus.h"
 
 static enum {
         ACTION_NONE,
@@ -50,15 +50,14 @@ static const char* arg_field = NULL;
 static int arg_no_pager = false;
 static int arg_no_legend = false;
 static int arg_one = false;
-
-static FILE* output = NULL;
+static FILE* arg_output = NULL;
 
 static Set *new_matches(void) {
         Set *set;
         char *tmp;
         int r;
 
-        set = set_new(trivial_hash_func, trivial_compare_func);
+        set = set_new(NULL);
         if (!set) {
                 log_oom();
                 return NULL;
@@ -73,7 +72,7 @@ static Set *new_matches(void) {
 
         r = set_consume(set, tmp);
         if (r < 0) {
-                log_error("failed to add to set: %s", strerror(-r));
+                log_error_errno(r, "failed to add to set: %m");
                 set_free(set);
                 return NULL;
         }
@@ -81,29 +80,6 @@ static Set *new_matches(void) {
         return set;
 }
 
-static int help(void) {
-
-        printf("%s [OPTIONS...]\n\n"
-               "List or retrieve coredumps from the journal.\n\n"
-               "Flags:\n"
-               "  -h --help          Show this help\n"
-               "     --version       Print version string\n"
-               "     --no-pager      Do not pipe output into a pager\n"
-               "     --no-legend     Do not print the column headers.\n"
-               "  -1                 Show information about most recent entry only\n"
-               "  -F --field=FIELD   List all values a certain field takes\n"
-               "  -o --output=FILE   Write output to FILE\n\n"
-
-               "Commands:\n"
-               "  list [MATCHES...]  List available coredumps (default)\n"
-               "  info [MATCHES...]  Show detailed information about one or more coredumps\n"
-               "  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 add_match(Set *set, const char *match) {
         int r = -ENOMEM;
         unsigned pid;
@@ -133,15 +109,33 @@ static int add_match(Set *set, const char *match) {
         log_debug("Adding pattern: %s", pattern);
         r = set_consume(set, pattern);
         if (r < 0) {
-                log_error("Failed to add pattern '%s': %s",
-                          pattern, strerror(-r));
+                log_error_errno(r, "Failed to add pattern: %m");
                 goto fail;
         }
 
         return 0;
 fail:
-        log_error("Failed to add match: %s", strerror(-r));
-        return r;
+        return log_error_errno(r, "Failed to add match: %m");
+}
+
+static void help(void) {
+        printf("%s [OPTIONS...]\n\n"
+               "List or retrieve coredumps from the journal.\n\n"
+               "Flags:\n"
+               "  -h --help          Show this help\n"
+               "     --version       Print version string\n"
+               "     --no-pager      Do not pipe output into a pager\n"
+               "     --no-legend     Do not print the column headers.\n"
+               "  -1                 Show information about most recent entry only\n"
+               "  -F --field=FIELD   List all values a certain field takes\n"
+               "  -o --output=FILE   Write output to FILE\n\n"
+
+               "Commands:\n"
+               "  list [MATCHES...]  List available coredumps (default)\n"
+               "  info [MATCHES...]  Show detailed information about one or more coredumps\n"
+               "  dump [MATCHES...]  Print first matching coredump to stdout\n"
+               "  gdb [MATCHES...]   Start gdb for the first matching coredump\n"
+               , program_invocation_short_name);
 }
 
 static int parse_argv(int argc, char *argv[], Set *matches) {
@@ -171,7 +165,8 @@ static int parse_argv(int argc, char *argv[], Set *matches) {
 
                 case 'h':
                         arg_action = ACTION_NONE;
-                        return help();
+                        help();
+                        return 0;
 
                 case ARG_VERSION:
                         arg_action = ACTION_NONE;
@@ -188,16 +183,14 @@ static int parse_argv(int argc, char *argv[], Set *matches) {
                         break;
 
                 case 'o':
-                        if (output) {
+                        if (arg_output) {
                                 log_error("cannot set output more than once");
                                 return -EINVAL;
                         }
 
-                        output = fopen(optarg, "we");
-                        if (!output) {
-                                log_error("writing to '%s': %m", optarg);
-                                return -errno;
-                        }
+                        arg_output = fopen(optarg, "we");
+                        if (!arg_output)
+                                return log_error_errno(errno, "writing to '%s': %m", optarg);
 
                         break;
 
@@ -329,10 +322,8 @@ static int print_list(FILE* file, sd_journal *j, int had_legend) {
         }
 
         r = sd_journal_get_realtime_usec(j, &t);
-        if (r < 0) {
-                log_error("Failed to get realtime timestamp: %s", strerror(-r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to get realtime timestamp: %m");
 
         format_timestamp(buf, sizeof(buf), t);
         present = filename && access(filename, F_OK) == 0;
@@ -524,10 +515,8 @@ static int focus(sd_journal *j) {
         r = sd_journal_seek_tail(j);
         if (r == 0)
                 r = sd_journal_previous(j);
-        if (r < 0) {
-                log_error("Failed to search journal: %s", strerror(-r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to search journal: %m");
         if (r == 0) {
                 log_error("No match found.");
                 return -ESRCH;
@@ -589,7 +578,7 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
          * compressed file (probably uncached). */
         r = sd_journal_get_data(j, "COREDUMP_FILENAME", (const void**) &data, &len);
         if (r < 0 && r != -ENOENT)
-                log_warning("Failed to retrieve COREDUMP_FILENAME: %s", strerror(-r));
+                log_warning_errno(r, "Failed to retrieve COREDUMP_FILENAME: %m");
         else if (r == 0)
                 retrieve(data, len, "COREDUMP_FILENAME", &filename);
 
@@ -617,10 +606,8 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
                                 return log_oom();
 
                         fdt = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC);
-                        if (fdt < 0) {
-                                log_error("Failed to create temporary file: %m");
-                                return -errno;
-                        }
+                        if (fdt < 0)
+                                return log_error_errno(errno, "Failed to create temporary file: %m");
                         log_debug("Created temporary file %s", temp);
 
                         fd = fdt;
@@ -636,7 +623,7 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
 
                         sz = write(fdt, data, len);
                         if (sz < 0) {
-                                log_error("Failed to write temporary file: %m");
+                                log_error_errno(errno, "Failed to write temporary file: %m");
                                 r = -errno;
                                 goto error;
                         }
@@ -651,14 +638,14 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
 
                         fdf = open(filename, O_RDONLY | O_CLOEXEC);
                         if (fdf < 0) {
-                                log_error("Failed to open %s: %m", filename);
+                                log_error_errno(errno, "Failed to open %s: %m", filename);
                                 r = -errno;
                                 goto error;
                         }
 
                         r = decompress_stream(filename, fdf, fd, -1);
                         if (r < 0) {
-                                log_error("Failed to decompress %s: %s", filename, strerror(-r));
+                                log_error_errno(r, "Failed to decompress %s: %m", filename);
                                 goto error;
                         }
 #else
@@ -670,7 +657,7 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) {
                         if (r == -ENOENT)
                                 log_error("Cannot retrieve coredump from journal nor disk.");
                         else
-                                log_error("Failed to retrieve COREDUMP field: %s", strerror(-r));
+                                log_error_errno(r, "Failed to retrieve COREDUMP field: %m");
                         goto error;
                 }
 
@@ -699,18 +686,16 @@ static int dump_core(sd_journal* j) {
         if (r < 0)
                 return r;
 
-        print_info(output ? stdout : stderr, j, false);
+        print_info(arg_output ? stdout : stderr, j, false);
 
-        if (on_tty() && !output) {
+        if (on_tty() && !arg_output) {
                 log_error("Refusing to dump core to tty.");
                 return -ENOTTY;
         }
 
-        r = save_core(j, output ? fileno(output) : STDOUT_FILENO, NULL, NULL);
-        if (r < 0) {
-                log_error("Coredump retrieval failed: %s", strerror(-r));
-                return r;
-        }
+        r = save_core(j, arg_output ? fileno(arg_output) : STDOUT_FILENO, NULL, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Coredump retrieval failed: %m");
 
         r = sd_journal_previous(j);
         if (r >= 0)
@@ -738,10 +723,8 @@ static int run_gdb(sd_journal *j) {
         fputs("\n", stdout);
 
         r = sd_journal_get_data(j, "COREDUMP_EXE", (const void**) &data, &len);
-        if (r < 0) {
-                log_error("Failed to retrieve COREDUMP_EXE field: %s", strerror(-r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to retrieve COREDUMP_EXE field: %m");
 
         assert(len > strlen("COREDUMP_EXE="));
         data += strlen("COREDUMP_EXE=");
@@ -762,27 +745,25 @@ static int run_gdb(sd_journal *j) {
         }
 
         r = save_core(j, -1, &path, &unlink_path);
-        if (r < 0) {
-                log_error("Failed to retrieve core: %s", strerror(-r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to retrieve core: %m");
 
         pid = fork();
         if (pid < 0) {
-                log_error("Failed to fork(): %m");
+                log_error_errno(errno, "Failed to fork(): %m");
                 r = -errno;
                 goto finish;
         }
         if (pid == 0) {
                 execlp("gdb", "gdb", exe, path, NULL);
 
-                log_error("Failed to invoke gdb: %m");
+                log_error_errno(errno, "Failed to invoke gdb: %m");
                 _exit(1);
         }
 
         r = wait_for_terminate(pid, &st);
         if (r < 0) {
-                log_error("Failed to wait for gdb: %m");
+                log_error_errno(errno, "Failed to wait for gdb: %m");
                 goto finish;
         }
 
@@ -821,9 +802,11 @@ int main(int argc, char *argv[]) {
         if (arg_action == ACTION_NONE)
                 goto end;
 
+        sigbus_install();
+
         r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
         if (r < 0) {
-                log_error("Failed to open journal: %s", strerror(-r));
+                log_error_errno(r, "Failed to open journal: %m");
                 goto end;
         }
 
@@ -833,8 +816,8 @@ int main(int argc, char *argv[]) {
         SET_FOREACH(match, matches, it) {
                 r = sd_journal_add_match(j, match, strlen(match));
                 if (r != 0) {
-                        log_error("Failed to add match '%s': %s",
-                                  match, strerror(-r));
+                        log_error_errno(r, "Failed to add match '%s': %m",
+                                        match);
                         goto end;
                 }
         }
@@ -871,8 +854,8 @@ int main(int argc, char *argv[]) {
 end:
         pager_close();
 
-        if (output)
-                fclose(output);
+        if (arg_output)
+                fclose(arg_output);
 
         return r >= 0 ? r : EXIT_FAILURE;
 }