chiark / gitweb /
journalctl: allow --lines=0 i.e. only new
[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                                 arg_lines = 10;
249
250                         break;
251
252                 case ARG_NO_TAIL:
253                         arg_no_tail = true;
254                         break;
255
256                 case ARG_NEW_ID128:
257                         arg_action = ACTION_NEW_ID128;
258                         break;
259
260                 case 'q':
261                         arg_quiet = true;
262                         break;
263
264                 case 'm':
265                         arg_merge = true;
266                         break;
267
268                 case 'b':
269                         arg_this_boot = true;
270                         break;
271
272                 case 'D':
273                         arg_directory = optarg;
274                         break;
275
276                 case 'c':
277                         arg_cursor = optarg;
278                         break;
279
280                 case ARG_HEADER:
281                         arg_action = ACTION_PRINT_HEADER;
282                         break;
283
284                 case ARG_VERIFY:
285                         arg_action = ACTION_VERIFY;
286                         break;
287
288                 case ARG_DISK_USAGE:
289                         arg_action = ACTION_DISK_USAGE;
290                         break;
291
292 #ifdef HAVE_GCRYPT
293                 case ARG_SETUP_KEYS:
294                         arg_action = ACTION_SETUP_KEYS;
295                         break;
296
297
298                 case ARG_VERIFY_KEY:
299                         arg_action = ACTION_VERIFY;
300                         arg_verify_key = optarg;
301                         arg_merge = false;
302                         break;
303
304                 case ARG_INTERVAL:
305                         r = parse_usec(optarg, &arg_interval);
306                         if (r < 0 || arg_interval <= 0) {
307                                 log_error("Failed to parse sealing key change interval: %s", optarg);
308                                 return -EINVAL;
309                         }
310                         break;
311 #else
312                 case ARG_SETUP_KEYS:
313                 case ARG_VERIFY_KEY:
314                 case ARG_INTERVAL:
315                         log_error("Forward-secure sealing not available.");
316                         return -ENOTSUP;
317 #endif
318
319                 case 'p': {
320                         const char *dots;
321
322                         dots = strstr(optarg, "..");
323                         if (dots) {
324                                 char *a;
325                                 int from, to, i;
326
327                                 /* a range */
328                                 a = strndup(optarg, dots - optarg);
329                                 if (!a)
330                                         return log_oom();
331
332                                 from = log_level_from_string(a);
333                                 to = log_level_from_string(dots + 2);
334                                 free(a);
335
336                                 if (from < 0 || to < 0) {
337                                         log_error("Failed to parse log level range %s", optarg);
338                                         return -EINVAL;
339                                 }
340
341                                 arg_priorities = 0;
342
343                                 if (from < to) {
344                                         for (i = from; i <= to; i++)
345                                                 arg_priorities |= 1 << i;
346                                 } else {
347                                         for (i = to; i <= from; i++)
348                                                 arg_priorities |= 1 << i;
349                                 }
350
351                         } else {
352                                 int p, i;
353
354                                 p = log_level_from_string(optarg);
355                                 if (p < 0) {
356                                         log_error("Unknown log level %s", optarg);
357                                         return -EINVAL;
358                                 }
359
360                                 arg_priorities = 0;
361
362                                 for (i = 0; i <= p; i++)
363                                         arg_priorities |= 1 << i;
364                         }
365
366                         break;
367                 }
368
369                 case ARG_SINCE:
370                         r = parse_timestamp(optarg, &arg_since);
371                         if (r < 0) {
372                                 log_error("Failed to parse timestamp: %s", optarg);
373                                 return -EINVAL;
374                         }
375                         arg_since_set = true;
376                         break;
377
378                 case ARG_UNTIL:
379                         r = parse_timestamp(optarg, &arg_until);
380                         if (r < 0) {
381                                 log_error("Failed to parse timestamp: %s", optarg);
382                                 return -EINVAL;
383                         }
384                         arg_until_set = true;
385                         break;
386
387                 case 'u':
388                         arg_unit = optarg;
389                         break;
390
391                 case '?':
392                         return -EINVAL;
393
394                 case 'F':
395                         arg_field = optarg;
396                         break;
397
398                 case 'x':
399                         arg_catalog = true;
400                         break;
401
402                 case ARG_LIST_CATALOG:
403                         arg_action = ACTION_LIST_CATALOG;
404                         break;
405
406                 case ARG_UPDATE_CATALOG:
407                         arg_action = ACTION_UPDATE_CATALOG;
408                         break;
409
410                 default:
411                         log_error("Unknown option code %c", c);
412                         return -EINVAL;
413                 }
414         }
415
416         if (arg_follow && !arg_no_tail && arg_lines < 0)
417                 arg_lines = 10;
418
419         if (arg_since_set && arg_until_set && arg_since_set > arg_until_set) {
420                 log_error("--since= must be before --until=.");
421                 return -EINVAL;
422         }
423
424         if (arg_cursor && arg_since_set) {
425                 log_error("Please specify either --since= or --cursor=, not both.");
426                 return -EINVAL;
427         }
428
429         return 1;
430 }
431
432 static int generate_new_id128(void) {
433         sd_id128_t id;
434         int r;
435         unsigned i;
436
437         r = sd_id128_randomize(&id);
438         if (r < 0) {
439                 log_error("Failed to generate ID: %s", strerror(-r));
440                 return r;
441         }
442
443         printf("As string:\n"
444                SD_ID128_FORMAT_STR "\n\n"
445                "As UUID:\n"
446                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n\n"
447                "As macro:\n"
448               "#define MESSAGE_XYZ SD_ID128_MAKE(",
449                SD_ID128_FORMAT_VAL(id),
450                SD_ID128_FORMAT_VAL(id));
451
452         for (i = 0; i < 16; i++)
453                 printf("%02x%s", id.bytes[i], i != 15 ? "," : "");
454
455         fputs(")\n", stdout);
456
457         return 0;
458 }
459
460 static int add_matches(sd_journal *j, char **args) {
461         char **i;
462         int r;
463
464         assert(j);
465
466         STRV_FOREACH(i, args) {
467
468                 if (streq(*i, "+"))
469                         r = sd_journal_add_disjunction(j);
470                 else if (path_is_absolute(*i)) {
471                         char *p, *t = NULL;
472                         const char *path;
473                         struct stat st;
474
475                         p = canonicalize_file_name(*i);
476                         path = p ? p : *i;
477
478                         if (stat(path, &st) < 0)  {
479                                 free(p);
480                                 log_error("Couldn't stat file: %m");
481                                 return -errno;
482                         }
483
484                         if (S_ISREG(st.st_mode) && (0111 & st.st_mode))
485                                 t = strappend("_EXE=", path);
486                         else if (S_ISCHR(st.st_mode))
487                                 asprintf(&t, "_KERNEL_DEVICE=c%u:%u", major(st.st_rdev), minor(st.st_rdev));
488                         else if (S_ISBLK(st.st_mode))
489                                 asprintf(&t, "_KERNEL_DEVICE=b%u:%u", major(st.st_rdev), minor(st.st_rdev));
490                         else {
491                                 free(p);
492                                 log_error("File is not a device node, regular file or is not executable: %s", *i);
493                                 return -EINVAL;
494                         }
495
496                         free(p);
497
498                         if (!t)
499                                 return log_oom();
500
501                         r = sd_journal_add_match(j, t, 0);
502                         free(t);
503                 } else
504                         r = sd_journal_add_match(j, *i, 0);
505
506                 if (r < 0) {
507                         log_error("Failed to add match '%s': %s", *i, strerror(-r));
508                         return r;
509                 }
510         }
511
512         return 0;
513 }
514
515 static int add_this_boot(sd_journal *j) {
516         char match[9+32+1] = "_BOOT_ID=";
517         sd_id128_t boot_id;
518         int r;
519
520         assert(j);
521
522         if (!arg_this_boot)
523                 return 0;
524
525         r = sd_id128_get_boot(&boot_id);
526         if (r < 0) {
527                 log_error("Failed to get boot id: %s", strerror(-r));
528                 return r;
529         }
530
531         sd_id128_to_string(boot_id, match + 9);
532         r = sd_journal_add_match(j, match, strlen(match));
533         if (r < 0) {
534                 log_error("Failed to add match: %s", strerror(-r));
535                 return r;
536         }
537
538         return 0;
539 }
540
541 static int add_unit(sd_journal *j) {
542         _cleanup_free_ char *m = NULL, *u = NULL;
543         int r;
544
545         assert(j);
546
547         if (isempty(arg_unit))
548                 return 0;
549
550         u = unit_name_mangle(arg_unit);
551         if (!u)
552                 return log_oom();
553
554         m = strappend("_SYSTEMD_UNIT=", u);
555         if (!m)
556                 return log_oom();
557
558         r = sd_journal_add_match(j, m, strlen(m));
559         if (r < 0) {
560                 log_error("Failed to add match: %s", strerror(-r));
561                 return r;
562         }
563
564         return 0;
565 }
566
567 static int add_priorities(sd_journal *j) {
568         char match[] = "PRIORITY=0";
569         int i, r;
570
571         assert(j);
572
573         if (arg_priorities == 0xFF)
574                 return 0;
575
576         for (i = LOG_EMERG; i <= LOG_DEBUG; i++)
577                 if (arg_priorities & (1 << i)) {
578                         match[sizeof(match)-2] = '0' + i;
579
580                         r = sd_journal_add_match(j, match, strlen(match));
581                         if (r < 0) {
582                                 log_error("Failed to add match: %s", strerror(-r));
583                                 return r;
584                         }
585                 }
586
587         return 0;
588 }
589
590 static int setup_keys(void) {
591 #ifdef HAVE_GCRYPT
592         size_t mpk_size, seed_size, state_size, i;
593         uint8_t *mpk, *seed, *state;
594         ssize_t l;
595         int fd = -1, r, attr = 0;
596         sd_id128_t machine, boot;
597         char *p = NULL, *k = NULL;
598         struct FSSHeader h;
599         uint64_t n;
600
601         r = sd_id128_get_machine(&machine);
602         if (r < 0) {
603                 log_error("Failed to get machine ID: %s", strerror(-r));
604                 return r;
605         }
606
607         r = sd_id128_get_boot(&boot);
608         if (r < 0) {
609                 log_error("Failed to get boot ID: %s", strerror(-r));
610                 return r;
611         }
612
613         if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
614                      SD_ID128_FORMAT_VAL(machine)) < 0)
615                 return log_oom();
616
617         if (access(p, F_OK) >= 0) {
618                 log_error("Sealing key file %s exists already.", p);
619                 r = -EEXIST;
620                 goto finish;
621         }
622
623         if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
624                      SD_ID128_FORMAT_VAL(machine)) < 0) {
625                 r = log_oom();
626                 goto finish;
627         }
628
629         mpk_size = FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR);
630         mpk = alloca(mpk_size);
631
632         seed_size = FSPRG_RECOMMENDED_SEEDLEN;
633         seed = alloca(seed_size);
634
635         state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
636         state = alloca(state_size);
637
638         fd = open("/dev/random", O_RDONLY|O_CLOEXEC|O_NOCTTY);
639         if (fd < 0) {
640                 log_error("Failed to open /dev/random: %m");
641                 r = -errno;
642                 goto finish;
643         }
644
645         log_info("Generating seed...");
646         l = loop_read(fd, seed, seed_size, true);
647         if (l < 0 || (size_t) l != seed_size) {
648                 log_error("Failed to read random seed: %s", strerror(EIO));
649                 r = -EIO;
650                 goto finish;
651         }
652
653         log_info("Generating key pair...");
654         FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
655
656         log_info("Generating sealing key...");
657         FSPRG_GenState0(state, mpk, seed, seed_size);
658
659         assert(arg_interval > 0);
660
661         n = now(CLOCK_REALTIME);
662         n /= arg_interval;
663
664         close_nointr_nofail(fd);
665         fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
666         if (fd < 0) {
667                 log_error("Failed to open %s: %m", k);
668                 r = -errno;
669                 goto finish;
670         }
671
672         /* Enable secure remove, exclusion from dump, synchronous
673          * writing and in-place updating */
674         if (ioctl(fd, FS_IOC_GETFLAGS, &attr) < 0)
675                 log_warning("FS_IOC_GETFLAGS failed: %m");
676
677         attr |= FS_SECRM_FL|FS_NODUMP_FL|FS_SYNC_FL|FS_NOCOW_FL;
678
679         if (ioctl(fd, FS_IOC_SETFLAGS, &attr) < 0)
680                 log_warning("FS_IOC_SETFLAGS failed: %m");
681
682         zero(h);
683         memcpy(h.signature, "KSHHRHLP", 8);
684         h.machine_id = machine;
685         h.boot_id = boot;
686         h.header_size = htole64(sizeof(h));
687         h.start_usec = htole64(n * arg_interval);
688         h.interval_usec = htole64(arg_interval);
689         h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
690         h.fsprg_state_size = htole64(state_size);
691
692         l = loop_write(fd, &h, sizeof(h), false);
693         if (l < 0 || (size_t) l != sizeof(h)) {
694                 log_error("Failed to write header: %s", strerror(EIO));
695                 r = -EIO;
696                 goto finish;
697         }
698
699         l = loop_write(fd, state, state_size, false);
700         if (l < 0 || (size_t) l != state_size) {
701                 log_error("Failed to write state: %s", strerror(EIO));
702                 r = -EIO;
703                 goto finish;
704         }
705
706         if (link(k, p) < 0) {
707                 log_error("Failed to link file: %m");
708                 r = -errno;
709                 goto finish;
710         }
711
712         if (on_tty()) {
713                 fprintf(stderr,
714                         "\n"
715                         "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
716                         "the following local file. This key file is automatically updated when the\n"
717                         "sealing key is advanced. It should not be used on multiple hosts.\n"
718                         "\n"
719                         "\t%s\n"
720                         "\n"
721                         "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
722                         "at a safe location and should not be saved locally on disk.\n"
723                         "\n\t" ANSI_HIGHLIGHT_RED_ON, p);
724                 fflush(stderr);
725         }
726         for (i = 0; i < seed_size; i++) {
727                 if (i > 0 && i % 3 == 0)
728                         putchar('-');
729                 printf("%02x", ((uint8_t*) seed)[i]);
730         }
731
732         printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
733
734         if (on_tty()) {
735                 char tsb[FORMAT_TIMESPAN_MAX], *hn;
736
737                 fprintf(stderr,
738                         ANSI_HIGHLIGHT_OFF "\n"
739                         "The sealing key is automatically changed every %s.\n",
740                         format_timespan(tsb, sizeof(tsb), arg_interval));
741
742                 hn = gethostname_malloc();
743
744                 if (hn) {
745                         hostname_cleanup(hn);
746                         fprintf(stderr, "\nThe keys have been generated for host %s/" SD_ID128_FORMAT_STR ".\n", hn, SD_ID128_FORMAT_VAL(machine));
747                 } else
748                         fprintf(stderr, "\nThe keys have been generated for host " SD_ID128_FORMAT_STR ".\n", SD_ID128_FORMAT_VAL(machine));
749
750 #ifdef HAVE_QRENCODE
751                 /* If this is not an UTF-8 system don't print any QR codes */
752                 if (is_locale_utf8()) {
753                         fputs("\nTo transfer the verification key to your phone please scan the QR code below:\n\n", stderr);
754                         print_qr_code(stderr, seed, seed_size, n, arg_interval, hn, machine);
755                 }
756 #endif
757                 free(hn);
758         }
759
760         r = 0;
761
762 finish:
763         if (fd >= 0)
764                 close_nointr_nofail(fd);
765
766         if (k) {
767                 unlink(k);
768                 free(k);
769         }
770
771         free(p);
772
773         return r;
774 #else
775         log_error("Forward-secure sealing not available.");
776         return -ENOTSUP;
777 #endif
778 }
779
780 static int verify(sd_journal *j) {
781         int r = 0;
782         Iterator i;
783         JournalFile *f;
784
785         assert(j);
786
787         log_show_color(true);
788
789         HASHMAP_FOREACH(f, j->files, i) {
790                 int k;
791                 usec_t first, validated, last;
792
793 #ifdef HAVE_GCRYPT
794                 if (!arg_verify_key && JOURNAL_HEADER_SEALED(f->header))
795                         log_notice("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
796 #endif
797
798                 k = journal_file_verify(f, arg_verify_key, &first, &validated, &last, true);
799                 if (k == -EINVAL) {
800                         /* If the key was invalid give up right-away. */
801                         return k;
802                 } else if (k < 0) {
803                         log_warning("FAIL: %s (%s)", f->path, strerror(-k));
804                         r = k;
805                 } else {
806                         char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX], c[FORMAT_TIMESPAN_MAX];
807                         log_info("PASS: %s", f->path);
808
809                         if (arg_verify_key && JOURNAL_HEADER_SEALED(f->header)) {
810                                 if (validated > 0) {
811                                         log_info("=> Validated from %s to %s, final %s entries not sealed.",
812                                                  format_timestamp(a, sizeof(a), first),
813                                                  format_timestamp(b, sizeof(b), validated),
814                                                  format_timespan(c, sizeof(c), last > validated ? last - validated : 0));
815                                 } else if (last > 0)
816                                         log_info("=> No sealing yet, %s of entries not sealed.",
817                                                  format_timespan(c, sizeof(c), last - first));
818                                 else
819                                         log_info("=> No sealing yet, no entries in file.");
820                         }
821                 }
822         }
823
824         return r;
825 }
826
827 static int access_check(void) {
828
829 #ifdef HAVE_ACL
830         if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) {
831                 log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages.");
832                 return -EACCES;
833         }
834
835         if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
836                 log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off.");
837 #else
838         if (geteuid() != 0 && in_group("adm") <= 0) {
839                 log_error("No access to messages. Only users in the group 'adm' can see messages.");
840                 return -EACCES;
841         }
842 #endif
843
844         return 0;
845 }
846
847 int main(int argc, char *argv[]) {
848         int r;
849         sd_journal *j = NULL;
850         bool need_seek = false;
851         sd_id128_t previous_boot_id;
852         bool previous_boot_id_valid = false, first_line = true;
853         int n_shown = 0;
854
855         setlocale(LC_ALL, "");
856         log_parse_environment();
857         log_open();
858
859         r = parse_argv(argc, argv);
860         if (r <= 0)
861                 goto finish;
862
863         signal(SIGWINCH, columns_lines_cache_reset);
864
865         if (arg_action == ACTION_NEW_ID128) {
866                 r = generate_new_id128();
867                 goto finish;
868         }
869
870         if (arg_action == ACTION_SETUP_KEYS) {
871                 r = setup_keys();
872                 goto finish;
873         }
874
875         if (arg_action == ACTION_LIST_CATALOG)  {
876                 r = catalog_list(stdout);
877                 if (r < 0)
878                         log_error("Failed to list catalog: %s", strerror(-r));
879                 goto finish;
880         }
881
882         if (arg_action == ACTION_UPDATE_CATALOG)  {
883                 r = catalog_update();
884                 goto finish;
885         }
886
887         r = access_check();
888         if (r < 0)
889                 goto finish;
890
891         if (arg_directory)
892                 r = sd_journal_open_directory(&j, arg_directory, 0);
893         else
894                 r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
895         if (r < 0) {
896                 log_error("Failed to open journal: %s", strerror(-r));
897                 goto finish;
898         }
899
900         if (arg_action == ACTION_VERIFY) {
901                 r = verify(j);
902                 goto finish;
903         }
904
905         if (arg_action == ACTION_PRINT_HEADER) {
906                 journal_print_header(j);
907                 r = 0;
908                 goto finish;
909         }
910
911         if (arg_action == ACTION_DISK_USAGE) {
912                 uint64_t bytes;
913                 char sbytes[FORMAT_BYTES_MAX];
914
915                 r = sd_journal_get_usage(j, &bytes);
916                 if (r < 0)
917                         goto finish;
918
919                 printf("Journals take up %s on disk.\n", format_bytes(sbytes, sizeof(sbytes), bytes));
920                 r = 0;
921                 goto finish;
922         }
923
924         r = add_this_boot(j);
925         if (r < 0)
926                 goto finish;
927
928         r = add_unit(j);
929         if (r < 0)
930                 goto finish;
931
932         r = add_matches(j, argv + optind);
933         if (r < 0)
934                 goto finish;
935
936         r = add_priorities(j);
937         if (r < 0)
938                 goto finish;
939
940         /* Opening the fd now means the first sd_journal_wait() will actually wait */
941         r = sd_journal_get_fd(j);
942         if (r < 0)
943                 goto finish;
944
945         if (arg_field) {
946                 const void *data;
947                 size_t size;
948
949                 r = sd_journal_query_unique(j, arg_field);
950                 if (r < 0) {
951                         log_error("Failed to query unique data objects: %s", strerror(-r));
952                         goto finish;
953                 }
954
955                 SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
956                         const void *eq;
957
958                         if (arg_lines >= 0 && n_shown >= arg_lines)
959                                 break;
960
961                         eq = memchr(data, '=', size);
962                         if (eq)
963                                 printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
964                         else
965                                 printf("%.*s\n", (int) size, (const char*) data);
966
967                         n_shown ++;
968                 }
969
970                 r = 0;
971                 goto finish;
972         }
973
974         if (arg_cursor) {
975                 r = sd_journal_seek_cursor(j, arg_cursor);
976                 if (r < 0) {
977                         log_error("Failed to seek to cursor: %s", strerror(-r));
978                         goto finish;
979                 }
980
981                 r = sd_journal_next(j);
982
983         } else if (arg_since_set) {
984                 r = sd_journal_seek_realtime_usec(j, arg_since);
985                 if (r < 0) {
986                         log_error("Failed to seek to date: %s", strerror(-r));
987                         goto finish;
988                 }
989                 r = sd_journal_next(j);
990
991         } else if (arg_lines >= 0) {
992                 r = sd_journal_seek_tail(j);
993                 if (r < 0) {
994                         log_error("Failed to seek to tail: %s", strerror(-r));
995                         goto finish;
996                 }
997
998                 r = sd_journal_previous_skip(j, arg_lines);
999
1000         } else {
1001                 r = sd_journal_seek_head(j);
1002                 if (r < 0) {
1003                         log_error("Failed to seek to head: %s", strerror(-r));
1004                         goto finish;
1005                 }
1006
1007                 r = sd_journal_next(j);
1008         }
1009
1010         if (r < 0) {
1011                 log_error("Failed to iterate through journal: %s", strerror(-r));
1012                 goto finish;
1013         }
1014
1015         if (!arg_no_pager && !arg_follow)
1016                 pager_open();
1017
1018         if (!arg_quiet) {
1019                 usec_t start, end;
1020                 char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX];
1021
1022                 r = sd_journal_get_cutoff_realtime_usec(j, &start, &end);
1023                 if (r < 0) {
1024                         log_error("Failed to get cutoff: %s", strerror(-r));
1025                         goto finish;
1026                 }
1027
1028                 if (r > 0) {
1029                         if (arg_follow)
1030                                 printf("-- Logs begin at %s. --\n",
1031                                        format_timestamp(start_buf, sizeof(start_buf), start));
1032                         else
1033                                 printf("-- Logs begin at %s, end at %s. --\n",
1034                                        format_timestamp(start_buf, sizeof(start_buf), start),
1035                                        format_timestamp(end_buf, sizeof(end_buf), end));
1036                 }
1037         }
1038
1039         for (;;) {
1040                 while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) {
1041                         int flags;
1042
1043                         if (need_seek) {
1044                                 r = sd_journal_next(j);
1045                                 if (r < 0) {
1046                                         log_error("Failed to iterate through journal: %s", strerror(-r));
1047                                         goto finish;
1048                                 }
1049                         }
1050
1051                         if (r == 0)
1052                                 break;
1053
1054                         if (arg_until_set) {
1055                                 usec_t usec;
1056
1057                                 r = sd_journal_get_realtime_usec(j, &usec);
1058                                 if (r < 0) {
1059                                         log_error("Failed to determine timestamp: %s", strerror(-r));
1060                                         goto finish;
1061                                 }
1062                         }
1063
1064                         if (!arg_merge) {
1065                                 sd_id128_t boot_id;
1066
1067                                 r = sd_journal_get_monotonic_usec(j, NULL, &boot_id);
1068                                 if (r >= 0) {
1069                                         if (previous_boot_id_valid &&
1070                                             !sd_id128_equal(boot_id, previous_boot_id))
1071                                                 printf(ANSI_HIGHLIGHT_ON "-- Reboot --" ANSI_HIGHLIGHT_OFF "\n");
1072
1073                                         previous_boot_id = boot_id;
1074                                         previous_boot_id_valid = true;
1075                                 }
1076                         }
1077
1078                         flags =
1079                                 arg_all * OUTPUT_SHOW_ALL |
1080                                 (arg_full || !on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
1081                                 on_tty() * OUTPUT_COLOR |
1082                                 arg_catalog * OUTPUT_CATALOG;
1083
1084                         r = output_journal(stdout, j, arg_output, 0, flags);
1085                         if (r < 0 || ferror(stdout))
1086                                 goto finish;
1087
1088                         need_seek = true;
1089                         n_shown++;
1090                 }
1091
1092                 if (!arg_follow)
1093                         break;
1094
1095                 r = sd_journal_wait(j, (uint64_t) -1);
1096                 if (r < 0) {
1097                         log_error("Couldn't wait for journal event: %s", strerror(-r));
1098                         goto finish;
1099                 }
1100
1101                 first_line = false;
1102         }
1103
1104 finish:
1105         if (j)
1106                 sd_journal_close(j);
1107
1108         pager_close();
1109
1110         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1111 }