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/>.
26 #include <sys/socket.h>
30 #include "logs-show.h"
36 #include "journal-internal.h"
38 /* up to three lines (each up to 100 characters),
39 or 300 characters, whichever is less */
40 #define PRINT_LINE_THRESHOLD 3
41 #define PRINT_CHAR_THRESHOLD 300
43 #define JSON_THRESHOLD 4096
45 static int print_catalog(FILE *f, sd_journal *j) {
47 _cleanup_free_ char *t = NULL, *z = NULL;
50 r = sd_journal_get_catalog(j, &t);
54 z = strreplace(strstrip(t), "\n", "\n-- ");
65 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
78 if (memcmp(data, field, fl))
86 memcpy(buf, (const char*) data + fl, nl);
96 static bool shall_print(const char *p, size_t l, OutputFlags flags) {
99 if (flags & OUTPUT_SHOW_ALL)
102 if (l >= PRINT_CHAR_THRESHOLD)
105 if (!utf8_is_printable(p, l))
111 static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
112 const char *color_on = "", *color_off = "";
113 const char *pos, *end;
114 bool ellipsized = false;
117 if (flags & OUTPUT_COLOR) {
118 if (priority <= LOG_ERR) {
119 color_on = ANSI_HIGHLIGHT_RED_ON;
120 color_off = ANSI_HIGHLIGHT_OFF;
121 } else if (priority <= LOG_NOTICE) {
122 color_on = ANSI_HIGHLIGHT_ON;
123 color_off = ANSI_HIGHLIGHT_OFF;
127 /* A special case: make sure that we print a newline when
128 the message is empty. */
129 if (message_len == 0)
133 pos < message + message_len;
134 pos = end + 1, line++) {
135 bool continuation = line > 0;
138 for (end = pos; end < message + message_len && *end != '\n'; end++)
143 /* We need to figure out when we are showing not-last line, *and*
144 * will skip subsequent lines. In that case, we will put the dots
145 * at the end of the line, instead of putting dots in the middle
149 line + 1 == PRINT_LINE_THRESHOLD ||
150 end + 1 >= message + PRINT_CHAR_THRESHOLD;
152 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
153 (prefix + len + 1 < n_columns && !tail_line)) {
154 fprintf(f, "%*s%s%.*s%s\n",
155 continuation * prefix, "",
156 color_on, len, pos, color_off);
160 /* Beyond this point, ellipsization will happen. */
163 if (prefix < n_columns && n_columns - prefix >= 3) {
164 if (n_columns - prefix > (unsigned) len + 3)
165 fprintf(f, "%*s%s%.*s...%s\n",
166 continuation * prefix, "",
167 color_on, len, pos, color_off);
169 _cleanup_free_ char *e;
171 e = ellipsize_mem(pos, len, n_columns - prefix,
172 tail_line ? 100 : 90);
174 fprintf(f, "%*s%s%.*s%s\n",
175 continuation * prefix, "",
176 color_on, len, pos, color_off);
178 fprintf(f, "%*s%s%s%s\n",
179 continuation * prefix, "",
180 color_on, e, color_off);
192 static int output_short(
203 _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
204 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, priority_len = 0;
206 bool ellipsized = false;
211 /* Set the threshold to one bigger than the actual print
212 * threshold, so that if the line is actually longer than what
213 * we're willing to print, ellipsization will occur. This way
214 * we won't output a misleading line without any indication of
217 sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
219 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
221 r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
227 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
233 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
239 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
245 r = parse_field(data, length, "_PID=", &pid, &pid_len);
251 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
257 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
263 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
269 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
280 if (!(flags & OUTPUT_SHOW_ALL))
281 strip_tab_ansi(&message, &message_len);
283 if (priority_len == 1 && *priority >= '0' && *priority <= '7')
286 if (mode == OUTPUT_SHORT_MONOTONIC) {
293 r = safe_atou64(monotonic, &t);
296 r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
299 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
303 fprintf(f, "[%5llu.%06llu]",
304 (unsigned long long) (t / USEC_PER_SEC),
305 (unsigned long long) (t % USEC_PER_SEC));
307 n += 1 + 5 + 1 + 6 + 1;
318 r = safe_atou64(realtime, &x);
321 r = sd_journal_get_realtime_usec(j, &x);
324 log_error("Failed to get realtime timestamp: %s", strerror(-r));
328 t = (time_t) (x / USEC_PER_SEC);
331 case OUTPUT_SHORT_ISO:
332 r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", localtime_r(&t, &tm));
334 case OUTPUT_SHORT_PRECISE:
335 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
337 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
338 ".%06llu", x % USEC_PER_SEC);
342 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
346 log_error("Failed to format time.");
354 if (hostname && shall_print(hostname, hostname_len, flags)) {
355 fprintf(f, " %.*s", (int) hostname_len, hostname);
356 n += hostname_len + 1;
359 if (identifier && shall_print(identifier, identifier_len, flags)) {
360 fprintf(f, " %.*s", (int) identifier_len, identifier);
361 n += identifier_len + 1;
362 } else if (comm && shall_print(comm, comm_len, flags)) {
363 fprintf(f, " %.*s", (int) comm_len, comm);
368 if (pid && shall_print(pid, pid_len, flags)) {
369 fprintf(f, "[%.*s]", (int) pid_len, pid);
371 } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
372 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
373 n += fake_pid_len + 2;
376 if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
377 char bytes[FORMAT_BYTES_MAX];
378 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
382 print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
385 if (flags & OUTPUT_CATALOG)
391 static int output_verbose(
400 _cleanup_free_ char *cursor = NULL;
402 char ts[FORMAT_TIMESTAMP_MAX + 7];
408 sd_journal_set_data_threshold(j, 0);
410 r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
412 log_debug("Source realtime timestamp not found");
414 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
415 "Failed to get source realtime timestamp: %s", strerror(-r));
418 _cleanup_free_ char *value = NULL;
421 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
423 log_debug("_SOURCE_REALTIME_TIMESTAMP invalid: %s", strerror(-r));
425 r = safe_atou64(value, &realtime);
427 log_debug("Failed to parse realtime timestamp: %s",
433 r = sd_journal_get_realtime_usec(j, &realtime);
435 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
436 "Failed to get realtime timestamp: %s", strerror(-r));
441 r = sd_journal_get_cursor(j, &cursor);
443 log_error("Failed to get cursor: %s", strerror(-r));
447 fprintf(f, "%s [%s]\n",
448 format_timestamp_us(ts, sizeof(ts), realtime),
451 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
454 const char *on = "", *off = "";
456 c = memchr(data, '=', length);
458 log_error("Invalid field.");
461 fieldlen = c - (const char*) data;
463 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
464 on = ANSI_HIGHLIGHT_ON;
465 off = ANSI_HIGHLIGHT_OFF;
468 if (flags & OUTPUT_SHOW_ALL ||
469 (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
470 && utf8_is_printable(data, length))) {
471 fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
472 print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
475 char bytes[FORMAT_BYTES_MAX];
477 fprintf(f, " %s%.*s=[%s blob data]%s\n",
479 (int) (c - (const char*) data),
481 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
489 if (flags & OUTPUT_CATALOG)
495 static int output_export(
505 usec_t realtime, monotonic;
506 _cleanup_free_ char *cursor = NULL;
512 sd_journal_set_data_threshold(j, 0);
514 r = sd_journal_get_realtime_usec(j, &realtime);
516 log_error("Failed to get realtime timestamp: %s", strerror(-r));
520 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
522 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
526 r = sd_journal_get_cursor(j, &cursor);
528 log_error("Failed to get cursor: %s", strerror(-r));
534 "__REALTIME_TIMESTAMP=%llu\n"
535 "__MONOTONIC_TIMESTAMP=%llu\n"
538 (unsigned long long) realtime,
539 (unsigned long long) monotonic,
540 sd_id128_to_string(boot_id, sid));
542 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
544 /* We already printed the boot id, from the data in
545 * the header, hence let's suppress it here */
547 startswith(data, "_BOOT_ID="))
550 if (!utf8_is_printable(data, length)) {
554 c = memchr(data, '=', length);
556 log_error("Invalid field.");
560 fwrite(data, c - (const char*) data, 1, f);
562 le64 = htole64(length - (c - (const char*) data) - 1);
563 fwrite(&le64, sizeof(le64), 1, f);
564 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
566 fwrite(data, length, 1, f);
588 if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
592 else if (!utf8_is_printable(p, l)) {
593 bool not_first = false;
599 fprintf(f, ", %u", (uint8_t) *p);
602 fprintf(f, "%u", (uint8_t) *p);
614 if (*p == '"' || *p == '\\') {
617 } else if (*p == '\n')
620 fprintf(f, "\\u%04x", *p);
632 static int output_json(
639 uint64_t realtime, monotonic;
640 _cleanup_free_ char *cursor = NULL;
647 bool done, separator;
651 sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
653 r = sd_journal_get_realtime_usec(j, &realtime);
655 log_error("Failed to get realtime timestamp: %s", strerror(-r));
659 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
661 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
665 r = sd_journal_get_cursor(j, &cursor);
667 log_error("Failed to get cursor: %s", strerror(-r));
671 if (mode == OUTPUT_JSON_PRETTY)
674 "\t\"__CURSOR\" : \"%s\",\n"
675 "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n"
676 "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n"
677 "\t\"_BOOT_ID\" : \"%s\"",
679 (unsigned long long) realtime,
680 (unsigned long long) monotonic,
681 sd_id128_to_string(boot_id, sid));
683 if (mode == OUTPUT_JSON_SSE)
687 "{ \"__CURSOR\" : \"%s\", "
688 "\"__REALTIME_TIMESTAMP\" : \"%llu\", "
689 "\"__MONOTONIC_TIMESTAMP\" : \"%llu\", "
690 "\"_BOOT_ID\" : \"%s\"",
692 (unsigned long long) realtime,
693 (unsigned long long) monotonic,
694 sd_id128_to_string(boot_id, sid));
697 h = hashmap_new(string_hash_func, string_compare_func);
701 /* First round, iterate through the entry and count how often each field appears */
702 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
708 memcmp(data, "_BOOT_ID=", 9) == 0)
711 eq = memchr(data, '=', length);
715 n = strndup(data, eq - (const char*) data);
721 u = PTR_TO_UINT(hashmap_get(h, n));
723 r = hashmap_put(h, n, UINT_TO_PTR(1));
729 r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
743 SD_JOURNAL_FOREACH_DATA(j, data, length) {
749 /* We already printed the boot id, from the data in
750 * the header, hence let's suppress it here */
752 memcmp(data, "_BOOT_ID=", 9) == 0)
755 eq = memchr(data, '=', length);
760 if (mode == OUTPUT_JSON_PRETTY)
766 m = eq - (const char*) data;
768 n = strndup(data, m);
774 u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
776 /* We already printed this, let's jump to the next */
782 /* Field only appears once, output it directly */
784 json_escape(f, data, m, flags);
787 json_escape(f, eq + 1, length - m - 1, flags);
789 hashmap_remove(h, n);
798 /* Field appears multiple times, output it as array */
799 json_escape(f, data, m, flags);
801 json_escape(f, eq + 1, length - m - 1, flags);
803 /* Iterate through the end of the list */
805 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
809 if (memcmp(data, n, m) != 0)
812 if (((const char*) data)[m] != '=')
816 json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
821 hashmap_remove(h, n);
825 /* Iterate data fields form the beginning */
835 if (mode == OUTPUT_JSON_PRETTY)
837 else if (mode == OUTPUT_JSON_SSE)
845 while ((k = hashmap_steal_first_key(h)))
853 static int output_cat(
867 sd_journal_set_data_threshold(j, 0);
869 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
871 /* An entry without MESSAGE=? */
875 log_error("Failed to get data: %s", strerror(-r));
881 fwrite((const char*) data + 8, 1, l - 8, f);
887 static int (*output_funcs[_OUTPUT_MODE_MAX])(
892 OutputFlags flags) = {
894 [OUTPUT_SHORT] = output_short,
895 [OUTPUT_SHORT_ISO] = output_short,
896 [OUTPUT_SHORT_PRECISE] = output_short,
897 [OUTPUT_SHORT_MONOTONIC] = output_short,
898 [OUTPUT_VERBOSE] = output_verbose,
899 [OUTPUT_EXPORT] = output_export,
900 [OUTPUT_JSON] = output_json,
901 [OUTPUT_JSON_PRETTY] = output_json,
902 [OUTPUT_JSON_SSE] = output_json,
903 [OUTPUT_CAT] = output_cat
916 assert(mode < _OUTPUT_MODE_MAX);
919 n_columns = columns();
921 ret = output_funcs[mode](f, j, mode, n_columns, flags);
924 if (ellipsized && ret > 0)
930 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
934 if (!(*flags & OUTPUT_BEGIN_NEWLINE))
937 /* Print a beginning new line if that's request, but only once
938 * on the first line we print. */
941 *flags &= ~OUTPUT_BEGIN_NEWLINE;
945 static int show_journal(FILE *f,
956 bool need_seek = false;
957 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
961 assert(mode < _OUTPUT_MODE_MAX);
964 r = sd_journal_seek_tail(j);
968 r = sd_journal_previous_skip(j, how_many);
977 r = sd_journal_next(j);
987 if (not_before > 0) {
988 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
990 /* -ESTALE is returned if the
991 timestamp is not from this boot */
997 if (usec < not_before)
1002 maybe_print_begin_newline(f, &flags);
1004 r = output_journal(f, j, mode, n_columns, flags, ellipsized);
1009 if (warn_cutoff && line < how_many && not_before > 0) {
1013 /* Check whether the cutoff line is too early */
1015 r = sd_id128_get_boot(&boot_id);
1019 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1023 if (r > 0 && not_before < cutoff) {
1024 maybe_print_begin_newline(f, &flags);
1025 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1028 warn_cutoff = false;
1031 if (!(flags & OUTPUT_FOLLOW))
1034 r = sd_journal_wait(j, (usec_t) -1);
1044 int add_matches_for_unit(sd_journal *j, const char *unit) {
1046 char *m1, *m2, *m3, *m4;
1051 m1 = strappenda("_SYSTEMD_UNIT=", unit);
1052 m2 = strappenda("COREDUMP_UNIT=", unit);
1053 m3 = strappenda("UNIT=", unit);
1054 m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
1057 /* Look for messages from the service itself */
1058 (r = sd_journal_add_match(j, m1, 0)) ||
1060 /* Look for coredumps of the service */
1061 (r = sd_journal_add_disjunction(j)) ||
1062 (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1063 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1064 (r = sd_journal_add_match(j, m2, 0)) ||
1066 /* Look for messages from PID 1 about this service */
1067 (r = sd_journal_add_disjunction(j)) ||
1068 (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1069 (r = sd_journal_add_match(j, m3, 0)) ||
1071 /* Look for messages from authorized daemons about this service */
1072 (r = sd_journal_add_disjunction(j)) ||
1073 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1074 (r = sd_journal_add_match(j, m4, 0))
1077 if (r == 0 && endswith(unit, ".slice")) {
1078 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1080 /* Show all messages belonging to a slice */
1082 (r = sd_journal_add_disjunction(j)) ||
1083 (r = sd_journal_add_match(j, m5, 0))
1090 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1092 char *m1, *m2, *m3, *m4;
1093 char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1098 m1 = strappenda("_SYSTEMD_USER_UNIT=", unit);
1099 m2 = strappenda("USER_UNIT=", unit);
1100 m3 = strappenda("COREDUMP_USER_UNIT=", unit);
1101 m4 = strappenda("OBJECT_SYSTEMD_USER_UNIT=", unit);
1102 sprintf(muid, "_UID=%lu", (unsigned long) uid);
1105 /* Look for messages from the user service itself */
1106 (r = sd_journal_add_match(j, m1, 0)) ||
1107 (r = sd_journal_add_match(j, muid, 0)) ||
1109 /* Look for messages from systemd about this service */
1110 (r = sd_journal_add_disjunction(j)) ||
1111 (r = sd_journal_add_match(j, m2, 0)) ||
1112 (r = sd_journal_add_match(j, muid, 0)) ||
1114 /* Look for coredumps of the service */
1115 (r = sd_journal_add_disjunction(j)) ||
1116 (r = sd_journal_add_match(j, m3, 0)) ||
1117 (r = sd_journal_add_match(j, muid, 0)) ||
1118 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1120 /* Look for messages from authorized daemons about this service */
1121 (r = sd_journal_add_disjunction(j)) ||
1122 (r = sd_journal_add_match(j, m4, 0)) ||
1123 (r = sd_journal_add_match(j, muid, 0)) ||
1124 (r = sd_journal_add_match(j, "_UID=0", 0))
1127 if (r == 0 && endswith(unit, ".slice")) {
1128 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1130 /* Show all messages belonging to a slice */
1132 (r = sd_journal_add_disjunction(j)) ||
1133 (r = sd_journal_add_match(j, m5, 0)) ||
1134 (r = sd_journal_add_match(j, muid, 0))
1141 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1142 _cleanup_close_pipe_ int pair[2] = { -1, -1 };
1143 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1153 if (!filename_is_safe(machine))
1156 r = container_get_leader(machine, &pid);
1160 r = namespace_open(pid, &pidnsfd, &mntnsfd, &rootfd);
1164 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1174 close_nointr_nofail(pair[0]);
1177 r = namespace_enter(pidnsfd, mntnsfd, rootfd);
1179 _exit(EXIT_FAILURE);
1181 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1183 _exit(EXIT_FAILURE);
1185 k = loop_read(fd, buf, 36, false);
1186 close_nointr_nofail(fd);
1188 _exit(EXIT_FAILURE);
1190 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1192 _exit(EXIT_FAILURE);
1194 _exit(EXIT_SUCCESS);
1197 close_nointr_nofail(pair[1]);
1200 r = wait_for_terminate(child, &si);
1201 if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1202 return r < 0 ? r : -EIO;
1204 k = recv(pair[0], buf, 36, 0);
1209 r = sd_id128_from_string(buf, boot_id);
1216 int add_match_this_boot(sd_journal *j, const char *machine) {
1217 char match[9+32+1] = "_BOOT_ID=";
1224 r = get_boot_id_for_machine(machine, &boot_id);
1226 log_error("Failed to get boot id of container %s: %s", machine, strerror(-r));
1230 r = sd_id128_get_boot(&boot_id);
1232 log_error("Failed to get boot id: %s", strerror(-r));
1237 sd_id128_to_string(boot_id, match + 9);
1238 r = sd_journal_add_match(j, match, strlen(match));
1240 log_error("Failed to add match: %s", strerror(-r));
1244 r = sd_journal_add_conjunction(j);
1251 int show_journal_by_unit(
1263 _cleanup_journal_close_ sd_journal*j = NULL;
1265 int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
1268 assert(mode < _OUTPUT_MODE_MAX);
1274 r = sd_journal_open(&j, jflags);
1278 r = add_match_this_boot(j, NULL);
1283 r = add_matches_for_unit(j, unit);
1285 r = add_matches_for_user_unit(j, unit, uid);
1289 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1290 _cleanup_free_ char *filter;
1292 filter = journal_make_match_string(j);
1293 log_debug("Journal filter: %s", filter);
1296 return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1299 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1300 [OUTPUT_SHORT] = "short",
1301 [OUTPUT_SHORT_ISO] = "short-iso",
1302 [OUTPUT_SHORT_PRECISE] = "short-precise",
1303 [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1304 [OUTPUT_VERBOSE] = "verbose",
1305 [OUTPUT_EXPORT] = "export",
1306 [OUTPUT_JSON] = "json",
1307 [OUTPUT_JSON_PRETTY] = "json-pretty",
1308 [OUTPUT_JSON_SSE] = "json-sse",
1309 [OUTPUT_CAT] = "cat"
1312 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);