chiark / gitweb /
util: add shell_maybe_quote() call for preparing a string for shell cmdline inclusion
[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
35 /* up to three lines (each up to 100 characters),
36    or 300 characters, whichever is less */
37 #define PRINT_LINE_THRESHOLD 3
38 #define PRINT_CHAR_THRESHOLD 300
39
40 #define JSON_THRESHOLD 4096
41
42 static int print_catalog(FILE *f, sd_journal *j) {
43         int r;
44         _cleanup_free_ char *t = NULL, *z = NULL;
45
46
47         r = sd_journal_get_catalog(j, &t);
48         if (r < 0)
49                 return r;
50
51         z = strreplace(strstrip(t), "\n", "\n-- ");
52         if (!z)
53                 return log_oom();
54
55         fputs("-- ", f);
56         fputs(z, f);
57         fputc('\n', f);
58
59         return 0;
60 }
61
62 static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) {
63         size_t fl, nl;
64         void *buf;
65
66         assert(data);
67         assert(field);
68         assert(target);
69         assert(target_size);
70
71         fl = strlen(field);
72         if (length < fl)
73                 return 0;
74
75         if (memcmp(data, field, fl))
76                 return 0;
77
78         nl = length - fl;
79         buf = malloc(nl+1);
80         if (!buf)
81                 return log_oom();
82
83         memcpy(buf, (const char*) data + fl, nl);
84         ((char*)buf)[nl] = 0;
85
86         free(*target);
87         *target = buf;
88         *target_size = nl;
89
90         return 1;
91 }
92
93 static bool shall_print(const char *p, size_t l, OutputFlags flags) {
94         assert(p);
95
96         if (flags & OUTPUT_SHOW_ALL)
97                 return true;
98
99         if (l >= PRINT_CHAR_THRESHOLD)
100                 return false;
101
102         if (!utf8_is_printable(p, l))
103                 return false;
104
105         return true;
106 }
107
108 static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
109         const char *color_on = "", *color_off = "";
110         const char *pos, *end;
111         bool ellipsized = false;
112         int line = 0;
113
114         if (flags & OUTPUT_COLOR) {
115                 if (priority <= LOG_ERR) {
116                         color_on = ANSI_HIGHLIGHT_RED_ON;
117                         color_off = ANSI_HIGHLIGHT_OFF;
118                 } else if (priority <= LOG_NOTICE) {
119                         color_on = ANSI_HIGHLIGHT_ON;
120                         color_off = ANSI_HIGHLIGHT_OFF;
121                 }
122         }
123
124         /* A special case: make sure that we print a newline when
125            the message is empty. */
126         if (message_len == 0)
127                 fputs("\n", f);
128
129         for (pos = message;
130              pos < message + message_len;
131              pos = end + 1, line++) {
132                 bool continuation = line > 0;
133                 bool tail_line;
134                 int len;
135                 for (end = pos; end < message + message_len && *end != '\n'; end++)
136                         ;
137                 len = end - pos;
138                 assert(len >= 0);
139
140                 /* We need to figure out when we are showing not-last line, *and*
141                  * will skip subsequent lines. In that case, we will put the dots
142                  * at the end of the line, instead of putting dots in the middle
143                  * or not at all.
144                  */
145                 tail_line =
146                         line + 1 == PRINT_LINE_THRESHOLD ||
147                         end + 1 >= message + PRINT_CHAR_THRESHOLD;
148
149                 if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
150                     (prefix + len + 1 < n_columns && !tail_line)) {
151                         fprintf(f, "%*s%s%.*s%s\n",
152                                 continuation * prefix, "",
153                                 color_on, len, pos, color_off);
154                         continue;
155                 }
156
157                 /* Beyond this point, ellipsization will happen. */
158                 ellipsized = true;
159
160                 if (prefix < n_columns && n_columns - prefix >= 3) {
161                         if (n_columns - prefix > (unsigned) len + 3)
162                                 fprintf(f, "%*s%s%.*s...%s\n",
163                                         continuation * prefix, "",
164                                         color_on, len, pos, color_off);
165                         else {
166                                 _cleanup_free_ char *e;
167
168                                 e = ellipsize_mem(pos, len, n_columns - prefix,
169                                                   tail_line ? 100 : 90);
170                                 if (!e)
171                                         fprintf(f, "%*s%s%.*s%s\n",
172                                                 continuation * prefix, "",
173                                                 color_on, len, pos, color_off);
174                                 else
175                                         fprintf(f, "%*s%s%s%s\n",
176                                                 continuation * prefix, "",
177                                                 color_on, e, color_off);
178                         }
179                 } else
180                         fputs("...\n", f);
181
182                 if (tail_line)
183                         break;
184         }
185
186         return ellipsized;
187 }
188
189 static int output_short(
190                 FILE *f,
191                 sd_journal *j,
192                 OutputMode mode,
193                 unsigned n_columns,
194                 OutputFlags flags) {
195
196         int r;
197         const void *data;
198         size_t length;
199         size_t n = 0;
200         _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL;
201         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;
202         int p = LOG_INFO;
203         bool ellipsized = false;
204
205         assert(f);
206         assert(j);
207
208         /* Set the threshold to one bigger than the actual print
209          * threshold, so that if the line is actually longer than what
210          * we're willing to print, ellipsization will occur. This way
211          * we won't output a misleading line without any indication of
212          * truncation.
213          */
214         sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1);
215
216         JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
217
218                 r = parse_field(data, length, "PRIORITY=", &priority, &priority_len);
219                 if (r < 0)
220                         return r;
221                 else if (r > 0)
222                         continue;
223
224                 r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len);
225                 if (r < 0)
226                         return r;
227                 else if (r > 0)
228                         continue;
229
230                 r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len);
231                 if (r < 0)
232                         return r;
233                 else if (r > 0)
234                         continue;
235
236                 r = parse_field(data, length, "_COMM=", &comm, &comm_len);
237                 if (r < 0)
238                         return r;
239                 else if (r > 0)
240                         continue;
241
242                 r = parse_field(data, length, "_PID=", &pid, &pid_len);
243                 if (r < 0)
244                         return r;
245                 else if (r > 0)
246                         continue;
247
248                 r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len);
249                 if (r < 0)
250                         return r;
251                 else if (r > 0)
252                         continue;
253
254                 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len);
255                 if (r < 0)
256                         return r;
257                 else if (r > 0)
258                         continue;
259
260                 r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len);
261                 if (r < 0)
262                         return r;
263                 else if (r > 0)
264                         continue;
265
266                 r = parse_field(data, length, "MESSAGE=", &message, &message_len);
267                 if (r < 0)
268                         return r;
269         }
270
271         if (r < 0)
272                 return r;
273
274         if (!message)
275                 return 0;
276
277         if (!(flags & OUTPUT_SHOW_ALL))
278                 strip_tab_ansi(&message, &message_len);
279
280         if (priority_len == 1 && *priority >= '0' && *priority <= '7')
281                 p = *priority - '0';
282
283         if (mode == OUTPUT_SHORT_MONOTONIC) {
284                 uint64_t t;
285                 sd_id128_t boot_id;
286
287                 r = -ENOENT;
288
289                 if (monotonic)
290                         r = safe_atou64(monotonic, &t);
291
292                 if (r < 0)
293                         r = sd_journal_get_monotonic_usec(j, &t, &boot_id);
294
295                 if (r < 0)
296                         return log_error_errno(r, "Failed to get monotonic timestamp: %m");
297
298                 fprintf(f, "[%5llu.%06llu]",
299                         (unsigned long long) (t / USEC_PER_SEC),
300                         (unsigned long long) (t % USEC_PER_SEC));
301
302                 n += 1 + 5 + 1 + 6 + 1;
303
304         } else {
305                 char buf[64];
306                 uint64_t x;
307                 time_t t;
308                 struct tm tm;
309                 struct tm *(*gettime_r)(const time_t *, struct tm *);
310
311                 r = -ENOENT;
312                 gettime_r = (flags & OUTPUT_UTC) ? gmtime_r : localtime_r;
313
314                 if (realtime)
315                         r = safe_atou64(realtime, &x);
316
317                 if (r < 0)
318                         r = sd_journal_get_realtime_usec(j, &x);
319
320                 if (r < 0)
321                         return log_error_errno(r, "Failed to get realtime timestamp: %m");
322
323                 t = (time_t) (x / USEC_PER_SEC);
324
325                 switch(mode) {
326                 case OUTPUT_SHORT_ISO:
327                         r = strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", gettime_r(&t, &tm));
328                         break;
329                 case OUTPUT_SHORT_PRECISE:
330                         r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
331                         if (r > 0) {
332                                 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
333                                          ".%06llu", (unsigned long long) (x % USEC_PER_SEC));
334                         }
335                         break;
336                 default:
337                         r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", gettime_r(&t, &tm));
338                 }
339
340                 if (r <= 0) {
341                         log_error("Failed to format time.");
342                         return -EINVAL;
343                 }
344
345                 fputs(buf, f);
346                 n += strlen(buf);
347         }
348
349         if (hostname && shall_print(hostname, hostname_len, flags)) {
350                 fprintf(f, " %.*s", (int) hostname_len, hostname);
351                 n += hostname_len + 1;
352         }
353
354         if (identifier && shall_print(identifier, identifier_len, flags)) {
355                 fprintf(f, " %.*s", (int) identifier_len, identifier);
356                 n += identifier_len + 1;
357         } else if (comm && shall_print(comm, comm_len, flags)) {
358                 fprintf(f, " %.*s", (int) comm_len, comm);
359                 n += comm_len + 1;
360         } else
361                 fputs(" unknown", f);
362
363         if (pid && shall_print(pid, pid_len, flags)) {
364                 fprintf(f, "[%.*s]", (int) pid_len, pid);
365                 n += pid_len + 2;
366         } else if (fake_pid && shall_print(fake_pid, fake_pid_len, flags)) {
367                 fprintf(f, "[%.*s]", (int) fake_pid_len, fake_pid);
368                 n += fake_pid_len + 2;
369         }
370
371         if (!(flags & OUTPUT_SHOW_ALL) && !utf8_is_printable(message, message_len)) {
372                 char bytes[FORMAT_BYTES_MAX];
373                 fprintf(f, ": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len));
374         } else {
375                 fputs(": ", f);
376                 ellipsized |=
377                         print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
378         }
379
380         if (flags & OUTPUT_CATALOG)
381                 print_catalog(f, j);
382
383         return ellipsized;
384 }
385
386 static int output_verbose(
387                 FILE *f,
388                 sd_journal *j,
389                 OutputMode mode,
390                 unsigned n_columns,
391                 OutputFlags flags) {
392
393         const void *data;
394         size_t length;
395         _cleanup_free_ char *cursor = NULL;
396         uint64_t realtime;
397         char ts[FORMAT_TIMESTAMP_MAX + 7];
398         int r;
399
400         assert(f);
401         assert(j);
402
403         sd_journal_set_data_threshold(j, 0);
404
405         r = sd_journal_get_data(j, "_SOURCE_REALTIME_TIMESTAMP", &data, &length);
406         if (r == -ENOENT)
407                 log_debug("Source realtime timestamp not found");
408         else if (r < 0) {
409                 log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
410                          "Failed to get source realtime timestamp: %s", strerror(-r));
411                 return r;
412         } else {
413                 _cleanup_free_ char *value = NULL;
414                 size_t size;
415
416                 r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &value, &size);
417                 if (r < 0)
418                         log_debug_errno(r, "_SOURCE_REALTIME_TIMESTAMP invalid: %m");
419                 else {
420                         r = safe_atou64(value, &realtime);
421                         if (r < 0)
422                                 log_debug_errno(r, "Failed to parse realtime timestamp: %m");
423                 }
424         }
425
426         if (r < 0) {
427                 r = sd_journal_get_realtime_usec(j, &realtime);
428                 if (r < 0) {
429                         log_full(r == -EADDRNOTAVAIL ? LOG_DEBUG : LOG_ERR,
430                                  "Failed to get realtime timestamp: %s", strerror(-r));
431                         return r;
432                 }
433         }
434
435         r = sd_journal_get_cursor(j, &cursor);
436         if (r < 0)
437                 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 -ENOMEM;
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 = -ENOMEM;
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                                 goto finish;
710                         }
711                 } else {
712                         r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
713                         free(n);
714                         if (r < 0)
715                                 goto finish;
716                 }
717         }
718
719         if (r < 0)
720                 return r;
721
722         separator = true;
723         do {
724                 done = true;
725
726                 SD_JOURNAL_FOREACH_DATA(j, data, length) {
727                         const char *eq;
728                         char *kk, *n;
729                         size_t m;
730                         unsigned u;
731
732                         /* We already printed the boot id, from the data in
733                          * the header, hence let's suppress it here */
734                         if (length >= 9 &&
735                             memcmp(data, "_BOOT_ID=", 9) == 0)
736                                 continue;
737
738                         eq = memchr(data, '=', length);
739                         if (!eq)
740                                 continue;
741
742                         if (separator) {
743                                 if (mode == OUTPUT_JSON_PRETTY)
744                                         fputs(",\n\t", f);
745                                 else
746                                         fputs(", ", f);
747                         }
748
749                         m = eq - (const char*) data;
750
751                         n = strndup(data, m);
752                         if (!n) {
753                                 r = -ENOMEM;
754                                 goto finish;
755                         }
756
757                         u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
758                         if (u == 0) {
759                                 /* We already printed this, let's jump to the next */
760                                 free(n);
761                                 separator = false;
762
763                                 continue;
764                         } else if (u == 1) {
765                                 /* Field only appears once, output it directly */
766
767                                 json_escape(f, data, m, flags);
768                                 fputs(" : ", f);
769
770                                 json_escape(f, eq + 1, length - m - 1, flags);
771
772                                 hashmap_remove(h, n);
773                                 free(kk);
774                                 free(n);
775
776                                 separator = true;
777
778                                 continue;
779
780                         } else {
781                                 /* Field appears multiple times, output it as array */
782                                 json_escape(f, data, m, flags);
783                                 fputs(" : [ ", f);
784                                 json_escape(f, eq + 1, length - m - 1, flags);
785
786                                 /* Iterate through the end of the list */
787
788                                 while (sd_journal_enumerate_data(j, &data, &length) > 0) {
789                                         if (length < m + 1)
790                                                 continue;
791
792                                         if (memcmp(data, n, m) != 0)
793                                                 continue;
794
795                                         if (((const char*) data)[m] != '=')
796                                                 continue;
797
798                                         fputs(", ", f);
799                                         json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
800                                 }
801
802                                 fputs(" ]", f);
803
804                                 hashmap_remove(h, n);
805                                 free(kk);
806                                 free(n);
807
808                                 /* Iterate data fields form the beginning */
809                                 done = false;
810                                 separator = true;
811
812                                 break;
813                         }
814                 }
815
816         } while (!done);
817
818         if (mode == OUTPUT_JSON_PRETTY)
819                 fputs("\n}\n", f);
820         else if (mode == OUTPUT_JSON_SSE)
821                 fputs("}\n\n", f);
822         else
823                 fputs(" }\n", f);
824
825         r = 0;
826
827 finish:
828         while ((k = hashmap_steal_first_key(h)))
829                 free(k);
830
831         hashmap_free(h);
832
833         return r;
834 }
835
836 static int output_cat(
837                 FILE *f,
838                 sd_journal *j,
839                 OutputMode mode,
840                 unsigned n_columns,
841                 OutputFlags flags) {
842
843         const void *data;
844         size_t l;
845         int r;
846
847         assert(j);
848         assert(f);
849
850         sd_journal_set_data_threshold(j, 0);
851
852         r = sd_journal_get_data(j, "MESSAGE", &data, &l);
853         if (r < 0) {
854                 /* An entry without MESSAGE=? */
855                 if (r == -ENOENT)
856                         return 0;
857
858                 return log_error_errno(r, "Failed to get data: %m");
859         }
860
861         assert(l >= 8);
862
863         fwrite((const char*) data + 8, 1, l - 8, f);
864         fputc('\n', f);
865
866         return 0;
867 }
868
869 static int (*output_funcs[_OUTPUT_MODE_MAX])(
870                 FILE *f,
871                 sd_journal*j,
872                 OutputMode mode,
873                 unsigned n_columns,
874                 OutputFlags flags) = {
875
876         [OUTPUT_SHORT] = output_short,
877         [OUTPUT_SHORT_ISO] = output_short,
878         [OUTPUT_SHORT_PRECISE] = output_short,
879         [OUTPUT_SHORT_MONOTONIC] = output_short,
880         [OUTPUT_VERBOSE] = output_verbose,
881         [OUTPUT_EXPORT] = output_export,
882         [OUTPUT_JSON] = output_json,
883         [OUTPUT_JSON_PRETTY] = output_json,
884         [OUTPUT_JSON_SSE] = output_json,
885         [OUTPUT_CAT] = output_cat
886 };
887
888 int output_journal(
889                 FILE *f,
890                 sd_journal *j,
891                 OutputMode mode,
892                 unsigned n_columns,
893                 OutputFlags flags,
894                 bool *ellipsized) {
895
896         int ret;
897         assert(mode >= 0);
898         assert(mode < _OUTPUT_MODE_MAX);
899
900         if (n_columns <= 0)
901                 n_columns = columns();
902
903         ret = output_funcs[mode](f, j, mode, n_columns, flags);
904         fflush(stdout);
905
906         if (ellipsized && ret > 0)
907                 *ellipsized = true;
908
909         return ret;
910 }
911
912 static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) {
913         assert(f);
914         assert(flags);
915
916         if (!(*flags & OUTPUT_BEGIN_NEWLINE))
917                 return 0;
918
919         /* Print a beginning new line if that's request, but only once
920          * on the first line we print. */
921
922         fputc('\n', f);
923         *flags &= ~OUTPUT_BEGIN_NEWLINE;
924         return 0;
925 }
926
927 static int show_journal(FILE *f,
928                         sd_journal *j,
929                         OutputMode mode,
930                         unsigned n_columns,
931                         usec_t not_before,
932                         unsigned how_many,
933                         OutputFlags flags,
934                         bool *ellipsized) {
935
936         int r;
937         unsigned line = 0;
938         bool need_seek = false;
939         int warn_cutoff = flags & OUTPUT_WARN_CUTOFF;
940
941         assert(j);
942         assert(mode >= 0);
943         assert(mode < _OUTPUT_MODE_MAX);
944
945         /* Seek to end */
946         r = sd_journal_seek_tail(j);
947         if (r < 0)
948                 goto finish;
949
950         r = sd_journal_previous_skip(j, how_many);
951         if (r < 0)
952                 goto finish;
953
954         for (;;) {
955                 for (;;) {
956                         usec_t usec;
957
958                         if (need_seek) {
959                                 r = sd_journal_next(j);
960                                 if (r < 0)
961                                         goto finish;
962                         }
963
964                         if (r == 0)
965                                 break;
966
967                         need_seek = true;
968
969                         if (not_before > 0) {
970                                 r = sd_journal_get_monotonic_usec(j, &usec, NULL);
971
972                                 /* -ESTALE is returned if the
973                                    timestamp is not from this boot */
974                                 if (r == -ESTALE)
975                                         continue;
976                                 else if (r < 0)
977                                         goto finish;
978
979                                 if (usec < not_before)
980                                         continue;
981                         }
982
983                         line ++;
984                         maybe_print_begin_newline(f, &flags);
985
986                         r = output_journal(f, j, mode, n_columns, flags, ellipsized);
987                         if (r < 0)
988                                 goto finish;
989                 }
990
991                 if (warn_cutoff && line < how_many && not_before > 0) {
992                         sd_id128_t boot_id;
993                         usec_t cutoff = 0;
994
995                         /* Check whether the cutoff line is too early */
996
997                         r = sd_id128_get_boot(&boot_id);
998                         if (r < 0)
999                                 goto finish;
1000
1001                         r = sd_journal_get_cutoff_monotonic_usec(j, boot_id, &cutoff, NULL);
1002                         if (r < 0)
1003                                 goto finish;
1004
1005                         if (r > 0 && not_before < cutoff) {
1006                                 maybe_print_begin_newline(f, &flags);
1007                                 fprintf(f, "Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.\n");
1008                         }
1009
1010                         warn_cutoff = false;
1011                 }
1012
1013                 if (!(flags & OUTPUT_FOLLOW))
1014                         break;
1015
1016                 r = sd_journal_wait(j, USEC_INFINITY);
1017                 if (r < 0)
1018                         goto finish;
1019
1020         }
1021
1022 finish:
1023         return r;
1024 }
1025
1026 int add_matches_for_unit(sd_journal *j, const char *unit) {
1027         int r;
1028         char *m1, *m2, *m3, *m4;
1029
1030         assert(j);
1031         assert(unit);
1032
1033         m1 = strjoina("_SYSTEMD_UNIT=", unit);
1034         m2 = strjoina("COREDUMP_UNIT=", unit);
1035         m3 = strjoina("UNIT=", unit);
1036         m4 = strjoina("OBJECT_SYSTEMD_UNIT=", unit);
1037
1038         (void)(
1039             /* Look for messages from the service itself */
1040             (r = sd_journal_add_match(j, m1, 0)) ||
1041
1042             /* Look for coredumps of the service */
1043             (r = sd_journal_add_disjunction(j)) ||
1044             (r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0)) ||
1045             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1046             (r = sd_journal_add_match(j, m2, 0)) ||
1047
1048              /* Look for messages from PID 1 about this service */
1049             (r = sd_journal_add_disjunction(j)) ||
1050             (r = sd_journal_add_match(j, "_PID=1", 0)) ||
1051             (r = sd_journal_add_match(j, m3, 0)) ||
1052
1053             /* Look for messages from authorized daemons about this service */
1054             (r = sd_journal_add_disjunction(j)) ||
1055             (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1056             (r = sd_journal_add_match(j, m4, 0))
1057         );
1058
1059         if (r == 0 && endswith(unit, ".slice")) {
1060                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1061
1062                 /* Show all messages belonging to a slice */
1063                 (void)(
1064                         (r = sd_journal_add_disjunction(j)) ||
1065                         (r = sd_journal_add_match(j, m5, 0))
1066                         );
1067         }
1068
1069         return r;
1070 }
1071
1072 int add_matches_for_user_unit(sd_journal *j, const char *unit, uid_t uid) {
1073         int r;
1074         char *m1, *m2, *m3, *m4;
1075         char muid[sizeof("_UID=") + DECIMAL_STR_MAX(uid_t)];
1076
1077         assert(j);
1078         assert(unit);
1079
1080         m1 = strjoina("_SYSTEMD_USER_UNIT=", unit);
1081         m2 = strjoina("USER_UNIT=", unit);
1082         m3 = strjoina("COREDUMP_USER_UNIT=", unit);
1083         m4 = strjoina("OBJECT_SYSTEMD_USER_UNIT=", unit);
1084         sprintf(muid, "_UID="UID_FMT, uid);
1085
1086         (void) (
1087                 /* Look for messages from the user service itself */
1088                 (r = sd_journal_add_match(j, m1, 0)) ||
1089                 (r = sd_journal_add_match(j, muid, 0)) ||
1090
1091                 /* Look for messages from systemd about this service */
1092                 (r = sd_journal_add_disjunction(j)) ||
1093                 (r = sd_journal_add_match(j, m2, 0)) ||
1094                 (r = sd_journal_add_match(j, muid, 0)) ||
1095
1096                 /* Look for coredumps of the service */
1097                 (r = sd_journal_add_disjunction(j)) ||
1098                 (r = sd_journal_add_match(j, m3, 0)) ||
1099                 (r = sd_journal_add_match(j, muid, 0)) ||
1100                 (r = sd_journal_add_match(j, "_UID=0", 0)) ||
1101
1102                 /* Look for messages from authorized daemons about this service */
1103                 (r = sd_journal_add_disjunction(j)) ||
1104                 (r = sd_journal_add_match(j, m4, 0)) ||
1105                 (r = sd_journal_add_match(j, muid, 0)) ||
1106                 (r = sd_journal_add_match(j, "_UID=0", 0))
1107         );
1108
1109         if (r == 0 && endswith(unit, ".slice")) {
1110                 char *m5 = strappend("_SYSTEMD_SLICE=", unit);
1111
1112                 /* Show all messages belonging to a slice */
1113                 (void)(
1114                         (r = sd_journal_add_disjunction(j)) ||
1115                         (r = sd_journal_add_match(j, m5, 0)) ||
1116                         (r = sd_journal_add_match(j, muid, 0))
1117                         );
1118         }
1119
1120         return r;
1121 }
1122
1123 static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
1124         _cleanup_close_pair_ int pair[2] = { -1, -1 };
1125         _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
1126         pid_t pid, child;
1127         siginfo_t si;
1128         char buf[37];
1129         ssize_t k;
1130         int r;
1131
1132         assert(machine);
1133         assert(boot_id);
1134
1135         if (!machine_name_is_valid(machine))
1136                 return -EINVAL;
1137
1138         r = container_get_leader(machine, &pid);
1139         if (r < 0)
1140                 return r;
1141
1142         r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
1143         if (r < 0)
1144                 return r;
1145
1146         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1147                 return -errno;
1148
1149         child = fork();
1150         if (child < 0)
1151                 return -errno;
1152
1153         if (child == 0) {
1154                 int fd;
1155
1156                 pair[0] = safe_close(pair[0]);
1157
1158                 r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
1159                 if (r < 0)
1160                         _exit(EXIT_FAILURE);
1161
1162                 fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1163                 if (fd < 0)
1164                         _exit(EXIT_FAILURE);
1165
1166                 r = loop_read_exact(fd, buf, 36, false);
1167                 safe_close(fd);
1168                 if (r < 0)
1169                         _exit(EXIT_FAILURE);
1170
1171                 k = send(pair[1], buf, 36, MSG_NOSIGNAL);
1172                 if (k != 36)
1173                         _exit(EXIT_FAILURE);
1174
1175                 _exit(EXIT_SUCCESS);
1176         }
1177
1178         pair[1] = safe_close(pair[1]);
1179
1180         r = wait_for_terminate(child, &si);
1181         if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
1182                 return r < 0 ? r : -EIO;
1183
1184         k = recv(pair[0], buf, 36, 0);
1185         if (k != 36)
1186                 return -EIO;
1187
1188         buf[36] = 0;
1189         r = sd_id128_from_string(buf, boot_id);
1190         if (r < 0)
1191                 return r;
1192
1193         return 0;
1194 }
1195
1196 int add_match_this_boot(sd_journal *j, const char *machine) {
1197         char match[9+32+1] = "_BOOT_ID=";
1198         sd_id128_t boot_id;
1199         int r;
1200
1201         assert(j);
1202
1203         if (machine) {
1204                 r = get_boot_id_for_machine(machine, &boot_id);
1205                 if (r < 0)
1206                         return log_error_errno(r, "Failed to get boot id of container %s: %m", machine);
1207         } else {
1208                 r = sd_id128_get_boot(&boot_id);
1209                 if (r < 0)
1210                         return log_error_errno(r, "Failed to get boot id: %m");
1211         }
1212
1213         sd_id128_to_string(boot_id, match + 9);
1214         r = sd_journal_add_match(j, match, strlen(match));
1215         if (r < 0)
1216                 return log_error_errno(r, "Failed to add match: %m");
1217
1218         r = sd_journal_add_conjunction(j);
1219         if (r < 0)
1220                 return r;
1221
1222         return 0;
1223 }
1224
1225 int show_journal_by_unit(
1226                 FILE *f,
1227                 const char *unit,
1228                 OutputMode mode,
1229                 unsigned n_columns,
1230                 usec_t not_before,
1231                 unsigned how_many,
1232                 uid_t uid,
1233                 OutputFlags flags,
1234                 int journal_open_flags,
1235                 bool system_unit,
1236                 bool *ellipsized) {
1237
1238         _cleanup_journal_close_ sd_journal*j = NULL;
1239         int r;
1240
1241         assert(mode >= 0);
1242         assert(mode < _OUTPUT_MODE_MAX);
1243         assert(unit);
1244
1245         if (how_many <= 0)
1246                 return 0;
1247
1248         r = sd_journal_open(&j, journal_open_flags);
1249         if (r < 0)
1250                 return r;
1251
1252         r = add_match_this_boot(j, NULL);
1253         if (r < 0)
1254                 return r;
1255
1256         if (system_unit)
1257                 r = add_matches_for_unit(j, unit);
1258         else
1259                 r = add_matches_for_user_unit(j, unit, uid);
1260         if (r < 0)
1261                 return r;
1262
1263         if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
1264                 _cleanup_free_ char *filter;
1265
1266                 filter = journal_make_match_string(j);
1267                 log_debug("Journal filter: %s", filter);
1268         }
1269
1270         return show_journal(f, j, mode, n_columns, not_before, how_many, flags, ellipsized);
1271 }
1272
1273 static const char *const output_mode_table[_OUTPUT_MODE_MAX] = {
1274         [OUTPUT_SHORT] = "short",
1275         [OUTPUT_SHORT_ISO] = "short-iso",
1276         [OUTPUT_SHORT_PRECISE] = "short-precise",
1277         [OUTPUT_SHORT_MONOTONIC] = "short-monotonic",
1278         [OUTPUT_VERBOSE] = "verbose",
1279         [OUTPUT_EXPORT] = "export",
1280         [OUTPUT_JSON] = "json",
1281         [OUTPUT_JSON_PRETTY] = "json-pretty",
1282         [OUTPUT_JSON_SSE] = "json-sse",
1283         [OUTPUT_CAT] = "cat"
1284 };
1285
1286 DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode);