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