chiark / gitweb /
04e1165191068b7494730fa99ebe49d2734200c9
[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                         log_error("Failed to get monotonic timestamp: %s", strerror(-r));
300                         return r;
301                 }
302
303                 fprintf(f, "[%5llu.%06llu]",
304                         (unsigned long long) (t / USEC_PER_SEC),
305                         (unsigned long long) (t % USEC_PER_SEC));
306
307                 n += 1 + 5 + 1 + 6 + 1;
308
309         } else {
310                 char buf[64];
311                 uint64_t x;
312                 time_t t;
313                 struct tm tm;
314                 struct tm *(*gettime_r)(const time_t *, struct tm *);
315
316                 r = -ENOENT;
317                 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
318
319                 if (realtime)
320                         r = safe_atou64(realtime, &x);
321
322                 if (r < 0)
323                         r = sd_journal_get_realtime_usec(j, &x);
324
325                 if (r < 0) {
326                         log_error("Failed to get realtime timestamp: %s", strerror(-r));
327                         return r;
328                 }
329
330                 t = (time_t) (x / USEC_PER_SEC);
331
332                 switch(mode) {
333                 case OUTPUT_SHORT_ISO:
334                         r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm));
335                         break;
336                 case OUTPUT_SHORT_PRECISE:
337                         r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
338                         if (r > 0) {
339                                 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
340                                          ".%06llu", (unsigned long long) (x % USEC_PER_SEC));
341                         }
342                         break;
343                 default:
344                         r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
345                 }
346
347                 if (r <= 0) {
348                         log_error("Failed to format time.");
349                         return -EINVAL;
350                 }
351
352                 fputs(buf, f);
353                 n += strlen(buf);
354         }
355
356         if (hostname && shall_print(hostname, hostname_len, flags)) {
357                 fprintf(f, " %.*s", (int) hostname_len, hostname);
358                 n += hostname_len + 1;
359         }
360
361         if (identifier && shall_print(identifier, identifier_len, flags)) {
362                 fprintf(f, " %.*s", (int) identifier_len, identifier);
363                 n += identifier_len + 1;
364         } else if (comm && shall_print(comm, comm_len, flags)) {
365                 fprintf(f, " %.*s", (int) comm_len, comm);
366                 n += comm_len + 1;
367         } else
368                 fputc(' ', f);
369
370         if (pid && shall_print(pid, pid_len, flags)) {
371                 fprintf(f, "[%.*s]", (int) pid_len, pid);
372                 n += pid_len + 2;
373         } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
374                 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
375                 n += fake_pid_len + 2;
376         }
377
378         if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
379                 char bytes[FORMAT_BYTES_MAX];
380                 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
381         } else {
382                 fputs(": ", f);
383                 ellipsized |=
384                         print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
385         }
386
387         if (flags & OUTPUT_CATALOG)
388                 print_catalog(f, j);
389
390         return ellipsized;
391 }
392
393 static int output_verbose(
394                 FILE *f,
395                 sd_journal *j,
396                 OutputMode mode,
397                 unsigned n_columns,
398                 OutputFlags flags) {
399
400         const void *data;
401         size_t length;
402         _cleanup_free_ char *cursor = NULL;
403         uint64_t realtime;
404         char ts[FORMAT_TIMESTAMP_MAX + 7];
405         int r;
406
407         assert(f);
408         assert(j);
409
410         sd_journal_set_data_threshold(j, 0);
411
412         r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
413         if (r == -ENOENT)
414                 log_debug("Source realtime timestamp not found");
415         else if (r < 0) {
416                 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
417                          "Failed to get source realtime timestamp: %s", strerror(-r));
418                 return r;
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("_SOURCE_REALTIME_TIMESTAMP invalid: %s", strerror(-r));
426                 else {
427                         r = safe_atou64(value, &realtime);
428                         if (r < 0)
429                                 log_debug("Failed to parse realtime timestamp: %s",
430                                           strerror(-r));
431                 }
432         }
433
434         if (r < 0) {
435                 r = sd_journal_get_realtime_usec(j, &realtime);
436                 if (r < 0) {
437                         log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
438                                  "Failed to get realtime timestamp: %s", strerror(-r));
439                         return r;
440                 }
441         }
442
443         r = sd_journal_get_cursor(j, &cursor);
444         if (r < 0) {
445                 log_error("Failed to get cursor: %s", strerror(-r));
446                 return r;
447         }
448
449         fprintf(f, "%s [%s]\n",
450                 flags & OUTPUT_UTC ?
451                 format_timestamp_us_utc(ts, sizeof(ts), realtime) :
452                 format_timestamp_us(ts, sizeof(ts), realtime),
453                 cursor);
454
455         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
456                 const char *c;
457                 int fieldlen;
458                 const char *on = "", *off = "";
459
460                 c = memchr(data, '=', length);
461                 if (!c) {
462                         log_error("Invalid field.");
463                         return -EINVAL;
464                 }
465                 fieldlen = c - (const char*) data;
466
467                 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
468                         on = ANSI_HIGHLIGHT_ON;
469                         off = ANSI_HIGHLIGHT_OFF;
470                 }
471
472                 if (flags & OUTPUT_SHOW_ALL ||
473                     (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
474                      && utf8_is_printable(data, length))) {
475                         fprintf(f, "    %s%.*s=", on, fieldlen, (const char*)data);
476                         print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
477                         fputs(off, f);
478                 } else {
479                         char bytes[FORMAT_BYTES_MAX];
480
481                         fprintf(f, "    %s%.*s=[%s blob data]%s\n",
482                                 on,
483                                 (int) (c - (const char*) data),
484                                 (const char*) data,
485                                 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
486                                 off);
487                 }
488         }
489
490         if (r < 0)
491                 return r;
492
493         if (flags & OUTPUT_CATALOG)
494                 print_catalog(f, j);
495
496         return 0;
497 }
498
499 static int output_export(
500                 FILE *f,
501                 sd_journal *j,
502                 OutputMode mode,
503                 unsigned n_columns,
504                 OutputFlags flags) {
505
506         sd_id128_t boot_id;
507         char sid[33];
508         int r;
509         usec_t realtime, monotonic;
510         _cleanup_free_ char *cursor = NULL;
511         const void *data;
512         size_t length;
513
514         assert(j);
515
516         sd_journal_set_data_threshold(j, 0);
517
518         r = sd_journal_get_realtime_usec(j, &realtime);
519         if (r < 0) {
520                 log_error("Failed to get realtime timestamp: %s", strerror(-r));
521                 return r;
522         }
523
524         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
525         if (r < 0) {
526                 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
527                 return r;
528         }
529
530         r = sd_journal_get_cursor(j, &cursor);
531         if (r < 0) {
532                 log_error("Failed to get cursor: %s", strerror(-r));
533                 return r;
534         }
535
536         fprintf(f,
537                 "__CURSOR=%s\n"
538                 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
539                 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
540                 "_BOOT_ID=%s\n",
541                 cursor,
542                 realtime,
543                 monotonic,
544                 sd_id128_to_string(boot_id, sid));
545
546         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
547
548                 /* We already printed the boot id, from the data in
549                  * the header, hence let's suppress it here */
550                 if (length >= 9 &&
551                     startswith(data, "_BOOT_ID="))
552                         continue;
553
554                 if (utf8_is_printable_newline(data, length, false))
555                         fwrite(data, length, 1, f);
556                 else {
557                         const char *c;
558                         uint64_t le64;
559
560                         c = memchr(data, '=', length);
561                         if (!c) {
562                                 log_error("Invalid field.");
563                                 return -EINVAL;
564                         }
565
566                         fwrite(data, c - (const char*) data, 1, f);
567                         fputc('\n', f);
568                         le64 = htole64(length - (c - (const char*) data) - 1);
569                         fwrite(&le64, sizeof(le64), 1, f);
570                         fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
571                 }
572
573                 fputc('\n', f);
574         }
575
576         if (r < 0)
577                 return r;
578
579         fputc('\n', f);
580
581         return 0;
582 }
583
584 void json_escape(
585                 FILE *f,
586                 const char* p,
587                 size_t l,
588                 OutputFlags flags) {
589
590         assert(f);
591         assert(p);
592
593         if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
594
595                 fputs("null", f);
596
597         else if (!utf8_is_printable(p, l)) {
598                 bool not_first = false;
599
600                 fputs("[ ", f);
601
602                 while (l > 0) {
603                         if (not_first)
604                                 fprintf(f, ", %u", (uint8_t) *p);
605                         else {
606                                 not_first = true;
607                                 fprintf(f, "%u", (uint8_t) *p);
608                         }
609
610                         p++;
611                         l--;
612                 }
613
614                 fputs(" ]", f);
615         } else {
616                 fputc('\"', f);
617
618                 while (l > 0) {
619                         if (*p == '"' || *p == '\\') {
620                                 fputc('\\', f);
621                                 fputc(*p, f);
622                         } else if (*p == '\n')
623                                 fputs("\\n", f);
624                         else if (*p < ' ')
625                                 fprintf(f, "\\u%04x", *p);
626                         else
627                                 fputc(*p, f);
628
629                         p++;
630                         l--;
631                 }
632
633                 fputc('\"', f);
634         }
635 }
636
637 static int output_json(
638                 FILE *f,
639                 sd_journal *j,
640                 OutputMode mode,
641                 unsigned n_columns,
642                 OutputFlags flags) {
643
644         uint64_t realtime, monotonic;
645         _cleanup_free_ char *cursor = NULL;
646         const void *data;
647         size_t length;
648         sd_id128_t boot_id;
649         char sid[33], *k;
650         int r;
651         Hashmap *h = NULL;
652         bool done, separator;
653
654         assert(j);
655
656         sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
657
658         r = sd_journal_get_realtime_usec(j, &realtime);
659         if (r < 0) {
660                 log_error("Failed to get realtime timestamp: %s", strerror(-r));
661                 return r;
662         }
663
664         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
665         if (r < 0) {
666                 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
667                 return r;
668         }
669
670         r = sd_journal_get_cursor(j, &cursor);
671         if (r < 0) {
672                 log_error("Failed to get cursor: %s", strerror(-r));
673                 return r;
674         }
675
676         if (mode == OUTPUT_JSON_PRETTY)
677                 fprintf(f,
678                         "{\n"
679                         "\t\"__CURSOR\" : \"%s\",\n"
680                         "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
681                         "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
682                         "\t\"_BOOT_ID\" : \"%s\"",
683                         cursor,
684                         realtime,
685                         monotonic,
686                         sd_id128_to_string(boot_id, sid));
687         else {
688                 if (mode == OUTPUT_JSON_SSE)
689                         fputs("data: ", f);
690
691                 fprintf(f,
692                         "{ \"__CURSOR\" : \"%s\", "
693                         "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
694                         "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
695                         "\"_BOOT_ID\" : \"%s\"",
696                         cursor,
697                         realtime,
698                         monotonic,
699                         sd_id128_to_string(boot_id, sid));
700         }
701
702         h = hashmap_new(&string_hash_ops);
703         if (!h)
704                 return -ENOMEM;
705
706         /* First round, iterate through the entry and count how often each field appears */
707         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
708                 const char *eq;
709                 char *n;
710                 unsigned u;
711
712                 if (length >= 9 &&
713                     memcmp(data, "_BOOT_ID=", 9) == 0)
714                         continue;
715
716                 eq = memchr(data, '=', length);
717                 if (!eq)
718                         continue;
719
720                 n = strndup(data, eq - (const char*) data);
721                 if (!n) {
722                         r = -ENOMEM;
723                         goto finish;
724                 }
725
726                 u = PTR_TO_UINT(hashmap_get(h, n));
727                 if (u == 0) {
728                         r = hashmap_put(h, n, UINT_TO_PTR(1));
729                         if (r < 0) {
730                                 free(n);
731                                 goto finish;
732                         }
733                 } else {
734                         r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
735                         free(n);
736                         if (r < 0)
737                                 goto finish;
738                 }
739         }
740
741         if (r < 0)
742                 return r;
743
744         separator = true;
745         do {
746                 done = true;
747
748                 SD_JOURNAL_FOREACH_DATA(j, data, length) {
749                         const char *eq;
750                         char *kk, *n;
751                         size_t m;
752                         unsigned u;
753
754                         /* We already printed the boot id, from the data in
755                          * the header, hence let's suppress it here */
756                         if (length >= 9 &&
757                             memcmp(data, "_BOOT_ID=", 9) == 0)
758                                 continue;
759
760                         eq = memchr(data, '=', length);
761                         if (!eq)
762                                 continue;
763
764                         if (separator) {
765                                 if (mode == OUTPUT_JSON_PRETTY)
766                                         fputs(",\n\t", f);
767                                 else
768                                         fputs(", ", f);
769                         }
770
771                         m = eq - (const char*) data;
772
773                         n = strndup(data, m);
774                         if (!n) {
775                                 r = -ENOMEM;
776                                 goto finish;
777                         }
778
779                         u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
780                         if (u == 0) {
781                                 /* We already printed this, let's jump to the next */
782                                 free(n);
783                                 separator = false;
784
785                                 continue;
786                         } else if (u == 1) {
787                                 /* Field only appears once, output it directly */
788
789                                 json_escape(f, data, m, flags);
790                                 fputs(" : ", f);
791
792                                 json_escape(f, eq + 1, length - m - 1, flags);
793
794                                 hashmap_remove(h, n);
795                                 free(kk);
796                                 free(n);
797
798                                 separator = true;
799
800                                 continue;
801
802                         } else {
803                                 /* Field appears multiple times, output it as array */
804                                 json_escape(f, data, m, flags);
805                                 fputs(" : [ ", f);
806                                 json_escape(f, eq + 1, length - m - 1, flags);
807
808                                 /* Iterate through the end of the list */
809
810                                 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
811                                         if (length < m + 1)
812                                                 continue;
813
814                                         if (memcmp(data, n, m) != 0)
815                                                 continue;
816
817                                         if (((const char*) data)[m] != '=')
818                                                 continue;
819
820                                         fputs(", ", f);
821                                         json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
822                                 }
823
824                                 fputs(" ]", f);
825
826                                 hashmap_remove(h, n);
827                                 free(kk);
828                                 free(n);
829
830                                 /* Iterate data fields form the beginning */
831                                 done = false;
832                                 separator = true;
833
834                                 break;
835                         }
836                 }
837
838         } while (!done);
839
840         if (mode == OUTPUT_JSON_PRETTY)
841                 fputs("\n}\n", f);
842         else if (mode == OUTPUT_JSON_SSE)
843                 fputs("}\n\n", f);
844         else
845                 fputs(" }\n", f);
846
847         r = 0;
848
849 finish:
850         while ((k = hashmap_steal_first_key(h)))
851                 free(k);
852
853         hashmap_free(h);
854
855         return r;
856 }
857
858 static int output_cat(
859                 FILE *f,
860                 sd_journal *j,
861                 OutputMode mode,
862                 unsigned n_columns,
863                 OutputFlags flags) {
864
865         const void *data;
866         size_t l;
867         int r;
868
869         assert(j);
870         assert(f);
871
872         sd_journal_set_data_threshold(j, 0);
873
874         r = sd_journal_get_data(j, "MESSAGE", &data, &l);
875         if (r < 0) {
876                 /* An entry without MESSAGE=? */
877                 if (r == -ENOENT)
878                         return 0;
879
880                 log_error("Failed to get data: %s", strerror(-r));
881                 return r;
882         }
883
884         assert(l >= 8);
885
886         fwrite((const char*) data + 8, 1, l - 8, f);
887         fputc('\n', f);
888
889         return 0;
890 }
891
892 static int (*output_funcs[_OUTPUT_MODE_MAX])(
893                 FILE *f,
894                 sd_journal*j,
895                 OutputMode mode,
896                 unsigned n_columns,
897                 OutputFlags flags) = {
898
899         [OUTPUT_SHORT] = output_short,
900         [OUTPUT_SHORT_ISO] = output_short,
901         [OUTPUT_SHORT_PRECISE] = output_short,
902         [OUTPUT_SHORT_MONOTONIC] = output_short,
903         [OUTPUT_VERBOSE] = output_verbose,
904         [OUTPUT_EXPORT] = output_export,
905         [OUTPUT_JSON] = output_json,
906         [OUTPUT_JSON_PRETTY] = output_json,
907         [OUTPUT_JSON_SSE] = output_json,
908         [OUTPUT_CAT] = output_cat
909 };
910
911 int output_journal(
912                 FILE *f,
913                 sd_journal *j,
914                 OutputMode mode,
915                 unsigned n_columns,
916                 OutputFlags flags,
917                 bool *ellipsized) {
918
919         int ret;
920         assert(mode >= 0);
921         assert(mode < _OUTPUT_MODE_MAX);
922
923         if (n_columns <= 0)
924                 n_columns = columns();
925
926         ret = output_funcs[mode](f, j, mode, n_columns, flags);
927         fflush(stdout);
928
929         if (ellipsized && ret > 0)
930                 *ellipsized = true;
931
932         return ret;
933 }
934
935 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
936         assert(f);
937         assert(flags);
938
939         if (!(*flags & OUTPUT_BEGIN_NEWLINE))
940                 return 0;
941
942         /* Print a beginning new line if that's request, but only once
943          * on the first line we print. */
944
945         fputc('\n', f);
946         *flags &= ~OUTPUT_BEGIN_NEWLINE;
947         return 0;
948 }
949
950 static int show_journal(FILE *f,
951                         sd_journal *j,
952                         OutputMode mode,
953                         unsigned n_columns,
954                         usec_t not_before,
955                         unsigned how_many,
956                         OutputFlags flags,
957                         bool *ellipsized) {
958
959         int r;
960         unsigned line = 0;
961         bool need_seek = false;
962         int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
963
964         assert(j);
965         assert(mode >= 0);
966         assert(mode < _OUTPUT_MODE_MAX);
967
968         /* Seek to end */
969         r = sd_journal_seek_tail(j);
970         if (r < 0)
971                 goto finish;
972
973         r = sd_journal_previous_skip(j, how_many);
974         if (r < 0)
975                 goto finish;
976
977         for (;;) {
978                 for (;;) {
979                         usec_t usec;
980
981                         if (need_seek) {
982                                 r = sd_journal_next(j);
983                                 if (r < 0)
984                                         goto finish;
985                         }
986
987                         if (r == 0)
988                                 break;
989
990                         need_seek = true;
991
992                         if (not_before > 0) {
993                                 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
994
995                                 /* -ESTALE is returned if the
996                                    timestamp is not from this boot */
997                                 if (r == -ESTALE)
998                                         continue;
999                                 else if (r < 0)
1000                                         goto finish;
1001
1002                                 if (usec < not_before)
1003                                         continue;
1004                         }
1005
1006                         line ++;
1007                         maybe_print_begin_newline(f, &flags);
1008
1009                         r = output_journal(f, j, mode, n_columns, flags, ellipsized);
1010                         if (r < 0)
1011                                 goto finish;
1012                 }
1013
1014                 if (warn_cutoff && line < how_many && not_before > 0) {
1015                         sd_id128_t boot_id;
1016                         usec_t cutoff;
1017
1018                         /* Check whether the cutoff line is too early */
1019
1020                         r = sd_id128_get_boot(&boot_id);
1021                         if (r < 0)
1022                                 goto finish;
1023
1024                         r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1025                         if (r < 0)
1026                                 goto finish;
1027
1028                         if (r > 0 && not_before < cutoff) {
1029                                 maybe_print_begin_newline(f, &flags);
1030                                 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1031                         }
1032
1033                         warn_cutoff = false;
1034                 }
1035
1036                 if (!(flags & OUTPUT_FOLLOW))
1037                         break;
1038
1039                 r = sd_journal_wait(j, USEC_INFINITY);
1040                 if (r < 0)
1041                         goto finish;
1042
1043         }
1044
1045 finish:
1046         return r;
1047 }
1048
1049 int add_matches_for_unit(sd_journal *j, const char *unit) {
1050         int r;
1051         char *m1, *m2, *m3, *m4;
1052
1053         assert(j);
1054         assert(unit);
1055
1056         m1 = strappenda("_SYSTEMD_UNIT=", unit);
1057         m2 = strappenda("COREDUMP_UNIT=", unit);
1058         m3 = strappenda("UNIT=", unit);
1059         m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
1060
1061         (void)(
1062             /* Look for messages from the service itself */
1063             (r = sd_journal_add_match(j, m1, 0)) ||
1064
1065             /* Look for coredumps of the service */
1066             (r = sd_journal_add_disjunction(j)) ||
1067             (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1068             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1069             (r = sd_journal_add_match(j, m2, 0)) ||
1070
1071              /* Look for messages from PID 1 about this service */
1072             (r = sd_journal_add_disjunction(j)) ||
1073             (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1074             (r = sd_journal_add_match(j, m3, 0)) ||
1075
1076             /* Look for messages from authorized daemons about this service */
1077             (r = sd_journal_add_disjunction(j)) ||
1078             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1079             (r = sd_journal_add_match(j, m4, 0))
1080         );
1081
1082         if (r == 0 && endswith(unit, ".slice")) {
1083                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1084
1085                 /* Show all messages belonging to a slice */
1086                 (void)(
1087                         (r = sd_journal_add_disjunction(j)) ||
1088                         (r = sd_journal_add_match(j, m5, 0))
1089                         );
1090         }
1091
1092         return r;
1093 }
1094
1095 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1096         int r;
1097         char *m1, *m2, *m3, *m4;
1098         char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1099
1100         assert(j);
1101         assert(unit);
1102
1103         m1 = strappenda("_SYSTEMD_USER_UNIT=", unit);
1104         m2 = strappenda("USER_UNIT=", unit);
1105         m3 = strappenda("COREDUMP_USER_UNIT=", unit);
1106         m4 = strappenda("OBJECT_SYSTEMD_USER_UNIT=", unit);
1107         sprintf(muid, "_UID="UID_FMT, uid);
1108
1109         (void) (
1110                 /* Look for messages from the user service itself */
1111                 (r = sd_journal_add_match(j, m1, 0)) ||
1112                 (r = sd_journal_add_match(j, muid, 0)) ||
1113
1114                 /* Look for messages from systemd about this service */
1115                 (r = sd_journal_add_disjunction(j)) ||
1116                 (r = sd_journal_add_match(j, m2, 0)) ||
1117                 (r = sd_journal_add_match(j, muid, 0)) ||
1118
1119                 /* Look for coredumps of the service */
1120                 (r = sd_journal_add_disjunction(j)) ||
1121                 (r = sd_journal_add_match(j, m3, 0)) ||
1122                 (r = sd_journal_add_match(j, muid, 0)) ||
1123                 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1124
1125                 /* Look for messages from authorized daemons about this service */
1126                 (r = sd_journal_add_disjunction(j)) ||
1127                 (r = sd_journal_add_match(j, m4, 0)) ||
1128                 (r = sd_journal_add_match(j, muid, 0)) ||
1129                 (r = sd_journal_add_match(j, "_UID=0", 0))
1130         );
1131
1132         if (r == 0 && endswith(unit, ".slice")) {
1133                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1134
1135                 /* Show all messages belonging to a slice */
1136                 (void)(
1137                         (r = sd_journal_add_disjunction(j)) ||
1138                         (r = sd_journal_add_match(j, m5, 0)) ||
1139                         (r = sd_journal_add_match(j, muid, 0))
1140                         );
1141         }
1142
1143         return r;
1144 }
1145
1146 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1147         _cleanup_close_pair_ int pair[2] = { -1, -1 };
1148         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1149         pid_t pid, child;
1150         siginfo_t si;
1151         char buf[37];
1152         ssize_t k;
1153         int r;
1154
1155         assert(machine);
1156         assert(boot_id);
1157
1158         if (!machine_name_is_valid(machine))
1159                 return -EINVAL;
1160
1161         r = container_get_leader(machine, &pid);
1162         if (r < 0)
1163                 return r;
1164
1165         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
1166         if (r < 0)
1167                 return r;
1168
1169         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1170                 return -errno;
1171
1172         child = fork();
1173         if (child < 0)
1174                 return -errno;
1175
1176         if (child == 0) {
1177                 int fd;
1178
1179                 pair[0] = safe_close(pair[0]);
1180
1181                 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
1182                 if (r < 0)
1183                         _exit(EXIT_FAILURE);
1184
1185                 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1186                 if (fd < 0)
1187                         _exit(EXIT_FAILURE);
1188
1189                 k = loop_read(fd, buf, 36, false);
1190                 safe_close(fd);
1191                 if (k != 36)
1192                         _exit(EXIT_FAILURE);
1193
1194                 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1195                 if (k != 36)
1196                         _exit(EXIT_FAILURE);
1197
1198                 _exit(EXIT_SUCCESS);
1199         }
1200
1201         pair[1] = safe_close(pair[1]);
1202
1203         r = wait_for_terminate(child, &si);
1204         if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1205                 return r < 0 ? r : -EIO;
1206
1207         k = recv(pair[0], buf, 36, 0);
1208         if (k != 36)
1209                 return -EIO;
1210
1211         buf[36] = 0;
1212         r = sd_id128_from_string(buf, boot_id);
1213         if (r < 0)
1214                 return r;
1215
1216         return 0;
1217 }
1218
1219 int add_match_this_boot(sd_journal *j, const char *machine) {
1220         char match[9+32+1] = "_BOOT_ID=";
1221         sd_id128_t boot_id;
1222         int r;
1223
1224         assert(j);
1225
1226         if (machine) {
1227                 r = get_boot_id_for_machine(machine, &boot_id);
1228                 if (r < 0) {
1229                         log_error("Failed to get boot id of container %s: %s", machine, strerror(-r));
1230                         return r;
1231                 }
1232         } else {
1233                 r = sd_id128_get_boot(&boot_id);
1234                 if (r < 0) {
1235                         log_error("Failed to get boot id: %s", strerror(-r));
1236                         return r;
1237                 }
1238         }
1239
1240         sd_id128_to_string(boot_id, match + 9);
1241         r = sd_journal_add_match(j, match, strlen(match));
1242         if (r < 0) {
1243                 log_error("Failed to add match: %s", strerror(-r));
1244                 return r;
1245         }
1246
1247         r = sd_journal_add_conjunction(j);
1248         if (r < 0)
1249                 return r;
1250
1251         return 0;
1252 }
1253
1254 int show_journal_by_unit(
1255                 FILE *f,
1256                 const char *unit,
1257                 OutputMode mode,
1258                 unsigned n_columns,
1259                 usec_t not_before,
1260                 unsigned how_many,
1261                 uid_t uid,
1262                 OutputFlags flags,
1263                 bool system,
1264                 bool *ellipsized) {
1265
1266         _cleanup_journal_close_ sd_journal*j = NULL;
1267         int r;
1268         int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
1269
1270         assert(mode >= 0);
1271         assert(mode < _OUTPUT_MODE_MAX);
1272         assert(unit);
1273
1274         if (how_many <= 0)
1275                 return 0;
1276
1277         r = sd_journal_open(&j, jflags);
1278         if (r < 0)
1279                 return r;
1280
1281         r = add_match_this_boot(j, NULL);
1282         if (r < 0)
1283                 return r;
1284
1285         if (system)
1286                 r = add_matches_for_unit(j, unit);
1287         else
1288                 r = add_matches_for_user_unit(j, unit, uid);
1289         if (r < 0)
1290                 return r;
1291
1292         if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1293                 _cleanup_free_ char *filter;
1294
1295                 filter = journal_make_match_string(j);
1296                 log_debug("Journal filter: %s", filter);
1297         }
1298
1299         return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1300 }
1301
1302 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1303         [OUTPUT_SHORT] = "short",
1304         [OUTPUT_SHORT_ISO] = "short-iso",
1305         [OUTPUT_SHORT_PRECISE] = "short-precise",
1306         [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1307         [OUTPUT_VERBOSE] = "verbose",
1308         [OUTPUT_EXPORT] = "export",
1309         [OUTPUT_JSON] = "json",
1310         [OUTPUT_JSON_PRETTY] = "json-pretty",
1311         [OUTPUT_JSON_SSE] = "json-sse",
1312         [OUTPUT_CAT] = "cat"
1313 };
1314
1315 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);