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