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;
314 struct tm *(*gettime_r)(const time_t *, struct tm *);
317 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
320 r = safe_atou64(realtime, &x);
323 r = sd_journal_get_realtime_usec(j, &x);
326 log_error("Failed to get realtime timestamp: %s", strerror(-r));
330 t = (time_t) (x / USEC_PER_SEC);
333 case OUTPUT_SHORT_ISO:
334 r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm));
336 case OUTPUT_SHORT_PRECISE:
337 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
339 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
340 ".%06llu", (unsigned long long) (x % USEC_PER_SEC));
344 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
348 log_error("Failed to format time.");
356 if (hostname && shall_print(hostname, hostname_len, flags)) {
357 fprintf(f, " %.*s", (int) hostname_len, hostname);
358 n += hostname_len + 1;
361 if (identifier && shall_print(identifier, identifier_len, flags)) {
362 fprintf(f, " %.*s", (int) identifier_len, identifier);
363 n += identifier_len + 1;
364 } else if (comm && shall_print(comm, comm_len, flags)) {
365 fprintf(f, " %.*s", (int) comm_len, comm);
370 if (pid && shall_print(pid, pid_len, flags)) {
371 fprintf(f, "[%.*s]", (int) pid_len, pid);
373 } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
374 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
375 n += fake_pid_len + 2;
378 if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
379 char bytes[FORMAT_BYTES_MAX];
380 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
384 print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
387 if (flags & OUTPUT_CATALOG)
393 static int output_verbose(
402 _cleanup_free_ char *cursor = NULL;
404 char ts[FORMAT_TIMESTAMP_MAX + 7];
410 sd_journal_set_data_threshold(j, 0);
412 r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
414 log_debug("Source realtime timestamp not found");
416 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
417 "Failed to get source realtime timestamp: %s", strerror(-r));
420 _cleanup_free_ char *value = NULL;
423 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
425 log_debug("_SOURCE_REALTIME_TIMESTAMP invalid: %s", strerror(-r));
427 r = safe_atou64(value, &realtime);
429 log_debug("Failed to parse realtime timestamp: %s",
435 r = sd_journal_get_realtime_usec(j, &realtime);
437 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
438 "Failed to get realtime timestamp: %s", strerror(-r));
443 r = sd_journal_get_cursor(j, &cursor);
445 log_error("Failed to get cursor: %s", strerror(-r));
449 fprintf(f, "%s [%s]\n",
451 format_timestamp_us_utc(ts, sizeof(ts), realtime) :
452 format_timestamp_us(ts, sizeof(ts), realtime),
455 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
458 const char *on = "", *off = "";
460 c = memchr(data, '=', length);
462 log_error("Invalid field.");
465 fieldlen = c - (const char*) data;
467 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
468 on = ANSI_HIGHLIGHT_ON;
469 off = ANSI_HIGHLIGHT_OFF;
472 if (flags & OUTPUT_SHOW_ALL ||
473 (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
474 && utf8_is_printable(data, length))) {
475 fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
476 print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
479 char bytes[FORMAT_BYTES_MAX];
481 fprintf(f, " %s%.*s=[%s blob data]%s\n",
483 (int) (c - (const char*) data),
485 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
493 if (flags & OUTPUT_CATALOG)
499 static int output_export(
509 usec_t realtime, monotonic;
510 _cleanup_free_ char *cursor = NULL;
516 sd_journal_set_data_threshold(j, 0);
518 r = sd_journal_get_realtime_usec(j, &realtime);
520 log_error("Failed to get realtime timestamp: %s", strerror(-r));
524 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
526 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
530 r = sd_journal_get_cursor(j, &cursor);
532 log_error("Failed to get cursor: %s", strerror(-r));
538 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
539 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
544 sd_id128_to_string(boot_id, sid));
546 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
548 /* We already printed the boot id, from the data in
549 * the header, hence let's suppress it here */
551 startswith(data, "_BOOT_ID="))
554 if (utf8_is_printable_newline(data, length, false))
555 fwrite(data, length, 1, f);
560 c = memchr(data, '=', length);
562 log_error("Invalid field.");
566 fwrite(data, c - (const char*) data, 1, f);
568 le64 = htole64(length - (c - (const char*) data) - 1);
569 fwrite(&le64, sizeof(le64), 1, f);
570 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
593 if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
597 else if (!utf8_is_printable(p, l)) {
598 bool not_first = false;
604 fprintf(f, ", %u", (uint8_t) *p);
607 fprintf(f, "%u", (uint8_t) *p);
619 if (*p == '"' || *p == '\\') {
622 } else if (*p == '\n')
625 fprintf(f, "\\u%04x", *p);
637 static int output_json(
644 uint64_t realtime, monotonic;
645 _cleanup_free_ char *cursor = NULL;
652 bool done, separator;
656 sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
658 r = sd_journal_get_realtime_usec(j, &realtime);
660 log_error("Failed to get realtime timestamp: %s", strerror(-r));
664 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
666 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
670 r = sd_journal_get_cursor(j, &cursor);
672 log_error("Failed to get cursor: %s", strerror(-r));
676 if (mode == OUTPUT_JSON_PRETTY)
679 "\t\"__CURSOR\" : \"%s\",\n"
680 "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
681 "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
682 "\t\"_BOOT_ID\" : \"%s\"",
686 sd_id128_to_string(boot_id, sid));
688 if (mode == OUTPUT_JSON_SSE)
692 "{ \"__CURSOR\" : \"%s\", "
693 "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
694 "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
695 "\"_BOOT_ID\" : \"%s\"",
699 sd_id128_to_string(boot_id, sid));
702 h = hashmap_new(&string_hash_ops);
706 /* First round, iterate through the entry and count how often each field appears */
707 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
713 memcmp(data, "_BOOT_ID=", 9) == 0)
716 eq = memchr(data, '=', length);
720 n = strndup(data, eq - (const char*) data);
726 u = PTR_TO_UINT(hashmap_get(h, n));
728 r = hashmap_put(h, n, UINT_TO_PTR(1));
734 r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
748 SD_JOURNAL_FOREACH_DATA(j, data, length) {
754 /* We already printed the boot id, from the data in
755 * the header, hence let's suppress it here */
757 memcmp(data, "_BOOT_ID=", 9) == 0)
760 eq = memchr(data, '=', length);
765 if (mode == OUTPUT_JSON_PRETTY)
771 m = eq - (const char*) data;
773 n = strndup(data, m);
779 u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
781 /* We already printed this, let's jump to the next */
787 /* Field only appears once, output it directly */
789 json_escape(f, data, m, flags);
792 json_escape(f, eq + 1, length - m - 1, flags);
794 hashmap_remove(h, n);
803 /* Field appears multiple times, output it as array */
804 json_escape(f, data, m, flags);
806 json_escape(f, eq + 1, length - m - 1, flags);
808 /* Iterate through the end of the list */
810 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
814 if (memcmp(data, n, m) != 0)
817 if (((const char*) data)[m] != '=')
821 json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
826 hashmap_remove(h, n);
830 /* Iterate data fields form the beginning */
840 if (mode == OUTPUT_JSON_PRETTY)
842 else if (mode == OUTPUT_JSON_SSE)
850 while ((k = hashmap_steal_first_key(h)))
858 static int output_cat(
872 sd_journal_set_data_threshold(j, 0);
874 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
876 /* An entry without MESSAGE=? */
880 log_error("Failed to get data: %s", strerror(-r));
886 fwrite((const char*) data + 8, 1, l - 8, f);
892 static int (*output_funcs[_OUTPUT_MODE_MAX])(
897 OutputFlags flags) = {
899 [OUTPUT_SHORT] = output_short,
900 [OUTPUT_SHORT_ISO] = output_short,
901 [OUTPUT_SHORT_PRECISE] = output_short,
902 [OUTPUT_SHORT_MONOTONIC] = output_short,
903 [OUTPUT_VERBOSE] = output_verbose,
904 [OUTPUT_EXPORT] = output_export,
905 [OUTPUT_JSON] = output_json,
906 [OUTPUT_JSON_PRETTY] = output_json,
907 [OUTPUT_JSON_SSE] = output_json,
908 [OUTPUT_CAT] = output_cat
921 assert(mode < _OUTPUT_MODE_MAX);
924 n_columns = columns();
926 ret = output_funcs[mode](f, j, mode, n_columns, flags);
929 if (ellipsized && ret > 0)
935 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
939 if (!(*flags & OUTPUT_BEGIN_NEWLINE))
942 /* Print a beginning new line if that's request, but only once
943 * on the first line we print. */
946 *flags &= ~OUTPUT_BEGIN_NEWLINE;
950 static int show_journal(FILE *f,
961 bool need_seek = false;
962 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
966 assert(mode < _OUTPUT_MODE_MAX);
969 r = sd_journal_seek_tail(j);
973 r = sd_journal_previous_skip(j, how_many);
982 r = sd_journal_next(j);
992 if (not_before > 0) {
993 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
995 /* -ESTALE is returned if the
996 timestamp is not from this boot */
1002 if (usec < not_before)
1007 maybe_print_begin_newline(f, &flags);
1009 r = output_journal(f, j, mode, n_columns, flags, ellipsized);
1014 if (warn_cutoff && line < how_many && not_before > 0) {
1018 /* Check whether the cutoff line is too early */
1020 r = sd_id128_get_boot(&boot_id);
1024 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1028 if (r > 0 && not_before < cutoff) {
1029 maybe_print_begin_newline(f, &flags);
1030 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1033 warn_cutoff = false;
1036 if (!(flags & OUTPUT_FOLLOW))
1039 r = sd_journal_wait(j, USEC_INFINITY);
1049 int add_matches_for_unit(sd_journal *j, const char *unit) {
1051 char *m1, *m2, *m3, *m4;
1056 m1 = strappenda("_SYSTEMD_UNIT=", unit);
1057 m2 = strappenda("COREDUMP_UNIT=", unit);
1058 m3 = strappenda("UNIT=", unit);
1059 m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
1062 /* Look for messages from the service itself */
1063 (r = sd_journal_add_match(j, m1, 0)) ||
1065 /* Look for coredumps of the service */
1066 (r = sd_journal_add_disjunction(j)) ||
1067 (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1068 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1069 (r = sd_journal_add_match(j, m2, 0)) ||
1071 /* Look for messages from PID 1 about this service */
1072 (r = sd_journal_add_disjunction(j)) ||
1073 (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1074 (r = sd_journal_add_match(j, m3, 0)) ||
1076 /* Look for messages from authorized daemons about this service */
1077 (r = sd_journal_add_disjunction(j)) ||
1078 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1079 (r = sd_journal_add_match(j, m4, 0))
1082 if (r == 0 && endswith(unit, ".slice")) {
1083 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1085 /* Show all messages belonging to a slice */
1087 (r = sd_journal_add_disjunction(j)) ||
1088 (r = sd_journal_add_match(j, m5, 0))
1095 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1097 char *m1, *m2, *m3, *m4;
1098 char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1103 m1 = strappenda("_SYSTEMD_USER_UNIT=", unit);
1104 m2 = strappenda("USER_UNIT=", unit);
1105 m3 = strappenda("COREDUMP_USER_UNIT=", unit);
1106 m4 = strappenda("OBJECT_SYSTEMD_USER_UNIT=", unit);
1107 sprintf(muid, "_UID="UID_FMT, uid);
1110 /* Look for messages from the user service itself */
1111 (r = sd_journal_add_match(j, m1, 0)) ||
1112 (r = sd_journal_add_match(j, muid, 0)) ||
1114 /* Look for messages from systemd about this service */
1115 (r = sd_journal_add_disjunction(j)) ||
1116 (r = sd_journal_add_match(j, m2, 0)) ||
1117 (r = sd_journal_add_match(j, muid, 0)) ||
1119 /* Look for coredumps of the service */
1120 (r = sd_journal_add_disjunction(j)) ||
1121 (r = sd_journal_add_match(j, m3, 0)) ||
1122 (r = sd_journal_add_match(j, muid, 0)) ||
1123 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1125 /* Look for messages from authorized daemons about this service */
1126 (r = sd_journal_add_disjunction(j)) ||
1127 (r = sd_journal_add_match(j, m4, 0)) ||
1128 (r = sd_journal_add_match(j, muid, 0)) ||
1129 (r = sd_journal_add_match(j, "_UID=0", 0))
1132 if (r == 0 && endswith(unit, ".slice")) {
1133 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1135 /* Show all messages belonging to a slice */
1137 (r = sd_journal_add_disjunction(j)) ||
1138 (r = sd_journal_add_match(j, m5, 0)) ||
1139 (r = sd_journal_add_match(j, muid, 0))
1146 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1147 _cleanup_close_pair_ int pair[2] = { -1, -1 };
1148 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1158 if (!machine_name_is_valid(machine))
1161 r = container_get_leader(machine, &pid);
1165 r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
1169 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1179 pair[0] = safe_close(pair[0]);
1181 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
1183 _exit(EXIT_FAILURE);
1185 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1187 _exit(EXIT_FAILURE);
1189 k = loop_read(fd, buf, 36, false);
1192 _exit(EXIT_FAILURE);
1194 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1196 _exit(EXIT_FAILURE);
1198 _exit(EXIT_SUCCESS);
1201 pair[1] = safe_close(pair[1]);
1203 r = wait_for_terminate(child, &si);
1204 if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1205 return r < 0 ? r : -EIO;
1207 k = recv(pair[0], buf, 36, 0);
1212 r = sd_id128_from_string(buf, boot_id);
1219 int add_match_this_boot(sd_journal *j, const char *machine) {
1220 char match[9+32+1] = "_BOOT_ID=";
1227 r = get_boot_id_for_machine(machine, &boot_id);
1229 log_error("Failed to get boot id of container %s: %s", machine, strerror(-r));
1233 r = sd_id128_get_boot(&boot_id);
1235 log_error("Failed to get boot id: %s", strerror(-r));
1240 sd_id128_to_string(boot_id, match + 9);
1241 r = sd_journal_add_match(j, match, strlen(match));
1243 log_error("Failed to add match: %s", strerror(-r));
1247 r = sd_journal_add_conjunction(j);
1254 int show_journal_by_unit(
1266 _cleanup_journal_close_ sd_journal*j = NULL;
1268 int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
1271 assert(mode < _OUTPUT_MODE_MAX);
1277 r = sd_journal_open(&j, jflags);
1281 r = add_match_this_boot(j, NULL);
1286 r = add_matches_for_unit(j, unit);
1288 r = add_matches_for_user_unit(j, unit, uid);
1292 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1293 _cleanup_free_ char *filter;
1295 filter = journal_make_match_string(j);
1296 log_debug("Journal filter: %s", filter);
1299 return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1302 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1303 [OUTPUT_SHORT] = "short",
1304 [OUTPUT_SHORT_ISO] = "short-iso",
1305 [OUTPUT_SHORT_PRECISE] = "short-precise",
1306 [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1307 [OUTPUT_VERBOSE] = "verbose",
1308 [OUTPUT_EXPORT] = "export",
1309 [OUTPUT_JSON] = "json",
1310 [OUTPUT_JSON_PRETTY] = "json-pretty",
1311 [OUTPUT_JSON_SSE] = "json-sse",
1312 [OUTPUT_CAT] = "cat"
1315 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);