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