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