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