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