chiark / gitweb /
Prep v225: Applying various fixes and changes to src/libelogind/sd-bus that got lost...
[elogind.git] / src / shared / logs-show.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2012 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <time.h>
23 #include <errno.h>
24 #include <sys/socket.h>
25 #include <string.h>
26 #include <fcntl.h>
27
28 #include "logs-show.h"
29 #include "log.h"
30 #include "util.h"
31 #include "utf8.h"
32 #include "hashmap.h"
33 #include "journal-internal.h"
34 #include "formats-util.h"
35 #include "process-util.h"
36 #include "terminal-util.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 log_error_errno(r, "Failed to get journal fields: %m");
276
277         if (!message) {
278                 log_debug("Skipping message without MESSAGE= field.");
279                 return 0;
280         }
281
282         if (!(flags & OUTPUT_SHOW_ALL))
283                 strip_tab_ansi(&message, &message_len);
284
285         if (priority_len == 1 && *priority >= '0' && *priority <= '7')
286                 p = *priority - '0';
287
288         if (mode == OUTPUT_SHORT_MONOTONIC) {
289                 uint64_t t;
290                 sd_id128_t boot_id;
291
292                 r = -ENOENT;
293
294                 if (monotonic)
295                         r = safe_atou64(monotonic, &t);
296
297                 if (r < 0)
298                         r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
299
300                 if (r < 0)
301                         return log_error_errno(r, "Failed to get monotonic timestamp: %m");
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                 struct tm *(*gettime_r)(const time_t *, struct tm *);
315
316                 r = -ENOENT;
317                 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
318
319                 if (realtime)
320                         r = safe_atou64(realtime, &x);
321
322                 if (r < 0)
323                         r = sd_journal_get_realtime_usec(j, &x);
324
325                 if (r < 0)
326                         return log_error_errno(r, "Failed to get realtime timestamp: %m");
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", gettime_r(&t, &tm));
333                         break;
334                 case OUTPUT_SHORT_PRECISE:
335                         r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
336                         if (r > 0) {
337                                 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
338                                          ".%06llu", (unsigned long long) (x % USEC_PER_SEC));
339                         }
340                         break;
341                 default:
342                         r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_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                 fputs(" unknown", 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                 return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get source realtime timestamp: %m");
415         else {
416                 _cleanup_free_ char *value = NULL;
417                 size_t size;
418
419                 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
420                 if (r < 0)
421                         log_debug_errno(r, "_SOURCE_REALTIME_TIMESTAMP invalid: %m");
422                 else {
423                         r = safe_atou64(value, &realtime);
424                         if (r < 0)
425                                 log_debug_errno(r, "Failed to parse realtime timestamp: %m");
426                 }
427         }
428
429         if (r < 0) {
430                 r = sd_journal_get_realtime_usec(j, &realtime);
431                 if (r < 0)
432                         return log_full_errno(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR, r, "Failed to get realtime timestamp: %m");
433         }
434
435         r = sd_journal_get_cursor(j, &cursor);
436         if (r < 0)
437                 return log_error_errno(r, "Failed to get cursor: %m");
438
439         fprintf(f, "%s [%s]\n",
440                 flags & OUTPUT_UTC ?
441                 format_timestamp_us_utc(ts, sizeof(ts), realtime) :
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                 return log_error_errno(r, "Failed to get realtime timestamp: %m");
511
512         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
513         if (r < 0)
514                 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
515
516         r = sd_journal_get_cursor(j, &cursor);
517         if (r < 0)
518                 return log_error_errno(r, "Failed to get cursor: %m");
519
520         fprintf(f,
521                 "__CURSOR=%s\n"
522                 "__REALTIME_TIMESTAMP="USEC_FMT"\n"
523                 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
524                 "_BOOT_ID=%s\n",
525                 cursor,
526                 realtime,
527                 monotonic,
528                 sd_id128_to_string(boot_id, sid));
529
530         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
531
532                 /* We already printed the boot id, from the data in
533                  * the header, hence let's suppress it here */
534                 if (length >= 9 &&
535                     startswith(data, "_BOOT_ID="))
536                         continue;
537
538                 if (utf8_is_printable_newline(data, length, false))
539                         fwrite(data, length, 1, f);
540                 else {
541                         const char *c;
542                         uint64_t le64;
543
544                         c = memchr(data, '=', length);
545                         if (!c) {
546                                 log_error("Invalid field.");
547                                 return -EINVAL;
548                         }
549
550                         fwrite(data, c - (const char*) data, 1, f);
551                         fputc('\n', f);
552                         le64 = htole64(length - (c - (const char*) data) - 1);
553                         fwrite(&le64, sizeof(le64), 1, f);
554                         fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
555                 }
556
557                 fputc('\n', f);
558         }
559
560         if (r < 0)
561                 return r;
562
563         fputc('\n', f);
564
565         return 0;
566 }
567
568 void json_escape(
569                 FILE *f,
570                 const char* p,
571                 size_t l,
572                 OutputFlags flags) {
573
574         assert(f);
575         assert(p);
576
577         if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
578
579                 fputs("null", f);
580
581         else if (!utf8_is_printable(p, l)) {
582                 bool not_first = false;
583
584                 fputs("[ ", f);
585
586                 while (l > 0) {
587                         if (not_first)
588                                 fprintf(f, ", %u", (uint8_t) *p);
589                         else {
590                                 not_first = true;
591                                 fprintf(f, "%u", (uint8_t) *p);
592                         }
593
594                         p++;
595                         l--;
596                 }
597
598                 fputs(" ]", f);
599         } else {
600                 fputc('\"', f);
601
602                 while (l > 0) {
603                         if (*p == '"' || *p == '\\') {
604                                 fputc('\\', f);
605                                 fputc(*p, f);
606                         } else if (*p == '\n')
607                                 fputs("\\n", f);
608                         else if (*p < ' ')
609                                 fprintf(f, "\\u%04x", *p);
610                         else
611                                 fputc(*p, f);
612
613                         p++;
614                         l--;
615                 }
616
617                 fputc('\"', f);
618         }
619 }
620
621 static int output_json(
622                 FILE *f,
623                 sd_journal *j,
624                 OutputMode mode,
625                 unsigned n_columns,
626                 OutputFlags flags) {
627
628         uint64_t realtime, monotonic;
629         _cleanup_free_ char *cursor = NULL;
630         const void *data;
631         size_t length;
632         sd_id128_t boot_id;
633         char sid[33], *k;
634         int r;
635         Hashmap *h = NULL;
636         bool done, separator;
637
638         assert(j);
639
640         sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
641
642         r = sd_journal_get_realtime_usec(j, &realtime);
643         if (r < 0)
644                 return log_error_errno(r, "Failed to get realtime timestamp: %m");
645
646         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
647         if (r < 0)
648                 return log_error_errno(r, "Failed to get monotonic timestamp: %m");
649
650         r = sd_journal_get_cursor(j, &cursor);
651         if (r < 0)
652                 return log_error_errno(r, "Failed to get cursor: %m");
653
654         if (mode == OUTPUT_JSON_PRETTY)
655                 fprintf(f,
656                         "{\n"
657                         "\t\"__CURSOR\" : \"%s\",\n"
658                         "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
659                         "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
660                         "\t\"_BOOT_ID\" : \"%s\"",
661                         cursor,
662                         realtime,
663                         monotonic,
664                         sd_id128_to_string(boot_id, sid));
665         else {
666                 if (mode == OUTPUT_JSON_SSE)
667                         fputs("data: ", f);
668
669                 fprintf(f,
670                         "{ \"__CURSOR\" : \"%s\", "
671                         "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
672                         "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
673                         "\"_BOOT_ID\" : \"%s\"",
674                         cursor,
675                         realtime,
676                         monotonic,
677                         sd_id128_to_string(boot_id, sid));
678         }
679
680         h = hashmap_new(&string_hash_ops);
681         if (!h)
682                 return log_oom();
683
684         /* First round, iterate through the entry and count how often each field appears */
685         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
686                 const char *eq;
687                 char *n;
688                 unsigned u;
689
690                 if (length >= 9 &&
691                     memcmp(data, "_BOOT_ID=", 9) == 0)
692                         continue;
693
694                 eq = memchr(data, '=', length);
695                 if (!eq)
696                         continue;
697
698                 n = strndup(data, eq - (const char*) data);
699                 if (!n) {
700                         r = log_oom();
701                         goto finish;
702                 }
703
704                 u = PTR_TO_UINT(hashmap_get(h, n));
705                 if (u == 0) {
706                         r = hashmap_put(h, n, UINT_TO_PTR(1));
707                         if (r < 0) {
708                                 free(n);
709                                 log_oom();
710                                 goto finish;
711                         }
712                 } else {
713                         r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
714                         free(n);
715                         if (r < 0) {
716                                 log_oom();
717                                 goto finish;
718                         }
719                 }
720         }
721
722         if (r < 0)
723                 return r;
724
725         separator = true;
726         do {
727                 done = true;
728
729                 SD_JOURNAL_FOREACH_DATA(j, data, length) {
730                         const char *eq;
731                         char *kk, *n;
732                         size_t m;
733                         unsigned u;
734
735                         /* We already printed the boot id, from the data in
736                          * the header, hence let's suppress it here */
737                         if (length >= 9 &&
738                             memcmp(data, "_BOOT_ID=", 9) == 0)
739                                 continue;
740
741                         eq = memchr(data, '=', length);
742                         if (!eq)
743                                 continue;
744
745                         if (separator) {
746                                 if (mode == OUTPUT_JSON_PRETTY)
747                                         fputs(",\n\t", f);
748                                 else
749                                         fputs(", ", f);
750                         }
751
752                         m = eq - (const char*) data;
753
754                         n = strndup(data, m);
755                         if (!n) {
756                                 r = log_oom();
757                                 goto finish;
758                         }
759
760                         u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
761                         if (u == 0) {
762                                 /* We already printed this, let's jump to the next */
763                                 free(n);
764                                 separator = false;
765
766                                 continue;
767                         } else if (u == 1) {
768                                 /* Field only appears once, output it directly */
769
770                                 json_escape(f, data, m, flags);
771                                 fputs(" : ", f);
772
773                                 json_escape(f, eq + 1, length - m - 1, flags);
774
775                                 hashmap_remove(h, n);
776                                 free(kk);
777                                 free(n);
778
779                                 separator = true;
780
781                                 continue;
782
783                         } else {
784                                 /* Field appears multiple times, output it as array */
785                                 json_escape(f, data, m, flags);
786                                 fputs(" : [ ", f);
787                                 json_escape(f, eq + 1, length - m - 1, flags);
788
789                                 /* Iterate through the end of the list */
790
791                                 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
792                                         if (length < m + 1)
793                                                 continue;
794
795                                         if (memcmp(data, n, m) != 0)
796                                                 continue;
797
798                                         if (((const char*) data)[m] != '=')
799                                                 continue;
800
801                                         fputs(", ", f);
802                                         json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
803                                 }
804
805                                 fputs(" ]", f);
806
807                                 hashmap_remove(h, n);
808                                 free(kk);
809                                 free(n);
810
811                                 /* Iterate data fields form the beginning */
812                                 done = false;
813                                 separator = true;
814
815                                 break;
816                         }
817                 }
818
819         } while (!done);
820
821         if (mode == OUTPUT_JSON_PRETTY)
822                 fputs("\n}\n", f);
823         else if (mode == OUTPUT_JSON_SSE)
824                 fputs("}\n\n", f);
825         else
826                 fputs(" }\n", f);
827
828         r = 0;
829
830 finish:
831         while ((k = hashmap_steal_first_key(h)))
832                 free(k);
833
834         hashmap_free(h);
835
836         return r;
837 }
838
839 static int output_cat(
840                 FILE *f,
841                 sd_journal *j,
842                 OutputMode mode,
843                 unsigned n_columns,
844                 OutputFlags flags) {
845
846         const void *data;
847         size_t l;
848         int r;
849
850         assert(j);
851         assert(f);
852
853         sd_journal_set_data_threshold(j, 0);
854
855         r = sd_journal_get_data(j, "MESSAGE", &data, &l);
856         if (r < 0) {
857                 /* An entry without MESSAGE=? */
858                 if (r == -ENOENT)
859                         return 0;
860
861                 return log_error_errno(r, "Failed to get data: %m");
862         }
863
864         assert(l >= 8);
865
866         fwrite((const char*) data + 8, 1, l - 8, f);
867         fputc('\n', f);
868
869         return 0;
870 }
871
872 static int (*output_funcs[_OUTPUT_MODE_MAX])(
873                 FILE *f,
874                 sd_journal*j,
875                 OutputMode mode,
876                 unsigned n_columns,
877                 OutputFlags flags) = {
878
879         [OUTPUT_SHORT] = output_short,
880         [OUTPUT_SHORT_ISO] = output_short,
881         [OUTPUT_SHORT_PRECISE] = output_short,
882         [OUTPUT_SHORT_MONOTONIC] = output_short,
883         [OUTPUT_VERBOSE] = output_verbose,
884         [OUTPUT_EXPORT] = output_export,
885         [OUTPUT_JSON] = output_json,
886         [OUTPUT_JSON_PRETTY] = output_json,
887         [OUTPUT_JSON_SSE] = output_json,
888         [OUTPUT_CAT] = output_cat
889 };
890
891 int output_journal(
892                 FILE *f,
893                 sd_journal *j,
894                 OutputMode mode,
895                 unsigned n_columns,
896                 OutputFlags flags,
897                 bool *ellipsized) {
898
899         int ret;
900         assert(mode >= 0);
901         assert(mode < _OUTPUT_MODE_MAX);
902
903         if (n_columns <= 0)
904                 n_columns = columns();
905
906         ret = output_funcs[mode](f, j, mode, n_columns, flags);
907         fflush(stdout);
908
909         if (ellipsized && ret > 0)
910                 *ellipsized = true;
911
912         return ret;
913 }
914
915 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
916         assert(f);
917         assert(flags);
918
919         if (!(*flags & OUTPUT_BEGIN_NEWLINE))
920                 return 0;
921
922         /* Print a beginning new line if that's request, but only once
923          * on the first line we print. */
924
925         fputc('\n', f);
926         *flags &= ~OUTPUT_BEGIN_NEWLINE;
927         return 0;
928 }
929
930 static int show_journal(FILE *f,
931                         sd_journal *j,
932                         OutputMode mode,
933                         unsigned n_columns,
934                         usec_t not_before,
935                         unsigned how_many,
936                         OutputFlags flags,
937                         bool *ellipsized) {
938
939         int r;
940         unsigned line = 0;
941         bool need_seek = false;
942         int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
943
944         assert(j);
945         assert(mode >= 0);
946         assert(mode < _OUTPUT_MODE_MAX);
947
948         /* Seek to end */
949         r = sd_journal_seek_tail(j);
950         if (r < 0)
951                 return log_error_errno(r, "Failed to seek to tail: %m");
952
953         r = sd_journal_previous_skip(j, how_many);
954         if (r < 0)
955                 return log_error_errno(r, "Failed to skip previous: %m");
956
957         for (;;) {
958                 for (;;) {
959                         usec_t usec;
960
961                         if (need_seek) {
962                                 r = sd_journal_next(j);
963                                 if (r < 0)
964                                         return log_error_errno(r, "Failed to iterate through journal: %m");
965                         }
966
967                         if (r == 0)
968                                 break;
969
970                         need_seek = true;
971
972                         if (not_before > 0) {
973                                 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
974
975                                 /* -ESTALE is returned if the
976                                    timestamp is not from this boot */
977                                 if (r == -ESTALE)
978                                         continue;
979                                 else if (r < 0)
980                                         return log_error_errno(r, "Failed to get journal time: %m");
981
982                                 if (usec < not_before)
983                                         continue;
984                         }
985
986                         line ++;
987                         maybe_print_begin_newline(f, &flags);
988
989                         r = output_journal(f, j, mode, n_columns, flags, ellipsized);
990                         if (r < 0)
991                                 return r;
992                 }
993
994                 if (warn_cutoff && line < how_many && not_before > 0) {
995                         sd_id128_t boot_id;
996                         usec_t cutoff = 0;
997
998                         /* Check whether the cutoff line is too early */
999
1000                         r = sd_id128_get_boot(&boot_id);
1001                         if (r < 0)
1002                                 return log_error_errno(r, "Failed to get boot id: %m");
1003
1004                         r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1005                         if (r < 0)
1006                                 return log_error_errno(r, "Failed to get journal cutoff time: %m");
1007
1008                         if (r > 0 && not_before < cutoff) {
1009                                 maybe_print_begin_newline(f, &flags);
1010                                 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1011                         }
1012
1013                         warn_cutoff = false;
1014                 }
1015
1016                 if (!(flags & OUTPUT_FOLLOW))
1017                         break;
1018
1019                 r = sd_journal_wait(j, USEC_INFINITY);
1020                 if (r < 0)
1021                         return log_error_errno(r, "Failed to wait for journal: %m");
1022
1023         }
1024
1025         return 0;
1026 }
1027
1028 int add_matches_for_unit(sd_journal *j, const char *unit) {
1029         int r;
1030         char *m1, *m2, *m3, *m4;
1031
1032         assert(j);
1033         assert(unit);
1034
1035         m1 = strjoina("_SYSTEMD_UNIT=", unit);
1036         m2 = strjoina("COREDUMP_UNIT=", unit);
1037         m3 = strjoina("UNIT=", unit);
1038         m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit);
1039
1040         (void)(
1041             /* Look for messages from the service itself */
1042             (r = sd_journal_add_match(j, m1, 0)) ||
1043
1044             /* Look for coredumps of the service */
1045             (r = sd_journal_add_disjunction(j)) ||
1046             (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1047             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1048             (r = sd_journal_add_match(j, m2, 0)) ||
1049
1050              /* Look for messages from PID 1 about this service */
1051             (r = sd_journal_add_disjunction(j)) ||
1052             (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1053             (r = sd_journal_add_match(j, m3, 0)) ||
1054
1055             /* Look for messages from authorized daemons about this service */
1056             (r = sd_journal_add_disjunction(j)) ||
1057             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1058             (r = sd_journal_add_match(j, m4, 0))
1059         );
1060
1061         if (r == 0 && endswith(unit, ".slice")) {
1062                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1063
1064                 /* Show all messages belonging to a slice */
1065                 (void)(
1066                         (r = sd_journal_add_disjunction(j)) ||
1067                         (r = sd_journal_add_match(j, m5, 0))
1068                         );
1069         }
1070
1071         return r;
1072 }
1073
1074 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1075         int r;
1076         char *m1, *m2, *m3, *m4;
1077         char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1078
1079         assert(j);
1080         assert(unit);
1081
1082         m1 = strjoina("_SYSTEMD_USER_UNIT=", unit);
1083         m2 = strjoina("USER_UNIT=", unit);
1084         m3 = strjoina("COREDUMP_USER_UNIT=", unit);
1085         m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit);
1086         sprintf(muid, "_UID="UID_FMT, uid);
1087
1088         (void) (
1089                 /* Look for messages from the user service itself */
1090                 (r = sd_journal_add_match(j, m1, 0)) ||
1091                 (r = sd_journal_add_match(j, muid, 0)) ||
1092
1093                 /* Look for messages from systemd about this service */
1094                 (r = sd_journal_add_disjunction(j)) ||
1095                 (r = sd_journal_add_match(j, m2, 0)) ||
1096                 (r = sd_journal_add_match(j, muid, 0)) ||
1097
1098                 /* Look for coredumps of the service */
1099                 (r = sd_journal_add_disjunction(j)) ||
1100                 (r = sd_journal_add_match(j, m3, 0)) ||
1101                 (r = sd_journal_add_match(j, muid, 0)) ||
1102                 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1103
1104                 /* Look for messages from authorized daemons about this service */
1105                 (r = sd_journal_add_disjunction(j)) ||
1106                 (r = sd_journal_add_match(j, m4, 0)) ||
1107                 (r = sd_journal_add_match(j, muid, 0)) ||
1108                 (r = sd_journal_add_match(j, "_UID=0", 0))
1109         );
1110
1111         if (r == 0 && endswith(unit, ".slice")) {
1112                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1113
1114                 /* Show all messages belonging to a slice */
1115                 (void)(
1116                         (r = sd_journal_add_disjunction(j)) ||
1117                         (r = sd_journal_add_match(j, m5, 0)) ||
1118                         (r = sd_journal_add_match(j, muid, 0))
1119                         );
1120         }
1121
1122         return r;
1123 }
1124
1125 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1126         _cleanup_close_pair_ int pair[2] = { -1, -1 };
1127         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1128         pid_t pid, child;
1129         siginfo_t si;
1130         char buf[37];
1131         ssize_t k;
1132         int r;
1133
1134         assert(machine);
1135         assert(boot_id);
1136
1137         if (!machine_name_is_valid(machine))
1138                 return -EINVAL;
1139
1140         r = container_get_leader(machine, &pid);
1141         if (r < 0)
1142                 return r;
1143
1144         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
1145         if (r < 0)
1146                 return r;
1147
1148         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1149                 return -errno;
1150
1151         child = fork();
1152         if (child < 0)
1153                 return -errno;
1154
1155         if (child == 0) {
1156                 int fd;
1157
1158                 pair[0] = safe_close(pair[0]);
1159
1160                 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
1161                 if (r < 0)
1162                         _exit(EXIT_FAILURE);
1163
1164                 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1165                 if (fd < 0)
1166                         _exit(EXIT_FAILURE);
1167
1168                 r = loop_read_exact(fd, buf, 36, false);
1169                 safe_close(fd);
1170                 if (r < 0)
1171                         _exit(EXIT_FAILURE);
1172
1173                 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1174                 if (k != 36)
1175                         _exit(EXIT_FAILURE);
1176
1177                 _exit(EXIT_SUCCESS);
1178         }
1179
1180         pair[1] = safe_close(pair[1]);
1181
1182         r = wait_for_terminate(child, &si);
1183         if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1184                 return r < 0 ? r : -EIO;
1185
1186         k = recv(pair[0], buf, 36, 0);
1187         if (k != 36)
1188                 return -EIO;
1189
1190         buf[36] = 0;
1191         r = sd_id128_from_string(buf, boot_id);
1192         if (r < 0)
1193                 return r;
1194
1195         return 0;
1196 }
1197
1198 int add_match_this_boot(sd_journal *j, const char *machine) {
1199         char match[9+32+1] = "_BOOT_ID=";
1200         sd_id128_t boot_id;
1201         int r;
1202
1203         assert(j);
1204
1205         if (machine) {
1206                 r = get_boot_id_for_machine(machine, &boot_id);
1207                 if (r < 0)
1208                         return log_error_errno(r, "Failed to get boot id of container %s: %m", machine);
1209         } else {
1210                 r = sd_id128_get_boot(&boot_id);
1211                 if (r < 0)
1212                         return log_error_errno(r, "Failed to get boot id: %m");
1213         }
1214
1215         sd_id128_to_string(boot_id, match + 9);
1216         r = sd_journal_add_match(j, match, strlen(match));
1217         if (r < 0)
1218                 return log_error_errno(r, "Failed to add match: %m");
1219
1220         r = sd_journal_add_conjunction(j);
1221         if (r < 0)
1222                 return log_error_errno(r, "Failed to add conjunction: %m");
1223
1224         return 0;
1225 }
1226
1227 int show_journal_by_unit(
1228                 FILE *f,
1229                 const char *unit,
1230                 OutputMode mode,
1231                 unsigned n_columns,
1232                 usec_t not_before,
1233                 unsigned how_many,
1234                 uid_t uid,
1235                 OutputFlags flags,
1236                 int journal_open_flags,
1237                 bool system_unit,
1238                 bool *ellipsized) {
1239
1240         _cleanup_journal_close_ sd_journal*j = NULL;
1241         int r;
1242
1243         assert(mode >= 0);
1244         assert(mode < _OUTPUT_MODE_MAX);
1245         assert(unit);
1246
1247         if (how_many <= 0)
1248                 return 0;
1249
1250         r = sd_journal_open(&j, journal_open_flags);
1251         if (r < 0)
1252                 return log_error_errno(r, "Failed to open journal: %m");
1253
1254         r = add_match_this_boot(j, NULL);
1255         if (r < 0)
1256                 return r;
1257
1258         if (system_unit)
1259                 r = add_matches_for_unit(j, unit);
1260         else
1261                 r = add_matches_for_user_unit(j, unit, uid);
1262         if (r < 0)
1263                 return log_error_errno(r, "Failed to add unit matches: %m");
1264
1265         if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
1266                 _cleanup_free_ char *filter;
1267
1268                 filter = journal_make_match_string(j);
1269                 if (!filter)
1270                         return log_oom();
1271
1272                 log_debug("Journal filter: %s", filter);
1273         }
1274
1275         return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1276 }
1277
1278 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1279         [OUTPUT_SHORT] = "short",
1280         [OUTPUT_SHORT_ISO] = "short-iso",
1281         [OUTPUT_SHORT_PRECISE] = "short-precise",
1282         [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1283         [OUTPUT_VERBOSE] = "verbose",
1284         [OUTPUT_EXPORT] = "export",
1285         [OUTPUT_JSON] = "json",
1286         [OUTPUT_JSON_PRETTY] = "json-pretty",
1287         [OUTPUT_JSON_SSE] = "json-sse",
1288         [OUTPUT_CAT] = "cat"
1289 };
1290
1291 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);