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