chiark / gitweb /
journalctl: add --force option to recreate FSS
[elogind.git] / src / journal / journalctl.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 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 <locale.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <stddef.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <time.h>
31 #include <getopt.h>
32 #include <signal.h>
33 #include <sys/stat.h>
34 #include <sys/ioctl.h>
35 #include <linux/fs.h>
36
37 #ifdef HAVE_ACL
38 #include <sys/acl.h>
39 #include "acl-util.h"
40 #endif
41
42 #include <systemd/sd-journal.h>
43
44 #include "log.h"
45 #include "logs-show.h"
46 #include "util.h"
47 #include "path-util.h"
48 #include "build.h"
49 #include "pager.h"
50 #include "logs-show.h"
51 #include "strv.h"
52 #include "journal-internal.h"
53 #include "journal-def.h"
54 #include "journal-verify.h"
55 #include "journal-authenticate.h"
56 #include "journal-qrcode.h"
57 #include "fsprg.h"
58 #include "unit-name.h"
59 #include "catalog.h"
60
61 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
62
63 static OutputMode arg_output = OUTPUT_SHORT;
64 static bool arg_pager_end = false;
65 static bool arg_follow = false;
66 static bool arg_full = false;
67 static bool arg_all = false;
68 static bool arg_no_pager = false;
69 static int arg_lines = -1;
70 static bool arg_no_tail = false;
71 static bool arg_quiet = false;
72 static bool arg_merge = false;
73 static bool arg_this_boot = false;
74 static bool arg_dmesg = false;
75 static const char *arg_cursor = NULL;
76 static const char *arg_directory = NULL;
77 static char **arg_file = NULL;
78 static int arg_priorities = 0xFF;
79 static const char *arg_verify_key = NULL;
80 #ifdef HAVE_GCRYPT
81 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
82 static bool arg_force = false;
83 #endif
84 static usec_t arg_since, arg_until;
85 static bool arg_since_set = false, arg_until_set = false;
86 static char **arg_system_units = NULL;
87 static char **arg_user_units = NULL;
88 static const char *arg_field = NULL;
89 static bool arg_catalog = false;
90 static bool arg_reverse = false;
91 static int arg_journal_type = 0;
92 static const char *arg_root = NULL;
93
94 static enum {
95         ACTION_SHOW,
96         ACTION_NEW_ID128,
97         ACTION_PRINT_HEADER,
98         ACTION_SETUP_KEYS,
99         ACTION_VERIFY,
100         ACTION_DISK_USAGE,
101         ACTION_LIST_CATALOG,
102         ACTION_DUMP_CATALOG,
103         ACTION_UPDATE_CATALOG
104 } arg_action = ACTION_SHOW;
105
106 static int help(void) {
107
108         printf("%s [OPTIONS...] [MATCHES...]\n\n"
109                "Query the journal.\n\n"
110                "Flags:\n"
111                "     --system            Show only the system journal\n"
112                "     --user              Show only the user journal for current user\n"
113                "     --since=DATE        Start showing entries newer or of the specified date\n"
114                "     --until=DATE        Stop showing entries older or of the specified date\n"
115                "  -c --cursor=CURSOR     Start showing entries from specified cursor\n"
116                "  -b --this-boot         Show data only from current boot\n"
117                "  -k --dmesg             Show kmsg log from current boot\n"
118                "  -u --unit=UNIT         Show data only from the specified unit\n"
119                "     --user-unit=UNIT    Show data only from the specified user session unit\n"
120                "  -p --priority=RANGE    Show only messages within the specified priority range\n"
121                "  -e --pager-end         Immediately jump to end of the journal in the pager\n"
122                "  -f --follow            Follow journal\n"
123                "  -n --lines[=INTEGER]   Number of journal entries to show\n"
124                "     --no-tail           Show all lines, even in follow mode\n"
125                "  -r --reverse           Show the newest entries first\n"
126                "  -o --output=STRING     Change journal output mode (short, short-monotonic,\n"
127                "                         verbose, export, json, json-pretty, json-sse, cat)\n"
128                "  -x --catalog           Add message explanations where available\n"
129                "  -l --full              Do not ellipsize fields\n"
130                "  -a --all               Show all fields, including long and unprintable\n"
131                "  -q --quiet             Don't show privilege warning\n"
132                "     --no-pager          Do not pipe output into a pager\n"
133                "  -m --merge             Show entries from all available journals\n"
134                "  -D --directory=PATH    Show journal files from directory\n"
135                "     --file=PATH         Show journal file\n"
136                "     --root=ROOT         Operate on catalog files underneath the root ROOT\n"
137 #ifdef HAVE_GCRYPT
138                "     --interval=TIME     Time interval for changing the FSS sealing key\n"
139                "     --verify-key=KEY    Specify FSS verification key\n"
140 #endif
141                "\nCommands:\n"
142                "  -h --help              Show this help\n"
143                "     --version           Show package version\n"
144                "     --new-id128         Generate a new 128 Bit ID\n"
145                "     --header            Show journal header information\n"
146                "     --disk-usage        Show total disk usage\n"
147                "  -F --field=FIELD       List all values a certain field takes\n"
148                "     --list-catalog      Show message IDs of all entries in the message catalog\n"
149                "     --dump-catalog      Show entries in the message catalog\n"
150                "     --update-catalog    Update the message catalog database\n"
151 #ifdef HAVE_GCRYPT
152                "     --setup-keys        Generate new FSS key pair\n"
153                "     --force             Force overriding new FSS key pair with --setup-keys\n"
154                "     --verify            Verify journal file consistency\n"
155 #endif
156                , program_invocation_short_name);
157
158         return 0;
159 }
160
161 static int parse_argv(int argc, char *argv[]) {
162
163         enum {
164                 ARG_VERSION = 0x100,
165                 ARG_NO_PAGER,
166                 ARG_NO_TAIL,
167                 ARG_NEW_ID128,
168                 ARG_USER,
169                 ARG_SYSTEM,
170                 ARG_ROOT,
171                 ARG_HEADER,
172                 ARG_SETUP_KEYS,
173                 ARG_FILE,
174                 ARG_INTERVAL,
175                 ARG_VERIFY,
176                 ARG_VERIFY_KEY,
177                 ARG_DISK_USAGE,
178                 ARG_SINCE,
179                 ARG_UNTIL,
180                 ARG_USER_UNIT,
181                 ARG_LIST_CATALOG,
182                 ARG_DUMP_CATALOG,
183                 ARG_UPDATE_CATALOG,
184                 ARG_FORCE,
185         };
186
187         static const struct option options[] = {
188                 { "help",         no_argument,       NULL, 'h'              },
189                 { "version" ,     no_argument,       NULL, ARG_VERSION      },
190                 { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
191                 { "pager-end",    no_argument,       NULL, 'e'              },
192                 { "follow",       no_argument,       NULL, 'f'              },
193                 { "force",        no_argument,       NULL, ARG_FORCE        },
194                 { "output",       required_argument, NULL, 'o'              },
195                 { "all",          no_argument,       NULL, 'a'              },
196                 { "full",         no_argument,       NULL, 'l'              },
197                 { "lines",        optional_argument, NULL, 'n'              },
198                 { "no-tail",      no_argument,       NULL, ARG_NO_TAIL      },
199                 { "new-id128",    no_argument,       NULL, ARG_NEW_ID128    },
200                 { "quiet",        no_argument,       NULL, 'q'              },
201                 { "merge",        no_argument,       NULL, 'm'              },
202                 { "this-boot",    no_argument,       NULL, 'b'              },
203                 { "dmesg",        no_argument,       NULL, 'k'              },
204                 { "system",       no_argument,       NULL, ARG_SYSTEM       },
205                 { "user",         no_argument,       NULL, ARG_USER         },
206                 { "directory",    required_argument, NULL, 'D'              },
207                 { "file",         required_argument, NULL, ARG_FILE         },
208                 { "root",         required_argument, NULL, ARG_ROOT         },
209                 { "header",       no_argument,       NULL, ARG_HEADER       },
210                 { "priority",     required_argument, NULL, 'p'              },
211                 { "setup-keys",   no_argument,       NULL, ARG_SETUP_KEYS   },
212                 { "interval",     required_argument, NULL, ARG_INTERVAL     },
213                 { "verify",       no_argument,       NULL, ARG_VERIFY       },
214                 { "verify-key",   required_argument, NULL, ARG_VERIFY_KEY   },
215                 { "disk-usage",   no_argument,       NULL, ARG_DISK_USAGE   },
216                 { "cursor",       required_argument, NULL, 'c'              },
217                 { "since",        required_argument, NULL, ARG_SINCE        },
218                 { "until",        required_argument, NULL, ARG_UNTIL        },
219                 { "unit",         required_argument, NULL, 'u'              },
220                 { "user-unit",    required_argument, NULL, ARG_USER_UNIT    },
221                 { "field",        required_argument, NULL, 'F'              },
222                 { "catalog",      no_argument,       NULL, 'x'              },
223                 { "list-catalog", no_argument,       NULL, ARG_LIST_CATALOG },
224                 { "dump-catalog", no_argument,       NULL, ARG_DUMP_CATALOG },
225                 { "update-catalog",no_argument,      NULL, ARG_UPDATE_CATALOG },
226                 { "reverse",      no_argument,       NULL, 'r'              },
227                 { NULL,           0,                 NULL, 0                }
228         };
229
230         int c, r;
231
232         assert(argc >= 0);
233         assert(argv);
234
235         while ((c = getopt_long(argc, argv, "hefo:aln::qmbkD:p:c:u:F:xr", options, NULL)) >= 0) {
236
237                 switch (c) {
238
239                 case 'h':
240                         help();
241                         return 0;
242
243                 case ARG_VERSION:
244                         puts(PACKAGE_STRING);
245                         puts(SYSTEMD_FEATURES);
246                         return 0;
247
248                 case ARG_NO_PAGER:
249                         arg_no_pager = true;
250                         break;
251
252                 case 'e':
253                         arg_pager_end = true;
254
255                         if (arg_lines < 0)
256                                 arg_lines = 1000;
257
258                         break;
259
260                 case 'f':
261                         arg_follow = true;
262                         break;
263
264                 case 'o':
265                         arg_output = output_mode_from_string(optarg);
266                         if (arg_output < 0) {
267                                 log_error("Unknown output format '%s'.", optarg);
268                                 return -EINVAL;
269                         }
270
271                         if (arg_output == OUTPUT_EXPORT ||
272                             arg_output == OUTPUT_JSON ||
273                             arg_output == OUTPUT_JSON_PRETTY ||
274                             arg_output == OUTPUT_JSON_SSE ||
275                             arg_output == OUTPUT_CAT)
276                                 arg_quiet = true;
277
278                         break;
279
280                 case 'l':
281                         arg_full = true;
282                         break;
283
284                 case 'a':
285                         arg_all = true;
286                         break;
287
288                 case 'n':
289                         if (optarg) {
290                                 r = safe_atoi(optarg, &arg_lines);
291                                 if (r < 0 || arg_lines < 0) {
292                                         log_error("Failed to parse lines '%s'", optarg);
293                                         return -EINVAL;
294                                 }
295                         } else {
296                                 int n;
297
298                                 /* Hmm, no argument? Maybe the next
299                                  * word on the command line is
300                                  * supposed to be the argument? Let's
301                                  * see if there is one, and is
302                                  * parsable as a positive
303                                  * integer... */
304
305                                 if (optind < argc &&
306                                     safe_atoi(argv[optind], &n) >= 0 &&
307                                     n >= 0) {
308
309                                         arg_lines = n;
310                                         optind++;
311                                 } else
312                                         arg_lines = 10;
313                         }
314
315                         break;
316
317                 case ARG_NO_TAIL:
318                         arg_no_tail = true;
319                         break;
320
321                 case ARG_NEW_ID128:
322                         arg_action = ACTION_NEW_ID128;
323                         break;
324
325                 case 'q':
326                         arg_quiet = true;
327                         break;
328
329                 case 'm':
330                         arg_merge = true;
331                         break;
332
333                 case 'b':
334                         arg_this_boot = true;
335                         break;
336
337                 case 'k':
338                         arg_this_boot = arg_dmesg = true;
339                         break;
340
341                 case ARG_SYSTEM:
342                         arg_journal_type |= SD_JOURNAL_SYSTEM;
343                         break;
344
345                 case ARG_USER:
346                         arg_journal_type |= SD_JOURNAL_CURRENT_USER;
347                         break;
348
349                 case 'D':
350                         arg_directory = optarg;
351                         break;
352
353                 case ARG_FILE:
354                         r = glob_extend(&arg_file, optarg);
355                         if (r < 0) {
356                                 log_error("Failed to add paths: %s", strerror(-r));
357                                 return r;
358                         };
359                         break;
360
361                 case ARG_ROOT:
362                         arg_root = optarg;
363                         break;
364
365                 case 'c':
366                         arg_cursor = optarg;
367                         break;
368
369                 case ARG_HEADER:
370                         arg_action = ACTION_PRINT_HEADER;
371                         break;
372
373                 case ARG_VERIFY:
374                         arg_action = ACTION_VERIFY;
375                         break;
376
377                 case ARG_DISK_USAGE:
378                         arg_action = ACTION_DISK_USAGE;
379                         break;
380
381 #ifdef HAVE_GCRYPT
382                 case ARG_FORCE:
383                         arg_force = true;
384                         break;
385
386                 case ARG_SETUP_KEYS:
387                         arg_action = ACTION_SETUP_KEYS;
388                         break;
389
390
391                 case ARG_VERIFY_KEY:
392                         arg_action = ACTION_VERIFY;
393                         arg_verify_key = optarg;
394                         arg_merge = false;
395                         break;
396
397                 case ARG_INTERVAL:
398                         r = parse_sec(optarg, &arg_interval);
399                         if (r < 0 || arg_interval <= 0) {
400                                 log_error("Failed to parse sealing key change interval: %s", optarg);
401                                 return -EINVAL;
402                         }
403                         break;
404 #else
405                 case ARG_SETUP_KEYS:
406                 case ARG_VERIFY_KEY:
407                 case ARG_INTERVAL:
408                 case ARG_FORCE:
409                         log_error("Forward-secure sealing not available.");
410                         return -ENOTSUP;
411 #endif
412
413                 case 'p': {
414                         const char *dots;
415
416                         dots = strstr(optarg, "..");
417                         if (dots) {
418                                 char *a;
419                                 int from, to, i;
420
421                                 /* a range */
422                                 a = strndup(optarg, dots - optarg);
423                                 if (!a)
424                                         return log_oom();
425
426                                 from = log_level_from_string(a);
427                                 to = log_level_from_string(dots + 2);
428                                 free(a);
429
430                                 if (from < 0 || to < 0) {
431                                         log_error("Failed to parse log level range %s", optarg);
432                                         return -EINVAL;
433                                 }
434
435                                 arg_priorities = 0;
436
437                                 if (from < to) {
438                                         for (i = from; i <= to; i++)
439                                                 arg_priorities |= 1 << i;
440                                 } else {
441                                         for (i = to; i <= from; i++)
442                                                 arg_priorities |= 1 << i;
443                                 }
444
445                         } else {
446                                 int p, i;
447
448                                 p = log_level_from_string(optarg);
449                                 if (p < 0) {
450                                         log_error("Unknown log level %s", optarg);
451                                         return -EINVAL;
452                                 }
453
454                                 arg_priorities = 0;
455
456                                 for (i = 0; i <= p; i++)
457                                         arg_priorities |= 1 << i;
458                         }
459
460                         break;
461                 }
462
463                 case ARG_SINCE:
464                         r = parse_timestamp(optarg, &arg_since);
465                         if (r < 0) {
466                                 log_error("Failed to parse timestamp: %s", optarg);
467                                 return -EINVAL;
468                         }
469                         arg_since_set = true;
470                         break;
471
472                 case ARG_UNTIL:
473                         r = parse_timestamp(optarg, &arg_until);
474                         if (r < 0) {
475                                 log_error("Failed to parse timestamp: %s", optarg);
476                                 return -EINVAL;
477                         }
478                         arg_until_set = true;
479                         break;
480
481                 case 'u':
482                         r = strv_extend(&arg_system_units, optarg);
483                         if (r < 0)
484                                 return log_oom();
485                         break;
486
487                 case ARG_USER_UNIT:
488                         r = strv_extend(&arg_user_units, optarg);
489                         if (r < 0)
490                                 return log_oom();
491                         break;
492
493                 case '?':
494                         return -EINVAL;
495
496                 case 'F':
497                         arg_field = optarg;
498                         break;
499
500                 case 'x':
501                         arg_catalog = true;
502                         break;
503
504                 case ARG_LIST_CATALOG:
505                         arg_action = ACTION_LIST_CATALOG;
506                         break;
507
508                 case ARG_DUMP_CATALOG:
509                         arg_action = ACTION_DUMP_CATALOG;
510                         break;
511
512                 case ARG_UPDATE_CATALOG:
513                         arg_action = ACTION_UPDATE_CATALOG;
514                         break;
515
516                 case 'r':
517                         arg_reverse = true;
518                         break;
519
520                 default:
521                         log_error("Unknown option code %c", c);
522                         return -EINVAL;
523                 }
524         }
525
526         if (arg_follow && !arg_no_tail && arg_lines < 0)
527                 arg_lines = 10;
528
529         if (arg_directory && arg_file) {
530                 log_error("Please specify either -D/--directory= or --file=, not both.");
531                 return -EINVAL;
532         }
533
534         if (arg_since_set && arg_until_set && arg_since > arg_until) {
535                 log_error("--since= must be before --until=.");
536                 return -EINVAL;
537         }
538
539         if (arg_cursor && arg_since_set) {
540                 log_error("Please specify either --since= or --cursor=, not both.");
541                 return -EINVAL;
542         }
543
544         if (arg_follow && arg_reverse) {
545                 log_error("Please specify either --reverse= or --follow=, not both.");
546                 return -EINVAL;
547         }
548
549         return 1;
550 }
551
552 static int generate_new_id128(void) {
553         sd_id128_t id;
554         int r;
555         unsigned i;
556
557         r = sd_id128_randomize(&id);
558         if (r < 0) {
559                 log_error("Failed to generate ID: %s", strerror(-r));
560                 return r;
561         }
562
563         printf("As string:\n"
564                SD_ID128_FORMAT_STR "\n\n"
565                "As UUID:\n"
566                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
567                "As macro:\n"
568                "#define MESSAGE_XYZ SD_ID128_MAKE(",
569                SD_ID128_FORMAT_VAL(id),
570                SD_ID128_FORMAT_VAL(id));
571         for (i = 0; i < 16; i++)
572                 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
573         fputs(")\n\n", stdout);
574
575         printf("As Python constant:\n"
576                ">>> import uuid\n"
577                ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
578                SD_ID128_FORMAT_VAL(id));
579
580         return 0;
581 }
582
583 static int add_matches(sd_journal *j, char **args) {
584         char **i;
585
586         assert(j);
587
588         STRV_FOREACH(i, args) {
589                 int r;
590
591                 if (streq(*i, "+"))
592                         r = sd_journal_add_disjunction(j);
593                 else if (path_is_absolute(*i)) {
594                         _cleanup_free_ char *p, *t = NULL;
595                         const char *path;
596                         struct stat st;
597
598                         p = canonicalize_file_name(*i);
599                         path = p ? p : *i;
600
601                         if (stat(path, &st) < 0)  {
602                                 log_error("Couldn't stat file: %m");
603                                 return -errno;
604                         }
605
606                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
607                                 t = strappend("_EXE=", path);
608                         else if (S_ISCHR(st.st_mode))
609                                 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
610                         else if (S_ISBLK(st.st_mode))
611                                 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
612                         else {
613                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
614                                 return -EINVAL;
615                         }
616
617                         if (!t)
618                                 return log_oom();
619
620                         r = sd_journal_add_match(j, t, 0);
621                 } else
622                         r = sd_journal_add_match(j, *i, 0);
623
624                 if (r < 0) {
625                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
626                         return r;
627                 }
628         }
629
630         return 0;
631 }
632
633 static int add_this_boot(sd_journal *j) {
634         if (!arg_this_boot)
635                 return 0;
636
637         return add_match_this_boot(j);
638 }
639
640 static int add_dmesg(sd_journal *j) {
641         int r;
642         assert(j);
643
644         if (!arg_dmesg)
645                 return 0;
646
647         r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
648         if (r < 0) {
649                 log_error("Failed to add match: %s", strerror(-r));
650                 return r;
651         }
652
653         r = sd_journal_add_conjunction(j);
654         if (r < 0)
655                 return r;
656
657         return 0;
658 }
659
660 static int add_units(sd_journal *j) {
661         _cleanup_free_ char *u = NULL;
662         int r;
663         char **i;
664
665         assert(j);
666
667         STRV_FOREACH(i, arg_system_units) {
668                 u = unit_name_mangle(*i);
669                 if (!u)
670                         return log_oom();
671                 r = add_matches_for_unit(j, u);
672                 if (r < 0)
673                         return r;
674                 r = sd_journal_add_disjunction(j);
675                 if (r < 0)
676                         return r;
677         }
678
679         STRV_FOREACH(i, arg_user_units) {
680                 u = unit_name_mangle(*i);
681                 if (!u)
682                         return log_oom();
683
684                 r = add_matches_for_user_unit(j, u, getuid());
685                 if (r < 0)
686                         return r;
687
688                 r = sd_journal_add_disjunction(j);
689                 if (r < 0)
690                         return r;
691
692         }
693
694         r = sd_journal_add_conjunction(j);
695         if (r < 0)
696                 return r;
697
698         return 0;
699 }
700
701 static int add_priorities(sd_journal *j) {
702         char match[] = "PRIORITY=0";
703         int i, r;
704         assert(j);
705
706         if (arg_priorities == 0xFF)
707                 return 0;
708
709         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
710                 if (arg_priorities & (1 << i)) {
711                         match[sizeof(match)-2] = '0' + i;
712
713                         r = sd_journal_add_match(j, match, strlen(match));
714                         if (r < 0) {
715                                 log_error("Failed to add match: %s", strerror(-r));
716                                 return r;
717                         }
718                 }
719
720         r = sd_journal_add_conjunction(j);
721         if (r < 0)
722                 return r;
723
724         return 0;
725 }
726
727 static int setup_keys(void) {
728 #ifdef HAVE_GCRYPT
729         size_t mpk_size, seed_size, state_size, i;
730         uint8_t *mpk, *seed, *state;
731         ssize_t l;
732         int fd = -1, r, attr = 0;
733         sd_id128_t machine, boot;
734         char *p = NULL, *k = NULL;
735         struct FSSHeader h;
736         uint64_t n;
737         struct stat st;
738
739         r = stat("/var/log/journal", &st);
740         if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
741                 log_error("stat(\"%s\") failed: %m", "/var/log/journal");
742                 return -errno;
743         }
744
745         if (r < 0 || !S_ISDIR(st.st_mode)) {
746                 log_error("%s is not a directory, must be using persistent logging for FSS.",
747                           "/var/log/journal");
748                 return r < 0 ? -errno : -ENOTDIR;
749         }
750
751         r = sd_id128_get_machine(&machine);
752         if (r < 0) {
753                 log_error("Failed to get machine ID: %s", strerror(-r));
754                 return r;
755         }
756
757         r = sd_id128_get_boot(&boot);
758         if (r < 0) {
759                 log_error("Failed to get boot ID: %s", strerror(-r));
760                 return r;
761         }
762
763         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
764                      SD_ID128_FORMAT_VAL(machine)) < 0)
765                 return log_oom();
766
767         if (access(p, F_OK) >= 0) {
768                 if (arg_force) {
769                         r = unlink(p);
770                         if (r < 0) {
771                                 log_error("unlink(\"%s\") failed: %m", p);
772                                 r = -errno;
773                                 goto finish;
774                         }
775                 } else {
776                         log_error("Sealing key file %s exists already. (--force to recreate)", p);
777                         r = -EEXIST;
778                         goto finish;
779                 }
780         }
781
782         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
783                      SD_ID128_FORMAT_VAL(machine)) < 0) {
784                 r = log_oom();
785                 goto finish;
786         }
787
788         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
789         mpk = alloca(mpk_size);
790
791         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
792         seed = alloca(seed_size);
793
794         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
795         state = alloca(state_size);
796
797         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
798         if (fd < 0) {
799                 log_error("Failed to open /dev/random: %m");
800                 r = -errno;
801                 goto finish;
802         }
803
804         log_info("Generating seed...");
805         l = loop_read(fd, seed, seed_size, true);
806         if (l < 0 || (size_t) l != seed_size) {
807                 log_error("Failed to read random seed: %s", strerror(EIO));
808                 r = -EIO;
809                 goto finish;
810         }
811
812         log_info("Generating key pair...");
813         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
814
815         log_info("Generating sealing key...");
816         FSPRG_GenState0(state, mpk, seed, seed_size);
817
818         assert(arg_interval > 0);
819
820         n = now(CLOCK_REALTIME);
821         n /= arg_interval;
822
823         close_nointr_nofail(fd);
824         fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
825         if (fd < 0) {
826                 log_error("Failed to open %s: %m", k);
827                 r = -errno;
828                 goto finish;
829         }
830
831         /* Enable secure remove, exclusion from dump, synchronous
832          * writing and in-place updating */
833         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
834                 log_warning("FS_IOC_GETFLAGS failed: %m");
835
836         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
837
838         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
839                 log_warning("FS_IOC_SETFLAGS failed: %m");
840
841         zero(h);
842         memcpy(h.signature, "KSHHRHLP", 8);
843         h.machine_id = machine;
844         h.boot_id = boot;
845         h.header_size = htole64(sizeof(h));
846         h.start_usec = htole64(n * arg_interval);
847         h.interval_usec = htole64(arg_interval);
848         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
849         h.fsprg_state_size = htole64(state_size);
850
851         l = loop_write(fd, &h, sizeof(h), false);
852         if (l < 0 || (size_t) l != sizeof(h)) {
853                 log_error("Failed to write header: %s", strerror(EIO));
854                 r = -EIO;
855                 goto finish;
856         }
857
858         l = loop_write(fd, state, state_size, false);
859         if (l < 0 || (size_t) l != state_size) {
860                 log_error("Failed to write state: %s", strerror(EIO));
861                 r = -EIO;
862                 goto finish;
863         }
864
865         if (link(k, p) < 0) {
866                 log_error("Failed to link file: %m");
867                 r = -errno;
868                 goto finish;
869         }
870
871         if (on_tty()) {
872                 fprintf(stderr,
873                         "\n"
874                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
875                         "the following local file. This key file is automatically updated when the\n"
876                         "sealing key is advanced. It should not be used on multiple hosts.\n"
877                         "\n"
878                         "\t%s\n"
879                         "\n"
880                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
881                         "at a safe location and should not be saved locally on disk.\n"
882                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
883                 fflush(stderr);
884         }
885         for (i = 0; i < seed_size; i++) {
886                 if (i > 0 && i % 3 == 0)
887                         putchar('-');
888                 printf("%02x", ((uint8_t*) seed)[i]);
889         }
890
891         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
892
893         if (on_tty()) {
894                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
895
896                 fprintf(stderr,
897                         ANSI_HIGHLIGHT_OFF "\n"
898                         "The sealing key is automatically changed every %s.\n",
899                         format_timespan(tsb, sizeof(tsb), arg_interval, 0));
900
901                 hn = gethostname_malloc();
902
903                 if (hn) {
904                         hostname_cleanup(hn, false);
905                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
906                 } else
907                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
908
909 #ifdef HAVE_QRENCODE
910                 /* If this is not an UTF-8 system don't print any QR codes */
911                 if (is_locale_utf8()) {
912                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
913                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
914                 }
915 #endif
916                 free(hn);
917         }
918
919         r = 0;
920
921 finish:
922         if (fd >= 0)
923                 close_nointr_nofail(fd);
924
925         if (k) {
926                 unlink(k);
927                 free(k);
928         }
929
930         free(p);
931
932         return r;
933 #else
934         log_error("Forward-secure sealing not available.");
935         return -ENOTSUP;
936 #endif
937 }
938
939 static int verify(sd_journal *j) {
940         int r = 0;
941         Iterator i;
942         JournalFile *f;
943
944         assert(j);
945
946         log_show_color(true);
947
948         HASHMAP_FOREACH(f, j->files, i) {
949                 int k;
950                 usec_t first, validated, last;
951
952 #ifdef HAVE_GCRYPT
953                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
954                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
955 #endif
956
957                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
958                 if (k == -EINVAL) {
959                         /* If the key was invalid give up right-away. */
960                         return k;
961                 } else if (k < 0) {
962                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
963                         r = k;
964                 } else {
965                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
966                         log_info("PASS: %s", f->path);
967
968                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
969                                 if (validated > 0) {
970                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
971                                                  format_timestamp(a, sizeof(a), first),
972                                                  format_timestamp(b, sizeof(b), validated),
973                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
974                                 } else if (last > 0)
975                                         log_info("=> No sealing yet, %s of entries not sealed.",
976                                                  format_timespan(c, sizeof(c), last - first, 0));
977                                 else
978                                         log_info("=> No sealing yet, no entries in file.");
979                         }
980                 }
981         }
982
983         return r;
984 }
985
986 #ifdef HAVE_ACL
987 static int access_check_var_log_journal(sd_journal *j) {
988         _cleanup_strv_free_ char **g = NULL;
989         bool have_access;
990         int r;
991
992         assert(j);
993
994         have_access = in_group("systemd-journal") > 0;
995
996         if (!have_access) {
997                 /* Let's enumerate all groups from the default ACL of
998                  * the directory, which generally should allow access
999                  * to most journal files too */
1000                 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1001                 if (r < 0)
1002                         return r;
1003         }
1004
1005         if (!have_access) {
1006
1007                 if (strv_isempty(g))
1008                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1009                                    "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1010                                    "      turn off this notice.");
1011                 else {
1012                         _cleanup_free_ char *s = NULL;
1013
1014                         r = strv_extend(&g, "systemd-journal");
1015                         if (r < 0)
1016                                 return log_oom();
1017
1018                         strv_sort(g);
1019                         strv_uniq(g);
1020
1021                         s = strv_join(g, "', '");
1022                         if (!s)
1023                                 return log_oom();
1024
1025                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1026                                    "      Users in the groups '%s' can see all messages.\n"
1027                                    "      Pass -q to turn off this notice.", s);
1028                 }
1029         }
1030
1031         return 0;
1032 }
1033 #endif
1034
1035 static int access_check(sd_journal *j) {
1036         Iterator it;
1037         void *code;
1038         int r = 0;
1039
1040         assert(j);
1041
1042         if (set_isempty(j->errors)) {
1043                 if (hashmap_isempty(j->files))
1044                         log_notice("No journal files were found.");
1045                 return 0;
1046         }
1047
1048         if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1049 #ifdef HAVE_ACL
1050                 /* If /var/log/journal doesn't even exist,
1051                  * unprivileged users have no access at all */
1052                 if (access("/var/log/journal", F_OK) < 0 &&
1053                     geteuid() != 0 &&
1054                     in_group("systemd-journal") <= 0) {
1055                         log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1056                                   "enabled. Users in the 'systemd-journal' group may always access messages.");
1057                         return -EACCES;
1058                 }
1059
1060                 /* If /var/log/journal exists, try to pring a nice
1061                    notice if the user lacks access to it */
1062                 if (!arg_quiet && geteuid() != 0) {
1063                         r = access_check_var_log_journal(j);
1064                         if (r < 0)
1065                                 return r;
1066                 }
1067 #else
1068                 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1069                         log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1070                                   "group may access messages.");
1071                         return -EACCES;
1072                 }
1073 #endif
1074
1075                 if (hashmap_isempty(j->files)) {
1076                         log_error("No journal files were opened due to insufficient permissions.");
1077                         r = -EACCES;
1078                 }
1079         }
1080
1081         SET_FOREACH(code, j->errors, it) {
1082                 int err;
1083
1084                 err = -PTR_TO_INT(code);
1085                 assert(err > 0);
1086
1087                 if (err != EACCES)
1088                         log_warning("Error was encountered while opening journal files: %s",
1089                                     strerror(err));
1090         }
1091
1092         return r;
1093 }
1094
1095 int main(int argc, char *argv[]) {
1096         int r;
1097         _cleanup_journal_close_ sd_journal*j = NULL;
1098         bool need_seek = false;
1099         sd_id128_t previous_boot_id;
1100         bool previous_boot_id_valid = false, first_line = true;
1101         int n_shown = 0;
1102
1103         setlocale(LC_ALL, "");
1104         log_parse_environment();
1105         log_open();
1106
1107         r = parse_argv(argc, argv);
1108         if (r <= 0)
1109                 goto finish;
1110
1111         signal(SIGWINCH, columns_lines_cache_reset);
1112
1113         if (arg_action == ACTION_NEW_ID128) {
1114                 r = generate_new_id128();
1115                 goto finish;
1116         }
1117
1118         if (arg_action == ACTION_SETUP_KEYS) {
1119                 r = setup_keys();
1120                 goto finish;
1121         }
1122
1123         if (arg_action == ACTION_UPDATE_CATALOG ||
1124             arg_action == ACTION_LIST_CATALOG ||
1125             arg_action == ACTION_DUMP_CATALOG) {
1126
1127                 const char* database = CATALOG_DATABASE;
1128                 _cleanup_free_ char *copy = NULL;
1129                 if (arg_root) {
1130                         copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1131                         if (!copy) {
1132                                 r = log_oom();
1133                                 goto finish;
1134                         }
1135                         path_kill_slashes(copy);
1136                         database = copy;
1137                 }
1138
1139                 if (arg_action == ACTION_UPDATE_CATALOG) {
1140                         r = catalog_update(database, arg_root, catalog_file_dirs);
1141                         if (r < 0)
1142                                 log_error("Failed to list catalog: %s", strerror(-r));
1143                 } else {
1144                         bool oneline = arg_action == ACTION_LIST_CATALOG;
1145
1146                         if (optind < argc)
1147                                 r = catalog_list_items(stdout, database,
1148                                                        oneline, argv + optind);
1149                         else
1150                                 r = catalog_list(stdout, database, oneline);
1151                         if (r < 0)
1152                                 log_error("Failed to list catalog: %s", strerror(-r));
1153                 }
1154
1155                 goto finish;
1156         }
1157
1158         if (arg_directory)
1159                 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1160         else if (arg_file)
1161                 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1162         else
1163                 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1164         if (r < 0) {
1165                 log_error("Failed to open %s: %s",
1166                           arg_directory ? arg_directory : arg_file ? "files" : "journal",
1167                           strerror(-r));
1168                 return EXIT_FAILURE;
1169         }
1170
1171         r = access_check(j);
1172         if (r < 0)
1173                 return EXIT_FAILURE;
1174
1175         if (arg_action == ACTION_VERIFY) {
1176                 r = verify(j);
1177                 goto finish;
1178         }
1179
1180         if (arg_action == ACTION_PRINT_HEADER) {
1181                 journal_print_header(j);
1182                 return EXIT_SUCCESS;
1183         }
1184
1185         if (arg_action == ACTION_DISK_USAGE) {
1186                 uint64_t bytes;
1187                 char sbytes[FORMAT_BYTES_MAX];
1188
1189                 r = sd_journal_get_usage(j, &bytes);
1190                 if (r < 0)
1191                         return EXIT_FAILURE;
1192
1193                 printf("Journals take up %s on disk.\n",
1194                        format_bytes(sbytes, sizeof(sbytes), bytes));
1195                 return EXIT_SUCCESS;
1196         }
1197
1198         r = add_this_boot(j);
1199         if (r < 0)
1200                 return EXIT_FAILURE;
1201
1202         r = add_dmesg(j);
1203         if (r < 0)
1204                 return EXIT_FAILURE;
1205
1206         r = add_units(j);
1207         strv_free(arg_system_units);
1208         strv_free(arg_user_units);
1209
1210         if (r < 0)
1211                 return EXIT_FAILURE;
1212
1213         r = add_priorities(j);
1214         if (r < 0)
1215                 return EXIT_FAILURE;
1216
1217         r = add_matches(j, argv + optind);
1218         if (r < 0)
1219                 return EXIT_FAILURE;
1220
1221         log_debug("Journal filter: %s", j->level0 ? journal_make_match_string(j) : "none");
1222
1223         if (arg_field) {
1224                 const void *data;
1225                 size_t size;
1226
1227                 r = sd_journal_set_data_threshold(j, 0);
1228                 if (r < 0) {
1229                         log_error("Failed to unset data size threshold");
1230                         return EXIT_FAILURE;
1231                 }
1232
1233                 r = sd_journal_query_unique(j, arg_field);
1234                 if (r < 0) {
1235                         log_error("Failed to query unique data objects: %s", strerror(-r));
1236                         return EXIT_FAILURE;
1237                 }
1238
1239                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1240                         const void *eq;
1241
1242                         if (arg_lines >= 0 && n_shown >= arg_lines)
1243                                 break;
1244
1245                         eq = memchr(data, '=', size);
1246                         if (eq)
1247                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1248                         else
1249                                 printf("%.*s\n", (int) size, (const char*) data);
1250
1251                         n_shown ++;
1252                 }
1253
1254                 return EXIT_SUCCESS;
1255         }
1256
1257         /* Opening the fd now means the first sd_journal_wait() will actually wait */
1258         if (arg_follow) {
1259                 r = sd_journal_get_fd(j);
1260                 if (r < 0)
1261                         return EXIT_FAILURE;
1262         }
1263
1264         if (arg_cursor) {
1265                 r = sd_journal_seek_cursor(j, arg_cursor);
1266                 if (r < 0) {
1267                         log_error("Failed to seek to cursor: %s", strerror(-r));
1268                         return EXIT_FAILURE;
1269                 }
1270                 if (!arg_reverse)
1271                         r = sd_journal_next(j);
1272                 else
1273                         r = sd_journal_previous(j);
1274
1275         } else if (arg_since_set && !arg_reverse) {
1276                 r = sd_journal_seek_realtime_usec(j, arg_since);
1277                 if (r < 0) {
1278                         log_error("Failed to seek to date: %s", strerror(-r));
1279                         return EXIT_FAILURE;
1280                 }
1281                 r = sd_journal_next(j);
1282
1283         } else if (arg_until_set && arg_reverse) {
1284                 r = sd_journal_seek_realtime_usec(j, arg_until);
1285                 if (r < 0) {
1286                         log_error("Failed to seek to date: %s", strerror(-r));
1287                         return EXIT_FAILURE;
1288                 }
1289                 r = sd_journal_previous(j);
1290
1291         } else if (arg_lines >= 0) {
1292                 r = sd_journal_seek_tail(j);
1293                 if (r < 0) {
1294                         log_error("Failed to seek to tail: %s", strerror(-r));
1295                         return EXIT_FAILURE;
1296                 }
1297
1298                 r = sd_journal_previous_skip(j, arg_lines);
1299
1300         } else if (arg_reverse) {
1301                 r = sd_journal_seek_tail(j);
1302                 if (r < 0) {
1303                         log_error("Failed to seek to tail: %s", strerror(-r));
1304                         return EXIT_FAILURE;
1305                 }
1306
1307                 r = sd_journal_previous(j);
1308
1309         } else {
1310                 r = sd_journal_seek_head(j);
1311                 if (r < 0) {
1312                         log_error("Failed to seek to head: %s", strerror(-r));
1313                         return EXIT_FAILURE;
1314                 }
1315
1316                 r = sd_journal_next(j);
1317         }
1318
1319         if (r < 0) {
1320                 log_error("Failed to iterate through journal: %s", strerror(-r));
1321                 return EXIT_FAILURE;
1322         }
1323
1324         if (!arg_no_pager && !arg_follow)
1325                 pager_open(arg_pager_end);
1326
1327         if (!arg_quiet) {
1328                 usec_t start, end;
1329                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1330
1331                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1332                 if (r < 0) {
1333                         log_error("Failed to get cutoff: %s", strerror(-r));
1334                         goto finish;
1335                 }
1336
1337                 if (r > 0) {
1338                         if (arg_follow)
1339                                 printf("-- Logs begin at %s. --\n",
1340                                        format_timestamp(start_buf, sizeof(start_buf), start));
1341                         else
1342                                 printf("-- Logs begin at %s, end at %s. --\n",
1343                                        format_timestamp(start_buf, sizeof(start_buf), start),
1344                                        format_timestamp(end_buf, sizeof(end_buf), end));
1345                 }
1346         }
1347
1348         for (;;) {
1349                 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1350                         int flags;
1351
1352                         if (need_seek) {
1353                                 if (!arg_reverse)
1354                                         r = sd_journal_next(j);
1355                                 else
1356                                         r = sd_journal_previous(j);
1357                                 if (r < 0) {
1358                                         log_error("Failed to iterate through journal: %s", strerror(-r));
1359                                         goto finish;
1360                                 }
1361                                 if (r == 0)
1362                                         break;
1363                         }
1364
1365                         if (arg_until_set && !arg_reverse) {
1366                                 usec_t usec;
1367
1368                                 r = sd_journal_get_realtime_usec(j, &usec);
1369                                 if (r < 0) {
1370                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1371                                         goto finish;
1372                                 }
1373                                 if (usec > arg_until)
1374                                         goto finish;
1375                         }
1376
1377                         if (arg_since_set && arg_reverse) {
1378                                 usec_t usec;
1379
1380                                 r = sd_journal_get_realtime_usec(j, &usec);
1381                                 if (r < 0) {
1382                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1383                                         goto finish;
1384                                 }
1385                                 if (usec < arg_since)
1386                                         goto finish;
1387                         }
1388
1389                         if (!arg_merge) {
1390                                 sd_id128_t boot_id;
1391                                 const char *color_on = on_tty() ? ANSI_HIGHLIGHT_ON : "",
1392                                            *color_off = on_tty() ? ANSI_HIGHLIGHT_OFF : "";
1393
1394                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1395                                 if (r >= 0) {
1396                                         if (previous_boot_id_valid &&
1397                                             !sd_id128_equal(boot_id, previous_boot_id))
1398                                                 printf("%s-- Reboot --%s\n", color_on, color_off);
1399
1400                                         previous_boot_id = boot_id;
1401                                         previous_boot_id_valid = true;
1402                                 }
1403                         }
1404
1405                         flags =
1406                                 arg_all * OUTPUT_SHOW_ALL |
1407                                 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1408                                 on_tty() * OUTPUT_COLOR |
1409                                 arg_catalog * OUTPUT_CATALOG;
1410
1411                         r = output_journal(stdout, j, arg_output, 0, flags);
1412                         need_seek = true;
1413                         if (r == -EADDRNOTAVAIL)
1414                                 break;
1415                         else if (r < 0 || ferror(stdout))
1416                                 goto finish;
1417
1418                         n_shown++;
1419                 }
1420
1421                 if (!arg_follow)
1422                         break;
1423
1424                 r = sd_journal_wait(j, (uint64_t) -1);
1425                 if (r < 0) {
1426                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1427                         goto finish;
1428                 }
1429
1430                 first_line = false;
1431         }
1432
1433 finish:
1434         pager_close();
1435
1436         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1437 }