chiark / gitweb /
e179b8a7b4e20ddbca46bba2672b8c53c16a3907
[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
36 /* up to three lines (each up to 100 characters),
37    or 300 characters, whichever is less */
38 #define PRINT_LINE_THRESHOLD 3
39 #define PRINT_CHAR_THRESHOLD 300
40
41 #define JSON_THRESHOLD 4096
42
43 static int print_catalog(FILE *f, sd_journal *j) {
44         int r;
45         _cleanup_free_ char *t = NULL, *z = NULL;
46
47
48         r = sd_journal_get_catalog(j, &t);
49         if (r < 0)
50                 return r;
51
52         z = strreplace(strstrip(t), "\n", "\n-- ");
53         if (!z)
54                 return log_oom();
55
56         fputs("-- ", f);
57         fputs(z, f);
58         fputc('\n', f);
59
60         return 0;
61 }
62
63 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
64         size_t fl, nl;
65         void *buf;
66
67         assert(data);
68         assert(field);
69         assert(target);
70         assert(target_size);
71
72         fl = strlen(field);
73         if (length < fl)
74                 return 0;
75
76         if (memcmp(data, field, fl))
77                 return 0;
78
79         nl = length - fl;
80         buf = malloc(nl+1);
81         if (!buf)
82                 return log_oom();
83
84         memcpy(buf, (const char*) data + fl, nl);
85         ((char*)buf)[nl] = 0;
86
87         free(*target);
88         *target = buf;
89         *target_size = nl;
90
91         return 1;
92 }
93
94 static bool shall_print(const char *p, size_t l, OutputFlags flags) {
95         assert(p);
96
97         if (flags & OUTPUT_SHOW_ALL)
98                 return true;
99
100         if (l >= PRINT_CHAR_THRESHOLD)
101                 return false;
102
103         if (!utf8_is_printable(p, l))
104                 return false;
105
106         return true;
107 }
108
109 static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
110         const char *color_on = "", *color_off = "";
111         const char *pos, *end;
112         bool ellipsized = false;
113         int line = 0;
114
115         if (flags & OUTPUT_COLOR) {
116                 if (priority <= LOG_ERR) {
117                         color_on = ANSI_HIGHLIGHT_RED_ON;
118                         color_off = ANSI_HIGHLIGHT_OFF;
119                 } else if (priority <= LOG_NOTICE) {
120                         color_on = ANSI_HIGHLIGHT_ON;
121                         color_off = ANSI_HIGHLIGHT_OFF;
122                 }
123         }
124
125         /* A special case: make sure that we print a newline when
126            the message is empty. */
127         if (message_len == 0)
128                 fputs("\n", f);
129
130         for (pos = message;
131              pos < message + message_len;
132              pos = end + 1, line++) {
133                 bool continuation = line > 0;
134                 bool tail_line;
135                 int len;
136                 for (end = pos; end < message + message_len && *end != '\n'; end++)
137                         ;
138                 len = end - pos;
139                 assert(len >= 0);
140
141                 /* We need to figure out when we are showing not-last line, *and*
142                  * will skip subsequent lines. In that case, we will put the dots
143                  * at the end of the line, instead of putting dots in the middle
144                  * or not at all.
145                  */
146                 tail_line =
147                         line + 1 == PRINT_LINE_THRESHOLD ||
148                         end + 1 >= message + PRINT_CHAR_THRESHOLD;
149
150                 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
151                     (prefix + len + 1 < n_columns && !tail_line)) {
152                         fprintf(f, "%*s%s%.*s%s\n",
153                                 continuation * prefix, "",
154                                 color_on, len, pos, color_off);
155                         continue;
156                 }
157
158                 /* Beyond this point, ellipsization will happen. */
159                 ellipsized = true;
160
161                 if (prefix < n_columns && n_columns - prefix >= 3) {
162                         if (n_columns - prefix > (unsigned) len + 3)
163                                 fprintf(f, "%*s%s%.*s...%s\n",
164                                         continuation * prefix, "",
165                                         color_on, len, pos, color_off);
166                         else {
167                                 _cleanup_free_ char *e;
168
169                                 e = ellipsize_mem(pos, len, n_columns - prefix,
170                                                   tail_line ? 100 : 90);
171                                 if (!e)
172                                         fprintf(f, "%*s%s%.*s%s\n",
173                                                 continuation * prefix, "",
174                                                 color_on, len, pos, color_off);
175                                 else
176                                         fprintf(f, "%*s%s%s%s\n",
177                                                 continuation * prefix, "",
178                                                 color_on, e, color_off);
179                         }
180                 } else
181                         fputs("...\n", f);
182
183                 if (tail_line)
184                         break;
185         }
186
187         return ellipsized;
188 }
189
190 static int output_short(
191                 FILE *f,
192                 sd_journal *j,
193                 OutputMode mode,
194                 unsigned n_columns,
195                 OutputFlags flags) {
196
197         int r;
198         const void *data;
199         size_t length;
200         size_t n = 0;
201         _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
202         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;
203         int p = LOG_INFO;
204         bool ellipsized = false;
205
206         assert(f);
207         assert(j);
208
209         /* Set the threshold to one bigger than the actual print
210          * threshold, so that if the line is actually longer than what
211          * we're willing to print, ellipsization will occur. This way
212          * we won't output a misleading line without any indication of
213          * truncation.
214          */
215         sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
216
217         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
218
219                 r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
220                 if (r < 0)
221                         return r;
222                 else if (r > 0)
223                         continue;
224
225                 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
226                 if (r < 0)
227                         return r;
228                 else if (r > 0)
229                         continue;
230
231                 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
232                 if (r < 0)
233                         return r;
234                 else if (r > 0)
235                         continue;
236
237                 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
238                 if (r < 0)
239                         return r;
240                 else if (r > 0)
241                         continue;
242
243                 r = parse_field(data, length, "_PID=", &pid, &pid_len);
244                 if (r < 0)
245                         return r;
246                 else if (r > 0)
247                         continue;
248
249                 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
250                 if (r < 0)
251                         return r;
252                 else if (r > 0)
253                         continue;
254
255                 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
256                 if (r < 0)
257                         return r;
258                 else if (r > 0)
259                         continue;
260
261                 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
262                 if (r < 0)
263                         return r;
264                 else if (r > 0)
265                         continue;
266
267                 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
268                 if (r < 0)
269                         return r;
270         }
271
272         if (r < 0)
273                 return r;
274
275         if (!message)
276                 return 0;
277
278         if (!(flags & OUTPUT_SHOW_ALL))
279                 strip_tab_ansi(&message, &message_len);
280
281         if (priority_len == 1 && *priority >= '0' && *priority <= '7')
282                 p = *priority - '0';
283
284         if (mode == OUTPUT_SHORT_MONOTONIC) {
285                 uint64_t t;
286                 sd_id128_t boot_id;
287
288                 r = -ENOENT;
289
290                 if (monotonic)
291                         r = safe_atou64(monotonic, &t);
292
293                 if (r < 0)
294                         r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
295
296                 if (r < 0)
297                         return log_error_errno(r, "Failed to get monotonic timestamp: %m");
298
299                 fprintf(f, "[%5llu.%06llu]",
300                         (unsigned long long) (t / USEC_PER_SEC),
301                         (unsigned long long) (t % USEC_PER_SEC));
302
303                 n += 1 + 5 + 1 + 6 + 1;
304
305         } else {
306                 char buf[64];
307                 uint64_t x;
308                 time_t t;
309                 struct tm tm;
310                 struct tm *(*gettime_r)(const time_t *, struct tm *);
311
312                 r = -ENOENT;
313                 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
314
315                 if (realtime)
316                         r = safe_atou64(realtime, &x);
317
318                 if (r < 0)
319                         r = sd_journal_get_realtime_usec(j, &x);
320
321                 if (r < 0)
322                         return log_error_errno(r, "Failed to get realtime timestamp: %m");
323
324                 t = (time_t) (x / USEC_PER_SEC);
325
326                 switch(mode) {
327                 case OUTPUT_SHORT_ISO:
328                         r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm));
329                         break;
330                 case OUTPUT_SHORT_PRECISE:
331                         r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
332                         if (r > 0) {
333                                 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
334                                          ".%06llu", (unsigned long long) (x % USEC_PER_SEC));
335                         }
336                         break;
337                 default:
338                         r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
339                 }
340
341                 if (r <= 0) {
342                         log_error("Failed to format time.");
343                         return -EINVAL;
344                 }
345
346                 fputs(buf, f);
347                 n += strlen(buf);
348         }
349
350         if (hostname && shall_print(hostname, hostname_len, flags)) {
351                 fprintf(f, " %.*s", (int) hostname_len, hostname);
352                 n += hostname_len + 1;
353         }
354
355         if (identifier && shall_print(identifier, identifier_len, flags)) {
356                 fprintf(f, " %.*s", (int) identifier_len, identifier);
357                 n += identifier_len + 1;
358         } else if (comm && shall_print(comm, comm_len, flags)) {
359                 fprintf(f, " %.*s", (int) comm_len, comm);
360                 n += comm_len + 1;
361         } else
362                 fputs(" unknown", f);
363
364         if (pid && shall_print(pid, pid_len, flags)) {
365                 fprintf(f, "[%.*s]", (int) pid_len, pid);
366                 n += pid_len + 2;
367         } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
368                 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
369                 n += fake_pid_len + 2;
370         }
371
372         if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
373                 char bytes[FORMAT_BYTES_MAX];
374                 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
375         } else {
376                 fputs(": ", f);
377                 ellipsized |=
378                         print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
379         }
380
381         if (flags & OUTPUT_CATALOG)
382                 print_catalog(f, j);
383
384         return ellipsized;
385 }
386
387 static int output_verbose(
388                 FILE *f,
389                 sd_journal *j,
390                 OutputMode mode,
391                 unsigned n_columns,
392                 OutputFlags flags) {
393
394         const void *data;
395         size_t length;
396         _cleanup_free_ char *cursor = NULL;
397         uint64_t realtime;
398         char ts[FORMAT_TIMESTAMP_MAX + 7];
399         int r;
400
401         assert(f);
402         assert(j);
403
404         sd_journal_set_data_threshold(j, 0);
405
406         r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
407         if (r == -ENOENT)
408                 log_debug("Source realtime timestamp not found");
409         else if (r < 0) {
410                 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
411                          "Failed to get source realtime timestamp: %s", strerror(-r));
412                 return r;
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                         log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
431                                  "Failed to get realtime timestamp: %s", strerror(-r));
432                         return r;
433                 }
434         }
435
436         r = sd_journal_get_cursor(j, &cursor);
437         if (r < 0)
438                 return log_error_errno(r, "Failed to get cursor: %m");
439
440         fprintf(f, "%s [%s]\n",
441                 flags & OUTPUT_UTC ?
442                 format_timestamp_us_utc(ts, sizeof(ts), realtime) :
443                 format_timestamp_us(ts, sizeof(ts), realtime),
444                 cursor);
445
446         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
447                 const char *c;
448                 int fieldlen;
449                 const char *on = "", *off = "";
450
451                 c = memchr(data, '=', length);
452                 if (!c) {
453                         log_error("Invalid field.");
454                         return -EINVAL;
455                 }
456                 fieldlen = c - (const char*) data;
457
458                 if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
459                         on = ANSI_HIGHLIGHT_ON;
460                         off = ANSI_HIGHLIGHT_OFF;
461                 }
462
463                 if (flags & OUTPUT_SHOW_ALL ||
464                     (((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
465                      && utf8_is_printable(data, length))) {
466                         fprintf(f, "    %s%.*s=", on, fieldlen, (const char*)data);
467                         print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
468                         fputs(off, f);
469                 } else {
470                         char bytes[FORMAT_BYTES_MAX];
471
472                         fprintf(f, "    %s%.*s=[%s blob data]%s\n",
473                                 on,
474                                 (int) (c - (const char*) data),
475                                 (const char*) data,
476                                 format_bytes(bytes, sizeof(bytes), length - (c - (const char *) data) - 1),
477                                 off);
478                 }
479         }
480
481         if (r < 0)
482                 return r;
483
484         if (flags & OUTPUT_CATALOG)
485                 print_catalog(f, j);
486
487         return 0;
488 }
489
490 static int output_export(
491                 FILE *f,
492                 sd_journal *j,
493                 OutputMode mode,
494                 unsigned n_columns,
495                 OutputFlags flags) {
496
497         sd_id128_t boot_id;
498         char sid[33];
499         int r;
500         usec_t realtime, monotonic;
501         _cleanup_free_ char *cursor = NULL;
502         const void *data;
503         size_t length;
504
505         assert(j);
506
507         sd_journal_set_data_threshold(j, 0);
508
509         r = sd_journal_get_realtime_usec(j, &realtime);
510         if (r < 0)
511                 return log_error_errno(r, "Failed to get realtime timestamp: %m");
512
513         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
514         if (r < 0)
515                 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
516
517         r = sd_journal_get_cursor(j, &cursor);
518         if (r < 0)
519                 return log_error_errno(r, "Failed to get cursor: %m");
520
521         fprintf(f,
522                 "__CURSOR=%s\n"
523                 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
524                 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
525                 "_BOOT_ID=%s\n",
526                 cursor,
527                 realtime,
528                 monotonic,
529                 sd_id128_to_string(boot_id, sid));
530
531         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
532
533                 /* We already printed the boot id, from the data in
534                  * the header, hence let's suppress it here */
535                 if (length >= 9 &&
536                     startswith(data, "_BOOT_ID="))
537                         continue;
538
539                 if (utf8_is_printable_newline(data, length, false))
540                         fwrite(data, length, 1, f);
541                 else {
542                         const char *c;
543                         uint64_t le64;
544
545                         c = memchr(data, '=', length);
546                         if (!c) {
547                                 log_error("Invalid field.");
548                                 return -EINVAL;
549                         }
550
551                         fwrite(data, c - (const char*) data, 1, f);
552                         fputc('\n', f);
553                         le64 = htole64(length - (c - (const char*) data) - 1);
554                         fwrite(&le64, sizeof(le64), 1, f);
555                         fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
556                 }
557
558                 fputc('\n', f);
559         }
560
561         if (r < 0)
562                 return r;
563
564         fputc('\n', f);
565
566         return 0;
567 }
568
569 void json_escape(
570                 FILE *f,
571                 const char* p,
572                 size_t l,
573                 OutputFlags flags) {
574
575         assert(f);
576         assert(p);
577
578         if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
579
580                 fputs("null", f);
581
582         else if (!utf8_is_printable(p, l)) {
583                 bool not_first = false;
584
585                 fputs("[ ", f);
586
587                 while (l > 0) {
588                         if (not_first)
589                                 fprintf(f, ", %u", (uint8_t) *p);
590                         else {
591                                 not_first = true;
592                                 fprintf(f, "%u", (uint8_t) *p);
593                         }
594
595                         p++;
596                         l--;
597                 }
598
599                 fputs(" ]", f);
600         } else {
601                 fputc('\"', f);
602
603                 while (l > 0) {
604                         if (*p == '"' || *p == '\\') {
605                                 fputc('\\', f);
606                                 fputc(*p, f);
607                         } else if (*p == '\n')
608                                 fputs("\\n", f);
609                         else if (*p < ' ')
610                                 fprintf(f, "\\u%04x", *p);
611                         else
612                                 fputc(*p, f);
613
614                         p++;
615                         l--;
616                 }
617
618                 fputc('\"', f);
619         }
620 }
621
622 static int output_json(
623                 FILE *f,
624                 sd_journal *j,
625                 OutputMode mode,
626                 unsigned n_columns,
627                 OutputFlags flags) {
628
629         uint64_t realtime, monotonic;
630         _cleanup_free_ char *cursor = NULL;
631         const void *data;
632         size_t length;
633         sd_id128_t boot_id;
634         char sid[33], *k;
635         int r;
636         Hashmap *h = NULL;
637         bool done, separator;
638
639         assert(j);
640
641         sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
642
643         r = sd_journal_get_realtime_usec(j, &realtime);
644         if (r < 0)
645                 return log_error_errno(r, "Failed to get realtime timestamp: %m");
646
647         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
648         if (r < 0)
649                 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
650
651         r = sd_journal_get_cursor(j, &cursor);
652         if (r < 0)
653                 return log_error_errno(r, "Failed to get cursor: %m");
654
655         if (mode == OUTPUT_JSON_PRETTY)
656                 fprintf(f,
657                         "{\n"
658                         "\t\"__CURSOR\" : \"%s\",\n"
659                         "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
660                         "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
661                         "\t\"_BOOT_ID\" : \"%s\"",
662                         cursor,
663                         realtime,
664                         monotonic,
665                         sd_id128_to_string(boot_id, sid));
666         else {
667                 if (mode == OUTPUT_JSON_SSE)
668                         fputs("data: ", f);
669
670                 fprintf(f,
671                         "{ \"__CURSOR\" : \"%s\", "
672                         "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
673                         "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
674                         "\"_BOOT_ID\" : \"%s\"",
675                         cursor,
676                         realtime,
677                         monotonic,
678                         sd_id128_to_string(boot_id, sid));
679         }
680
681         h = hashmap_new(&string_hash_ops);
682         if (!h)
683                 return -ENOMEM;
684
685         /* First round, iterate through the entry and count how often each field appears */
686         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
687                 const char *eq;
688                 char *n;
689                 unsigned u;
690
691                 if (length >= 9 &&
692                     memcmp(data, "_BOOT_ID=", 9) == 0)
693                         continue;
694
695                 eq = memchr(data, '=', length);
696                 if (!eq)
697                         continue;
698
699                 n = strndup(data, eq - (const char*) data);
700                 if (!n) {
701                         r = -ENOMEM;
702                         goto finish;
703                 }
704
705                 u = PTR_TO_UINT(hashmap_get(h, n));
706                 if (u == 0) {
707                         r = hashmap_put(h, n, UINT_TO_PTR(1));
708                         if (r < 0) {
709                                 free(n);
710                                 goto finish;
711                         }
712                 } else {
713                         r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
714                         free(n);
715                         if (r < 0)
716                                 goto finish;
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 = -ENOMEM;
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                 goto finish;
950
951         r = sd_journal_previous_skip(j, how_many);
952         if (r < 0)
953                 goto finish;
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                                         goto finish;
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                                         goto finish;
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                                 goto finish;
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                                 goto finish;
1001
1002                         r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1003                         if (r < 0)
1004                                 goto finish;
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                         goto finish;
1020
1021         }
1022
1023 finish:
1024         return r;
1025 }
1026
1027 int add_matches_for_unit(sd_journal *j, const char *unit) {
1028         int r;
1029         char *m1, *m2, *m3, *m4;
1030
1031         assert(j);
1032         assert(unit);
1033
1034         m1 = strjoina("_SYSTEMD_UNIT=", unit);
1035         m2 = strjoina("COREDUMP_UNIT=", unit);
1036         m3 = strjoina("UNIT=", unit);
1037         m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit);
1038
1039         (void)(
1040             /* Look for messages from the service itself */
1041             (r = sd_journal_add_match(j, m1, 0)) ||
1042
1043             /* Look for coredumps of the service */
1044             (r = sd_journal_add_disjunction(j)) ||
1045             (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1046             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1047             (r = sd_journal_add_match(j, m2, 0)) ||
1048
1049              /* Look for messages from PID 1 about this service */
1050             (r = sd_journal_add_disjunction(j)) ||
1051             (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1052             (r = sd_journal_add_match(j, m3, 0)) ||
1053
1054             /* Look for messages from authorized daemons about this service */
1055             (r = sd_journal_add_disjunction(j)) ||
1056             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1057             (r = sd_journal_add_match(j, m4, 0))
1058         );
1059
1060         if (r == 0 && endswith(unit, ".slice")) {
1061                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1062
1063                 /* Show all messages belonging to a slice */
1064                 (void)(
1065                         (r = sd_journal_add_disjunction(j)) ||
1066                         (r = sd_journal_add_match(j, m5, 0))
1067                         );
1068         }
1069
1070         return r;
1071 }
1072
1073 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1074         int r;
1075         char *m1, *m2, *m3, *m4;
1076         char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1077
1078         assert(j);
1079         assert(unit);
1080
1081         m1 = strjoina("_SYSTEMD_USER_UNIT=", unit);
1082         m2 = strjoina("USER_UNIT=", unit);
1083         m3 = strjoina("COREDUMP_USER_UNIT=", unit);
1084         m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit);
1085         sprintf(muid, "_UID="UID_FMT, uid);
1086
1087         (void) (
1088                 /* Look for messages from the user service itself */
1089                 (r = sd_journal_add_match(j, m1, 0)) ||
1090                 (r = sd_journal_add_match(j, muid, 0)) ||
1091
1092                 /* Look for messages from systemd about this service */
1093                 (r = sd_journal_add_disjunction(j)) ||
1094                 (r = sd_journal_add_match(j, m2, 0)) ||
1095                 (r = sd_journal_add_match(j, muid, 0)) ||
1096
1097                 /* Look for coredumps of the service */
1098                 (r = sd_journal_add_disjunction(j)) ||
1099                 (r = sd_journal_add_match(j, m3, 0)) ||
1100                 (r = sd_journal_add_match(j, muid, 0)) ||
1101                 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1102
1103                 /* Look for messages from authorized daemons about this service */
1104                 (r = sd_journal_add_disjunction(j)) ||
1105                 (r = sd_journal_add_match(j, m4, 0)) ||
1106                 (r = sd_journal_add_match(j, muid, 0)) ||
1107                 (r = sd_journal_add_match(j, "_UID=0", 0))
1108         );
1109
1110         if (r == 0 && endswith(unit, ".slice")) {
1111                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1112
1113                 /* Show all messages belonging to a slice */
1114                 (void)(
1115                         (r = sd_journal_add_disjunction(j)) ||
1116                         (r = sd_journal_add_match(j, m5, 0)) ||
1117                         (r = sd_journal_add_match(j, muid, 0))
1118                         );
1119         }
1120
1121         return r;
1122 }
1123
1124 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1125         _cleanup_close_pair_ int pair[2] = { -1, -1 };
1126         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1127         pid_t pid, child;
1128         siginfo_t si;
1129         char buf[37];
1130         ssize_t k;
1131         int r;
1132
1133         assert(machine);
1134         assert(boot_id);
1135
1136         if (!machine_name_is_valid(machine))
1137                 return -EINVAL;
1138
1139         r = container_get_leader(machine, &pid);
1140         if (r < 0)
1141                 return r;
1142
1143         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
1144         if (r < 0)
1145                 return r;
1146
1147         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1148                 return -errno;
1149
1150         child = fork();
1151         if (child < 0)
1152                 return -errno;
1153
1154         if (child == 0) {
1155                 int fd;
1156
1157                 pair[0] = safe_close(pair[0]);
1158
1159                 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
1160                 if (r < 0)
1161                         _exit(EXIT_FAILURE);
1162
1163                 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1164                 if (fd < 0)
1165                         _exit(EXIT_FAILURE);
1166
1167                 r = loop_read_exact(fd, buf, 36, false);
1168                 safe_close(fd);
1169                 if (r < 0)
1170                         _exit(EXIT_FAILURE);
1171
1172                 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1173                 if (k != 36)
1174                         _exit(EXIT_FAILURE);
1175
1176                 _exit(EXIT_SUCCESS);
1177         }
1178
1179         pair[1] = safe_close(pair[1]);
1180
1181         r = wait_for_terminate(child, &si);
1182         if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1183                 return r < 0 ? r : -EIO;
1184
1185         k = recv(pair[0], buf, 36, 0);
1186         if (k != 36)
1187                 return -EIO;
1188
1189         buf[36] = 0;
1190         r = sd_id128_from_string(buf, boot_id);
1191         if (r < 0)
1192                 return r;
1193
1194         return 0;
1195 }
1196
1197 int add_match_this_boot(sd_journal *j, const char *machine) {
1198         char match[9+32+1] = "_BOOT_ID=";
1199         sd_id128_t boot_id;
1200         int r;
1201
1202         assert(j);
1203
1204         if (machine) {
1205                 r = get_boot_id_for_machine(machine, &boot_id);
1206                 if (r < 0)
1207                         return log_error_errno(r, "Failed to get boot id of container %s: %m", machine);
1208         } else {
1209                 r = sd_id128_get_boot(&boot_id);
1210                 if (r < 0)
1211                         return log_error_errno(r, "Failed to get boot id: %m");
1212         }
1213
1214         sd_id128_to_string(boot_id, match + 9);
1215         r = sd_journal_add_match(j, match, strlen(match));
1216         if (r < 0)
1217                 return log_error_errno(r, "Failed to add match: %m");
1218
1219         r = sd_journal_add_conjunction(j);
1220         if (r < 0)
1221                 return r;
1222
1223         return 0;
1224 }
1225
1226 int show_journal_by_unit(
1227                 FILE *f,
1228                 const char *unit,
1229                 OutputMode mode,
1230                 unsigned n_columns,
1231                 usec_t not_before,
1232                 unsigned how_many,
1233                 uid_t uid,
1234                 OutputFlags flags,
1235                 int journal_open_flags,
1236                 bool system_unit,
1237                 bool *ellipsized) {
1238
1239         _cleanup_journal_close_ sd_journal*j = NULL;
1240         int r;
1241
1242         assert(mode >= 0);
1243         assert(mode < _OUTPUT_MODE_MAX);
1244         assert(unit);
1245
1246         if (how_many <= 0)
1247                 return 0;
1248
1249         r = sd_journal_open(&j, journal_open_flags);
1250         if (r < 0)
1251                 return r;
1252
1253         r = add_match_this_boot(j, NULL);
1254         if (r < 0)
1255                 return r;
1256
1257         if (system_unit)
1258                 r = add_matches_for_unit(j, unit);
1259         else
1260                 r = add_matches_for_user_unit(j, unit, uid);
1261         if (r < 0)
1262                 return r;
1263
1264         if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
1265                 _cleanup_free_ char *filter;
1266
1267                 filter = journal_make_match_string(j);
1268                 log_debug("Journal filter: %s", filter);
1269         }
1270
1271         return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1272 }
1273
1274 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1275         [OUTPUT_SHORT] = "short",
1276         [OUTPUT_SHORT_ISO] = "short-iso",
1277         [OUTPUT_SHORT_PRECISE] = "short-precise",
1278         [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1279         [OUTPUT_VERBOSE] = "verbose",
1280         [OUTPUT_EXPORT] = "export",
1281         [OUTPUT_JSON] = "json",
1282         [OUTPUT_JSON_PRETTY] = "json-pretty",
1283         [OUTPUT_JSON_SSE] = "json-sse",
1284         [OUTPUT_CAT] = "cat"
1285 };
1286
1287 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);