chiark / gitweb /
90845097049b183098417325c74239118b6e1697
[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 <sys/poll.h>
31 #include <time.h>
32 #include <getopt.h>
33 #include <signal.h>
34 #include <sys/stat.h>
35 #include <sys/ioctl.h>
36 #include <linux/fs.h>
37
38 #include <systemd/sd-journal.h>
39
40 #include "log.h"
41 #include "util.h"
42 #include "path-util.h"
43 #include "build.h"
44 #include "pager.h"
45 #include "logs-show.h"
46 #include "strv.h"
47 #include "journal-internal.h"
48 #include "journal-def.h"
49 #include "journal-verify.h"
50 #include "journal-authenticate.h"
51 #include "journal-qrcode.h"
52 #include "fsprg.h"
53 #include "unit-name.h"
54 #include "catalog.h"
55
56 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
57
58 static OutputMode arg_output = OUTPUT_SHORT;
59 static bool arg_follow = false;
60 static bool arg_full = false;
61 static bool arg_all = false;
62 static bool arg_no_pager = false;
63 static int arg_lines = -1;
64 static bool arg_no_tail = false;
65 static bool arg_quiet = false;
66 static bool arg_merge = false;
67 static bool arg_this_boot = false;
68 static const char *arg_cursor = NULL;
69 static const char *arg_directory = NULL;
70 static int arg_priorities = 0xFF;
71 static const char *arg_verify_key = NULL;
72 #ifdef HAVE_GCRYPT
73 static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
74 #endif
75 static usec_t arg_since, arg_until;
76 static bool arg_since_set = false, arg_until_set = false;
77 static const char *arg_unit = NULL;
78 static const char *arg_field = NULL;
79 static bool arg_catalog = false;
80
81 static enum {
82         ACTION_SHOW,
83         ACTION_NEW_ID128,
84         ACTION_PRINT_HEADER,
85         ACTION_SETUP_KEYS,
86         ACTION_VERIFY,
87         ACTION_DISK_USAGE,
88         ACTION_LIST_CATALOG,
89         ACTION_UPDATE_CATALOG
90 } arg_action = ACTION_SHOW;
91
92 static int help(void) {
93
94         printf("%s [OPTIONS...] [MATCHES...]\n\n"
95                "Query the journal.\n\n"
96                "Flags:\n"
97                "     --since=DATE        Start showing entries newer or of the specified date\n"
98                "     --until=DATE        Stop showing entries older or of the specified date\n"
99                "  -c --cursor=CURSOR     Start showing entries from specified cursor\n"
100                "  -b --this-boot         Show data only from current boot\n"
101                "  -u --unit=UNIT         Show data only from the specified unit\n"
102                "  -p --priority=RANGE    Show only messages within the specified priority range\n"
103                "  -f --follow            Follow journal\n"
104                "  -n --lines[=INTEGER]   Number of journal entries to show\n"
105                "     --no-tail           Show all lines, even in follow mode\n"
106                "  -o --output=STRING     Change journal output mode (short, short-monotonic,\n"
107                "                         verbose, export, json, json-pretty, json-sse, cat)\n"
108                "  -x --catalog           Add message explanations where available\n"
109                "     --full              Do not ellipsize fields\n"
110                "  -a --all               Show all fields, including long and unprintable\n"
111                "  -q --quiet             Don't show privilege warning\n"
112                "     --no-pager          Do not pipe output into a pager\n"
113                "  -m --merge             Show entries from all available journals\n"
114                "  -D --directory=PATH    Show journal files from directory\n"
115 #ifdef HAVE_GCRYPT
116                "     --interval=TIME     Time interval for changing the FSS sealing key\n"
117                "     --verify-key=KEY    Specify FSS verification key\n"
118 #endif
119                "\nCommands:\n"
120                "  -h --help              Show this help\n"
121                "     --version           Show package version\n"
122                "     --new-id128         Generate a new 128 Bit ID\n"
123                "     --header            Show journal header information\n"
124                "     --disk-usage        Show total disk usage\n"
125                "  -F --field=FIELD       List all values a certain field takes\n"
126                "     --list-catalog      Show message IDs of all entries in the message catalog\n"
127                "     --update-catalog    Update the message catalog database\n"
128 #ifdef HAVE_GCRYPT
129                "     --setup-keys        Generate new FSS key pair\n"
130                "     --verify            Verify journal file consistency\n"
131 #endif
132                , program_invocation_short_name);
133
134         return 0;
135 }
136
137 static int parse_argv(int argc, char *argv[]) {
138
139         enum {
140                 ARG_VERSION = 0x100,
141                 ARG_NO_PAGER,
142                 ARG_NO_TAIL,
143                 ARG_NEW_ID128,
144                 ARG_HEADER,
145                 ARG_FULL,
146                 ARG_SETUP_KEYS,
147                 ARG_INTERVAL,
148                 ARG_VERIFY,
149                 ARG_VERIFY_KEY,
150                 ARG_DISK_USAGE,
151                 ARG_SINCE,
152                 ARG_UNTIL,
153                 ARG_LIST_CATALOG,
154                 ARG_UPDATE_CATALOG
155         };
156
157         static const struct option options[] = {
158                 { "help",         no_argument,       NULL, 'h'              },
159                 { "version" ,     no_argument,       NULL, ARG_VERSION      },
160                 { "no-pager",     no_argument,       NULL, ARG_NO_PAGER     },
161                 { "follow",       no_argument,       NULL, 'f'              },
162                 { "output",       required_argument, NULL, 'o'              },
163                 { "all",          no_argument,       NULL, 'a'              },
164                 { "full",         no_argument,       NULL, ARG_FULL         },
165                 { "lines",        optional_argument, NULL, 'n'              },
166                 { "no-tail",      no_argument,       NULL, ARG_NO_TAIL      },
167                 { "new-id128",    no_argument,       NULL, ARG_NEW_ID128    },
168                 { "quiet",        no_argument,       NULL, 'q'              },
169                 { "merge",        no_argument,       NULL, 'm'              },
170                 { "this-boot",    no_argument,       NULL, 'b'              },
171                 { "directory",    required_argument, NULL, 'D'              },
172                 { "header",       no_argument,       NULL, ARG_HEADER       },
173                 { "priority",     required_argument, NULL, 'p'              },
174                 { "setup-keys",   no_argument,       NULL, ARG_SETUP_KEYS   },
175                 { "interval",     required_argument, NULL, ARG_INTERVAL     },
176                 { "verify",       no_argument,       NULL, ARG_VERIFY       },
177                 { "verify-key",   required_argument, NULL, ARG_VERIFY_KEY   },
178                 { "disk-usage",   no_argument,       NULL, ARG_DISK_USAGE   },
179                 { "cursor",       required_argument, NULL, 'c'              },
180                 { "since",        required_argument, NULL, ARG_SINCE        },
181                 { "until",        required_argument, NULL, ARG_UNTIL        },
182                 { "unit",         required_argument, NULL, 'u'              },
183                 { "field",        required_argument, NULL, 'F'              },
184                 { "catalog",      no_argument,       NULL, 'x'              },
185                 { "list-catalog", no_argument,       NULL, ARG_LIST_CATALOG },
186                 { "update-catalog",no_argument,      NULL, ARG_UPDATE_CATALOG },
187                 { NULL,           0,                 NULL, 0                }
188         };
189
190         int c, r;
191
192         assert(argc >= 0);
193         assert(argv);
194
195         while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:F:x", options, NULL)) >= 0) {
196
197                 switch (c) {
198
199                 case 'h':
200                         help();
201                         return 0;
202
203                 case ARG_VERSION:
204                         puts(PACKAGE_STRING);
205                         puts(SYSTEMD_FEATURES);
206                         return 0;
207
208                 case ARG_NO_PAGER:
209                         arg_no_pager = true;
210                         break;
211
212                 case 'f':
213                         arg_follow = true;
214                         break;
215
216                 case 'o':
217                         arg_output = output_mode_from_string(optarg);
218                         if (arg_output < 0) {
219                                 log_error("Unknown output format '%s'.", optarg);
220                                 return -EINVAL;
221                         }
222
223                         if (arg_output == OUTPUT_EXPORT ||
224                             arg_output == OUTPUT_JSON ||
225                             arg_output == OUTPUT_JSON_PRETTY ||
226                             arg_output == OUTPUT_JSON_SSE ||
227                             arg_output == OUTPUT_CAT)
228                                 arg_quiet = true;
229
230                         break;
231
232                 case ARG_FULL:
233                         arg_full = true;
234                         break;
235
236                 case 'a':
237                         arg_all = true;
238                         break;
239
240                 case 'n':
241                         if (optarg) {
242                                 r = safe_atoi(optarg, &arg_lines);
243                                 if (r < 0 || arg_lines < 0) {
244                                         log_error("Failed to parse lines '%s'", optarg);
245                                         return -EINVAL;
246                                 }
247                         } else {
248                                 int n;
249
250                                 /* Hmm, no argument? Maybe the next
251                                  * word on the command line is
252                                  * supposed to be the argument? Let's
253                                  * see if there is one, and is
254                                  * parsable as a positive
255                                  * integer... */
256
257                                 if (optind < argc &&
258                                     safe_atoi(argv[optind], &n) >= 0 &&
259                                     n >= 0) {
260
261                                         arg_lines = n;
262                                         optind++;
263                                 } else
264                                         arg_lines = 10;
265                         }
266
267                         break;
268
269                 case ARG_NO_TAIL:
270                         arg_no_tail = true;
271                         break;
272
273                 case ARG_NEW_ID128:
274                         arg_action = ACTION_NEW_ID128;
275                         break;
276
277                 case 'q':
278                         arg_quiet = true;
279                         break;
280
281                 case 'm':
282                         arg_merge = true;
283                         break;
284
285                 case 'b':
286                         arg_this_boot = true;
287                         break;
288
289                 case 'D':
290                         arg_directory = optarg;
291                         break;
292
293                 case 'c':
294                         arg_cursor = optarg;
295                         break;
296
297                 case ARG_HEADER:
298                         arg_action = ACTION_PRINT_HEADER;
299                         break;
300
301                 case ARG_VERIFY:
302                         arg_action = ACTION_VERIFY;
303                         break;
304
305                 case ARG_DISK_USAGE:
306                         arg_action = ACTION_DISK_USAGE;
307                         break;
308
309 #ifdef HAVE_GCRYPT
310                 case ARG_SETUP_KEYS:
311                         arg_action = ACTION_SETUP_KEYS;
312                         break;
313
314
315                 case ARG_VERIFY_KEY:
316                         arg_action = ACTION_VERIFY;
317                         arg_verify_key = optarg;
318                         arg_merge = false;
319                         break;
320
321                 case ARG_INTERVAL:
322                         r = parse_usec(optarg, &arg_interval);
323                         if (r < 0 || arg_interval <= 0) {
324                                 log_error("Failed to parse sealing key change interval: %s", optarg);
325                                 return -EINVAL;
326                         }
327                         break;
328 #else
329                 case ARG_SETUP_KEYS:
330                 case ARG_VERIFY_KEY:
331                 case ARG_INTERVAL:
332                         log_error("Forward-secure sealing not available.");
333                         return -ENOTSUP;
334 #endif
335
336                 case 'p': {
337                         const char *dots;
338
339                         dots = strstr(optarg, "..");
340                         if (dots) {
341                                 char *a;
342                                 int from, to, i;
343
344                                 /* a range */
345                                 a = strndup(optarg, dots - optarg);
346                                 if (!a)
347                                         return log_oom();
348
349                                 from = log_level_from_string(a);
350                                 to = log_level_from_string(dots + 2);
351                                 free(a);
352
353                                 if (from < 0 || to < 0) {
354                                         log_error("Failed to parse log level range %s", optarg);
355                                         return -EINVAL;
356                                 }
357
358                                 arg_priorities = 0;
359
360                                 if (from < to) {
361                                         for (i = from; i <= to; i++)
362                                                 arg_priorities |= 1 << i;
363                                 } else {
364                                         for (i = to; i <= from; i++)
365                                                 arg_priorities |= 1 << i;
366                                 }
367
368                         } else {
369                                 int p, i;
370
371                                 p = log_level_from_string(optarg);
372                                 if (p < 0) {
373                                         log_error("Unknown log level %s", optarg);
374                                         return -EINVAL;
375                                 }
376
377                                 arg_priorities = 0;
378
379                                 for (i = 0; i <= p; i++)
380                                         arg_priorities |= 1 << i;
381                         }
382
383                         break;
384                 }
385
386                 case ARG_SINCE:
387                         r = parse_timestamp(optarg, &arg_since);
388                         if (r < 0) {
389                                 log_error("Failed to parse timestamp: %s", optarg);
390                                 return -EINVAL;
391                         }
392                         arg_since_set = true;
393                         break;
394
395                 case ARG_UNTIL:
396                         r = parse_timestamp(optarg, &arg_until);
397                         if (r < 0) {
398                                 log_error("Failed to parse timestamp: %s", optarg);
399                                 return -EINVAL;
400                         }
401                         arg_until_set = true;
402                         break;
403
404                 case 'u':
405                         arg_unit = optarg;
406                         break;
407
408                 case '?':
409                         return -EINVAL;
410
411                 case 'F':
412                         arg_field = optarg;
413                         break;
414
415                 case 'x':
416                         arg_catalog = true;
417                         break;
418
419                 case ARG_LIST_CATALOG:
420                         arg_action = ACTION_LIST_CATALOG;
421                         break;
422
423                 case ARG_UPDATE_CATALOG:
424                         arg_action = ACTION_UPDATE_CATALOG;
425                         break;
426
427                 default:
428                         log_error("Unknown option code %c", c);
429                         return -EINVAL;
430                 }
431         }
432
433         if (arg_follow && !arg_no_tail && arg_lines < 0)
434                 arg_lines = 10;
435
436         if (arg_since_set && arg_until_set && arg_since > arg_until) {
437                 log_error("--since= must be before --until=.");
438                 return -EINVAL;
439         }
440
441         if (arg_cursor && arg_since_set) {
442                 log_error("Please specify either --since= or --cursor=, not both.");
443                 return -EINVAL;
444         }
445
446         return 1;
447 }
448
449 static int generate_new_id128(void) {
450         sd_id128_t id;
451         int r;
452         unsigned i;
453
454         r = sd_id128_randomize(&id);
455         if (r < 0) {
456                 log_error("Failed to generate ID: %s", strerror(-r));
457                 return r;
458         }
459
460         printf("As string:\n"
461                SD_ID128_FORMAT_STR "\n\n"
462                "As UUID:\n"
463                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
464                "As macro:\n"
465                "#define MESSAGE_XYZ SD_ID128_MAKE(",
466                SD_ID128_FORMAT_VAL(id),
467                SD_ID128_FORMAT_VAL(id));
468         for (i = 0; i < 16; i++)
469                 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
470         fputs(")\n\n", stdout);
471
472         printf("As Python constant:\n"
473                ">>> import uuid\n"
474                ">>> MESSAGE_XYZ = uuid.UUID('" SD_ID128_FORMAT_STR "')\n",
475                SD_ID128_FORMAT_VAL(id));
476
477         return 0;
478 }
479
480 static int add_matches(sd_journal *j, char **args) {
481         char **i;
482         int r;
483
484         assert(j);
485
486         STRV_FOREACH(i, args) {
487
488                 if (streq(*i, "+"))
489                         r = sd_journal_add_disjunction(j);
490                 else if (path_is_absolute(*i)) {
491                         char *p, *t = NULL;
492                         const char *path;
493                         struct stat st;
494
495                         p = canonicalize_file_name(*i);
496                         path = p ? p : *i;
497
498                         if (stat(path, &st) < 0)  {
499                                 free(p);
500                                 log_error("Couldn't stat file: %m");
501                                 return -errno;
502                         }
503
504                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
505                                 t = strappend("_EXE=", path);
506                         else if (S_ISCHR(st.st_mode))
507                                 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
508                         else if (S_ISBLK(st.st_mode))
509                                 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
510                         else {
511                                 free(p);
512                                 log_error("File is not a device node, regular file or is not executable: %s", *i);
513                                 return -EINVAL;
514                         }
515
516                         free(p);
517
518                         if (!t)
519                                 return log_oom();
520
521                         r = sd_journal_add_match(j, t, 0);
522                         free(t);
523                 } else
524                         r = sd_journal_add_match(j, *i, 0);
525
526                 if (r < 0) {
527                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
528                         return r;
529                 }
530         }
531
532         return 0;
533 }
534
535 static int add_this_boot(sd_journal *j) {
536         char match[9+32+1] = "_BOOT_ID=";
537         sd_id128_t boot_id;
538         int r;
539
540         assert(j);
541
542         if (!arg_this_boot)
543                 return 0;
544
545         r = sd_id128_get_boot(&boot_id);
546         if (r < 0) {
547                 log_error("Failed to get boot id: %s", strerror(-r));
548                 return r;
549         }
550
551         sd_id128_to_string(boot_id, match + 9);
552         r = sd_journal_add_match(j, match, strlen(match));
553         if (r < 0) {
554                 log_error("Failed to add match: %s", strerror(-r));
555                 return r;
556         }
557
558         return 0;
559 }
560
561 static int add_unit(sd_journal *j) {
562         _cleanup_free_ char *m = NULL, *u = NULL;
563         int r;
564
565         assert(j);
566
567         if (isempty(arg_unit))
568                 return 0;
569
570         u = unit_name_mangle(arg_unit);
571         if (!u)
572                 return log_oom();
573
574         m = strappend("_SYSTEMD_UNIT=", u);
575         if (!m)
576                 return log_oom();
577
578         r = sd_journal_add_match(j, m, strlen(m));
579         if (r < 0) {
580                 log_error("Failed to add match: %s", strerror(-r));
581                 return r;
582         }
583
584         return 0;
585 }
586
587 static int add_priorities(sd_journal *j) {
588         char match[] = "PRIORITY=0";
589         int i, r;
590
591         assert(j);
592
593         if (arg_priorities == 0xFF)
594                 return 0;
595
596         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
597                 if (arg_priorities & (1 << i)) {
598                         match[sizeof(match)-2] = '0' + i;
599
600                         r = sd_journal_add_match(j, match, strlen(match));
601                         if (r < 0) {
602                                 log_error("Failed to add match: %s", strerror(-r));
603                                 return r;
604                         }
605                 }
606
607         return 0;
608 }
609
610 static int setup_keys(void) {
611 #ifdef HAVE_GCRYPT
612         size_t mpk_size, seed_size, state_size, i;
613         uint8_t *mpk, *seed, *state;
614         ssize_t l;
615         int fd = -1, r, attr = 0;
616         sd_id128_t machine, boot;
617         char *p = NULL, *k = NULL;
618         struct FSSHeader h;
619         uint64_t n;
620
621         r = sd_id128_get_machine(&machine);
622         if (r < 0) {
623                 log_error("Failed to get machine ID: %s", strerror(-r));
624                 return r;
625         }
626
627         r = sd_id128_get_boot(&boot);
628         if (r < 0) {
629                 log_error("Failed to get boot ID: %s", strerror(-r));
630                 return r;
631         }
632
633         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
634                      SD_ID128_FORMAT_VAL(machine)) < 0)
635                 return log_oom();
636
637         if (access(p, F_OK) >= 0) {
638                 log_error("Sealing key file %s exists already.", p);
639                 r = -EEXIST;
640                 goto finish;
641         }
642
643         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
644                      SD_ID128_FORMAT_VAL(machine)) < 0) {
645                 r = log_oom();
646                 goto finish;
647         }
648
649         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
650         mpk = alloca(mpk_size);
651
652         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
653         seed = alloca(seed_size);
654
655         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
656         state = alloca(state_size);
657
658         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
659         if (fd < 0) {
660                 log_error("Failed to open /dev/random: %m");
661                 r = -errno;
662                 goto finish;
663         }
664
665         log_info("Generating seed...");
666         l = loop_read(fd, seed, seed_size, true);
667         if (l < 0 || (size_t) l != seed_size) {
668                 log_error("Failed to read random seed: %s", strerror(EIO));
669                 r = -EIO;
670                 goto finish;
671         }
672
673         log_info("Generating key pair...");
674         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
675
676         log_info("Generating sealing key...");
677         FSPRG_GenState0(state, mpk, seed, seed_size);
678
679         assert(arg_interval > 0);
680
681         n = now(CLOCK_REALTIME);
682         n /= arg_interval;
683
684         close_nointr_nofail(fd);
685         fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
686         if (fd < 0) {
687                 log_error("Failed to open %s: %m", k);
688                 r = -errno;
689                 goto finish;
690         }
691
692         /* Enable secure remove, exclusion from dump, synchronous
693          * writing and in-place updating */
694         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
695                 log_warning("FS_IOC_GETFLAGS failed: %m");
696
697         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
698
699         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
700                 log_warning("FS_IOC_SETFLAGS failed: %m");
701
702         zero(h);
703         memcpy(h.signature, "KSHHRHLP", 8);
704         h.machine_id = machine;
705         h.boot_id = boot;
706         h.header_size = htole64(sizeof(h));
707         h.start_usec = htole64(n * arg_interval);
708         h.interval_usec = htole64(arg_interval);
709         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
710         h.fsprg_state_size = htole64(state_size);
711
712         l = loop_write(fd, &h, sizeof(h), false);
713         if (l < 0 || (size_t) l != sizeof(h)) {
714                 log_error("Failed to write header: %s", strerror(EIO));
715                 r = -EIO;
716                 goto finish;
717         }
718
719         l = loop_write(fd, state, state_size, false);
720         if (l < 0 || (size_t) l != state_size) {
721                 log_error("Failed to write state: %s", strerror(EIO));
722                 r = -EIO;
723                 goto finish;
724         }
725
726         if (link(k, p) < 0) {
727                 log_error("Failed to link file: %m");
728                 r = -errno;
729                 goto finish;
730         }
731
732         if (on_tty()) {
733                 fprintf(stderr,
734                         "\n"
735                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
736                         "the following local file. This key file is automatically updated when the\n"
737                         "sealing key is advanced. It should not be used on multiple hosts.\n"
738                         "\n"
739                         "\t%s\n"
740                         "\n"
741                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
742                         "at a safe location and should not be saved locally on disk.\n"
743                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
744                 fflush(stderr);
745         }
746         for (i = 0; i < seed_size; i++) {
747                 if (i > 0 && i % 3 == 0)
748                         putchar('-');
749                 printf("%02x", ((uint8_t*) seed)[i]);
750         }
751
752         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
753
754         if (on_tty()) {
755                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
756
757                 fprintf(stderr,
758                         ANSI_HIGHLIGHT_OFF "\n"
759                         "The sealing key is automatically changed every %s.\n",
760                         format_timespan(tsb, sizeof(tsb), arg_interval));
761
762                 hn = gethostname_malloc();
763
764                 if (hn) {
765                         hostname_cleanup(hn);
766                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
767                 } else
768                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
769
770 #ifdef HAVE_QRENCODE
771                 /* If this is not an UTF-8 system don't print any QR codes */
772                 if (is_locale_utf8()) {
773                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
774                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
775                 }
776 #endif
777                 free(hn);
778         }
779
780         r = 0;
781
782 finish:
783         if (fd >= 0)
784                 close_nointr_nofail(fd);
785
786         if (k) {
787                 unlink(k);
788                 free(k);
789         }
790
791         free(p);
792
793         return r;
794 #else
795         log_error("Forward-secure sealing not available.");
796         return -ENOTSUP;
797 #endif
798 }
799
800 static int verify(sd_journal *j) {
801         int r = 0;
802         Iterator i;
803         JournalFile *f;
804
805         assert(j);
806
807         log_show_color(true);
808
809         HASHMAP_FOREACH(f, j->files, i) {
810                 int k;
811                 usec_t first, validated, last;
812
813 #ifdef HAVE_GCRYPT
814                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
815                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
816 #endif
817
818                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
819                 if (k == -EINVAL) {
820                         /* If the key was invalid give up right-away. */
821                         return k;
822                 } else if (k < 0) {
823                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
824                         r = k;
825                 } else {
826                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
827                         log_info("PASS: %s", f->path);
828
829                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
830                                 if (validated > 0) {
831                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
832                                                  format_timestamp(a, sizeof(a), first),
833                                                  format_timestamp(b, sizeof(b), validated),
834                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0));
835                                 } else if (last > 0)
836                                         log_info("=> No sealing yet, %s of entries not sealed.",
837                                                  format_timespan(c, sizeof(c), last - first));
838                                 else
839                                         log_info("=> No sealing yet, no entries in file.");
840                         }
841                 }
842         }
843
844         return r;
845 }
846
847 static int access_check(void) {
848
849 #ifdef HAVE_ACL
850         if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) {
851                 log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages.");
852                 return -EACCES;
853         }
854
855         if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
856                 log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off.");
857 #else
858         if (geteuid() != 0 && in_group("adm") <= 0) {
859                 log_error("No access to messages. Only users in the group 'adm' can see messages.");
860                 return -EACCES;
861         }
862 #endif
863
864         return 0;
865 }
866
867 int main(int argc, char *argv[]) {
868         int r;
869         sd_journal *j = NULL;
870         bool need_seek = false;
871         sd_id128_t previous_boot_id;
872         bool previous_boot_id_valid = false, first_line = true;
873         int n_shown = 0;
874
875         setlocale(LC_ALL, "");
876         log_parse_environment();
877         log_open();
878
879         r = parse_argv(argc, argv);
880         if (r <= 0)
881                 goto finish;
882
883         signal(SIGWINCH, columns_lines_cache_reset);
884
885         if (arg_action == ACTION_NEW_ID128) {
886                 r = generate_new_id128();
887                 goto finish;
888         }
889
890         if (arg_action == ACTION_SETUP_KEYS) {
891                 r = setup_keys();
892                 goto finish;
893         }
894
895         if (arg_action == ACTION_LIST_CATALOG)  {
896                 r = catalog_list(stdout);
897                 if (r < 0)
898                         log_error("Failed to list catalog: %s", strerror(-r));
899                 goto finish;
900         }
901
902         if (arg_action == ACTION_UPDATE_CATALOG)  {
903                 r = catalog_update();
904                 goto finish;
905         }
906
907         r = access_check();
908         if (r < 0)
909                 goto finish;
910
911         if (arg_directory)
912                 r = sd_journal_open_directory(&j, arg_directory, 0);
913         else
914                 r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
915         if (r < 0) {
916                 log_error("Failed to open journal: %s", strerror(-r));
917                 goto finish;
918         }
919
920         if (arg_action == ACTION_VERIFY) {
921                 r = verify(j);
922                 goto finish;
923         }
924
925         if (arg_action == ACTION_PRINT_HEADER) {
926                 journal_print_header(j);
927                 r = 0;
928                 goto finish;
929         }
930
931         if (arg_action == ACTION_DISK_USAGE) {
932                 uint64_t bytes;
933                 char sbytes[FORMAT_BYTES_MAX];
934
935                 r = sd_journal_get_usage(j, &bytes);
936                 if (r < 0)
937                         goto finish;
938
939                 printf("Journals take up %s on disk.\n", format_bytes(sbytes, sizeof(sbytes), bytes));
940                 r = 0;
941                 goto finish;
942         }
943
944         r = add_this_boot(j);
945         if (r < 0)
946                 goto finish;
947
948         r = add_unit(j);
949         if (r < 0)
950                 goto finish;
951
952         r = add_matches(j, argv + optind);
953         if (r < 0)
954                 goto finish;
955
956         r = add_priorities(j);
957         if (r < 0)
958                 goto finish;
959
960         /* Opening the fd now means the first sd_journal_wait() will actually wait */
961         r = sd_journal_get_fd(j);
962         if (r < 0)
963                 goto finish;
964
965         if (arg_field) {
966                 const void *data;
967                 size_t size;
968
969                 r = sd_journal_query_unique(j, arg_field);
970                 if (r < 0) {
971                         log_error("Failed to query unique data objects: %s", strerror(-r));
972                         goto finish;
973                 }
974
975                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
976                         const void *eq;
977
978                         if (arg_lines >= 0 && n_shown >= arg_lines)
979                                 break;
980
981                         eq = memchr(data, '=', size);
982                         if (eq)
983                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
984                         else
985                                 printf("%.*s\n", (int) size, (const char*) data);
986
987                         n_shown ++;
988                 }
989
990                 r = 0;
991                 goto finish;
992         }
993
994         if (arg_cursor) {
995                 r = sd_journal_seek_cursor(j, arg_cursor);
996                 if (r < 0) {
997                         log_error("Failed to seek to cursor: %s", strerror(-r));
998                         goto finish;
999                 }
1000
1001                 r = sd_journal_next(j);
1002
1003         } else if (arg_since_set) {
1004                 r = sd_journal_seek_realtime_usec(j, arg_since);
1005                 if (r < 0) {
1006                         log_error("Failed to seek to date: %s", strerror(-r));
1007                         goto finish;
1008                 }
1009                 r = sd_journal_next(j);
1010
1011         } else if (arg_lines >= 0) {
1012                 r = sd_journal_seek_tail(j);
1013                 if (r < 0) {
1014                         log_error("Failed to seek to tail: %s", strerror(-r));
1015                         goto finish;
1016                 }
1017
1018                 r = sd_journal_previous_skip(j, arg_lines);
1019
1020         } else {
1021                 r = sd_journal_seek_head(j);
1022                 if (r < 0) {
1023                         log_error("Failed to seek to head: %s", strerror(-r));
1024                         goto finish;
1025                 }
1026
1027                 r = sd_journal_next(j);
1028         }
1029
1030         if (r < 0) {
1031                 log_error("Failed to iterate through journal: %s", strerror(-r));
1032                 goto finish;
1033         }
1034
1035         if (!arg_no_pager && !arg_follow)
1036                 pager_open();
1037
1038         if (!arg_quiet) {
1039                 usec_t start, end;
1040                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1041
1042                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1043                 if (r < 0) {
1044                         log_error("Failed to get cutoff: %s", strerror(-r));
1045                         goto finish;
1046                 }
1047
1048                 if (r > 0) {
1049                         if (arg_follow)
1050                                 printf("-- Logs begin at %s. --\n",
1051                                        format_timestamp(start_buf, sizeof(start_buf), start));
1052                         else
1053                                 printf("-- Logs begin at %s, end at %s. --\n",
1054                                        format_timestamp(start_buf, sizeof(start_buf), start),
1055                                        format_timestamp(end_buf, sizeof(end_buf), end));
1056                 }
1057         }
1058
1059         for (;;) {
1060                 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1061                         int flags;
1062
1063                         if (need_seek) {
1064                                 r = sd_journal_next(j);
1065                                 if (r < 0) {
1066                                         log_error("Failed to iterate through journal: %s", strerror(-r));
1067                                         goto finish;
1068                                 }
1069                         }
1070
1071                         if (r == 0)
1072                                 break;
1073
1074                         if (arg_until_set) {
1075                                 usec_t usec;
1076
1077                                 r = sd_journal_get_realtime_usec(j, &usec);
1078                                 if (r < 0) {
1079                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1080                                         goto finish;
1081                                 }
1082                                 if (usec > arg_until)
1083                                         goto finish;
1084                         }
1085
1086                         if (!arg_merge) {
1087                                 sd_id128_t boot_id;
1088
1089                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1090                                 if (r >= 0) {
1091                                         if (previous_boot_id_valid &&
1092                                             !sd_id128_equal(boot_id, previous_boot_id))
1093                                                 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1094
1095                                         previous_boot_id = boot_id;
1096                                         previous_boot_id_valid = true;
1097                                 }
1098                         }
1099
1100                         flags =
1101                                 arg_all * OUTPUT_SHOW_ALL |
1102                                 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1103                                 on_tty() * OUTPUT_COLOR |
1104                                 arg_catalog * OUTPUT_CATALOG;
1105
1106                         r = output_journal(stdout, j, arg_output, 0, flags);
1107                         if (r < 0 || ferror(stdout))
1108                                 goto finish;
1109
1110                         need_seek = true;
1111                         n_shown++;
1112                 }
1113
1114                 if (!arg_follow)
1115                         break;
1116
1117                 r = sd_journal_wait(j, (uint64_t) -1);
1118                 if (r < 0) {
1119                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1120                         goto finish;
1121                 }
1122
1123                 first_line = false;
1124         }
1125
1126 finish:
1127         if (j)
1128                 sd_journal_close(j);
1129
1130         pager_close();
1131
1132         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1133 }