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