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