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