chiark / gitweb /
sd-bus,log: remove unused variables
[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", (unsigned long long) (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="USEC_FMT"\n"
535                 "__MONOTONIC_TIMESTAMP="USEC_FMT"\n"
536                 "_BOOT_ID=%s\n",
537                 cursor,
538                 realtime,
539                 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_newline(data, length, false))
551                         fwrite(data, length, 1, f);
552                 else {
553                         const char *c;
554                         uint64_t le64;
555
556                         c = memchr(data, '=', length);
557                         if (!c) {
558                                 log_error("Invalid field.");
559                                 return -EINVAL;
560                         }
561
562                         fwrite(data, c - (const char*) data, 1, f);
563                         fputc('\n', f);
564                         le64 = htole64(length - (c - (const char*) data) - 1);
565                         fwrite(&le64, sizeof(le64), 1, f);
566                         fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
567                 }
568
569                 fputc('\n', f);
570         }
571
572         if (r < 0)
573                 return r;
574
575         fputc('\n', f);
576
577         return 0;
578 }
579
580 void json_escape(
581                 FILE *f,
582                 const char* p,
583                 size_t l,
584                 OutputFlags flags) {
585
586         assert(f);
587         assert(p);
588
589         if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD)
590
591                 fputs("null", f);
592
593         else if (!utf8_is_printable(p, l)) {
594                 bool not_first = false;
595
596                 fputs("[ ", f);
597
598                 while (l > 0) {
599                         if (not_first)
600                                 fprintf(f, ", %u", (uint8_t) *p);
601                         else {
602                                 not_first = true;
603                                 fprintf(f, "%u", (uint8_t) *p);
604                         }
605
606                         p++;
607                         l--;
608                 }
609
610                 fputs(" ]", f);
611         } else {
612                 fputc('\"', f);
613
614                 while (l > 0) {
615                         if (*p == '"' || *p == '\\') {
616                                 fputc('\\', f);
617                                 fputc(*p, f);
618                         } else if (*p == '\n')
619                                 fputs("\\n", f);
620                         else if (*p < ' ')
621                                 fprintf(f, "\\u%04x", *p);
622                         else
623                                 fputc(*p, f);
624
625                         p++;
626                         l--;
627                 }
628
629                 fputc('\"', f);
630         }
631 }
632
633 static int output_json(
634                 FILE *f,
635                 sd_journal *j,
636                 OutputMode mode,
637                 unsigned n_columns,
638                 OutputFlags flags) {
639
640         uint64_t realtime, monotonic;
641         _cleanup_free_ char *cursor = NULL;
642         const void *data;
643         size_t length;
644         sd_id128_t boot_id;
645         char sid[33], *k;
646         int r;
647         Hashmap *h = NULL;
648         bool done, separator;
649
650         assert(j);
651
652         sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD);
653
654         r = sd_journal_get_realtime_usec(j, &realtime);
655         if (r < 0) {
656                 log_error("Failed to get realtime timestamp: %s", strerror(-r));
657                 return r;
658         }
659
660         r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
661         if (r < 0) {
662                 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
663                 return r;
664         }
665
666         r = sd_journal_get_cursor(j, &cursor);
667         if (r < 0) {
668                 log_error("Failed to get cursor: %s", strerror(-r));
669                 return r;
670         }
671
672         if (mode == OUTPUT_JSON_PRETTY)
673                 fprintf(f,
674                         "{\n"
675                         "\t\"__CURSOR\" : \"%s\",\n"
676                         "\t\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\",\n"
677                         "\t\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\",\n"
678                         "\t\"_BOOT_ID\" : \"%s\"",
679                         cursor,
680                         realtime,
681                         monotonic,
682                         sd_id128_to_string(boot_id, sid));
683         else {
684                 if (mode == OUTPUT_JSON_SSE)
685                         fputs("data: ", f);
686
687                 fprintf(f,
688                         "{ \"__CURSOR\" : \"%s\", "
689                         "\"__REALTIME_TIMESTAMP\" : \""USEC_FMT"\", "
690                         "\"__MONOTONIC_TIMESTAMP\" : \""USEC_FMT"\", "
691                         "\"_BOOT_ID\" : \"%s\"",
692                         cursor,
693                         realtime,
694                         monotonic,
695                         sd_id128_to_string(boot_id, sid));
696         }
697
698         h = hashmap_new(string_hash_func, string_compare_func);
699         if (!h)
700                 return -ENOMEM;
701
702         /* First round, iterate through the entry and count how often each field appears */
703         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
704                 const char *eq;
705                 char *n;
706                 unsigned u;
707
708                 if (length >= 9 &&
709                     memcmp(data, "_BOOT_ID=", 9) == 0)
710                         continue;
711
712                 eq = memchr(data, '=', length);
713                 if (!eq)
714                         continue;
715
716                 n = strndup(data, eq - (const char*) data);
717                 if (!n) {
718                         r = -ENOMEM;
719                         goto finish;
720                 }
721
722                 u = PTR_TO_UINT(hashmap_get(h, n));
723                 if (u == 0) {
724                         r = hashmap_put(h, n, UINT_TO_PTR(1));
725                         if (r < 0) {
726                                 free(n);
727                                 goto finish;
728                         }
729                 } else {
730                         r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
731                         free(n);
732                         if (r < 0)
733                                 goto finish;
734                 }
735         }
736
737         if (r < 0)
738                 return r;
739
740         separator = true;
741         do {
742                 done = true;
743
744                 SD_JOURNAL_FOREACH_DATA(j, data, length) {
745                         const char *eq;
746                         char *kk, *n;
747                         size_t m;
748                         unsigned u;
749
750                         /* We already printed the boot id, from the data in
751                          * the header, hence let's suppress it here */
752                         if (length >= 9 &&
753                             memcmp(data, "_BOOT_ID=", 9) == 0)
754                                 continue;
755
756                         eq = memchr(data, '=', length);
757                         if (!eq)
758                                 continue;
759
760                         if (separator) {
761                                 if (mode == OUTPUT_JSON_PRETTY)
762                                         fputs(",\n\t", f);
763                                 else
764                                         fputs(", ", f);
765                         }
766
767                         m = eq - (const char*) data;
768
769                         n = strndup(data, m);
770                         if (!n) {
771                                 r = -ENOMEM;
772                                 goto finish;
773                         }
774
775                         u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
776                         if (u == 0) {
777                                 /* We already printed this, let's jump to the next */
778                                 free(n);
779                                 separator = false;
780
781                                 continue;
782                         } else if (u == 1) {
783                                 /* Field only appears once, output it directly */
784
785                                 json_escape(f, data, m, flags);
786                                 fputs(" : ", f);
787
788                                 json_escape(f, eq + 1, length - m - 1, flags);
789
790                                 hashmap_remove(h, n);
791                                 free(kk);
792                                 free(n);
793
794                                 separator = true;
795
796                                 continue;
797
798                         } else {
799                                 /* Field appears multiple times, output it as array */
800                                 json_escape(f, data, m, flags);
801                                 fputs(" : [ ", f);
802                                 json_escape(f, eq + 1, length - m - 1, flags);
803
804                                 /* Iterate through the end of the list */
805
806                                 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
807                                         if (length < m + 1)
808                                                 continue;
809
810                                         if (memcmp(data, n, m) != 0)
811                                                 continue;
812
813                                         if (((const char*) data)[m] != '=')
814                                                 continue;
815
816                                         fputs(", ", f);
817                                         json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
818                                 }
819
820                                 fputs(" ]", f);
821
822                                 hashmap_remove(h, n);
823                                 free(kk);
824                                 free(n);
825
826                                 /* Iterate data fields form the beginning */
827                                 done = false;
828                                 separator = true;
829
830                                 break;
831                         }
832                 }
833
834         } while (!done);
835
836         if (mode == OUTPUT_JSON_PRETTY)
837                 fputs("\n}\n", f);
838         else if (mode == OUTPUT_JSON_SSE)
839                 fputs("}\n\n", f);
840         else
841                 fputs(" }\n", f);
842
843         r = 0;
844
845 finish:
846         while ((k = hashmap_steal_first_key(h)))
847                 free(k);
848
849         hashmap_free(h);
850
851         return r;
852 }
853
854 static int output_cat(
855                 FILE *f,
856                 sd_journal *j,
857                 OutputMode mode,
858                 unsigned n_columns,
859                 OutputFlags flags) {
860
861         const void *data;
862         size_t l;
863         int r;
864
865         assert(j);
866         assert(f);
867
868         sd_journal_set_data_threshold(j, 0);
869
870         r = sd_journal_get_data(j, "MESSAGE", &data, &l);
871         if (r < 0) {
872                 /* An entry without MESSAGE=? */
873                 if (r == -ENOENT)
874                         return 0;
875
876                 log_error("Failed to get data: %s", strerror(-r));
877                 return r;
878         }
879
880         assert(l >= 8);
881
882         fwrite((const char*) data + 8, 1, l - 8, f);
883         fputc('\n', f);
884
885         return 0;
886 }
887
888 static int (*output_funcs[_OUTPUT_MODE_MAX])(
889                 FILE *f,
890                 sd_journal*j,
891                 OutputMode mode,
892                 unsigned n_columns,
893                 OutputFlags flags) = {
894
895         [OUTPUT_SHORT] = output_short,
896         [OUTPUT_SHORT_ISO] = output_short,
897         [OUTPUT_SHORT_PRECISE] = output_short,
898         [OUTPUT_SHORT_MONOTONIC] = output_short,
899         [OUTPUT_VERBOSE] = output_verbose,
900         [OUTPUT_EXPORT] = output_export,
901         [OUTPUT_JSON] = output_json,
902         [OUTPUT_JSON_PRETTY] = output_json,
903         [OUTPUT_JSON_SSE] = output_json,
904         [OUTPUT_CAT] = output_cat
905 };
906
907 int output_journal(
908                 FILE *f,
909                 sd_journal *j,
910                 OutputMode mode,
911                 unsigned n_columns,
912                 OutputFlags flags,
913                 bool *ellipsized) {
914
915         int ret;
916         assert(mode >= 0);
917         assert(mode < _OUTPUT_MODE_MAX);
918
919         if (n_columns <= 0)
920                 n_columns = columns();
921
922         ret = output_funcs[mode](f, j, mode, n_columns, flags);
923         fflush(stdout);
924
925         if (ellipsized && ret > 0)
926                 *ellipsized = true;
927
928         return ret;
929 }
930
931 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
932         assert(f);
933         assert(flags);
934
935         if (!(*flags & OUTPUT_BEGIN_NEWLINE))
936                 return 0;
937
938         /* Print a beginning new line if that's request, but only once
939          * on the first line we print. */
940
941         fputc('\n', f);
942         *flags &= ~OUTPUT_BEGIN_NEWLINE;
943         return 0;
944 }
945
946 static int show_journal(FILE *f,
947                         sd_journal *j,
948                         OutputMode mode,
949                         unsigned n_columns,
950                         usec_t not_before,
951                         unsigned how_many,
952                         OutputFlags flags,
953                         bool *ellipsized) {
954
955         int r;
956         unsigned line = 0;
957         bool need_seek = false;
958         int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
959
960         assert(j);
961         assert(mode >= 0);
962         assert(mode < _OUTPUT_MODE_MAX);
963
964         /* Seek to end */
965         r = sd_journal_seek_tail(j);
966         if (r < 0)
967                 goto finish;
968
969         r = sd_journal_previous_skip(j, how_many);
970         if (r < 0)
971                 goto finish;
972
973         for (;;) {
974                 for (;;) {
975                         usec_t usec;
976
977                         if (need_seek) {
978                                 r = sd_journal_next(j);
979                                 if (r < 0)
980                                         goto finish;
981                         }
982
983                         if (r == 0)
984                                 break;
985
986                         need_seek = true;
987
988                         if (not_before > 0) {
989                                 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
990
991                                 /* -ESTALE is returned if the
992                                    timestamp is not from this boot */
993                                 if (r == -ESTALE)
994                                         continue;
995                                 else if (r < 0)
996                                         goto finish;
997
998                                 if (usec < not_before)
999                                         continue;
1000                         }
1001
1002                         line ++;
1003                         maybe_print_begin_newline(f, &flags);
1004
1005                         r = output_journal(f, j, mode, n_columns, flags, ellipsized);
1006                         if (r < 0)
1007                                 goto finish;
1008                 }
1009
1010                 if (warn_cutoff && line < how_many && not_before > 0) {
1011                         sd_id128_t boot_id;
1012                         usec_t cutoff;
1013
1014                         /* Check whether the cutoff line is too early */
1015
1016                         r = sd_id128_get_boot(&boot_id);
1017                         if (r < 0)
1018                                 goto finish;
1019
1020                         r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1021                         if (r < 0)
1022                                 goto finish;
1023
1024                         if (r > 0 && not_before < cutoff) {
1025                                 maybe_print_begin_newline(f, &flags);
1026                                 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1027                         }
1028
1029                         warn_cutoff = false;
1030                 }
1031
1032                 if (!(flags & OUTPUT_FOLLOW))
1033                         break;
1034
1035                 r = sd_journal_wait(j, USEC_INFINITY);
1036                 if (r < 0)
1037                         goto finish;
1038
1039         }
1040
1041 finish:
1042         return r;
1043 }
1044
1045 int add_matches_for_unit(sd_journal *j, const char *unit) {
1046         int r;
1047         char *m1, *m2, *m3, *m4;
1048
1049         assert(j);
1050         assert(unit);
1051
1052         m1 = strappenda("_SYSTEMD_UNIT=", unit);
1053         m2 = strappenda("COREDUMP_UNIT=", unit);
1054         m3 = strappenda("UNIT=", unit);
1055         m4 = strappenda("OBJECT_SYSTEMD_UNIT=", unit);
1056
1057         (void)(
1058             /* Look for messages from the service itself */
1059             (r = sd_journal_add_match(j, m1, 0)) ||
1060
1061             /* Look for coredumps of the service */
1062             (r = sd_journal_add_disjunction(j)) ||
1063             (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1064             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1065             (r = sd_journal_add_match(j, m2, 0)) ||
1066
1067              /* Look for messages from PID 1 about this service */
1068             (r = sd_journal_add_disjunction(j)) ||
1069             (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1070             (r = sd_journal_add_match(j, m3, 0)) ||
1071
1072             /* Look for messages from authorized daemons about this service */
1073             (r = sd_journal_add_disjunction(j)) ||
1074             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1075             (r = sd_journal_add_match(j, m4, 0))
1076         );
1077
1078         if (r == 0 && endswith(unit, ".slice")) {
1079                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1080
1081                 /* Show all messages belonging to a slice */
1082                 (void)(
1083                         (r = sd_journal_add_disjunction(j)) ||
1084                         (r = sd_journal_add_match(j, m5, 0))
1085                         );
1086         }
1087
1088         return r;
1089 }
1090
1091 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1092         int r;
1093         char *m1, *m2, *m3, *m4;
1094         char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1095
1096         assert(j);
1097         assert(unit);
1098
1099         m1 = strappenda("_SYSTEMD_USER_UNIT=", unit);
1100         m2 = strappenda("USER_UNIT=", unit);
1101         m3 = strappenda("COREDUMP_USER_UNIT=", unit);
1102         m4 = strappenda("OBJECT_SYSTEMD_USER_UNIT=", unit);
1103         sprintf(muid, "_UID="UID_FMT, uid);
1104
1105         (void) (
1106                 /* Look for messages from the user service itself */
1107                 (r = sd_journal_add_match(j, m1, 0)) ||
1108                 (r = sd_journal_add_match(j, muid, 0)) ||
1109
1110                 /* Look for messages from systemd about this service */
1111                 (r = sd_journal_add_disjunction(j)) ||
1112                 (r = sd_journal_add_match(j, m2, 0)) ||
1113                 (r = sd_journal_add_match(j, muid, 0)) ||
1114
1115                 /* Look for coredumps of the service */
1116                 (r = sd_journal_add_disjunction(j)) ||
1117                 (r = sd_journal_add_match(j, m3, 0)) ||
1118                 (r = sd_journal_add_match(j, muid, 0)) ||
1119                 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1120
1121                 /* Look for messages from authorized daemons about this service */
1122                 (r = sd_journal_add_disjunction(j)) ||
1123                 (r = sd_journal_add_match(j, m4, 0)) ||
1124                 (r = sd_journal_add_match(j, muid, 0)) ||
1125                 (r = sd_journal_add_match(j, "_UID=0", 0))
1126         );
1127
1128         if (r == 0 && endswith(unit, ".slice")) {
1129                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1130
1131                 /* Show all messages belonging to a slice */
1132                 (void)(
1133                         (r = sd_journal_add_disjunction(j)) ||
1134                         (r = sd_journal_add_match(j, m5, 0)) ||
1135                         (r = sd_journal_add_match(j, muid, 0))
1136                         );
1137         }
1138
1139         return r;
1140 }
1141
1142 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1143         _cleanup_close_pair_ int pair[2] = { -1, -1 };
1144         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1145         pid_t pid, child;
1146         siginfo_t si;
1147         char buf[37];
1148         ssize_t k;
1149         int r;
1150
1151         assert(machine);
1152         assert(boot_id);
1153
1154         if (!filename_is_safe(machine))
1155                 return -EINVAL;
1156
1157         r = container_get_leader(machine, &pid);
1158         if (r < 0)
1159                 return r;
1160
1161         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
1162         if (r < 0)
1163                 return r;
1164
1165         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1166                 return -errno;
1167
1168         child = fork();
1169         if (child < 0)
1170                 return -errno;
1171
1172         if (child == 0) {
1173                 int fd;
1174
1175                 pair[0] = safe_close(pair[0]);
1176
1177                 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
1178                 if (r < 0)
1179                         _exit(EXIT_FAILURE);
1180
1181                 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1182                 if (fd < 0)
1183                         _exit(EXIT_FAILURE);
1184
1185                 k = loop_read(fd, buf, 36, false);
1186                 safe_close(fd);
1187                 if (k != 36)
1188                         _exit(EXIT_FAILURE);
1189
1190                 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1191                 if (k != 36)
1192                         _exit(EXIT_FAILURE);
1193
1194                 _exit(EXIT_SUCCESS);
1195         }
1196
1197         pair[1] = safe_close(pair[1]);
1198
1199         r = wait_for_terminate(child, &si);
1200         if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1201                 return r < 0 ? r : -EIO;
1202
1203         k = recv(pair[0], buf, 36, 0);
1204         if (k != 36)
1205                 return -EIO;
1206
1207         buf[36] = 0;
1208         r = sd_id128_from_string(buf, boot_id);
1209         if (r < 0)
1210                 return r;
1211
1212         return 0;
1213 }
1214
1215 int add_match_this_boot(sd_journal *j, const char *machine) {
1216         char match[9+32+1] = "_BOOT_ID=";
1217         sd_id128_t boot_id;
1218         int r;
1219
1220         assert(j);
1221
1222         if (machine) {
1223                 r = get_boot_id_for_machine(machine, &boot_id);
1224                 if (r < 0) {
1225                         log_error("Failed to get boot id of container %s: %s", machine, strerror(-r));
1226                         return r;
1227                 }
1228         } else {
1229                 r = sd_id128_get_boot(&boot_id);
1230                 if (r < 0) {
1231                         log_error("Failed to get boot id: %s", strerror(-r));
1232                         return r;
1233                 }
1234         }
1235
1236         sd_id128_to_string(boot_id, match + 9);
1237         r = sd_journal_add_match(j, match, strlen(match));
1238         if (r < 0) {
1239                 log_error("Failed to add match: %s", strerror(-r));
1240                 return r;
1241         }
1242
1243         r = sd_journal_add_conjunction(j);
1244         if (r < 0)
1245                 return r;
1246
1247         return 0;
1248 }
1249
1250 int show_journal_by_unit(
1251                 FILE *f,
1252                 const char *unit,
1253                 OutputMode mode,
1254                 unsigned n_columns,
1255                 usec_t not_before,
1256                 unsigned how_many,
1257                 uid_t uid,
1258                 OutputFlags flags,
1259                 bool system,
1260                 bool *ellipsized) {
1261
1262         _cleanup_journal_close_ sd_journal*j = NULL;
1263         int r;
1264         int jflags = SD_JOURNAL_LOCAL_ONLY | system * SD_JOURNAL_SYSTEM;
1265
1266         assert(mode >= 0);
1267         assert(mode < _OUTPUT_MODE_MAX);
1268         assert(unit);
1269
1270         if (how_many <= 0)
1271                 return 0;
1272
1273         r = sd_journal_open(&j, jflags);
1274         if (r < 0)
1275                 return r;
1276
1277         r = add_match_this_boot(j, NULL);
1278         if (r < 0)
1279                 return r;
1280
1281         if (system)
1282                 r = add_matches_for_unit(j, unit);
1283         else
1284                 r = add_matches_for_user_unit(j, unit, uid);
1285         if (r < 0)
1286                 return r;
1287
1288         if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1289                 _cleanup_free_ char *filter;
1290
1291                 filter = journal_make_match_string(j);
1292                 log_debug("Journal filter: %s", filter);
1293         }
1294
1295         return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1296 }
1297
1298 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1299         [OUTPUT_SHORT] = "short",
1300         [OUTPUT_SHORT_ISO] = "short-iso",
1301         [OUTPUT_SHORT_PRECISE] = "short-precise",
1302         [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1303         [OUTPUT_VERBOSE] = "verbose",
1304         [OUTPUT_EXPORT] = "export",
1305         [OUTPUT_JSON] = "json",
1306         [OUTPUT_JSON_PRETTY] = "json-pretty",
1307         [OUTPUT_JSON_SSE] = "json-sse",
1308         [OUTPUT_CAT] = "cat"
1309 };
1310
1311 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);