chiark / gitweb /
systemctl: allow globbing in commands which take multiple unit names
[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 "fileio.h"
49 #include "build.h"
50 #include "pager.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 = true;
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_boot = false;
74 static sd_id128_t arg_boot_id = {};
75 static int arg_boot_offset = 0;
76 static bool arg_dmesg = false;
77 static const char *arg_cursor = NULL;
78 static const char *arg_after_cursor = NULL;
79 static bool arg_show_cursor = false;
80 static const char *arg_directory = NULL;
81 static char **arg_file = NULL;
82 static int arg_priorities = 0xFF;
83 static const char *arg_verify_key = NULL;
84 #ifdef HAVE_GCRYPT
85 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
86 static bool arg_force = false;
87 #endif
88 static usec_t arg_since, arg_until;
89 static bool arg_since_set = false, arg_until_set = false;
90 static char **arg_system_units = NULL;
91 static char **arg_user_units = NULL;
92 static const char *arg_field = NULL;
93 static bool arg_catalog = false;
94 static bool arg_reverse = false;
95 static int arg_journal_type = 0;
96 static const char *arg_root = NULL;
97 static const char *arg_machine = NULL;
98
99 static enum {
100         ACTION_SHOW,
101         ACTION_NEW_ID128,
102         ACTION_PRINT_HEADER,
103         ACTION_SETUP_KEYS,
104         ACTION_VERIFY,
105         ACTION_DISK_USAGE,
106         ACTION_LIST_CATALOG,
107         ACTION_DUMP_CATALOG,
108         ACTION_UPDATE_CATALOG,
109         ACTION_LIST_BOOTS,
110 } arg_action = ACTION_SHOW;
111
112 typedef struct boot_id_t {
113         sd_id128_t id;
114         uint64_t first;
115         uint64_t last;
116 } boot_id_t;
117
118 static void pager_open_if_enabled(void) {
119
120         if (arg_no_pager)
121                 return;
122
123         pager_open(arg_pager_end);
124 }
125
126 static int parse_boot_descriptor(const char *x, sd_id128_t *boot_id, int *offset) {
127         sd_id128_t id = SD_ID128_NULL;
128         int off = 0, r;
129
130         if (strlen(x) >= 32) {
131                 char *t;
132
133                 t = strndupa(x, 32);
134                 r = sd_id128_from_string(t, &id);
135                 if (r >= 0)
136                         x += 32;
137
138                 if (*x != '-' && *x != '+' && *x != 0)
139                         return -EINVAL;
140
141                 if (*x != 0) {
142                         r = safe_atoi(x, &off);
143                         if (r < 0)
144                                 return r;
145                 }
146         } else {
147                 r = safe_atoi(x, &off);
148                 if (r < 0)
149                         return r;
150         }
151
152         if (boot_id)
153                 *boot_id = id;
154
155         if (offset)
156                 *offset = off;
157
158         return 0;
159 }
160
161 static int help(void) {
162
163         pager_open_if_enabled();
164
165         printf("%s [OPTIONS...] [MATCHES...]\n\n"
166                "Query the journal.\n\n"
167                "Flags:\n"
168                "     --system              Show only the system journal\n"
169                "     --user                Show only the user journal for the current user\n"
170                "  -M --machine=CONTAINER   Operate on local container\n"
171                "     --since=DATE          Start showing entries on or newer than the specified date\n"
172                "     --until=DATE          Stop showing entries on or older than the specified date\n"
173                "  -c --cursor=CURSOR       Start showing entries from the specified cursor\n"
174                "     --after-cursor=CURSOR Start showing entries from after the specified cursor\n"
175                "     --show-cursor         Print the cursor after all the entries\n"
176                "  -b --boot[=ID]           Show data only from ID or, if unspecified, the current boot\n"
177                "     --list-boots          Show terse information about recorded boots\n"
178                "  -k --dmesg               Show kernel message log from the current boot\n"
179                "  -u --unit=UNIT           Show data only from the specified unit\n"
180                "     --user-unit=UNIT      Show data only from the specified user session unit\n"
181                "  -p --priority=RANGE      Show only messages within the specified priority range\n"
182                "  -e --pager-end           Immediately jump to end of the journal in the pager\n"
183                "  -f --follow              Follow the journal\n"
184                "  -n --lines[=INTEGER]     Number of journal entries to show\n"
185                "     --no-tail             Show all lines, even in follow mode\n"
186                "  -r --reverse             Show the newest entries first\n"
187                "  -o --output=STRING       Change journal output mode (short, short-iso,\n"
188                "                                   short-precise, short-monotonic, verbose,\n"
189                "                                   export, json, json-pretty, json-sse, cat)\n"
190                "  -x --catalog             Add message explanations where available\n"
191                "     --no-full             Ellipsize fields\n"
192                "  -a --all                 Show all fields, including long and unprintable\n"
193                "  -q --quiet               Do not show privilege warning\n"
194                "     --no-pager            Do not pipe output into a pager\n"
195                "  -m --merge               Show entries from all available journals\n"
196                "  -D --directory=PATH      Show journal files from directory\n"
197                "     --file=PATH           Show journal file\n"
198                "     --root=ROOT           Operate on catalog files underneath the root ROOT\n"
199 #ifdef HAVE_GCRYPT
200                "     --interval=TIME       Time interval for changing the FSS sealing key\n"
201                "     --verify-key=KEY      Specify FSS verification key\n"
202                "     --force               Force overriding of the FSS key pair with --setup-keys\n"
203 #endif
204                "\nCommands:\n"
205                "  -h --help                Show this help text\n"
206                "     --version             Show package version\n"
207                "     --new-id128           Generate a new 128-bit ID\n"
208                "     --header              Show journal header information\n"
209                "     --disk-usage          Show total disk usage of all journal files\n"
210                "  -F --field=FIELD         List all values that a specified field takes\n"
211                "     --list-catalog        Show message IDs of all entries in the message catalog\n"
212                "     --dump-catalog        Show entries in the message catalog\n"
213                "     --update-catalog      Update the message catalog database\n"
214 #ifdef HAVE_GCRYPT
215                "     --setup-keys          Generate a new FSS key pair\n"
216                "     --verify              Verify journal file consistency\n"
217 #endif
218                , program_invocation_short_name);
219
220         return 0;
221 }
222
223 static int parse_argv(int argc, char *argv[]) {
224
225         enum {
226                 ARG_VERSION = 0x100,
227                 ARG_NO_PAGER,
228                 ARG_NO_FULL,
229                 ARG_NO_TAIL,
230                 ARG_NEW_ID128,
231                 ARG_LIST_BOOTS,
232                 ARG_USER,
233                 ARG_SYSTEM,
234                 ARG_ROOT,
235                 ARG_HEADER,
236                 ARG_SETUP_KEYS,
237                 ARG_FILE,
238                 ARG_INTERVAL,
239                 ARG_VERIFY,
240                 ARG_VERIFY_KEY,
241                 ARG_DISK_USAGE,
242                 ARG_SINCE,
243                 ARG_UNTIL,
244                 ARG_AFTER_CURSOR,
245                 ARG_SHOW_CURSOR,
246                 ARG_USER_UNIT,
247                 ARG_LIST_CATALOG,
248                 ARG_DUMP_CATALOG,
249                 ARG_UPDATE_CATALOG,
250                 ARG_FORCE,
251         };
252
253         static const struct option options[] = {
254                 { "help",           no_argument,       NULL, 'h'                },
255                 { "version" ,       no_argument,       NULL, ARG_VERSION        },
256                 { "no-pager",       no_argument,       NULL, ARG_NO_PAGER       },
257                 { "pager-end",      no_argument,       NULL, 'e'                },
258                 { "follow",         no_argument,       NULL, 'f'                },
259                 { "force",          no_argument,       NULL, ARG_FORCE          },
260                 { "output",         required_argument, NULL, 'o'                },
261                 { "all",            no_argument,       NULL, 'a'                },
262                 { "full",           no_argument,       NULL, 'l'                },
263                 { "no-full",        no_argument,       NULL, ARG_NO_FULL        },
264                 { "lines",          optional_argument, NULL, 'n'                },
265                 { "no-tail",        no_argument,       NULL, ARG_NO_TAIL        },
266                 { "new-id128",      no_argument,       NULL, ARG_NEW_ID128      },
267                 { "quiet",          no_argument,       NULL, 'q'                },
268                 { "merge",          no_argument,       NULL, 'm'                },
269                 { "boot",           optional_argument, NULL, 'b'                },
270                 { "list-boots",     no_argument,       NULL, ARG_LIST_BOOTS     },
271                 { "this-boot",      optional_argument, NULL, 'b'                }, /* deprecated */
272                 { "dmesg",          no_argument,       NULL, 'k'                },
273                 { "system",         no_argument,       NULL, ARG_SYSTEM         },
274                 { "user",           no_argument,       NULL, ARG_USER           },
275                 { "directory",      required_argument, NULL, 'D'                },
276                 { "file",           required_argument, NULL, ARG_FILE           },
277                 { "root",           required_argument, NULL, ARG_ROOT           },
278                 { "header",         no_argument,       NULL, ARG_HEADER         },
279                 { "priority",       required_argument, NULL, 'p'                },
280                 { "setup-keys",     no_argument,       NULL, ARG_SETUP_KEYS     },
281                 { "interval",       required_argument, NULL, ARG_INTERVAL       },
282                 { "verify",         no_argument,       NULL, ARG_VERIFY         },
283                 { "verify-key",     required_argument, NULL, ARG_VERIFY_KEY     },
284                 { "disk-usage",     no_argument,       NULL, ARG_DISK_USAGE     },
285                 { "cursor",         required_argument, NULL, 'c'                },
286                 { "after-cursor",   required_argument, NULL, ARG_AFTER_CURSOR   },
287                 { "show-cursor",    no_argument,       NULL, ARG_SHOW_CURSOR    },
288                 { "since",          required_argument, NULL, ARG_SINCE          },
289                 { "until",          required_argument, NULL, ARG_UNTIL          },
290                 { "unit",           required_argument, NULL, 'u'                },
291                 { "user-unit",      required_argument, NULL, ARG_USER_UNIT      },
292                 { "field",          required_argument, NULL, 'F'                },
293                 { "catalog",        no_argument,       NULL, 'x'                },
294                 { "list-catalog",   no_argument,       NULL, ARG_LIST_CATALOG   },
295                 { "dump-catalog",   no_argument,       NULL, ARG_DUMP_CATALOG   },
296                 { "update-catalog", no_argument,       NULL, ARG_UPDATE_CATALOG },
297                 { "reverse",        no_argument,       NULL, 'r'                },
298                 { "machine",        required_argument, NULL, 'M'                },
299                 {}
300         };
301
302         int c, r;
303
304         assert(argc >= 0);
305         assert(argv);
306
307         while ((c = getopt_long(argc, argv, "hefo:aln::qmb::kD:p:c:u:F:xrM:", options, NULL)) >= 0) {
308
309                 switch (c) {
310
311                 case 'h':
312                         return help();
313
314                 case ARG_VERSION:
315                         puts(PACKAGE_STRING);
316                         puts(SYSTEMD_FEATURES);
317                         return 0;
318
319                 case ARG_NO_PAGER:
320                         arg_no_pager = true;
321                         break;
322
323                 case 'e':
324                         arg_pager_end = true;
325
326                         if (arg_lines < 0)
327                                 arg_lines = 1000;
328
329                         break;
330
331                 case 'f':
332                         arg_follow = true;
333                         break;
334
335                 case 'o':
336                         arg_output = output_mode_from_string(optarg);
337                         if (arg_output < 0) {
338                                 log_error("Unknown output format '%s'.", optarg);
339                                 return -EINVAL;
340                         }
341
342                         if (arg_output == OUTPUT_EXPORT ||
343                             arg_output == OUTPUT_JSON ||
344                             arg_output == OUTPUT_JSON_PRETTY ||
345                             arg_output == OUTPUT_JSON_SSE ||
346                             arg_output == OUTPUT_CAT)
347                                 arg_quiet = true;
348
349                         break;
350
351                 case 'l':
352                         arg_full = true;
353                         break;
354
355                 case ARG_NO_FULL:
356                         arg_full = false;
357                         break;
358
359                 case 'a':
360                         arg_all = true;
361                         break;
362
363                 case 'n':
364                         if (optarg) {
365                                 r = safe_atoi(optarg, &arg_lines);
366                                 if (r < 0 || arg_lines < 0) {
367                                         log_error("Failed to parse lines '%s'", optarg);
368                                         return -EINVAL;
369                                 }
370                         } else {
371                                 int n;
372
373                                 /* Hmm, no argument? Maybe the next
374                                  * word on the command line is
375                                  * supposed to be the argument? Let's
376                                  * see if there is one, and is
377                                  * parsable as a positive
378                                  * integer... */
379
380                                 if (optind < argc &&
381                                     safe_atoi(argv[optind], &n) >= 0 &&
382                                     n >= 0) {
383
384                                         arg_lines = n;
385                                         optind++;
386                                 } else
387                                         arg_lines = 10;
388                         }
389
390                         break;
391
392                 case ARG_NO_TAIL:
393                         arg_no_tail = true;
394                         break;
395
396                 case ARG_NEW_ID128:
397                         arg_action = ACTION_NEW_ID128;
398                         break;
399
400                 case 'q':
401                         arg_quiet = true;
402                         break;
403
404                 case 'm':
405                         arg_merge = true;
406                         break;
407
408                 case 'b':
409                         arg_boot = true;
410
411                         if (optarg) {
412                                 r =  parse_boot_descriptor(optarg, &arg_boot_id, &arg_boot_offset);
413                                 if (r < 0) {
414                                         log_error("Failed to parse boot descriptor '%s'", optarg);
415                                         return -EINVAL;
416                                 }
417                         } else {
418
419                                 /* Hmm, no argument? Maybe the next
420                                  * word on the command line is
421                                  * supposed to be the argument? Let's
422                                  * see if there is one and is parsable
423                                  * as a boot descriptor... */
424
425                                 if (optind < argc &&
426                                     parse_boot_descriptor(argv[optind], &arg_boot_id, &arg_boot_offset) >= 0)
427                                         optind++;
428                         }
429
430                         break;
431
432                 case ARG_LIST_BOOTS:
433                         arg_action = ACTION_LIST_BOOTS;
434                         break;
435
436                 case 'k':
437                         arg_boot = arg_dmesg = true;
438                         break;
439
440                 case ARG_SYSTEM:
441                         arg_journal_type |= SD_JOURNAL_SYSTEM;
442                         break;
443
444                 case ARG_USER:
445                         arg_journal_type |= SD_JOURNAL_CURRENT_USER;
446                         break;
447
448                 case 'M':
449                         arg_machine = optarg;
450                         break;
451
452                 case 'D':
453                         arg_directory = optarg;
454                         break;
455
456                 case ARG_FILE:
457                         r = glob_extend(&arg_file, optarg);
458                         if (r < 0) {
459                                 log_error("Failed to add paths: %s", strerror(-r));
460                                 return r;
461                         };
462                         break;
463
464                 case ARG_ROOT:
465                         arg_root = optarg;
466                         break;
467
468                 case 'c':
469                         arg_cursor = optarg;
470                         break;
471
472                 case ARG_AFTER_CURSOR:
473                         arg_after_cursor = optarg;
474                         break;
475
476                 case ARG_SHOW_CURSOR:
477                         arg_show_cursor = true;
478                         break;
479
480                 case ARG_HEADER:
481                         arg_action = ACTION_PRINT_HEADER;
482                         break;
483
484                 case ARG_VERIFY:
485                         arg_action = ACTION_VERIFY;
486                         break;
487
488                 case ARG_DISK_USAGE:
489                         arg_action = ACTION_DISK_USAGE;
490                         break;
491
492 #ifdef HAVE_GCRYPT
493                 case ARG_FORCE:
494                         arg_force = true;
495                         break;
496
497                 case ARG_SETUP_KEYS:
498                         arg_action = ACTION_SETUP_KEYS;
499                         break;
500
501
502                 case ARG_VERIFY_KEY:
503                         arg_action = ACTION_VERIFY;
504                         arg_verify_key = optarg;
505                         arg_merge = false;
506                         break;
507
508                 case ARG_INTERVAL:
509                         r = parse_sec(optarg, &arg_interval);
510                         if (r < 0 || arg_interval <= 0) {
511                                 log_error("Failed to parse sealing key change interval: %s", optarg);
512                                 return -EINVAL;
513                         }
514                         break;
515 #else
516                 case ARG_SETUP_KEYS:
517                 case ARG_VERIFY_KEY:
518                 case ARG_INTERVAL:
519                 case ARG_FORCE:
520                         log_error("Forward-secure sealing not available.");
521                         return -ENOTSUP;
522 #endif
523
524                 case 'p': {
525                         const char *dots;
526
527                         dots = strstr(optarg, "..");
528                         if (dots) {
529                                 char *a;
530                                 int from, to, i;
531
532                                 /* a range */
533                                 a = strndup(optarg, dots - optarg);
534                                 if (!a)
535                                         return log_oom();
536
537                                 from = log_level_from_string(a);
538                                 to = log_level_from_string(dots + 2);
539                                 free(a);
540
541                                 if (from < 0 || to < 0) {
542                                         log_error("Failed to parse log level range %s", optarg);
543                                         return -EINVAL;
544                                 }
545
546                                 arg_priorities = 0;
547
548                                 if (from < to) {
549                                         for (i = from; i <= to; i++)
550                                                 arg_priorities |= 1 << i;
551                                 } else {
552                                         for (i = to; i <= from; i++)
553                                                 arg_priorities |= 1 << i;
554                                 }
555
556                         } else {
557                                 int p, i;
558
559                                 p = log_level_from_string(optarg);
560                                 if (p < 0) {
561                                         log_error("Unknown log level %s", optarg);
562                                         return -EINVAL;
563                                 }
564
565                                 arg_priorities = 0;
566
567                                 for (i = 0; i <= p; i++)
568                                         arg_priorities |= 1 << i;
569                         }
570
571                         break;
572                 }
573
574                 case ARG_SINCE:
575                         r = parse_timestamp(optarg, &arg_since);
576                         if (r < 0) {
577                                 log_error("Failed to parse timestamp: %s", optarg);
578                                 return -EINVAL;
579                         }
580                         arg_since_set = true;
581                         break;
582
583                 case ARG_UNTIL:
584                         r = parse_timestamp(optarg, &arg_until);
585                         if (r < 0) {
586                                 log_error("Failed to parse timestamp: %s", optarg);
587                                 return -EINVAL;
588                         }
589                         arg_until_set = true;
590                         break;
591
592                 case 'u':
593                         r = strv_extend(&arg_system_units, optarg);
594                         if (r < 0)
595                                 return log_oom();
596                         break;
597
598                 case ARG_USER_UNIT:
599                         r = strv_extend(&arg_user_units, optarg);
600                         if (r < 0)
601                                 return log_oom();
602                         break;
603
604                 case 'F':
605                         arg_field = optarg;
606                         break;
607
608                 case 'x':
609                         arg_catalog = true;
610                         break;
611
612                 case ARG_LIST_CATALOG:
613                         arg_action = ACTION_LIST_CATALOG;
614                         break;
615
616                 case ARG_DUMP_CATALOG:
617                         arg_action = ACTION_DUMP_CATALOG;
618                         break;
619
620                 case ARG_UPDATE_CATALOG:
621                         arg_action = ACTION_UPDATE_CATALOG;
622                         break;
623
624                 case 'r':
625                         arg_reverse = true;
626                         break;
627
628                 case '?':
629                         return -EINVAL;
630
631                 default:
632                         assert_not_reached("Unhandled option");
633                 }
634         }
635
636         if (arg_follow && !arg_no_tail && arg_lines < 0)
637                 arg_lines = 10;
638
639         if (!!arg_directory + !!arg_file + !!arg_machine > 1) {
640                 log_error("Please specify either -D/--directory= or --file= or -M/--machine=, not more than one.");
641                 return -EINVAL;
642         }
643
644         if (arg_since_set && arg_until_set && arg_since > arg_until) {
645                 log_error("--since= must be before --until=.");
646                 return -EINVAL;
647         }
648
649         if (!!arg_cursor + !!arg_after_cursor + !!arg_since_set > 1) {
650                 log_error("Please specify only one of --since=, --cursor=, and --after-cursor.");
651                 return -EINVAL;
652         }
653
654         if (arg_follow && arg_reverse) {
655                 log_error("Please specify either --reverse= or --follow=, not both.");
656                 return -EINVAL;
657         }
658
659         return 1;
660 }
661
662 static int generate_new_id128(void) {
663         sd_id128_t id;
664         int r;
665         unsigned i;
666
667         r = sd_id128_randomize(&id);
668         if (r < 0) {
669                 log_error("Failed to generate ID: %s", strerror(-r));
670                 return r;
671         }
672
673         printf("As string:\n"
674                SD_ID128_FORMAT_STR "\n\n"
675                "As UUID:\n"
676                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
677                "As macro:\n"
678                "#define MESSAGE_XYZ SD_ID128_MAKE(",
679                SD_ID128_FORMAT_VAL(id),
680                SD_ID128_FORMAT_VAL(id));
681         for (i = 0; i < 16; i++)
682                 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
683         fputs(")\n\n", stdout);
684
685         printf("As Python constant:\n"
686                ">>> import uuid\n"
687                ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
688                SD_ID128_FORMAT_VAL(id));
689
690         return 0;
691 }
692
693 static int add_matches(sd_journal *j, char **args) {
694         char **i;
695
696         assert(j);
697
698         STRV_FOREACH(i, args) {
699                 int r;
700
701                 if (streq(*i, "+"))
702                         r = sd_journal_add_disjunction(j);
703                 else if (path_is_absolute(*i)) {
704                         _cleanup_free_ char *p, *t = NULL, *t2 = NULL;
705                         const char *path;
706                         _cleanup_free_ char *interpreter = NULL;
707                         struct stat st;
708
709                         p = canonicalize_file_name(*i);
710                         path = p ? p : *i;
711
712                         if (stat(path, &st) < 0)  {
713                                 log_error("Couldn't stat file: %m");
714                                 return -errno;
715                         }
716
717                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode)) {
718                                 if (executable_is_script(path, &interpreter) > 0) {
719                                         _cleanup_free_ char *comm;
720
721                                         comm = strndup(basename(path), 15);
722                                         if (!comm)
723                                                 return log_oom();
724
725                                         t = strappend("_COMM=", comm);
726
727                                         /* Append _EXE only if the interpreter is not a link.
728                                            Otherwise it might be outdated often. */
729                                         if (lstat(interpreter, &st) == 0 &&
730                                             !S_ISLNK(st.st_mode)) {
731                                                 t2 = strappend("_EXE=", interpreter);
732                                                 if (!t2)
733                                                         return log_oom();
734                                         }
735                                 } else
736                                         t = strappend("_EXE=", path);
737                         } else if (S_ISCHR(st.st_mode))
738                                 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
739                         else if (S_ISBLK(st.st_mode))
740                                 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
741                         else {
742                                 log_error("File is neither a device node, nor regular file, nor executable: %s", *i);
743                                 return -EINVAL;
744                         }
745
746                         if (!t)
747                                 return log_oom();
748
749                         r = sd_journal_add_match(j, t, 0);
750                         if (t2)
751                                 r = sd_journal_add_match(j, t2, 0);
752                 } else
753                         r = sd_journal_add_match(j, *i, 0);
754
755                 if (r < 0) {
756                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
757                         return r;
758                 }
759         }
760
761         return 0;
762 }
763
764 static int boot_id_cmp(const void *a, const void *b) {
765         uint64_t _a, _b;
766
767         _a = ((const boot_id_t *)a)->first;
768         _b = ((const boot_id_t *)b)->first;
769
770         return _a < _b ? -1 : (_a > _b ? 1 : 0);
771 }
772
773 static int list_boots(sd_journal *j) {
774         int r;
775         const void *data;
776         unsigned int count = 0;
777         int w, i;
778         size_t length, allocated = 0;
779         boot_id_t *id;
780         _cleanup_free_ boot_id_t *all_ids = NULL;
781
782         r = sd_journal_query_unique(j, "_BOOT_ID");
783         if (r < 0)
784                 return r;
785
786         SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
787                 if (length < strlen("_BOOT_ID="))
788                         continue;
789
790                 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
791                         return log_oom();
792
793                 id = &all_ids[count];
794
795                 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
796                 if (r < 0)
797                         continue;
798
799                 r = sd_journal_add_match(j, data, length);
800                 if (r < 0)
801                         return r;
802
803                 r = sd_journal_seek_head(j);
804                 if (r < 0)
805                         return r;
806
807                 r = sd_journal_next(j);
808                 if (r < 0)
809                         return r;
810                 else if (r == 0)
811                         goto flush;
812
813                 r = sd_journal_get_realtime_usec(j, &id->first);
814                 if (r < 0)
815                         return r;
816
817                 r = sd_journal_seek_tail(j);
818                 if (r < 0)
819                         return r;
820
821                 r = sd_journal_previous(j);
822                 if (r < 0)
823                         return r;
824                 else if (r == 0)
825                         goto flush;
826
827                 r = sd_journal_get_realtime_usec(j, &id->last);
828                 if (r < 0)
829                         return r;
830
831                 count++;
832         flush:
833                 sd_journal_flush_matches(j);
834         }
835
836         qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
837
838         /* numbers are one less, but we need an extra char for the sign */
839         w = DECIMAL_STR_WIDTH(count - 1) + 1;
840
841         for (id = all_ids, i = 0; id < all_ids + count; id++, i++) {
842                 char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
843
844                 printf("% *i " SD_ID128_FORMAT_STR " %s—%s\n",
845                        w, i - count + 1,
846                        SD_ID128_FORMAT_VAL(id->id),
847                        format_timestamp(a, sizeof(a), id->first),
848                        format_timestamp(b, sizeof(b), id->last));
849         }
850
851         return 0;
852 }
853
854 static int get_relative_boot_id(sd_journal *j, sd_id128_t *boot_id, int relative) {
855         int r;
856         const void *data;
857         unsigned int count = 0;
858         size_t length, allocated = 0;
859         boot_id_t ref_boot_id = {SD_ID128_NULL}, *id;
860         _cleanup_free_ boot_id_t *all_ids = NULL;
861
862         assert(j);
863         assert(boot_id);
864
865         r = sd_journal_query_unique(j, "_BOOT_ID");
866         if (r < 0)
867                 return r;
868
869         SD_JOURNAL_FOREACH_UNIQUE(j, data, length) {
870                 if (length < strlen("_BOOT_ID="))
871                         continue;
872
873                 if (!GREEDY_REALLOC(all_ids, allocated, count + 1))
874                         return log_oom();
875
876                 id = &all_ids[count];
877
878                 r = sd_id128_from_string(((const char *)data) + strlen("_BOOT_ID="), &id->id);
879                 if (r < 0)
880                         continue;
881
882                 r = sd_journal_add_match(j, data, length);
883                 if (r < 0)
884                         return r;
885
886                 r = sd_journal_seek_head(j);
887                 if (r < 0)
888                         return r;
889
890                 r = sd_journal_next(j);
891                 if (r < 0)
892                         return r;
893                 else if (r == 0)
894                         goto flush;
895
896                 r = sd_journal_get_realtime_usec(j, &id->first);
897                 if (r < 0)
898                         return r;
899
900                 if (sd_id128_equal(id->id, *boot_id))
901                         ref_boot_id = *id;
902
903                 count++;
904         flush:
905                 sd_journal_flush_matches(j);
906         }
907
908         qsort_safe(all_ids, count, sizeof(boot_id_t), boot_id_cmp);
909
910         if (sd_id128_equal(*boot_id, SD_ID128_NULL)) {
911                 if (relative > (int) count || relative <= -(int)count)
912                         return -EADDRNOTAVAIL;
913
914                 *boot_id = all_ids[(relative <= 0)*count + relative - 1].id;
915         } else {
916                 id = bsearch(&ref_boot_id, all_ids, count, sizeof(boot_id_t), boot_id_cmp);
917
918                 if (!id ||
919                     relative <= 0 ? (id - all_ids) + relative < 0 :
920                                     (id - all_ids) + relative >= (int) count)
921                         return -EADDRNOTAVAIL;
922
923                 *boot_id = (id + relative)->id;
924         }
925
926         return 0;
927 }
928
929 static int add_boot(sd_journal *j) {
930         char match[9+32+1] = "_BOOT_ID=";
931         int r;
932
933         assert(j);
934
935         if (!arg_boot)
936                 return 0;
937
938         if (arg_boot_offset == 0 && sd_id128_equal(arg_boot_id, SD_ID128_NULL))
939                 return add_match_this_boot(j, arg_machine);
940
941         r = get_relative_boot_id(j, &arg_boot_id, arg_boot_offset);
942         if (r < 0) {
943                 if (sd_id128_equal(arg_boot_id, SD_ID128_NULL))
944                         log_error("Failed to look up boot %+i: %s", arg_boot_offset, strerror(-r));
945                 else
946                         log_error("Failed to look up boot ID "SD_ID128_FORMAT_STR"%+i: %s",
947                                   SD_ID128_FORMAT_VAL(arg_boot_id), arg_boot_offset, strerror(-r));
948                 return r;
949         }
950
951         sd_id128_to_string(arg_boot_id, match + 9);
952
953         r = sd_journal_add_match(j, match, sizeof(match) - 1);
954         if (r < 0) {
955                 log_error("Failed to add match: %s", strerror(-r));
956                 return r;
957         }
958
959         r = sd_journal_add_conjunction(j);
960         if (r < 0)
961                 return r;
962
963         return 0;
964 }
965
966 static int add_dmesg(sd_journal *j) {
967         int r;
968         assert(j);
969
970         if (!arg_dmesg)
971                 return 0;
972
973         r = sd_journal_add_match(j, "_TRANSPORT=kernel", strlen("_TRANSPORT=kernel"));
974         if (r < 0) {
975                 log_error("Failed to add match: %s", strerror(-r));
976                 return r;
977         }
978
979         r = sd_journal_add_conjunction(j);
980         if (r < 0)
981                 return r;
982
983         return 0;
984 }
985
986 static int add_units(sd_journal *j) {
987         _cleanup_free_ char *u = NULL;
988         int r;
989         char **i;
990
991         assert(j);
992
993         STRV_FOREACH(i, arg_system_units) {
994                 u = unit_name_mangle(*i, false);
995                 if (!u)
996                         return log_oom();
997                 r = add_matches_for_unit(j, u);
998                 if (r < 0)
999                         return r;
1000                 r = sd_journal_add_disjunction(j);
1001                 if (r < 0)
1002                         return r;
1003         }
1004
1005         STRV_FOREACH(i, arg_user_units) {
1006                 u = unit_name_mangle(*i, false);
1007                 if (!u)
1008                         return log_oom();
1009
1010                 r = add_matches_for_user_unit(j, u, getuid());
1011                 if (r < 0)
1012                         return r;
1013
1014                 r = sd_journal_add_disjunction(j);
1015                 if (r < 0)
1016                         return r;
1017
1018         }
1019
1020         r = sd_journal_add_conjunction(j);
1021         if (r < 0)
1022                 return r;
1023
1024         return 0;
1025 }
1026
1027 static int add_priorities(sd_journal *j) {
1028         char match[] = "PRIORITY=0";
1029         int i, r;
1030         assert(j);
1031
1032         if (arg_priorities == 0xFF)
1033                 return 0;
1034
1035         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
1036                 if (arg_priorities & (1 << i)) {
1037                         match[sizeof(match)-2] = '0' + i;
1038
1039                         r = sd_journal_add_match(j, match, strlen(match));
1040                         if (r < 0) {
1041                                 log_error("Failed to add match: %s", strerror(-r));
1042                                 return r;
1043                         }
1044                 }
1045
1046         r = sd_journal_add_conjunction(j);
1047         if (r < 0)
1048                 return r;
1049
1050         return 0;
1051 }
1052
1053 static int setup_keys(void) {
1054 #ifdef HAVE_GCRYPT
1055         size_t mpk_size, seed_size, state_size, i;
1056         uint8_t *mpk, *seed, *state;
1057         ssize_t l;
1058         int fd = -1, r, attr = 0;
1059         sd_id128_t machine, boot;
1060         char *p = NULL, *k = NULL;
1061         struct FSSHeader h;
1062         uint64_t n;
1063         struct stat st;
1064
1065         r = stat("/var/log/journal", &st);
1066         if (r < 0 && errno != ENOENT && errno != ENOTDIR) {
1067                 log_error("stat(\"%s\") failed: %m", "/var/log/journal");
1068                 return -errno;
1069         }
1070
1071         if (r < 0 || !S_ISDIR(st.st_mode)) {
1072                 log_error("%s is not a directory, must be using persistent logging for FSS.",
1073                           "/var/log/journal");
1074                 return r < 0 ? -errno : -ENOTDIR;
1075         }
1076
1077         r = sd_id128_get_machine(&machine);
1078         if (r < 0) {
1079                 log_error("Failed to get machine ID: %s", strerror(-r));
1080                 return r;
1081         }
1082
1083         r = sd_id128_get_boot(&boot);
1084         if (r < 0) {
1085                 log_error("Failed to get boot ID: %s", strerror(-r));
1086                 return r;
1087         }
1088
1089         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
1090                      SD_ID128_FORMAT_VAL(machine)) < 0)
1091                 return log_oom();
1092
1093         if (access(p, F_OK) >= 0) {
1094                 if (arg_force) {
1095                         r = unlink(p);
1096                         if (r < 0) {
1097                                 log_error("unlink(\"%s\") failed: %m", p);
1098                                 r = -errno;
1099                                 goto finish;
1100                         }
1101                 } else {
1102                         log_error("Sealing key file %s exists already. (--force to recreate)", p);
1103                         r = -EEXIST;
1104                         goto finish;
1105                 }
1106         }
1107
1108         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
1109                      SD_ID128_FORMAT_VAL(machine)) < 0) {
1110                 r = log_oom();
1111                 goto finish;
1112         }
1113
1114         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
1115         mpk = alloca(mpk_size);
1116
1117         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
1118         seed = alloca(seed_size);
1119
1120         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
1121         state = alloca(state_size);
1122
1123         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
1124         if (fd < 0) {
1125                 log_error("Failed to open /dev/random: %m");
1126                 r = -errno;
1127                 goto finish;
1128         }
1129
1130         log_info("Generating seed...");
1131         l = loop_read(fd, seed, seed_size, true);
1132         if (l < 0 || (size_t) l != seed_size) {
1133                 log_error("Failed to read random seed: %s", strerror(EIO));
1134                 r = -EIO;
1135                 goto finish;
1136         }
1137
1138         log_info("Generating key pair...");
1139         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
1140
1141         log_info("Generating sealing key...");
1142         FSPRG_GenState0(state, mpk, seed, seed_size);
1143
1144         assert(arg_interval > 0);
1145
1146         n = now(CLOCK_REALTIME);
1147         n /= arg_interval;
1148
1149         close_nointr_nofail(fd);
1150         fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
1151         if (fd < 0) {
1152                 log_error("Failed to open %s: %m", k);
1153                 r = -errno;
1154                 goto finish;
1155         }
1156
1157         /* Enable secure remove, exclusion from dump, synchronous
1158          * writing and in-place updating */
1159         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
1160                 log_warning("FS_IOC_GETFLAGS failed: %m");
1161
1162         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
1163
1164         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
1165                 log_warning("FS_IOC_SETFLAGS failed: %m");
1166
1167         zero(h);
1168         memcpy(h.signature, "KSHHRHLP", 8);
1169         h.machine_id = machine;
1170         h.boot_id = boot;
1171         h.header_size = htole64(sizeof(h));
1172         h.start_usec = htole64(n * arg_interval);
1173         h.interval_usec = htole64(arg_interval);
1174         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
1175         h.fsprg_state_size = htole64(state_size);
1176
1177         l = loop_write(fd, &h, sizeof(h), false);
1178         if (l < 0 || (size_t) l != sizeof(h)) {
1179                 log_error("Failed to write header: %s", strerror(EIO));
1180                 r = -EIO;
1181                 goto finish;
1182         }
1183
1184         l = loop_write(fd, state, state_size, false);
1185         if (l < 0 || (size_t) l != state_size) {
1186                 log_error("Failed to write state: %s", strerror(EIO));
1187                 r = -EIO;
1188                 goto finish;
1189         }
1190
1191         if (link(k, p) < 0) {
1192                 log_error("Failed to link file: %m");
1193                 r = -errno;
1194                 goto finish;
1195         }
1196
1197         if (on_tty()) {
1198                 fprintf(stderr,
1199                         "\n"
1200                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
1201                         "the following local file. This key file is automatically updated when the\n"
1202                         "sealing key is advanced. It should not be used on multiple hosts.\n"
1203                         "\n"
1204                         "\t%s\n"
1205                         "\n"
1206                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
1207                         "at a safe location and should not be saved locally on disk.\n"
1208                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
1209                 fflush(stderr);
1210         }
1211         for (i = 0; i < seed_size; i++) {
1212                 if (i > 0 && i % 3 == 0)
1213                         putchar('-');
1214                 printf("%02x", ((uint8_t*) seed)[i]);
1215         }
1216
1217         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
1218
1219         if (on_tty()) {
1220                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
1221
1222                 fprintf(stderr,
1223                         ANSI_HIGHLIGHT_OFF "\n"
1224                         "The sealing key is automatically changed every %s.\n",
1225                         format_timespan(tsb, sizeof(tsb), arg_interval, 0));
1226
1227                 hn = gethostname_malloc();
1228
1229                 if (hn) {
1230                         hostname_cleanup(hn, false);
1231                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
1232                 } else
1233                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
1234
1235 #ifdef HAVE_QRENCODE
1236                 /* If this is not an UTF-8 system don't print any QR codes */
1237                 if (is_locale_utf8()) {
1238                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
1239                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
1240                 }
1241 #endif
1242                 free(hn);
1243         }
1244
1245         r = 0;
1246
1247 finish:
1248         if (fd >= 0)
1249                 close_nointr_nofail(fd);
1250
1251         if (k) {
1252                 unlink(k);
1253                 free(k);
1254         }
1255
1256         free(p);
1257
1258         return r;
1259 #else
1260         log_error("Forward-secure sealing not available.");
1261         return -ENOTSUP;
1262 #endif
1263 }
1264
1265 static int verify(sd_journal *j) {
1266         int r = 0;
1267         Iterator i;
1268         JournalFile *f;
1269
1270         assert(j);
1271
1272         log_show_color(true);
1273
1274         HASHMAP_FOREACH(f, j->files, i) {
1275                 int k;
1276                 usec_t first, validated, last;
1277
1278 #ifdef HAVE_GCRYPT
1279                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
1280                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
1281 #endif
1282
1283                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
1284                 if (k == -EINVAL) {
1285                         /* If the key was invalid give up right-away. */
1286                         return k;
1287                 } else if (k < 0) {
1288                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
1289                         r = k;
1290                 } else {
1291                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
1292                         log_info("PASS: %s", f->path);
1293
1294                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
1295                                 if (validated > 0) {
1296                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
1297                                                  format_timestamp(a, sizeof(a), first),
1298                                                  format_timestamp(b, sizeof(b), validated),
1299                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0, 0));
1300                                 } else if (last > 0)
1301                                         log_info("=> No sealing yet, %s of entries not sealed.",
1302                                                  format_timespan(c, sizeof(c), last - first, 0));
1303                                 else
1304                                         log_info("=> No sealing yet, no entries in file.");
1305                         }
1306                 }
1307         }
1308
1309         return r;
1310 }
1311
1312 #ifdef HAVE_ACL
1313 static int access_check_var_log_journal(sd_journal *j) {
1314         _cleanup_strv_free_ char **g = NULL;
1315         bool have_access;
1316         int r;
1317
1318         assert(j);
1319
1320         have_access = in_group("systemd-journal") > 0;
1321
1322         if (!have_access) {
1323                 /* Let's enumerate all groups from the default ACL of
1324                  * the directory, which generally should allow access
1325                  * to most journal files too */
1326                 r = search_acl_groups(&g, "/var/log/journal/", &have_access);
1327                 if (r < 0)
1328                         return r;
1329         }
1330
1331         if (!have_access) {
1332
1333                 if (strv_isempty(g))
1334                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1335                                    "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
1336                                    "      turn off this notice.");
1337                 else {
1338                         _cleanup_free_ char *s = NULL;
1339
1340                         r = strv_extend(&g, "systemd-journal");
1341                         if (r < 0)
1342                                 return log_oom();
1343
1344                         strv_sort(g);
1345                         strv_uniq(g);
1346
1347                         s = strv_join(g, "', '");
1348                         if (!s)
1349                                 return log_oom();
1350
1351                         log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
1352                                    "      Users in the groups '%s' can see all messages.\n"
1353                                    "      Pass -q to turn off this notice.", s);
1354                 }
1355         }
1356
1357         return 0;
1358 }
1359 #endif
1360
1361 static int access_check(sd_journal *j) {
1362         Iterator it;
1363         void *code;
1364         int r = 0;
1365
1366         assert(j);
1367
1368         if (set_isempty(j->errors)) {
1369                 if (hashmap_isempty(j->files))
1370                         log_notice("No journal files were found.");
1371                 return 0;
1372         }
1373
1374         if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
1375 #ifdef HAVE_ACL
1376                 /* If /var/log/journal doesn't even exist,
1377                  * unprivileged users have no access at all */
1378                 if (access("/var/log/journal", F_OK) < 0 &&
1379                     geteuid() != 0 &&
1380                     in_group("systemd-journal") <= 0) {
1381                         log_error("Unprivileged users cannot access messages, unless persistent log storage is\n"
1382                                   "enabled. Users in the 'systemd-journal' group may always access messages.");
1383                         return -EACCES;
1384                 }
1385
1386                 /* If /var/log/journal exists, try to pring a nice
1387                    notice if the user lacks access to it */
1388                 if (!arg_quiet && geteuid() != 0) {
1389                         r = access_check_var_log_journal(j);
1390                         if (r < 0)
1391                                 return r;
1392                 }
1393 #else
1394                 if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
1395                         log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
1396                                   "group may access messages.");
1397                         return -EACCES;
1398                 }
1399 #endif
1400
1401                 if (hashmap_isempty(j->files)) {
1402                         log_error("No journal files were opened due to insufficient permissions.");
1403                         r = -EACCES;
1404                 }
1405         }
1406
1407         SET_FOREACH(code, j->errors, it) {
1408                 int err;
1409
1410                 err = -PTR_TO_INT(code);
1411                 assert(err > 0);
1412
1413                 if (err != EACCES)
1414                         log_warning("Error was encountered while opening journal files: %s",
1415                                     strerror(err));
1416         }
1417
1418         return r;
1419 }
1420
1421 int main(int argc, char *argv[]) {
1422         int r;
1423         _cleanup_journal_close_ sd_journal *j = NULL;
1424         bool need_seek = false;
1425         sd_id128_t previous_boot_id;
1426         bool previous_boot_id_valid = false, first_line = true;
1427         int n_shown = 0;
1428         bool ellipsized = false;
1429
1430         setlocale(LC_ALL, "");
1431         log_parse_environment();
1432         log_open();
1433
1434         r = parse_argv(argc, argv);
1435         if (r <= 0)
1436                 goto finish;
1437
1438         signal(SIGWINCH, columns_lines_cache_reset);
1439
1440         if (arg_action == ACTION_NEW_ID128) {
1441                 r = generate_new_id128();
1442                 goto finish;
1443         }
1444
1445         if (arg_action == ACTION_SETUP_KEYS) {
1446                 r = setup_keys();
1447                 goto finish;
1448         }
1449
1450         if (arg_action == ACTION_UPDATE_CATALOG ||
1451             arg_action == ACTION_LIST_CATALOG ||
1452             arg_action == ACTION_DUMP_CATALOG) {
1453
1454                 const char* database = CATALOG_DATABASE;
1455                 _cleanup_free_ char *copy = NULL;
1456                 if (arg_root) {
1457                         copy = strjoin(arg_root, "/", CATALOG_DATABASE, NULL);
1458                         if (!copy) {
1459                                 r = log_oom();
1460                                 goto finish;
1461                         }
1462                         path_kill_slashes(copy);
1463                         database = copy;
1464                 }
1465
1466                 if (arg_action == ACTION_UPDATE_CATALOG) {
1467                         r = catalog_update(database, arg_root, catalog_file_dirs);
1468                         if (r < 0)
1469                                 log_error("Failed to list catalog: %s", strerror(-r));
1470                 } else {
1471                         bool oneline = arg_action == ACTION_LIST_CATALOG;
1472
1473                         if (optind < argc)
1474                                 r = catalog_list_items(stdout, database,
1475                                                        oneline, argv + optind);
1476                         else
1477                                 r = catalog_list(stdout, database, oneline);
1478                         if (r < 0)
1479                                 log_error("Failed to list catalog: %s", strerror(-r));
1480                 }
1481
1482                 goto finish;
1483         }
1484
1485         if (arg_directory)
1486                 r = sd_journal_open_directory(&j, arg_directory, arg_journal_type);
1487         else if (arg_file)
1488                 r = sd_journal_open_files(&j, (const char**) arg_file, 0);
1489         else if (arg_machine)
1490                 r = sd_journal_open_container(&j, arg_machine, 0);
1491         else
1492                 r = sd_journal_open(&j, !arg_merge*SD_JOURNAL_LOCAL_ONLY + arg_journal_type);
1493         if (r < 0) {
1494                 log_error("Failed to open %s: %s",
1495                           arg_directory ? arg_directory : arg_file ? "files" : "journal",
1496                           strerror(-r));
1497                 return EXIT_FAILURE;
1498         }
1499
1500         r = access_check(j);
1501         if (r < 0)
1502                 return EXIT_FAILURE;
1503
1504         if (arg_action == ACTION_VERIFY) {
1505                 r = verify(j);
1506                 goto finish;
1507         }
1508
1509         if (arg_action == ACTION_PRINT_HEADER) {
1510                 journal_print_header(j);
1511                 return EXIT_SUCCESS;
1512         }
1513
1514         if (arg_action == ACTION_DISK_USAGE) {
1515                 uint64_t bytes;
1516                 char sbytes[FORMAT_BYTES_MAX];
1517
1518                 r = sd_journal_get_usage(j, &bytes);
1519                 if (r < 0)
1520                         return EXIT_FAILURE;
1521
1522                 printf("Journals take up %s on disk.\n",
1523                        format_bytes(sbytes, sizeof(sbytes), bytes));
1524                 return EXIT_SUCCESS;
1525         }
1526
1527         if (arg_action == ACTION_LIST_BOOTS) {
1528                 r = list_boots(j);
1529                 goto finish;
1530         }
1531
1532         /* add_boot() must be called first!
1533          * It may need to seek the journal to find parent boot IDs. */
1534         r = add_boot(j);
1535         if (r < 0)
1536                 return EXIT_FAILURE;
1537
1538         r = add_dmesg(j);
1539         if (r < 0)
1540                 return EXIT_FAILURE;
1541
1542         r = add_units(j);
1543         strv_free(arg_system_units);
1544         strv_free(arg_user_units);
1545
1546         if (r < 0)
1547                 return EXIT_FAILURE;
1548
1549         r = add_priorities(j);
1550         if (r < 0)
1551                 return EXIT_FAILURE;
1552
1553         r = add_matches(j, argv + optind);
1554         if (r < 0)
1555                 return EXIT_FAILURE;
1556
1557         if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
1558                 _cleanup_free_ char *filter;
1559
1560                 filter = journal_make_match_string(j);
1561                 log_debug("Journal filter: %s", filter);
1562         }
1563
1564         if (arg_field) {
1565                 const void *data;
1566                 size_t size;
1567
1568                 r = sd_journal_set_data_threshold(j, 0);
1569                 if (r < 0) {
1570                         log_error("Failed to unset data size threshold");
1571                         return EXIT_FAILURE;
1572                 }
1573
1574                 r = sd_journal_query_unique(j, arg_field);
1575                 if (r < 0) {
1576                         log_error("Failed to query unique data objects: %s", strerror(-r));
1577                         return EXIT_FAILURE;
1578                 }
1579
1580                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
1581                         const void *eq;
1582
1583                         if (arg_lines >= 0 && n_shown >= arg_lines)
1584                                 break;
1585
1586                         eq = memchr(data, '=', size);
1587                         if (eq)
1588                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
1589                         else
1590                                 printf("%.*s\n", (int) size, (const char*) data);
1591
1592                         n_shown ++;
1593                 }
1594
1595                 return EXIT_SUCCESS;
1596         }
1597
1598         /* Opening the fd now means the first sd_journal_wait() will actually wait */
1599         if (arg_follow) {
1600                 r = sd_journal_get_fd(j);
1601                 if (r < 0)
1602                         return EXIT_FAILURE;
1603         }
1604
1605         if (arg_cursor || arg_after_cursor) {
1606                 r = sd_journal_seek_cursor(j, arg_cursor ? arg_cursor : arg_after_cursor);
1607                 if (r < 0) {
1608                         log_error("Failed to seek to cursor: %s", strerror(-r));
1609                         return EXIT_FAILURE;
1610                 }
1611                 if (!arg_reverse)
1612                         r = sd_journal_next_skip(j, 1 + !!arg_after_cursor);
1613                 else
1614                         r = sd_journal_previous_skip(j, 1 + !!arg_after_cursor);
1615
1616                 if (arg_after_cursor && r < 2 && !arg_follow)
1617                         /* We couldn't find the next entry after the cursor. */
1618                         arg_lines = 0;
1619
1620         } else if (arg_since_set && !arg_reverse) {
1621                 r = sd_journal_seek_realtime_usec(j, arg_since);
1622                 if (r < 0) {
1623                         log_error("Failed to seek to date: %s", strerror(-r));
1624                         return EXIT_FAILURE;
1625                 }
1626                 r = sd_journal_next(j);
1627
1628         } else if (arg_until_set && arg_reverse) {
1629                 r = sd_journal_seek_realtime_usec(j, arg_until);
1630                 if (r < 0) {
1631                         log_error("Failed to seek to date: %s", strerror(-r));
1632                         return EXIT_FAILURE;
1633                 }
1634                 r = sd_journal_previous(j);
1635
1636         } else if (arg_lines >= 0) {
1637                 r = sd_journal_seek_tail(j);
1638                 if (r < 0) {
1639                         log_error("Failed to seek to tail: %s", strerror(-r));
1640                         return EXIT_FAILURE;
1641                 }
1642
1643                 r = sd_journal_previous_skip(j, arg_lines);
1644
1645         } else if (arg_reverse) {
1646                 r = sd_journal_seek_tail(j);
1647                 if (r < 0) {
1648                         log_error("Failed to seek to tail: %s", strerror(-r));
1649                         return EXIT_FAILURE;
1650                 }
1651
1652                 r = sd_journal_previous(j);
1653
1654         } else {
1655                 r = sd_journal_seek_head(j);
1656                 if (r < 0) {
1657                         log_error("Failed to seek to head: %s", strerror(-r));
1658                         return EXIT_FAILURE;
1659                 }
1660
1661                 r = sd_journal_next(j);
1662         }
1663
1664         if (r < 0) {
1665                 log_error("Failed to iterate through journal: %s", strerror(-r));
1666                 return EXIT_FAILURE;
1667         }
1668
1669         if (!arg_follow)
1670                 pager_open_if_enabled();
1671
1672         if (!arg_quiet) {
1673                 usec_t start, end;
1674                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1675
1676                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1677                 if (r < 0) {
1678                         log_error("Failed to get cutoff: %s", strerror(-r));
1679                         goto finish;
1680                 }
1681
1682                 if (r > 0) {
1683                         if (arg_follow)
1684                                 printf("-- Logs begin at %s. --\n",
1685                                        format_timestamp(start_buf, sizeof(start_buf), start));
1686                         else
1687                                 printf("-- Logs begin at %s, end at %s. --\n",
1688                                        format_timestamp(start_buf, sizeof(start_buf), start),
1689                                        format_timestamp(end_buf, sizeof(end_buf), end));
1690                 }
1691         }
1692
1693         for (;;) {
1694                 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1695                         int flags;
1696
1697                         if (need_seek) {
1698                                 if (!arg_reverse)
1699                                         r = sd_journal_next(j);
1700                                 else
1701                                         r = sd_journal_previous(j);
1702                                 if (r < 0) {
1703                                         log_error("Failed to iterate through journal: %s", strerror(-r));
1704                                         goto finish;
1705                                 }
1706                                 if (r == 0)
1707                                         break;
1708                         }
1709
1710                         if (arg_until_set && !arg_reverse) {
1711                                 usec_t usec;
1712
1713                                 r = sd_journal_get_realtime_usec(j, &usec);
1714                                 if (r < 0) {
1715                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1716                                         goto finish;
1717                                 }
1718                                 if (usec > arg_until)
1719                                         goto finish;
1720                         }
1721
1722                         if (arg_since_set && arg_reverse) {
1723                                 usec_t usec;
1724
1725                                 r = sd_journal_get_realtime_usec(j, &usec);
1726                                 if (r < 0) {
1727                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1728                                         goto finish;
1729                                 }
1730                                 if (usec < arg_since)
1731                                         goto finish;
1732                         }
1733
1734                         if (!arg_merge) {
1735                                 sd_id128_t boot_id;
1736
1737                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1738                                 if (r >= 0) {
1739                                         if (previous_boot_id_valid &&
1740                                             !sd_id128_equal(boot_id, previous_boot_id))
1741                                                 printf("%s-- Reboot --%s\n",
1742                                                        ansi_highlight(), ansi_highlight_off());
1743
1744                                         previous_boot_id = boot_id;
1745                                         previous_boot_id_valid = true;
1746                                 }
1747                         }
1748
1749                         flags =
1750                                 arg_all * OUTPUT_SHOW_ALL |
1751                                 arg_full * OUTPUT_FULL_WIDTH |
1752                                 on_tty() * OUTPUT_COLOR |
1753                                 arg_catalog * OUTPUT_CATALOG;
1754
1755                         r = output_journal(stdout, j, arg_output, 0, flags, &ellipsized);
1756                         need_seek = true;
1757                         if (r == -EADDRNOTAVAIL)
1758                                 break;
1759                         else if (r < 0 || ferror(stdout))
1760                                 goto finish;
1761
1762                         n_shown++;
1763                 }
1764
1765                 if (!arg_follow) {
1766                         if (arg_show_cursor) {
1767                                 _cleanup_free_ char *cursor = NULL;
1768
1769                                 r = sd_journal_get_cursor(j, &cursor);
1770                                 if (r < 0 && r != -EADDRNOTAVAIL)
1771                                         log_error("Failed to get cursor: %s", strerror(-r));
1772                                 else if (r >= 0)
1773                                         printf("-- cursor: %s\n", cursor);
1774                         }
1775
1776                         break;
1777                 }
1778
1779                 r = sd_journal_wait(j, (uint64_t) -1);
1780                 if (r < 0) {
1781                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1782                         goto finish;
1783                 }
1784
1785                 first_line = false;
1786         }
1787
1788 finish:
1789         pager_close();
1790
1791         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1792 }