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