]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/logs-show.c
Add SPDX license identifiers to source files under the LGPL
[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=", strlen("_SOURCE_REALTIME_TIMESTAMP="), &value, NULL);
510 if (r < 0)
511 return r;
512 assert(r > 0);
513
514 r = safe_atou64(value, &realtime);
515 if (r < 0)
516 log_debug_errno(r, "Failed to parse realtime timestamp: %m");
517 }
518
519 if (r < 0) {
520 r = sd_journal_get_realtime_usec(j, &realtime);
521 if (r < 0)
522 return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get realtime timestamp: %m");
523 }
524
525 r = sd_journal_get_cursor(j, &cursor);
526 if (r < 0)
527 return log_error_errno(r, "Failed to get cursor: %m");
528
529 timestamp = flags & OUTPUT_UTC ? format_timestamp_us_utc(ts, sizeof ts, realtime)
530 : format_timestamp_us(ts, sizeof ts, realtime);
531 fprintf(f, "%s [%s]\n",
532 timestamp ?: "(no timestamp)",
533 cursor);
534
535 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
536 const char *c;
537 int fieldlen;
538 const char *on = "", *off = "";
539
540 c = memchr(data, '=', length);
541 if (!c) {
542 log_error("Invalid field.");
543 return -EINVAL;
544 }
545 fieldlen = c - (const char*) data;
546
547 r = field_set_test(output_fields, data, fieldlen);
548 if (r < 0)
549 return r;
550 if (!r)
551 continue;
552
553 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
554 on = ANSI_HIGHLIGHT;
555 off = ANSI_NORMAL;
556 }
557
558 if ((flags & OUTPUT_SHOW_ALL) ||
559 (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
560 && utf8_is_printable(data, length))) {
561 fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
562 print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
563 fputs(off, f);
564 } else {
565 char bytes[FORMAT_BYTES_MAX];
566
567 fprintf(f, " %s%.*s=[%s blob data]%s\n",
568 on,
569 (int) (c - (const char*) data),
570 (const char*) data,
571 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
572 off);
573 }
574 }
575
576 if (r < 0)
577 return r;
578
579 if (flags & OUTPUT_CATALOG)
580 print_catalog(f, j);
581
582 return 0;
583 }
584
585 static int output_export(
586 FILE *f,
587 sd_journal *j,
588 OutputMode mode,
589 unsigned n_columns,
590 OutputFlags flags,
591 Set *output_fields) {
592
593 sd_id128_t boot_id;
594 char sid[33];
595 int r;
596 usec_t realtime, monotonic;
597 _cleanup_free_ char *cursor = NULL;
598 const void *data;
599 size_t length;
600
601 assert(j);
602
603 sd_journal_set_data_threshold(j, 0);
604
605 r = sd_journal_get_realtime_usec(j, &realtime);
606 if (r < 0)
607 return log_error_errno(r, "Failed to get realtime timestamp: %m");
608
609 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
610 if (r < 0)
611 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
612
613 r = sd_journal_get_cursor(j, &cursor);
614 if (r < 0)
615 return log_error_errno(r, "Failed to get cursor: %m");
616
617 fprintf(f,
618 "__CURSOR=%s\n"
619 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
620 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
621 "_BOOT_ID=%s\n",
622 cursor,
623 realtime,
624 monotonic,
625 sd_id128_to_string(boot_id, sid));
626
627 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
628 const char *c;
629
630 /* We already printed the boot id, from the data in
631 * the header, hence let's suppress it here */
632 if (length >= 9 &&
633 startswith(data, "_BOOT_ID="))
634 continue;
635
636 c = memchr(data, '=', length);
637 if (!c) {
638 log_error("Invalid field.");
639 return -EINVAL;
640 }
641
642 r = field_set_test(output_fields, data, c - (const char *) data);
643 if (r < 0)
644 return r;
645 if (!r)
646 continue;
647
648 if (utf8_is_printable_newline(data, length, false))
649 fwrite(data, length, 1, f);
650 else {
651 uint64_t le64;
652
653 fwrite(data, c - (const char*) data, 1, f);
654 fputc('\n', f);
655 le64 = htole64(length - (c - (const char*) data) - 1);
656 fwrite(&le64, sizeof(le64), 1, f);
657 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
658 }
659
660 fputc('\n', f);
661 }
662
663 if (r < 0)
664 return r;
665
666 fputc('\n', f);
667
668 return 0;
669 }
670
671 void json_escape(
672 FILE *f,
673 const char* p,
674 size_t l,
675 OutputFlags flags) {
676
677 assert(f);
678 assert(p);
679
680 if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
681 fputs("null", f);
682
683 else if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(p, l)) {
684 bool not_first = false;
685
686 fputs("[ ", f);
687
688 while (l > 0) {
689 if (not_first)
690 fprintf(f, ", %u", (uint8_t) *p);
691 else {
692 not_first = true;
693 fprintf(f, "%u", (uint8_t) *p);
694 }
695
696 p++;
697 l--;
698 }
699
700 fputs(" ]", f);
701 } else {
702 fputc('\"', f);
703
704 while (l > 0) {
705 if (IN_SET(*p, '"', '\\')) {
706 fputc('\\', f);
707 fputc(*p, f);
708 } else if (*p == '\n')
709 fputs("\\n", f);
710 else if ((uint8_t) *p < ' ')
711 fprintf(f, "\\u%04x", (uint8_t) *p);
712 else
713 fputc(*p, f);
714
715 p++;
716 l--;
717 }
718
719 fputc('\"', f);
720 }
721 }
722
723 static int output_json(
724 FILE *f,
725 sd_journal *j,
726 OutputMode mode,
727 unsigned n_columns,
728 OutputFlags flags,
729 Set *output_fields) {
730
731 uint64_t realtime, monotonic;
732 _cleanup_free_ char *cursor = NULL;
733 const void *data;
734 size_t length;
735 sd_id128_t boot_id;
736 char sid[33], *k;
737 int r;
738 Hashmap *h = NULL;
739 bool done, separator;
740
741 assert(j);
742
743 sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
744
745 r = sd_journal_get_realtime_usec(j, &realtime);
746 if (r < 0)
747 return log_error_errno(r, "Failed to get realtime timestamp: %m");
748
749 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
750 if (r < 0)
751 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
752
753 r = sd_journal_get_cursor(j, &cursor);
754 if (r < 0)
755 return log_error_errno(r, "Failed to get cursor: %m");
756
757 if (mode == OUTPUT_JSON_PRETTY)
758 fprintf(f,
759 "{\n"
760 "\t\"__CURSOR\" : \"%s\",\n"
761 "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
762 "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
763 "\t\"_BOOT_ID\" : \"%s\"",
764 cursor,
765 realtime,
766 monotonic,
767 sd_id128_to_string(boot_id, sid));
768 else {
769 if (mode == OUTPUT_JSON_SSE)
770 fputs("data: ", f);
771
772 fprintf(f,
773 "{ \"__CURSOR\" : \"%s\", "
774 "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
775 "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
776 "\"_BOOT_ID\" : \"%s\"",
777 cursor,
778 realtime,
779 monotonic,
780 sd_id128_to_string(boot_id, sid));
781 }
782
783 h = hashmap_new(&string_hash_ops);
784 if (!h)
785 return log_oom();
786
787 /* First round, iterate through the entry and count how often each field appears */
788 JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
789 const char *eq;
790 char *n;
791 unsigned u;
792
793 if (length >= 9 &&
794 memcmp(data, "_BOOT_ID=", 9) == 0)
795 continue;
796
797 eq = memchr(data, '=', length);
798 if (!eq)
799 continue;
800
801 n = strndup(data, eq - (const char*) data);
802 if (!n) {
803 r = log_oom();
804 goto finish;
805 }
806
807 u = PTR_TO_UINT(hashmap_get(h, n));
808 if (u == 0) {
809 r = hashmap_put(h, n, UINT_TO_PTR(1));
810 if (r < 0) {
811 free(n);
812 log_oom();
813 goto finish;
814 }
815 } else {
816 r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
817 free(n);
818 if (r < 0) {
819 log_oom();
820 goto finish;
821 }
822 }
823 }
824
825 if (r < 0)
826 return r;
827
828 separator = true;
829 do {
830 done = true;
831
832 SD_JOURNAL_FOREACH_DATA(j, data, length) {
833 const char *eq;
834 char *kk, *n;
835 size_t m;
836 unsigned u;
837
838 /* We already printed the boot id, from the data in
839 * the header, hence let's suppress it here */
840 if (length >= 9 &&
841 memcmp(data, "_BOOT_ID=", 9) == 0)
842 continue;
843
844 eq = memchr(data, '=', length);
845 if (!eq)
846 continue;
847
848 m = eq - (const char*) data;
849
850 n = strndup(data, m);
851 if (!n) {
852 r = log_oom();
853 goto finish;
854 }
855
856 if (output_fields && !set_get(output_fields, n)) {
857 free(n);
858 continue;
859 }
860
861 if (separator) {
862 if (mode == OUTPUT_JSON_PRETTY)
863 fputs(",\n\t", f);
864 else
865 fputs(", ", f);
866 }
867
868 u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
869 if (u == 0) {
870 /* We already printed this, let's jump to the next */
871 free(n);
872 separator = false;
873
874 continue;
875 } else if (u == 1) {
876 /* Field only appears once, output it directly */
877
878 json_escape(f, data, m, flags);
879 fputs(" : ", f);
880
881 json_escape(f, eq + 1, length - m - 1, flags);
882
883 hashmap_remove(h, n);
884 free(kk);
885 free(n);
886
887 separator = true;
888
889 continue;
890
891 } else {
892 /* Field appears multiple times, output it as array */
893 json_escape(f, data, m, flags);
894 fputs(" : [ ", f);
895 json_escape(f, eq + 1, length - m - 1, flags);
896
897 /* Iterate through the end of the list */
898
899 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
900 if (length < m + 1)
901 continue;
902
903 if (memcmp(data, n, m) != 0)
904 continue;
905
906 if (((const char*) data)[m] != '=')
907 continue;
908
909 fputs(", ", f);
910 json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
911 }
912
913 fputs(" ]", f);
914
915 hashmap_remove(h, n);
916 free(kk);
917 free(n);
918
919 /* Iterate data fields form the beginning */
920 done = false;
921 separator = true;
922
923 break;
924 }
925 }
926
927 } while (!done);
928
929 if (mode == OUTPUT_JSON_PRETTY)
930 fputs("\n}\n", f);
931 else if (mode == OUTPUT_JSON_SSE)
932 fputs("}\n\n", f);
933 else
934 fputs(" }\n", f);
935
936 r = 0;
937
938 finish:
939 while ((k = hashmap_steal_first_key(h)))
940 free(k);
941
942 hashmap_free(h);
943
944 return r;
945 }
946
947 static int output_cat(
948 FILE *f,
949 sd_journal *j,
950 OutputMode mode,
951 unsigned n_columns,
952 OutputFlags flags,
953 Set *output_fields) {
954
955 const void *data;
956 size_t l;
957 int r;
958
959 assert(j);
960 assert(f);
961
962 sd_journal_set_data_threshold(j, 0);
963
964 r = sd_journal_get_data(j, "MESSAGE", &data, &l);
965 if (r < 0) {
966 /* An entry without MESSAGE=? */
967 if (r == -ENOENT)
968 return 0;
969
970 return log_error_errno(r, "Failed to get data: %m");
971 }
972
973 assert(l >= 8);
974
975 fwrite((const char*) data + 8, 1, l - 8, f);
976 fputc('\n', f);
977
978 return 0;
979 }
980
981 static int (*output_funcs[_OUTPUT_MODE_MAX])(
982 FILE *f,
983 sd_journal*j,
984 OutputMode mode,
985 unsigned n_columns,
986 OutputFlags flags,
987 Set *output_fields) = {
988
989 [OUTPUT_SHORT] = output_short,
990 [OUTPUT_SHORT_ISO] = output_short,
991 [OUTPUT_SHORT_ISO_PRECISE] = output_short,
992 [OUTPUT_SHORT_PRECISE] = output_short,
993 [OUTPUT_SHORT_MONOTONIC] = output_short,
994 [OUTPUT_SHORT_UNIX] = output_short,
995 [OUTPUT_SHORT_FULL] = output_short,
996 [OUTPUT_VERBOSE] = output_verbose,
997 [OUTPUT_EXPORT] = output_export,
998 [OUTPUT_JSON] = output_json,
999 [OUTPUT_JSON_PRETTY] = output_json,
1000 [OUTPUT_JSON_SSE] = output_json,
1001 [OUTPUT_CAT] = output_cat
1002 };
1003
1004 int output_journal(
1005 FILE *f,
1006 sd_journal *j,
1007 OutputMode mode,
1008 unsigned n_columns,
1009 OutputFlags flags,
1010 char **output_fields,
1011 bool *ellipsized) {
1012
1013 int ret;
1014 _cleanup_set_free_free_ Set *fields = NULL;
1015 assert(mode >= 0);
1016 assert(mode < _OUTPUT_MODE_MAX);
1017
1018 if (n_columns <= 0)
1019 n_columns = columns();
1020
1021 if (output_fields) {
1022 fields = set_new(&string_hash_ops);
1023 if (!fields)
1024 return log_oom();
1025
1026 ret = set_put_strdupv(fields, output_fields);
1027 if (ret < 0)
1028 return ret;
1029 }
1030
1031 ret = output_funcs[mode](f, j, mode, n_columns, flags, fields);
1032
1033 if (ellipsized && ret > 0)
1034 *ellipsized = true;
1035
1036 return ret;
1037 }
1038
1039 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
1040 assert(f);
1041 assert(flags);
1042
1043 if (!(*flags & OUTPUT_BEGIN_NEWLINE))
1044 return 0;
1045
1046 /* Print a beginning new line if that's request, but only once
1047 * on the first line we print. */
1048
1049 fputc('\n', f);
1050 *flags &= ~OUTPUT_BEGIN_NEWLINE;
1051 return 0;
1052 }
1053
1054 static int show_journal(FILE *f,
1055 sd_journal *j,
1056 OutputMode mode,
1057 unsigned n_columns,
1058 usec_t not_before,
1059 unsigned how_many,
1060 OutputFlags flags,
1061 bool *ellipsized) {
1062
1063 int r;
1064 unsigned line = 0;
1065 bool need_seek = false;
1066 int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
1067
1068 assert(j);
1069 assert(mode >= 0);
1070 assert(mode < _OUTPUT_MODE_MAX);
1071
1072 /* Seek to end */
1073 r = sd_journal_seek_tail(j);
1074 if (r < 0)
1075 return log_error_errno(r, "Failed to seek to tail: %m");
1076
1077 r = sd_journal_previous_skip(j, how_many);
1078 if (r < 0)
1079 return log_error_errno(r, "Failed to skip previous: %m");
1080
1081 for (;;) {
1082 for (;;) {
1083 usec_t usec;
1084
1085 if (need_seek) {
1086 r = sd_journal_next(j);
1087 if (r < 0)
1088 return log_error_errno(r, "Failed to iterate through journal: %m");
1089 }
1090
1091 if (r == 0)
1092 break;
1093
1094 need_seek = true;
1095
1096 if (not_before > 0) {
1097 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
1098
1099 /* -ESTALE is returned if the
1100 timestamp is not from this boot */
1101 if (r == -ESTALE)
1102 continue;
1103 else if (r < 0)
1104 return log_error_errno(r, "Failed to get journal time: %m");
1105
1106 if (usec < not_before)
1107 continue;
1108 }
1109
1110 line++;
1111 maybe_print_begin_newline(f, &flags);
1112
1113 r = output_journal(f, j, mode, n_columns, flags, NULL, ellipsized);
1114 if (r < 0)
1115 return r;
1116 }
1117
1118 if (warn_cutoff && line < how_many && not_before > 0) {
1119 sd_id128_t boot_id;
1120 usec_t cutoff = 0;
1121
1122 /* Check whether the cutoff line is too early */
1123
1124 r = sd_id128_get_boot(&boot_id);
1125 if (r < 0)
1126 return log_error_errno(r, "Failed to get boot id: %m");
1127
1128 r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1129 if (r < 0)
1130 return log_error_errno(r, "Failed to get journal cutoff time: %m");
1131
1132 if (r > 0 && not_before < cutoff) {
1133 maybe_print_begin_newline(f, &flags);
1134 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1135 }
1136
1137 warn_cutoff = false;
1138 }
1139
1140 if (!(flags & OUTPUT_FOLLOW))
1141 break;
1142
1143 r = sd_journal_wait(j, USEC_INFINITY);
1144 if (r < 0)
1145 return log_error_errno(r, "Failed to wait for journal: %m");
1146
1147 }
1148
1149 return 0;
1150 }
1151
1152 int add_matches_for_unit(sd_journal *j, const char *unit) {
1153 const char *m1, *m2, *m3, *m4;
1154 int r;
1155
1156 assert(j);
1157 assert(unit);
1158
1159 m1 = strjoina("_SYSTEMD_UNIT=", unit);
1160 m2 = strjoina("COREDUMP_UNIT=", unit);
1161 m3 = strjoina("UNIT=", unit);
1162 m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit);
1163
1164 (void)(
1165 /* Look for messages from the service itself */
1166 (r = sd_journal_add_match(j, m1, 0)) ||
1167
1168 /* Look for coredumps of the service */
1169 (r = sd_journal_add_disjunction(j)) ||
1170 (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1171 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1172 (r = sd_journal_add_match(j, m2, 0)) ||
1173
1174 /* Look for messages from PID 1 about this service */
1175 (r = sd_journal_add_disjunction(j)) ||
1176 (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1177 (r = sd_journal_add_match(j, m3, 0)) ||
1178
1179 /* Look for messages from authorized daemons about this service */
1180 (r = sd_journal_add_disjunction(j)) ||
1181 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1182 (r = sd_journal_add_match(j, m4, 0))
1183 );
1184
1185 if (r == 0 && endswith(unit, ".slice")) {
1186 const char *m5;
1187
1188 m5 = strjoina("_SYSTEMD_SLICE=", unit);
1189
1190 /* Show all messages belonging to a slice */
1191 (void)(
1192 (r = sd_journal_add_disjunction(j)) ||
1193 (r = sd_journal_add_match(j, m5, 0))
1194 );
1195 }
1196
1197 return r;
1198 }
1199
1200 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1201 int r;
1202 char *m1, *m2, *m3, *m4;
1203 char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1204
1205 assert(j);
1206 assert(unit);
1207
1208 m1 = strjoina("_SYSTEMD_USER_UNIT=", unit);
1209 m2 = strjoina("USER_UNIT=", unit);
1210 m3 = strjoina("COREDUMP_USER_UNIT=", unit);
1211 m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit);
1212 sprintf(muid, "_UID="UID_FMT, uid);
1213
1214 (void) (
1215 /* Look for messages from the user service itself */
1216 (r = sd_journal_add_match(j, m1, 0)) ||
1217 (r = sd_journal_add_match(j, muid, 0)) ||
1218
1219 /* Look for messages from systemd about this service */
1220 (r = sd_journal_add_disjunction(j)) ||
1221 (r = sd_journal_add_match(j, m2, 0)) ||
1222 (r = sd_journal_add_match(j, muid, 0)) ||
1223
1224 /* Look for coredumps of the service */
1225 (r = sd_journal_add_disjunction(j)) ||
1226 (r = sd_journal_add_match(j, m3, 0)) ||
1227 (r = sd_journal_add_match(j, muid, 0)) ||
1228 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1229
1230 /* Look for messages from authorized daemons about this service */
1231 (r = sd_journal_add_disjunction(j)) ||
1232 (r = sd_journal_add_match(j, m4, 0)) ||
1233 (r = sd_journal_add_match(j, muid, 0)) ||
1234 (r = sd_journal_add_match(j, "_UID=0", 0))
1235 );
1236
1237 if (r == 0 && endswith(unit, ".slice")) {
1238 const char *m5;
1239
1240 m5 = strjoina("_SYSTEMD_SLICE=", unit);
1241
1242 /* Show all messages belonging to a slice */
1243 (void)(
1244 (r = sd_journal_add_disjunction(j)) ||
1245 (r = sd_journal_add_match(j, m5, 0)) ||
1246 (r = sd_journal_add_match(j, muid, 0))
1247 );
1248 }
1249
1250 return r;
1251 }
1252
1253 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1254 _cleanup_close_pair_ int pair[2] = { -1, -1 };
1255 _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1256 pid_t pid, child;
1257 siginfo_t si;
1258 char buf[37];
1259 ssize_t k;
1260 int r;
1261
1262 assert(machine);
1263 assert(boot_id);
1264
1265 if (!machine_name_is_valid(machine))
1266 return -EINVAL;
1267
1268 r = container_get_leader(machine, &pid);
1269 if (r < 0)
1270 return r;
1271
1272 r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, NULL, &rootfd);
1273 if (r < 0)
1274 return r;
1275
1276 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1277 return -errno;
1278
1279 child = fork();
1280 if (child < 0)
1281 return -errno;
1282
1283 if (child == 0) {
1284 int fd;
1285
1286 pair[0] = safe_close(pair[0]);
1287
1288 r = namespace_enter(pidnsfd, mntnsfd, -1, -1, rootfd);
1289 if (r < 0)
1290 _exit(EXIT_FAILURE);
1291
1292 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1293 if (fd < 0)
1294 _exit(EXIT_FAILURE);
1295
1296 r = loop_read_exact(fd, buf, 36, false);
1297 safe_close(fd);
1298 if (r < 0)
1299 _exit(EXIT_FAILURE);
1300
1301 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1302 if (k != 36)
1303 _exit(EXIT_FAILURE);
1304
1305 _exit(EXIT_SUCCESS);
1306 }
1307
1308 pair[1] = safe_close(pair[1]);
1309
1310 r = wait_for_terminate(child, &si);
1311 if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1312 return r < 0 ? r : -EIO;
1313
1314 k = recv(pair[0], buf, 36, 0);
1315 if (k != 36)
1316 return -EIO;
1317
1318 buf[36] = 0;
1319 r = sd_id128_from_string(buf, boot_id);
1320 if (r < 0)
1321 return r;
1322
1323 return 0;
1324 }
1325
1326 int add_match_this_boot(sd_journal *j, const char *machine) {
1327 char match[9+32+1] = "_BOOT_ID=";
1328 sd_id128_t boot_id;
1329 int r;
1330
1331 assert(j);
1332
1333 if (machine) {
1334 r = get_boot_id_for_machine(machine, &boot_id);
1335 if (r < 0)
1336 return log_error_errno(r, "Failed to get boot id of container %s: %m", machine);
1337 } else {
1338 r = sd_id128_get_boot(&boot_id);
1339 if (r < 0)
1340 return log_error_errno(r, "Failed to get boot id: %m");
1341 }
1342
1343 sd_id128_to_string(boot_id, match + 9);
1344 r = sd_journal_add_match(j, match, strlen(match));
1345 if (r < 0)
1346 return log_error_errno(r, "Failed to add match: %m");
1347
1348 r = sd_journal_add_conjunction(j);
1349 if (r < 0)
1350 return log_error_errno(r, "Failed to add conjunction: %m");
1351
1352 return 0;
1353 }
1354
1355 int show_journal_by_unit(
1356 FILE *f,
1357 const char *unit,
1358 OutputMode mode,
1359 unsigned n_columns,
1360 usec_t not_before,
1361 unsigned how_many,
1362 uid_t uid,
1363 OutputFlags flags,
1364 int journal_open_flags,
1365 bool system_unit,
1366 bool *ellipsized) {
1367
1368 _cleanup_(sd_journal_closep) sd_journal *j = NULL;
1369 int r;
1370
1371 assert(mode >= 0);
1372 assert(mode < _OUTPUT_MODE_MAX);
1373 assert(unit);
1374
1375 if (how_many <= 0)
1376 return 0;
1377
1378 r = sd_journal_open(&j, journal_open_flags);
1379 if (r < 0)
1380 return log_error_errno(r, "Failed to open journal: %m");
1381
1382 r = add_match_this_boot(j, NULL);
1383 if (r < 0)
1384 return r;
1385
1386 if (system_unit)
1387 r = add_matches_for_unit(j, unit);
1388 else
1389 r = add_matches_for_user_unit(j, unit, uid);
1390 if (r < 0)
1391 return log_error_errno(r, "Failed to add unit matches: %m");
1392
1393 if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
1394 _cleanup_free_ char *filter;
1395
1396 filter = journal_make_match_string(j);
1397 if (!filter)
1398 return log_oom();
1399
1400 log_debug("Journal filter: %s", filter);
1401 }
1402
1403 return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1404 }