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