chiark / gitweb /
journal: when show blob data show length
[elogind.git] / src / logs-show.c
index 58d1e99dfa18fe947efd7c97b066ad53d0f6d54d..5a001331407f9fa7a9c08a0fa707101c91fc2540 100644 (file)
@@ -58,7 +58,9 @@ static int parse_field(const void *data, size_t length, const char *field, char
                 return 0;
 
         nl = length - fl;
                 return 0;
 
         nl = length - fl;
-        buf = memdup((const char*) data + fl, nl);
+        buf = malloc(nl+1);
+        memcpy(buf, (const char*) data + fl, nl);
+        ((char*)buf)[nl] = 0;
         if (!buf) {
                 log_error("Out of memory");
                 return -ENOMEM;
         if (!buf) {
                 log_error("Out of memory");
                 return -ENOMEM;
@@ -84,13 +86,13 @@ static bool shall_print(bool show_all, char *p, size_t l) {
         return true;
 }
 
         return true;
 }
 
-static int output_short(sd_journal *j, unsigned line, bool show_all, bool monotonic) {
+static int output_short(sd_journal *j, unsigned line, bool show_all, bool monotonic_mode) {
         int r;
         const void *data;
         size_t length;
         size_t n = 0;
         int r;
         const void *data;
         size_t length;
         size_t n = 0;
-        char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL;
-        size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0;
+        char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL;
+        size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0;
 
         assert(j);
 
 
         assert(j);
 
@@ -126,6 +128,18 @@ static int output_short(sd_journal *j, unsigned line, bool show_all, bool monoto
                 else if (r > 0)
                         continue;
 
                 else if (r > 0)
                         continue;
 
+                r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
+                if (r < 0)
+                        goto finish;
+                else if (r > 0)
+                        continue;
+
+                r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
+                if (r < 0)
+                        goto finish;
+                else if (r > 0)
+                        continue;
+
                 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
                 if (r < 0)
                         goto finish;
                 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
                 if (r < 0)
                         goto finish;
@@ -136,31 +150,49 @@ static int output_short(sd_journal *j, unsigned line, bool show_all, bool monoto
                 goto finish;
         }
 
                 goto finish;
         }
 
-        if (monotonic) {
+        if (monotonic_mode) {
                 uint64_t t;
                 uint64_t t;
+                sd_id128_t boot_id;
+
+                r = -ENOENT;
 
 
-                r = sd_journal_get_monotonic_usec(j, &t, NULL);
-                if (r >= 0) {
-                        printf("[%5llu.%06llu]",
-                               (unsigned long long) (t / USEC_PER_SEC),
-                               (unsigned long long) (t % USEC_PER_SEC));
+                if (monotonic)
+                        r = safe_atou64(monotonic, &t);
 
 
-                        n += 1 + 5 + 1 + 6 + 1;
+                if (r < 0)
+                        r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
+
+                if (r < 0) {
+                        log_error("Failed to get monotonic: %s", strerror(-r));
+                        goto finish;
                 }
 
                 }
 
+                printf("[%5llu.%06llu]",
+                       (unsigned long long) (t / USEC_PER_SEC),
+                       (unsigned long long) (t % USEC_PER_SEC));
+
+                n += 1 + 5 + 1 + 6 + 1;
+
         } else {
                 char buf[64];
         } else {
                 char buf[64];
-                uint64_t realtime;
+                uint64_t x;
                 time_t t;
                 struct tm tm;
 
                 time_t t;
                 struct tm tm;
 
-                r = sd_journal_get_realtime_usec(j, &realtime);
+                r = -ENOENT;
+
+                if (realtime)
+                        r = safe_atou64(realtime, &x);
+
+                if (r < 0)
+                        r = sd_journal_get_realtime_usec(j, &x);
+
                 if (r < 0) {
                         log_error("Failed to get realtime: %s", strerror(-r));
                         goto finish;
                 }
 
                 if (r < 0) {
                         log_error("Failed to get realtime: %s", strerror(-r));
                         goto finish;
                 }
 
-                t = (time_t) (realtime / USEC_PER_SEC);
+                t = (time_t) (x / USEC_PER_SEC);
                 if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
                         log_error("Failed to format time.");
                         goto finish;
                 if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
                         log_error("Failed to format time.");
                         goto finish;
@@ -193,9 +225,10 @@ static int output_short(sd_journal *j, unsigned line, bool show_all, bool monoto
 
         if (show_all)
                 printf(": %.*s\n", (int) message_len, message);
 
         if (show_all)
                 printf(": %.*s\n", (int) message_len, message);
-        else if (contains_unprintable(message, message_len))
-                fputs(": [blob data]\n", stdout);
-        else if (message_len + n < columns())
+        else if (contains_unprintable(message, message_len)) {
+                char bytes[FORMAT_BYTES_MAX];
+                printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
+        } else if (message_len + n < columns())
                 printf(": %.*s\n", (int) message_len, message);
         else if (n < columns()) {
                 char *e;
                 printf(": %.*s\n", (int) message_len, message);
         else if (n < columns()) {
                 char *e;
@@ -205,7 +238,7 @@ static int output_short(sd_journal *j, unsigned line, bool show_all, bool monoto
                 if (!e)
                         printf(": %.*s\n", (int) message_len, message);
                 else
                 if (!e)
                         printf(": %.*s\n", (int) message_len, message);
                 else
-                        printf(": %s", e);
+                        printf(": %s\n", e);
 
                 free(e);
         } else
 
                 free(e);
         } else
@@ -220,6 +253,8 @@ finish:
         free(pid);
         free(fake_pid);
         free(message);
         free(pid);
         free(fake_pid);
         free(message);
+        free(monotonic);
+        free(realtime);
 
         return r;
 }
 
         return r;
 }
@@ -264,6 +299,7 @@ static int output_verbose(sd_journal *j, unsigned line, bool show_all) {
                 if (!show_all && (length > PRINT_THRESHOLD ||
                                   contains_unprintable(data, length))) {
                         const char *c;
                 if (!show_all && (length > PRINT_THRESHOLD ||
                                   contains_unprintable(data, length))) {
                         const char *c;
+                        char bytes[FORMAT_BYTES_MAX];
 
                         c = memchr(data, '=', length);
                         if (!c) {
 
                         c = memchr(data, '=', length);
                         if (!c) {
@@ -271,9 +307,10 @@ static int output_verbose(sd_journal *j, unsigned line, bool show_all) {
                                 return -EINVAL;
                         }
 
                                 return -EINVAL;
                         }
 
-                        printf("\t%.*s=[blob data]\n",
+                        printf("\t%.*s=[%s blob data]\n",
                                (int) (c - (const char*) data),
                                (int) (c - (const char*) data),
-                               (const char*) data);
+                               (const char*) data,
+                               format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1));
                 } else
                         printf("\t%.*s\n", (int) length, (const char*) data);
         }
                 } else
                         printf("\t%.*s\n", (int) length, (const char*) data);
         }
@@ -454,12 +491,34 @@ static int output_json(sd_journal *j, unsigned line, bool show_all) {
         return 0;
 }
 
         return 0;
 }
 
+static int output_cat(sd_journal *j, unsigned line, bool show_all) {
+        const void *data;
+        size_t l;
+        int r;
+
+        assert(j);
+
+        r = sd_journal_get_data(j, "MESSAGE", &data, &l);
+        if (r < 0) {
+                log_error("Failed to get data: %s", strerror(-r));
+                return r;
+        }
+
+        assert(l >= 8);
+
+        fwrite((const char*) data + 8, 1, l - 8, stdout);
+        putchar('\n');
+
+        return 0;
+}
+
 static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool show_all) = {
         [OUTPUT_SHORT] = output_short_realtime,
         [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic,
         [OUTPUT_VERBOSE] = output_verbose,
         [OUTPUT_EXPORT] = output_export,
 static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool show_all) = {
         [OUTPUT_SHORT] = output_short_realtime,
         [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic,
         [OUTPUT_VERBOSE] = output_verbose,
         [OUTPUT_EXPORT] = output_export,
-        [OUTPUT_JSON] = output_json
+        [OUTPUT_JSON] = output_json,
+        [OUTPUT_CAT] = output_cat
 };
 
 int output_journal(sd_journal *j, OutputMode mode, unsigned line, bool show_all) {
 };
 
 int output_journal(sd_journal *j, OutputMode mode, unsigned line, bool show_all) {
@@ -602,7 +661,8 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
         [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
         [OUTPUT_VERBOSE] = "verbose",
         [OUTPUT_EXPORT] = "export",
         [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
         [OUTPUT_VERBOSE] = "verbose",
         [OUTPUT_EXPORT] = "export",
-        [OUTPUT_JSON] = "json"
+        [OUTPUT_JSON] = "json",
+        [OUTPUT_CAT] = "cat"
 };
 
 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);
 };
 
 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);