]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/logs-show.c
journald: suppress low-level audit text prefix in MESSAGE= field
[thirdparty/systemd.git] / src / shared / logs-show.c
CommitLineData
86aa7ba4
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2012 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
86aa7ba4
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
86aa7ba4 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
86aa7ba4
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <time.h>
23#include <assert.h>
24#include <errno.h>
df50185b 25#include <sys/poll.h>
2a410422 26#include <sys/socket.h>
55d7bfc1 27#include <string.h>
b6741478 28#include <fcntl.h>
86aa7ba4
LP
29
30#include "logs-show.h"
31#include "log.h"
32#include "util.h"
ba961854 33#include "utf8.h"
d99ae53a 34#include "hashmap.h"
b6741478 35#include "fileio.h"
dfb33a97 36#include "journal-internal.h"
86aa7ba4 37
a6f0104a
ZJS
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
42
08ace05b 43#define JSON_THRESHOLD 4096
86aa7ba4 44
d4205751
LP
45static int print_catalog(FILE *f, sd_journal *j) {
46 int r;
47 _cleanup_free_ char *t = NULL, *z = NULL;
48
49
50 r = sd_journal_get_catalog(j, &t);
51 if (r < 0)
52 return r;
53
54 z = strreplace(strstrip(t), "\n", "\n-- ");
55 if (!z)
56 return log_oom();
57
58 fputs("-- ", f);
59 fputs(z, f);
60 fputc('\n', f);
61
62 return 0;
63}
64
55d7bfc1
LP
65static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
66 size_t fl, nl;
67 void *buf;
68
69 assert(data);
70 assert(field);
71 assert(target);
72 assert(target_size);
73
74 fl = strlen(field);
75 if (length < fl)
76 return 0;
77
78 if (memcmp(data, field, fl))
79 return 0;
80
81 nl = length - fl;
bf967366 82 buf = malloc(nl+1);
0d0f0c50
SL
83 if (!buf)
84 return log_oom();
55d7bfc1 85
46b0d922
LP
86 memcpy(buf, (const char*) data + fl, nl);
87 ((char*)buf)[nl] = 0;
88
6c1e6b98 89 free(*target);
55d7bfc1
LP
90 *target = buf;
91 *target_size = nl;
92
93 return 1;
94}
95
08ace05b
LP
96static bool shall_print(const char *p, size_t l, OutputFlags flags) {
97 assert(p);
98
99 if (flags & OUTPUT_SHOW_ALL)
55d7bfc1
LP
100 return true;
101
a6f0104a 102 if (l >= PRINT_CHAR_THRESHOLD)
55d7bfc1
LP
103 return false;
104
31f7bf19 105 if (!utf8_is_printable(p, l))
55d7bfc1
LP
106 return false;
107
108 return true;
109}
110
00f117a5 111static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
31f7bf19
ZJS
112 const char *color_on = "", *color_off = "";
113 const char *pos, *end;
94e0bd7d 114 bool ellipsized = false;
a6f0104a 115 int line = 0;
31f7bf19
ZJS
116
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;
124 }
125 }
126
47d80904
UU
127 /* A special case: make sure that we print a newline when
128 the message is empty. */
129 if (message_len == 0)
130 fputs("\n", f);
131
a6f0104a
ZJS
132 for (pos = message;
133 pos < message + message_len;
134 pos = end + 1, line++) {
135 bool continuation = line > 0;
136 bool tail_line;
31f7bf19
ZJS
137 int len;
138 for (end = pos; end < message + message_len && *end != '\n'; end++)
139 ;
140 len = end - pos;
141 assert(len >= 0);
142
2526d626 143 /* We need to figure out when we are showing not-last line, *and*
a6f0104a
ZJS
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
146 * or not at all.
147 */
148 tail_line =
149 line + 1 == PRINT_LINE_THRESHOLD ||
2526d626 150 end + 1 >= message + PRINT_CHAR_THRESHOLD;
a6f0104a
ZJS
151
152 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
153 (prefix + len + 1 < n_columns && !tail_line)) {
31f7bf19
ZJS
154 fprintf(f, "%*s%s%.*s%s\n",
155 continuation * prefix, "",
156 color_on, len, pos, color_off);
a6f0104a
ZJS
157 continue;
158 }
31f7bf19 159
a6f0104a
ZJS
160 /* Beyond this point, ellipsization will happen. */
161 ellipsized = true;
31f7bf19 162
a6f0104a
ZJS
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",
b4b02cbe
ZJS
166 continuation * prefix, "",
167 color_on, len, pos, color_off);
a6f0104a
ZJS
168 else {
169 _cleanup_free_ char *e;
170
171 e = ellipsize_mem(pos, len, n_columns - prefix,
172 tail_line ? 100 : 90);
173 if (!e)
174 fprintf(f, "%*s%s%.*s%s\n",
175 continuation * prefix, "",
176 color_on, len, pos, color_off);
177 else
178 fprintf(f, "%*s%s%s%s\n",
179 continuation * prefix, "",
180 color_on, e, color_off);
181 }
182 } else
31f7bf19
ZJS
183 fputs("...\n", f);
184
a6f0104a
ZJS
185 if (tail_line)
186 break;
31f7bf19 187 }
94e0bd7d
ZJS
188
189 return ellipsized;
31f7bf19
ZJS
190}
191
08ace05b
LP
192static int output_short(
193 FILE *f,
194 sd_journal *j,
195 OutputMode mode,
196 unsigned n_columns,
197 OutputFlags flags) {
198
86aa7ba4 199 int r;
86aa7ba4
LP
200 const void *data;
201 size_t length;
202 size_t n = 0;
08ace05b 203 _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
49826187
LP
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;
205 int p = LOG_INFO;
94e0bd7d 206 bool ellipsized = false;
86aa7ba4 207
08ace05b 208 assert(f);
86aa7ba4
LP
209 assert(j);
210
a6f0104a 211 /* Set the threshold to one bigger than the actual print
69ab8088 212 * threshold, so that if the line is actually longer than what
a6f0104a
ZJS
213 * we're willing to print, ellipsization will occur. This way
214 * we won't output a misleading line without any indication of
215 * truncation.
216 */
217 sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
93b73b06 218
a72b6353 219 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
55d7bfc1 220
49826187
LP
221 r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
222 if (r < 0)
08ace05b 223 return r;
49826187
LP
224 else if (r > 0)
225 continue;
226
55d7bfc1
LP
227 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
228 if (r < 0)
08ace05b 229 return r;
55d7bfc1
LP
230 else if (r > 0)
231 continue;
232
4cd9a9d9 233 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
55d7bfc1 234 if (r < 0)
08ace05b 235 return r;
55d7bfc1
LP
236 else if (r > 0)
237 continue;
238
239 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
240 if (r < 0)
08ace05b 241 return r;
55d7bfc1
LP
242 else if (r > 0)
243 continue;
244
245 r = parse_field(data, length, "_PID=", &pid, &pid_len);
246 if (r < 0)
08ace05b 247 return r;
55d7bfc1
LP
248 else if (r > 0)
249 continue;
250
6c1e6b98
LP
251 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
252 if (r < 0)
08ace05b 253 return r;
6c1e6b98
LP
254 else if (r > 0)
255 continue;
256
bf967366
LP
257 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
258 if (r < 0)
08ace05b 259 return r;
bf967366
LP
260 else if (r > 0)
261 continue;
262
263 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
264 if (r < 0)
08ace05b 265 return r;
bf967366
LP
266 else if (r > 0)
267 continue;
268
55d7bfc1
LP
269 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
270 if (r < 0)
08ace05b 271 return r;
55d7bfc1
LP
272 }
273
a72b6353
ZJS
274 if (r < 0)
275 return r;
276
08ace05b
LP
277 if (!message)
278 return 0;
55d7bfc1 279
e8bc0ea2
LP
280 if (!(flags & OUTPUT_SHOW_ALL))
281 strip_tab_ansi(&message, &message_len);
282
49826187
LP
283 if (priority_len == 1 && *priority >= '0' && *priority <= '7')
284 p = *priority - '0';
285
a6e87e90 286 if (mode == OUTPUT_SHORT_MONOTONIC) {
67a12205 287 uint64_t t;
3ebcdf8c
LP
288 sd_id128_t boot_id;
289
bf967366
LP
290 r = -ENOENT;
291
292 if (monotonic)
293 r = safe_atou64(monotonic, &t);
294
295 if (r < 0)
3ebcdf8c 296 r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
86aa7ba4 297
3ebcdf8c 298 if (r < 0) {
a72b6353 299 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
08ace05b 300 return r;
67a12205
LP
301 }
302
08ace05b 303 fprintf(f, "[%5llu.%06llu]",
609e002e
LP
304 (unsigned long long) (t / USEC_PER_SEC),
305 (unsigned long long) (t % USEC_PER_SEC));
3ebcdf8c
LP
306
307 n += 1 + 5 + 1 + 6 + 1;
308
67a12205
LP
309 } else {
310 char buf[64];
bf967366 311 uint64_t x;
67a12205
LP
312 time_t t;
313 struct tm tm;
9fd29044 314 struct tm *(*gettime_r)(const time_t *, struct tm *);
731a676c 315
bf967366 316 r = -ENOENT;
9fd29044 317 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
bf967366
LP
318
319 if (realtime)
320 r = safe_atou64(realtime, &x);
321
322 if (r < 0)
323 r = sd_journal_get_realtime_usec(j, &x);
67a12205 324
67a12205 325 if (r < 0) {
a72b6353 326 log_error("Failed to get realtime timestamp: %s", strerror(-r));
08ace05b 327 return r;
67a12205
LP
328 }
329
bf967366 330 t = (time_t) (x / USEC_PER_SEC);
f02d8367
ZJS
331
332 switch(mode) {
333 case OUTPUT_SHORT_ISO:
9fd29044 334 r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm));
f02d8367
ZJS
335 break;
336 case OUTPUT_SHORT_PRECISE:
9fd29044 337 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
f02d8367
ZJS
338 if (r > 0) {
339 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
609e002e 340 ".%06llu", (unsigned long long) (x % USEC_PER_SEC));
f02d8367
ZJS
341 }
342 break;
343 default:
9fd29044 344 r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
f02d8367 345 }
44bc6e1f
TT
346
347 if (r <= 0) {
67a12205 348 log_error("Failed to format time.");
44bc6e1f 349 return -EINVAL;
67a12205
LP
350 }
351
08ace05b 352 fputs(buf, f);
67a12205
LP
353 n += strlen(buf);
354 }
86aa7ba4 355
08ace05b
LP
356 if (hostname && shall_print(hostname, hostname_len, flags)) {
357 fprintf(f, " %.*s", (int) hostname_len, hostname);
55d7bfc1
LP
358 n += hostname_len + 1;
359 }
360
08ace05b
LP
361 if (identifier && shall_print(identifier, identifier_len, flags)) {
362 fprintf(f, " %.*s", (int) identifier_len, identifier);
4cd9a9d9 363 n += identifier_len + 1;
08ace05b
LP
364 } else if (comm && shall_print(comm, comm_len, flags)) {
365 fprintf(f, " %.*s", (int) comm_len, comm);
55d7bfc1 366 n += comm_len + 1;
b5936820 367 } else
08ace05b 368 fputc(' ', f);
86aa7ba4 369
08ace05b
LP
370 if (pid && shall_print(pid, pid_len, flags)) {
371 fprintf(f, "[%.*s]", (int) pid_len, pid);
55d7bfc1 372 n += pid_len + 2;
08ace05b
LP
373 } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
374 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
6c1e6b98 375 n += fake_pid_len + 2;
86aa7ba4
LP
376 }
377
31f7bf19 378 if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
e6acda19 379 char bytes[FORMAT_BYTES_MAX];
08ace05b 380 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
31f7bf19
ZJS
381 } else {
382 fputs(": ", f);
94e0bd7d
ZJS
383 ellipsized |=
384 print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
31f7bf19 385 }
55d7bfc1 386
d4205751
LP
387 if (flags & OUTPUT_CATALOG)
388 print_catalog(f, j);
389
94e0bd7d 390 return ellipsized;
86aa7ba4
LP
391}
392
08ace05b
LP
393static int output_verbose(
394 FILE *f,
395 sd_journal *j,
396 OutputMode mode,
397 unsigned n_columns,
398 OutputFlags flags) {
399
86aa7ba4
LP
400 const void *data;
401 size_t length;
7fd1b19b 402 _cleanup_free_ char *cursor = NULL;
86aa7ba4 403 uint64_t realtime;
f02d8367 404 char ts[FORMAT_TIMESTAMP_MAX + 7];
86aa7ba4
LP
405 int r;
406
08ace05b 407 assert(f);
86aa7ba4
LP
408 assert(j);
409
93b73b06
LP
410 sd_journal_set_data_threshold(j, 0);
411
cf40f0be
ZJS
412 r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
413 if (r == -ENOENT)
414 log_debug("Source realtime timestamp not found");
415 else if (r < 0) {
a72b6353 416 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
cf40f0be 417 "Failed to get source realtime timestamp: %s", strerror(-r));
86aa7ba4 418 return r;
cf40f0be
ZJS
419 } else {
420 _cleanup_free_ char *value = NULL;
421 size_t size;
422
423 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
424 if (r < 0)
425 log_debug("_SOURCE_REALTIME_TIMESTAMP invalid: %s", strerror(-r));
426 else {
427 r = safe_atou64(value, &realtime);
428 if (r < 0)
429 log_debug("Failed to parse realtime timestamp: %s",
430 strerror(-r));
431 }
432 }
433
434 if (r < 0) {
435 r = sd_journal_get_realtime_usec(j, &realtime);
436 if (r < 0) {
437 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
438 "Failed to get realtime timestamp: %s", strerror(-r));
439 return r;
440 }
86aa7ba4
LP
441 }
442
443 r = sd_journal_get_cursor(j, &cursor);
444 if (r < 0) {
445 log_error("Failed to get cursor: %s", strerror(-r));
446 return r;
447 }
448
08ace05b 449 fprintf(f, "%s [%s]\n",
5ab99e07
LP
450 flags & OUTPUT_UTC ?
451 format_timestamp_us_utc(ts, sizeof(ts), realtime) :
452 format_timestamp_us(ts, sizeof(ts), realtime),
08ace05b 453 cursor);
86aa7ba4 454
a72b6353 455 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
31f7bf19
ZJS
456 const char *c;
457 int fieldlen;
7ac4fa7e
ZJS
458 const char *on = "", *off = "";
459
31f7bf19
ZJS
460 c = memchr(data, '=', length);
461 if (!c) {
462 log_error("Invalid field.");
463 return -EINVAL;
464 }
465 fieldlen = c - (const char*) data;
86aa7ba4 466
7ac4fa7e
ZJS
467 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
468 on = ANSI_HIGHLIGHT_ON;
469 off = ANSI_HIGHLIGHT_OFF;
470 }
471
472 if (flags & OUTPUT_SHOW_ALL ||
a6f0104a
ZJS
473 (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
474 && utf8_is_printable(data, length))) {
7ac4fa7e 475 fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
31f7bf19 476 print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
7ac4fa7e 477 fputs(off, f);
31f7bf19
ZJS
478 } else {
479 char bytes[FORMAT_BYTES_MAX];
86aa7ba4 480
7ac4fa7e
ZJS
481 fprintf(f, " %s%.*s=[%s blob data]%s\n",
482 on,
31f7bf19
ZJS
483 (int) (c - (const char*) data),
484 (const char*) data,
7ac4fa7e
ZJS
485 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
486 off);
31f7bf19 487 }
86aa7ba4
LP
488 }
489
a72b6353
ZJS
490 if (r < 0)
491 return r;
492
d4205751
LP
493 if (flags & OUTPUT_CATALOG)
494 print_catalog(f, j);
495
86aa7ba4
LP
496 return 0;
497}
498
08ace05b
LP
499static int output_export(
500 FILE *f,
501 sd_journal *j,
502 OutputMode mode,
503 unsigned n_columns,
504 OutputFlags flags) {
505
86aa7ba4
LP
506 sd_id128_t boot_id;
507 char sid[33];
508 int r;
509 usec_t realtime, monotonic;
7fd1b19b 510 _cleanup_free_ char *cursor = NULL;
86aa7ba4
LP
511 const void *data;
512 size_t length;
513
514 assert(j);
515
93b73b06
LP
516 sd_journal_set_data_threshold(j, 0);
517
86aa7ba4
LP
518 r = sd_journal_get_realtime_usec(j, &realtime);
519 if (r < 0) {
520 log_error("Failed to get realtime timestamp: %s", strerror(-r));
521 return r;
522 }
523
524 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
525 if (r < 0) {
526 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
527 return r;
528 }
529
530 r = sd_journal_get_cursor(j, &cursor);
531 if (r < 0) {
532 log_error("Failed to get cursor: %s", strerror(-r));
533 return r;
534 }
535
08ace05b
LP
536 fprintf(f,
537 "__CURSOR=%s\n"
de0671ee
ZJS
538 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
539 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
08ace05b
LP
540 "_BOOT_ID=%s\n",
541 cursor,
de0671ee
ZJS
542 realtime,
543 monotonic,
08ace05b 544 sd_id128_to_string(boot_id, sid));
86aa7ba4 545
a72b6353 546 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
86aa7ba4 547
112301ae
LP
548 /* We already printed the boot id, from the data in
549 * the header, hence let's suppress it here */
550 if (length >= 9 &&
2a0e0692 551 startswith(data, "_BOOT_ID="))
112301ae
LP
552 continue;
553
0ade5ffe
ZJS
554 if (utf8_is_printable_newline(data, length, false))
555 fwrite(data, length, 1, f);
556 else {
86aa7ba4
LP
557 const char *c;
558 uint64_t le64;
559
560 c = memchr(data, '=', length);
561 if (!c) {
562 log_error("Invalid field.");
563 return -EINVAL;
564 }
565
08ace05b
LP
566 fwrite(data, c - (const char*) data, 1, f);
567 fputc('\n', f);
86aa7ba4 568 le64 = htole64(length - (c - (const char*) data) - 1);
08ace05b
LP
569 fwrite(&le64, sizeof(le64), 1, f);
570 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
0ade5ffe 571 }
86aa7ba4 572
08ace05b 573 fputc('\n', f);
86aa7ba4
LP
574 }
575
a72b6353
ZJS
576 if (r < 0)
577 return r;
578
08ace05b 579 fputc('\n', f);
86aa7ba4
LP
580
581 return 0;
582}
583
240a5fe8 584void json_escape(
08ace05b
LP
585 FILE *f,
586 const char* p,
587 size_t l,
588 OutputFlags flags) {
589
590 assert(f);
591 assert(p);
592
93b73b06 593 if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
08ace05b
LP
594
595 fputs("null", f);
596
31f7bf19 597 else if (!utf8_is_printable(p, l)) {
86aa7ba4
LP
598 bool not_first = false;
599
08ace05b 600 fputs("[ ", f);
86aa7ba4
LP
601
602 while (l > 0) {
603 if (not_first)
08ace05b 604 fprintf(f, ", %u", (uint8_t) *p);
86aa7ba4
LP
605 else {
606 not_first = true;
08ace05b 607 fprintf(f, "%u", (uint8_t) *p);
86aa7ba4
LP
608 }
609
610 p++;
611 l--;
612 }
613
08ace05b 614 fputs(" ]", f);
86aa7ba4 615 } else {
08ace05b 616 fputc('\"', f);
86aa7ba4
LP
617
618 while (l > 0) {
619 if (*p == '"' || *p == '\\') {
08ace05b
LP
620 fputc('\\', f);
621 fputc(*p, f);
31f7bf19
ZJS
622 } else if (*p == '\n')
623 fputs("\\n", f);
624 else if (*p < ' ')
08ace05b
LP
625 fprintf(f, "\\u%04x", *p);
626 else
627 fputc(*p, f);
86aa7ba4
LP
628
629 p++;
630 l--;
631 }
632
08ace05b 633 fputc('\"', f);
86aa7ba4
LP
634 }
635}
636
08ace05b
LP
637static int output_json(
638 FILE *f,
639 sd_journal *j,
640 OutputMode mode,
641 unsigned n_columns,
642 OutputFlags flags) {
643
86aa7ba4 644 uint64_t realtime, monotonic;
7fd1b19b 645 _cleanup_free_ char *cursor = NULL;
86aa7ba4
LP
646 const void *data;
647 size_t length;
648 sd_id128_t boot_id;
2e729834 649 char sid[33], *k;
86aa7ba4 650 int r;
d99ae53a
LP
651 Hashmap *h = NULL;
652 bool done, separator;
86aa7ba4
LP
653
654 assert(j);
655
93b73b06
LP
656 sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
657
86aa7ba4
LP
658 r = sd_journal_get_realtime_usec(j, &realtime);
659 if (r < 0) {
660 log_error("Failed to get realtime timestamp: %s", strerror(-r));
661 return r;
662 }
663
664 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
665 if (r < 0) {
666 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
667 return r;
668 }
669
670 r = sd_journal_get_cursor(j, &cursor);
671 if (r < 0) {
672 log_error("Failed to get cursor: %s", strerror(-r));
673 return r;
674 }
675
a6e87e90 676 if (mode == OUTPUT_JSON_PRETTY)
08ace05b
LP
677 fprintf(f,
678 "{\n"
679 "\t\"__CURSOR\" : \"%s\",\n"
de0671ee
ZJS
680 "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
681 "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
08ace05b
LP
682 "\t\"_BOOT_ID\" : \"%s\"",
683 cursor,
de0671ee
ZJS
684 realtime,
685 monotonic,
08ace05b 686 sd_id128_to_string(boot_id, sid));
48383c25
LP
687 else {
688 if (mode == OUTPUT_JSON_SSE)
689 fputs("data: ", f);
690
08ace05b
LP
691 fprintf(f,
692 "{ \"__CURSOR\" : \"%s\", "
de0671ee
ZJS
693 "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
694 "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
08ace05b
LP
695 "\"_BOOT_ID\" : \"%s\"",
696 cursor,
de0671ee
ZJS
697 realtime,
698 monotonic,
08ace05b 699 sd_id128_to_string(boot_id, sid));
48383c25 700 }
86aa7ba4 701
d5099efc 702 h = hashmap_new(&string_hash_ops);
d99ae53a
LP
703 if (!h)
704 return -ENOMEM;
705
706 /* First round, iterate through the entry and count how often each field appears */
a72b6353 707 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
d99ae53a
LP
708 const char *eq;
709 char *n;
710 unsigned u;
86aa7ba4 711
112301ae
LP
712 if (length >= 9 &&
713 memcmp(data, "_BOOT_ID=", 9) == 0)
714 continue;
715
d99ae53a
LP
716 eq = memchr(data, '=', length);
717 if (!eq)
718 continue;
86aa7ba4 719
d99ae53a
LP
720 n = strndup(data, eq - (const char*) data);
721 if (!n) {
722 r = -ENOMEM;
723 goto finish;
724 }
a6e87e90 725
d99ae53a
LP
726 u = PTR_TO_UINT(hashmap_get(h, n));
727 if (u == 0) {
728 r = hashmap_put(h, n, UINT_TO_PTR(1));
729 if (r < 0) {
730 free(n);
731 goto finish;
732 }
733 } else {
734 r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
735 free(n);
736 if (r < 0)
737 goto finish;
738 }
86aa7ba4
LP
739 }
740
a72b6353
ZJS
741 if (r < 0)
742 return r;
743
d99ae53a
LP
744 separator = true;
745 do {
746 done = true;
747
748 SD_JOURNAL_FOREACH_DATA(j, data, length) {
749 const char *eq;
750 char *kk, *n;
751 size_t m;
752 unsigned u;
753
754 /* We already printed the boot id, from the data in
755 * the header, hence let's suppress it here */
756 if (length >= 9 &&
757 memcmp(data, "_BOOT_ID=", 9) == 0)
758 continue;
759
760 eq = memchr(data, '=', length);
761 if (!eq)
762 continue;
763
764 if (separator) {
765 if (mode == OUTPUT_JSON_PRETTY)
766 fputs(",\n\t", f);
767 else
768 fputs(", ", f);
769 }
770
771 m = eq - (const char*) data;
772
773 n = strndup(data, m);
774 if (!n) {
775 r = -ENOMEM;
776 goto finish;
777 }
778
779 u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
780 if (u == 0) {
781 /* We already printed this, let's jump to the next */
782 free(n);
783 separator = false;
784
785 continue;
786 } else if (u == 1) {
787 /* Field only appears once, output it directly */
788
789 json_escape(f, data, m, flags);
790 fputs(" : ", f);
791
792 json_escape(f, eq + 1, length - m - 1, flags);
793
794 hashmap_remove(h, n);
795 free(kk);
796 free(n);
797
798 separator = true;
799
800 continue;
801
802 } else {
803 /* Field appears multiple times, output it as array */
804 json_escape(f, data, m, flags);
805 fputs(" : [ ", f);
806 json_escape(f, eq + 1, length - m - 1, flags);
807
808 /* Iterate through the end of the list */
809
810 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
811 if (length < m + 1)
812 continue;
813
814 if (memcmp(data, n, m) != 0)
815 continue;
816
817 if (((const char*) data)[m] != '=')
818 continue;
819
820 fputs(", ", f);
821 json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
822 }
823
824 fputs(" ]", f);
825
826 hashmap_remove(h, n);
827 free(kk);
828 free(n);
829
830 /* Iterate data fields form the beginning */
831 done = false;
832 separator = true;
833
834 break;
835 }
836 }
837
838 } while (!done);
839
a6e87e90 840 if (mode == OUTPUT_JSON_PRETTY)
08ace05b 841 fputs("\n}\n", f);
48383c25
LP
842 else if (mode == OUTPUT_JSON_SSE)
843 fputs("}\n\n", f);
a6e87e90 844 else
08ace05b 845 fputs(" }\n", f);
86aa7ba4 846
d99ae53a
LP
847 r = 0;
848
849finish:
850 while ((k = hashmap_steal_first_key(h)))
851 free(k);
852
853 hashmap_free(h);
854
855 return r;
86aa7ba4
LP
856}
857
08ace05b
LP
858static int output_cat(
859 FILE *f,
860 sd_journal *j,
861 OutputMode mode,
862 unsigned n_columns,
863 OutputFlags flags) {
864
d3f2bdbf
LP
865 const void *data;
866 size_t l;
867 int r;
868
869 assert(j);
08ace05b 870 assert(f);
d3f2bdbf 871
93b73b06
LP
872 sd_journal_set_data_threshold(j, 0);
873
d3f2bdbf
LP
874 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
875 if (r < 0) {
c198300f
LP
876 /* An entry without MESSAGE=? */
877 if (r == -ENOENT)
878 return 0;
879
d3f2bdbf
LP
880 log_error("Failed to get data: %s", strerror(-r));
881 return r;
882 }
883
884 assert(l >= 8);
885
08ace05b
LP
886 fwrite((const char*) data + 8, 1, l - 8, f);
887 fputc('\n', f);
d3f2bdbf
LP
888
889 return 0;
890}
891
08ace05b
LP
892static int (*output_funcs[_OUTPUT_MODE_MAX])(
893 FILE *f,
894 sd_journal*j,
895 OutputMode mode,
896 unsigned n_columns,
897 OutputFlags flags) = {
898
a6e87e90 899 [OUTPUT_SHORT] = output_short,
44bc6e1f 900 [OUTPUT_SHORT_ISO] = output_short,
f02d8367
ZJS
901 [OUTPUT_SHORT_PRECISE] = output_short,
902 [OUTPUT_SHORT_MONOTONIC] = output_short,
86aa7ba4
LP
903 [OUTPUT_VERBOSE] = output_verbose,
904 [OUTPUT_EXPORT] = output_export,
d3f2bdbf 905 [OUTPUT_JSON] = output_json,
a6e87e90 906 [OUTPUT_JSON_PRETTY] = output_json,
48383c25 907 [OUTPUT_JSON_SSE] = output_json,
d3f2bdbf 908 [OUTPUT_CAT] = output_cat
86aa7ba4
LP
909};
910
08ace05b
LP
911int output_journal(
912 FILE *f,
913 sd_journal *j,
914 OutputMode mode,
915 unsigned n_columns,
94e0bd7d
ZJS
916 OutputFlags flags,
917 bool *ellipsized) {
08ace05b 918
e268b81e 919 int ret;
df50185b 920 assert(mode >= 0);
86aa7ba4
LP
921 assert(mode < _OUTPUT_MODE_MAX);
922
34a35ece
LP
923 if (n_columns <= 0)
924 n_columns = columns();
925
08ace05b 926 ret = output_funcs[mode](f, j, mode, n_columns, flags);
e268b81e 927 fflush(stdout);
94e0bd7d
ZJS
928
929 if (ellipsized && ret > 0)
930 *ellipsized = true;
931
e268b81e 932 return ret;
86aa7ba4
LP
933}
934
ea6c2dd1
LP
935static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
936 assert(f);
937 assert(flags);
938
939 if (!(*flags & OUTPUT_BEGIN_NEWLINE))
940 return 0;
941
942 /* Print a beginning new line if that's request, but only once
943 * on the first line we print. */
944
945 fputc('\n', f);
946 *flags &= ~OUTPUT_BEGIN_NEWLINE;
947 return 0;
948}
949
1a6c43e9
MT
950static int show_journal(FILE *f,
951 sd_journal *j,
952 OutputMode mode,
953 unsigned n_columns,
954 usec_t not_before,
955 unsigned how_many,
94e0bd7d
ZJS
956 OutputFlags flags,
957 bool *ellipsized) {
86aa7ba4 958
86aa7ba4 959 int r;
df50185b
LP
960 unsigned line = 0;
961 bool need_seek = false;
085d7120 962 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
86aa7ba4 963
1a6c43e9 964 assert(j);
df50185b
LP
965 assert(mode >= 0);
966 assert(mode < _OUTPUT_MODE_MAX);
1946b0bd
LP
967
968 /* Seek to end */
86aa7ba4
LP
969 r = sd_journal_seek_tail(j);
970 if (r < 0)
971 goto finish;
972
df50185b
LP
973 r = sd_journal_previous_skip(j, how_many);
974 if (r < 0)
975 goto finish;
86aa7ba4 976
df50185b
LP
977 for (;;) {
978 for (;;) {
979 usec_t usec;
980
981 if (need_seek) {
982 r = sd_journal_next(j);
983 if (r < 0)
984 goto finish;
985 }
986
987 if (r == 0)
988 break;
86aa7ba4 989
df50185b
LP
990 need_seek = true;
991
992 if (not_before > 0) {
993 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
994
995 /* -ESTALE is returned if the
996 timestamp is not from this boot */
997 if (r == -ESTALE)
998 continue;
999 else if (r < 0)
1000 goto finish;
1001
1002 if (usec < not_before)
1003 continue;
1004 }
1005
1006 line ++;
ea6c2dd1 1007 maybe_print_begin_newline(f, &flags);
df50185b 1008
94e0bd7d 1009 r = output_journal(f, j, mode, n_columns, flags, ellipsized);
df50185b
LP
1010 if (r < 0)
1011 goto finish;
1012 }
1013
08984293
LP
1014 if (warn_cutoff && line < how_many && not_before > 0) {
1015 sd_id128_t boot_id;
1016 usec_t cutoff;
1017
1018 /* Check whether the cutoff line is too early */
1019
1020 r = sd_id128_get_boot(&boot_id);
1021 if (r < 0)
1022 goto finish;
1023
1024 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1025 if (r < 0)
1026 goto finish;
1027
ea6c2dd1
LP
1028 if (r > 0 && not_before < cutoff) {
1029 maybe_print_begin_newline(f, &flags);
08ace05b 1030 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
ea6c2dd1 1031 }
08984293
LP
1032
1033 warn_cutoff = false;
1034 }
1035
085d7120 1036 if (!(flags & OUTPUT_FOLLOW))
86aa7ba4
LP
1037 break;
1038
3a43da28 1039 r = sd_journal_wait(j, USEC_INFINITY);
df50185b
LP
1040 if (r < 0)
1041 goto finish;
1042
86aa7ba4
LP
1043 }
1044
1a6c43e9
MT
1045finish:
1046 return r;
1047}
1048
886a64fe 1049int add_matches_for_unit(sd_journal *j, const char *unit) {
1a6c43e9 1050 int r;
2d0b2e87 1051 char *m1, *m2, *m3, *m4;
1a6c43e9 1052
886a64fe 1053 assert(j);
1a6c43e9
MT
1054 assert(unit);
1055
2d0b2e87
ZJS
1056 m1 = strappenda("_SYSTEMD_UNIT=", unit);
1057 m2 = strappenda("COREDUMP_UNIT=", unit);
1058 m3 = strappenda("UNIT=", unit);
1059 m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
1a6c43e9 1060
886a64fe
ZJS
1061 (void)(
1062 /* Look for messages from the service itself */
1063 (r = sd_journal_add_match(j, m1, 0)) ||
1064
1065 /* Look for coredumps of the service */
1066 (r = sd_journal_add_disjunction(j)) ||
fdcd37df
ZJS
1067 (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1068 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
886a64fe
ZJS
1069 (r = sd_journal_add_match(j, m2, 0)) ||
1070
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)) ||
2d0b2e87
ZJS
1074 (r = sd_journal_add_match(j, m3, 0)) ||
1075
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))
886a64fe 1080 );
2d0b2e87 1081
69ae3ee0
ZJS
1082 if (r == 0 && endswith(unit, ".slice")) {
1083 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1084
1085 /* Show all messages belonging to a slice */
1086 (void)(
1087 (r = sd_journal_add_disjunction(j)) ||
1088 (r = sd_journal_add_match(j, m5, 0))
1089 );
1090 }
1091
886a64fe
ZJS
1092 return r;
1093}
1a6c43e9 1094
886a64fe
ZJS
1095int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1096 int r;
2d0b2e87
ZJS
1097 char *m1, *m2, *m3, *m4;
1098 char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1a6c43e9 1099
886a64fe
ZJS
1100 assert(j);
1101 assert(unit);
1a6c43e9 1102
2d0b2e87
ZJS
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);
de0671ee 1107 sprintf(muid, "_UID="UID_FMT, uid);
1a6c43e9 1108
886a64fe
ZJS
1109 (void) (
1110 /* Look for messages from the user service itself */
1111 (r = sd_journal_add_match(j, m1, 0)) ||
2d0b2e87 1112 (r = sd_journal_add_match(j, muid, 0)) ||
886a64fe
ZJS
1113
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)) ||
2d0b2e87 1117 (r = sd_journal_add_match(j, muid, 0)) ||
886a64fe
ZJS
1118
1119 /* Look for coredumps of the service */
1120 (r = sd_journal_add_disjunction(j)) ||
1121 (r = sd_journal_add_match(j, m3, 0)) ||
2d0b2e87
ZJS
1122 (r = sd_journal_add_match(j, muid, 0)) ||
1123 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1124
1125 /* Look for messages from authorized daemons about this service */
1126 (r = sd_journal_add_disjunction(j)) ||
fdcd37df 1127 (r = sd_journal_add_match(j, m4, 0)) ||
2d0b2e87 1128 (r = sd_journal_add_match(j, muid, 0)) ||
fdcd37df 1129 (r = sd_journal_add_match(j, "_UID=0", 0))
886a64fe 1130 );
69ae3ee0
ZJS
1131
1132 if (r == 0 && endswith(unit, ".slice")) {
1133 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1134
1135 /* Show all messages belonging to a slice */
1136 (void)(
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))
1140 );
1141 }
1142
1a6c43e9
MT
1143 return r;
1144}
1145
b6741478 1146static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
3d94f76c 1147 _cleanup_close_pair_ int pair[2] = { -1, -1 };
a4475f57 1148 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
b6741478
LP
1149 pid_t pid, child;
1150 siginfo_t si;
1151 char buf[37];
1152 ssize_t k;
1153 int r;
1154
1155 assert(machine);
1156 assert(boot_id);
1157
affcf189 1158 if (!machine_name_is_valid(machine))
b6741478
LP
1159 return -EINVAL;
1160
e04b0cdb 1161 r = container_get_leader(machine, &pid);
b6741478
LP
1162 if (r < 0)
1163 return r;
e04b0cdb 1164
878cd7e9 1165 r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
b6741478
LP
1166 if (r < 0)
1167 return r;
1168
e04b0cdb 1169 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
b6741478
LP
1170 return -errno;
1171
1172 child = fork();
1173 if (child < 0)
1174 return -errno;
1175
1176 if (child == 0) {
1177 int fd;
1178
03e334a1 1179 pair[0] = safe_close(pair[0]);
b6741478 1180
878cd7e9 1181 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
b6741478
LP
1182 if (r < 0)
1183 _exit(EXIT_FAILURE);
1184
1185 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1186 if (fd < 0)
1187 _exit(EXIT_FAILURE);
1188
1189 k = loop_read(fd, buf, 36, false);
03e334a1 1190 safe_close(fd);
b6741478
LP
1191 if (k != 36)
1192 _exit(EXIT_FAILURE);
1193
e04b0cdb 1194 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
b6741478
LP
1195 if (k != 36)
1196 _exit(EXIT_FAILURE);
1197
1198 _exit(EXIT_SUCCESS);
1199 }
1200
03e334a1 1201 pair[1] = safe_close(pair[1]);
b6741478 1202
b6741478
LP
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;
1206
fbadf045
LP
1207 k = recv(pair[0], buf, 36, 0);
1208 if (k != 36)
1209 return -EIO;
1210
b6741478
LP
1211 buf[36] = 0;
1212 r = sd_id128_from_string(buf, boot_id);
1213 if (r < 0)
1214 return r;
1215
1216 return 0;
1217}
1218
1219int add_match_this_boot(sd_journal *j, const char *machine) {
5ec76417
ZJS
1220 char match[9+32+1] = "_BOOT_ID=";
1221 sd_id128_t boot_id;
1222 int r;
1223
1224 assert(j);
1225
b6741478
LP
1226 if (machine) {
1227 r = get_boot_id_for_machine(machine, &boot_id);
1228 if (r < 0) {
1229 log_error("Failed to get boot id of container %s: %s", machine, strerror(-r));
1230 return r;
1231 }
1232 } else {
1233 r = sd_id128_get_boot(&boot_id);
1234 if (r < 0) {
1235 log_error("Failed to get boot id: %s", strerror(-r));
1236 return r;
1237 }
5ec76417
ZJS
1238 }
1239
1240 sd_id128_to_string(boot_id, match + 9);
1241 r = sd_journal_add_match(j, match, strlen(match));
1242 if (r < 0) {
1243 log_error("Failed to add match: %s", strerror(-r));
1244 return r;
1245 }
1246
1247 r = sd_journal_add_conjunction(j);
1248 if (r < 0)
1249 return r;
1250
1251 return 0;
1252}
1253
886a64fe 1254int show_journal_by_unit(
1a6c43e9
MT
1255 FILE *f,
1256 const char *unit,
1257 OutputMode mode,
1258 unsigned n_columns,
1259 usec_t not_before,
1260 unsigned how_many,
1261 uid_t uid,
886a64fe 1262 OutputFlags flags,
94e0bd7d
ZJS
1263 bool system,
1264 bool *ellipsized) {
1a6c43e9 1265
7fd1b19b 1266 _cleanup_journal_close_ sd_journal*j = NULL;
1a6c43e9 1267 int r;
a688baa8 1268 int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
1a6c43e9
MT
1269
1270 assert(mode >= 0);
1271 assert(mode < _OUTPUT_MODE_MAX);
1272 assert(unit);
1273
1a6c43e9
MT
1274 if (how_many <= 0)
1275 return 0;
1276
886a64fe 1277 r = sd_journal_open(&j, jflags);
f9045468 1278 if (r < 0)
763c7aa2 1279 return r;
f9045468 1280
b6741478 1281 r = add_match_this_boot(j, NULL);
5ec76417
ZJS
1282 if (r < 0)
1283 return r;
1284
886a64fe
ZJS
1285 if (system)
1286 r = add_matches_for_unit(j, unit);
1287 else
1288 r = add_matches_for_user_unit(j, unit, uid);
1a6c43e9 1289 if (r < 0)
763c7aa2 1290 return r;
1a6c43e9 1291
4ad16808
ZJS
1292 if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1293 _cleanup_free_ char *filter;
1294
1295 filter = journal_make_match_string(j);
1296 log_debug("Journal filter: %s", filter);
1297 }
5ec76417 1298
94e0bd7d 1299 return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
86aa7ba4 1300}
df50185b
LP
1301
1302static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1303 [OUTPUT_SHORT] = "short",
44bc6e1f 1304 [OUTPUT_SHORT_ISO] = "short-iso",
f02d8367
ZJS
1305 [OUTPUT_SHORT_PRECISE] = "short-precise",
1306 [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
df50185b
LP
1307 [OUTPUT_VERBOSE] = "verbose",
1308 [OUTPUT_EXPORT] = "export",
d3f2bdbf 1309 [OUTPUT_JSON] = "json",
a6e87e90 1310 [OUTPUT_JSON_PRETTY] = "json-pretty",
48383c25 1311 [OUTPUT_JSON_SSE] = "json-sse",
d3f2bdbf 1312 [OUTPUT_CAT] = "cat"
df50185b
LP
1313};
1314
1315DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);