1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2012 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "logs-show.h"
32 #define PRINT_THRESHOLD 128
34 static bool contains_unprintable(const void *p, size_t l) {
37 for (j = p; j < (const char *) p + l; j++)
38 if (*j < ' ' || *j >= 127)
44 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
57 if (memcmp(data, field, fl))
62 memcpy(buf, (const char*) data + fl, nl);
65 log_error("Out of memory");
76 static bool shall_print(bool show_all, char *p, size_t l) {
80 if (l > PRINT_THRESHOLD)
83 if (contains_unprintable(p, l))
89 static int output_short(sd_journal *j, unsigned line, unsigned n_columns, bool show_all, bool monotonic_mode) {
94 char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL;
95 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;
99 SD_JOURNAL_FOREACH_DATA(j, data, length) {
101 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
107 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
113 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
119 r = parse_field(data, length, "_PID=", &pid, &pid_len);
125 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
131 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
137 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
143 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
153 if (monotonic_mode) {
160 r = safe_atou64(monotonic, &t);
163 r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
166 log_error("Failed to get monotonic: %s", strerror(-r));
170 printf("[%5llu.%06llu]",
171 (unsigned long long) (t / USEC_PER_SEC),
172 (unsigned long long) (t % USEC_PER_SEC));
174 n += 1 + 5 + 1 + 6 + 1;
185 r = safe_atou64(realtime, &x);
188 r = sd_journal_get_realtime_usec(j, &x);
191 log_error("Failed to get realtime: %s", strerror(-r));
195 t = (time_t) (x / USEC_PER_SEC);
196 if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
197 log_error("Failed to format time.");
205 if (hostname && shall_print(show_all, hostname, hostname_len)) {
206 printf(" %.*s", (int) hostname_len, hostname);
207 n += hostname_len + 1;
210 if (identifier && shall_print(show_all, identifier, identifier_len)) {
211 printf(" %.*s", (int) identifier_len, identifier);
212 n += identifier_len + 1;
213 } else if (comm && shall_print(show_all, comm, comm_len)) {
214 printf(" %.*s", (int) comm_len, comm);
219 if (pid && shall_print(show_all, pid, pid_len)) {
220 printf("[%.*s]", (int) pid_len, pid);
222 } else if (fake_pid && shall_print(show_all, fake_pid, fake_pid_len)) {
223 printf("[%.*s]", (int) fake_pid_len, fake_pid);
224 n += fake_pid_len + 2;
228 printf(": %.*s\n", (int) message_len, message);
229 else if (contains_unprintable(message, message_len)) {
230 char bytes[FORMAT_BYTES_MAX];
231 printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
232 } else if (message_len + n < n_columns)
233 printf(": %.*s\n", (int) message_len, message);
234 else if (n < n_columns) {
237 e = ellipsize_mem(message, message_len, n_columns - n - 2, 90);
240 printf(": %.*s\n", (int) message_len, message);
263 static int output_short_realtime(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) {
264 return output_short(j, line, n_columns, show_all, false);
267 static int output_short_monotonic(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) {
268 return output_short(j, line, n_columns, show_all, true);
271 static int output_verbose(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) {
276 char ts[FORMAT_TIMESTAMP_MAX];
281 r = sd_journal_get_realtime_usec(j, &realtime);
283 log_error("Failed to get realtime timestamp: %s", strerror(-r));
287 r = sd_journal_get_cursor(j, &cursor);
289 log_error("Failed to get cursor: %s", strerror(-r));
294 format_timestamp(ts, sizeof(ts), realtime),
299 SD_JOURNAL_FOREACH_DATA(j, data, length) {
300 if (!show_all && (length > PRINT_THRESHOLD ||
301 contains_unprintable(data, length))) {
303 char bytes[FORMAT_BYTES_MAX];
305 c = memchr(data, '=', length);
307 log_error("Invalid field.");
311 printf("\t%.*s=[%s blob data]\n",
312 (int) (c - (const char*) data),
314 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1));
316 printf("\t%.*s\n", (int) length, (const char*) data);
322 static int output_export(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) {
326 usec_t realtime, monotonic;
333 r = sd_journal_get_realtime_usec(j, &realtime);
335 log_error("Failed to get realtime timestamp: %s", strerror(-r));
339 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
341 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
345 r = sd_journal_get_cursor(j, &cursor);
347 log_error("Failed to get cursor: %s", strerror(-r));
351 printf("__CURSOR=%s\n"
352 "__REALTIME_TIMESTAMP=%llu\n"
353 "__MONOTONIC_TIMESTAMP=%llu\n"
356 (unsigned long long) realtime,
357 (unsigned long long) monotonic,
358 sd_id128_to_string(boot_id, sid));
362 SD_JOURNAL_FOREACH_DATA(j, data, length) {
364 /* We already printed the boot id, from the data in
365 * the header, hence let's suppress it here */
367 memcmp(data, "_BOOT_ID=", 9) == 0)
370 if (contains_unprintable(data, length)) {
374 c = memchr(data, '=', length);
376 log_error("Invalid field.");
380 fwrite(data, c - (const char*) data, 1, stdout);
382 le64 = htole64(length - (c - (const char*) data) - 1);
383 fwrite(&le64, sizeof(le64), 1, stdout);
384 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout);
386 fwrite(data, length, 1, stdout);
396 static void json_escape(const char* p, size_t l) {
398 if (contains_unprintable(p, l)) {
399 bool not_first = false;
405 printf(", %u", (uint8_t) *p);
408 printf("%u", (uint8_t) *p);
420 if (*p == '"' || *p == '\\') {
434 static int output_json(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) {
435 uint64_t realtime, monotonic;
445 r = sd_journal_get_realtime_usec(j, &realtime);
447 log_error("Failed to get realtime timestamp: %s", strerror(-r));
451 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
453 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
457 r = sd_journal_get_cursor(j, &cursor);
459 log_error("Failed to get cursor: %s", strerror(-r));
466 fputs(",\n", stdout);
469 "\t\"__CURSOR\" : \"%s\",\n"
470 "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
471 "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
472 "\t\"_BOOT_ID\" : \"%s\"",
474 (unsigned long long) realtime,
475 (unsigned long long) monotonic,
476 sd_id128_to_string(boot_id, sid));
480 SD_JOURNAL_FOREACH_DATA(j, data, length) {
483 /* We already printed the boot id, from the data in
484 * the header, hence let's suppress it here */
486 memcmp(data, "_BOOT_ID=", 9) == 0)
489 c = memchr(data, '=', length);
491 log_error("Invalid field.");
495 fputs(",\n\t", stdout);
496 json_escape(data, c - (const char*) data);
497 fputs(" : ", stdout);
498 json_escape(c + 1, length - (c - (const char*) data) - 1);
501 fputs("\n}", stdout);
507 static int output_cat(sd_journal *j, unsigned line, unsigned n_columns, bool show_all) {
514 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
516 log_error("Failed to get data: %s", strerror(-r));
522 fwrite((const char*) data + 8, 1, l - 8, stdout);
528 static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, unsigned n_columns, bool show_all) = {
529 [OUTPUT_SHORT] = output_short_realtime,
530 [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic,
531 [OUTPUT_VERBOSE] = output_verbose,
532 [OUTPUT_EXPORT] = output_export,
533 [OUTPUT_JSON] = output_json,
534 [OUTPUT_CAT] = output_cat
537 int output_journal(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, bool show_all) {
539 assert(mode < _OUTPUT_MODE_MAX);
542 n_columns = columns();
544 return output_funcs[mode](j, line, n_columns, show_all);
547 int show_journal_by_unit(
557 sd_journal *j = NULL;
561 bool need_seek = false;
564 assert(mode < _OUTPUT_MODE_MAX);
567 if (!endswith(unit, ".service") &&
568 !endswith(unit, ".socket") &&
569 !endswith(unit, ".mount") &&
570 !endswith(unit, ".swap"))
576 if (asprintf(&m, "_SYSTEMD_UNIT=%s", unit) < 0) {
581 r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY);
585 fd = sd_journal_get_fd(j);
589 r = sd_journal_add_match(j, m, strlen(m));
593 r = sd_journal_seek_tail(j);
597 r = sd_journal_previous_skip(j, how_many);
601 if (mode == OUTPUT_JSON) {
611 r = sd_journal_next(j);
621 if (not_before > 0) {
622 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
624 /* -ESTALE is returned if the
625 timestamp is not from this boot */
631 if (usec < not_before)
637 r = output_journal(j, mode, line, n_columns, show_all);
645 r = fd_wait_for_event(fd, POLLIN, (usec_t) -1);
649 r = sd_journal_process(j);
655 if (mode == OUTPUT_JSON)
656 fputs("\n]\n", stdout);
668 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
669 [OUTPUT_SHORT] = "short",
670 [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
671 [OUTPUT_VERBOSE] = "verbose",
672 [OUTPUT_EXPORT] = "export",
673 [OUTPUT_JSON] = "json",
677 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);