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