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