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