#include "journal-authenticate.h"
#include "journal-qrcode.h"
#include "fsprg.h"
+#include "unit-name.h"
#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
static OutputMode arg_output = OUTPUT_SHORT;
static bool arg_follow = false;
-static bool arg_show_all = false;
+static bool arg_all = false;
static bool arg_no_pager = false;
static unsigned arg_lines = 0;
static bool arg_no_tail = false;
#endif
static usec_t arg_since, arg_until;
static bool arg_since_set = false, arg_until_set = false;
+static const char *arg_unit = NULL;
+static const char *arg_field = NULL;
static enum {
ACTION_SHOW,
static int help(void) {
- printf("%s [OPTIONS...] [MATCH]\n\n"
- "Send control commands to or query the journal.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --no-pager Do not pipe output into a pager\n"
- " -a --all Show all fields, including long and unprintable\n"
- " -c --cursor=CURSOR Start showing entries from specified cursor\n"
+ printf("%s [OPTIONS...] [MATCHES...]\n\n"
+ "Query the journal.\n\n"
+ "Flags:\n"
" --since=DATE Start showing entries newer or of the specified date\n"
" --until=DATE Stop showing entries older or of the specified date\n"
+ " -c --cursor=CURSOR Start showing entries from specified cursor\n"
+ " -b --this-boot Show data only from current boot\n"
+ " -u --unit=UNIT Show data only from the specified unit\n"
+ " -p --priority=RANGE Show only messages within the specified priority range\n"
" -f --follow Follow journal\n"
" -n --lines[=INTEGER] Number of journal entries to show\n"
" --no-tail Show all lines, even in follow mode\n"
" -o --output=STRING Change journal output mode (short, short-monotonic,\n"
" verbose, export, json, json-pretty, json-sse, cat)\n"
+ " -a --all Show all fields, including long and unprintable\n"
" -q --quiet Don't show privilege warning\n"
+ " --no-pager Do not pipe output into a pager\n"
" -m --merge Show entries from all available journals\n"
- " -b --this-boot Show data only from current boot\n"
" -D --directory=PATH Show journal files from directory\n"
- " -p --priority=RANGE Show only messages within the specified priority range\n\n"
- "Commands:\n"
+#ifdef HAVE_GCRYPT
+ " --interval=TIME Time interval for changing the FSS sealing key\n"
+ " --verify-key=KEY Specify FSS verification key\n"
+#endif
+ "\nCommands:\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
" --new-id128 Generate a new 128 Bit ID\n"
" --header Show journal header information\n"
" --disk-usage Show total disk usage\n"
+ " -F --field=FIELD List all values a certain field takes\n"
#ifdef HAVE_GCRYPT
" --setup-keys Generate new FSS key pair\n"
- " --interval=TIME Time interval for changing the FSS sealing key\n"
" --verify Verify journal file consistency\n"
- " --verify-key=KEY Specify FSS verification key\n"
#endif
, program_invocation_short_name);
{ "cursor", required_argument, NULL, 'c' },
{ "since", required_argument, NULL, ARG_SINCE },
{ "until", required_argument, NULL, ARG_UNTIL },
+ { "unit", required_argument, NULL, 'u' },
+ { "field", required_argument, NULL, 'F' },
{ NULL, 0, NULL, 0 }
};
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:", options, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "hfo:an::qmbD:p:c:u:F:", options, NULL)) >= 0) {
switch (c) {
case 'f':
arg_follow = true;
- signal(SIGWINCH, columns_cache_reset);
break;
case 'o':
break;
case 'a':
- arg_show_all = true;
+ arg_all = true;
break;
case 'n':
arg_until_set = true;
break;
+ case 'u':
+ arg_unit = optarg;
+ break;
+
case '?':
return -EINVAL;
+ case 'F':
+ arg_field = optarg;
+ break;
+
default:
log_error("Unknown option code %c", c);
return -EINVAL;
return 1;
}
-static bool on_tty(void) {
- static int t = -1;
-
- /* Note that this is invoked relatively early, before we start
- * the pager. That means the value we return reflects whether
- * we originally were started on a tty, not if we currently
- * are. But this is intended, since we want colour and so on
- * when run in our own pager. */
-
- if (_unlikely_(t < 0))
- t = isatty(STDOUT_FILENO) > 0;
-
- return t;
-}
-
static int generate_new_id128(void) {
sd_id128_t id;
int r;
return 0;
}
+static int add_unit(sd_journal *j) {
+ _cleanup_free_ char *m = NULL, *u = NULL;
+ int r;
+
+ assert(j);
+
+ if (isempty(arg_unit))
+ return 0;
+
+ u = unit_name_mangle(arg_unit);
+ if (!u)
+ return log_oom();
+
+ m = strappend("_SYSTEMD_UNIT=", u);
+ if (!m)
+ return log_oom();
+
+ r = sd_journal_add_match(j, m, strlen(m));
+ if (r < 0) {
+ log_error("Failed to add match: %s", strerror(-r));
+ return r;
+ }
+
+ return 0;
+}
+
static int add_priorities(sd_journal *j) {
char match[] = "PRIORITY=0";
int i, r;
if (arg_priorities & (1 << i)) {
match[sizeof(match)-2] = '0' + i;
- log_info("adding match %s", match);
-
r = sd_journal_add_match(j, match, strlen(match));
if (r < 0) {
log_error("Failed to add match: %s", strerror(-r));
goto finish;
}
- if (isatty(STDOUT_FILENO)) {
+ if (on_tty()) {
fprintf(stderr,
"\n"
"The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
- if (isatty(STDOUT_FILENO)) {
+ if (on_tty()) {
char tsb[FORMAT_TIMESPAN_MAX], *hn;
fprintf(stderr,
return r;
}
+static int access_check(void) {
+
+#ifdef HAVE_ACL
+ if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) {
+ log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages.");
+ return -EACCES;
+ }
+
+ if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
+ log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off.");
+#else
+ if (geteuid() != 0 && in_group("adm") <= 0) {
+ log_error("No access to messages. Only users in the group 'adm' can see messages.");
+ return -EACCES;
+ }
+#endif
+
+ return 0;
+}
+
int main(int argc, char *argv[]) {
int r;
sd_journal *j = NULL;
bool need_seek = false;
sd_id128_t previous_boot_id;
bool previous_boot_id_valid = false;
- bool have_pager;
unsigned n_shown = 0;
log_parse_environment();
if (r <= 0)
goto finish;
+ signal(SIGWINCH, columns_lines_cache_reset);
+
if (arg_action == ACTION_NEW_ID128) {
r = generate_new_id128();
goto finish;
goto finish;
}
+ r = access_check();
+ if (r < 0)
+ goto finish;
+
if (arg_directory)
r = sd_journal_open_directory(&j, arg_directory, 0);
else
r = sd_journal_open(&j, arg_merge ? 0 : SD_JOURNAL_LOCAL_ONLY);
-
if (r < 0) {
log_error("Failed to open journal: %s", strerror(-r));
goto finish;
goto finish;
}
-#ifdef HAVE_ACL
- if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("adm") <= 0) {
- log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'adm' can always see messages.");
- r = -EACCES;
- goto finish;
- }
-
- if (!arg_quiet && geteuid() != 0 && in_group("adm") <= 0)
- log_warning("Showing user generated messages only. Users in the group 'adm' can see all messages. Pass -q to turn this notice off.");
-#else
- if (geteuid() != 0 && in_group("adm") <= 0) {
- log_error("No access to messages. Only users in the group 'adm' can see messages.");
- r = -EACCES;
+ r = add_this_boot(j);
+ if (r < 0)
goto finish;
- }
-#endif
- r = add_this_boot(j);
+ r = add_unit(j);
if (r < 0)
goto finish;
if (r < 0)
goto finish;
+ if (arg_field) {
+ const void *data;
+ size_t size;
+
+ r = sd_journal_query_unique(j, arg_field);
+ if (r < 0) {
+ log_error("Failed to query unique data objects: %s", strerror(-r));
+ goto finish;
+ }
+
+ SD_JOURNAL_FOREACH_UNIQUE(j, data, size) {
+ const void *eq;
+
+ if (arg_lines > 0 && n_shown >= arg_lines)
+ break;
+
+ eq = memchr(data, '=', size);
+ if (eq)
+ printf("%.*s\n", (int) (size - ((const uint8_t*) eq - (const uint8_t*) data + 1)), (const char*) eq + 1);
+ else
+ printf("%.*s\n", (int) size, (const char*) data);
+
+ n_shown ++;
+ }
+
+ r = 0;
+ goto finish;
+ }
+
if (arg_cursor) {
r = sd_journal_seek_cursor(j, arg_cursor);
if (r < 0) {
goto finish;
}
- on_tty();
- have_pager = !arg_no_pager && !arg_follow && pager_open();
+ if (!arg_no_pager && !arg_follow)
+ pager_open();
if (!arg_quiet) {
usec_t start, end;
}
flags =
- arg_show_all * OUTPUT_SHOW_ALL |
- have_pager * OUTPUT_FULL_WIDTH |
+ arg_all * OUTPUT_SHOW_ALL |
+ (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
on_tty() * OUTPUT_COLOR;
r = output_journal(stdout, j, arg_output, 0, flags);