+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
#include "stdio-util.h"
#include "string-table.h"
#include "string-util.h"
+#include "strv.h"
#include "terminal-util.h"
#include "time-util.h"
#include "utf8.h"
return 0;
}
+static int field_set_test(Set *fields, const char *name, size_t n) {
+ char *s = NULL;
+
+ if (!fields)
+ return 1;
+
+ s = strndupa(name, n);
+ if (!s)
+ return log_oom();
+
+ return set_get(fields, s) ? 1 : 0;
+}
+
static bool shall_print(const char *p, size_t l, OutputFlags flags) {
assert(p);
return true;
}
-static bool print_multiline(FILE *f, unsigned prefix, unsigned n_columns, OutputFlags flags, int priority, const char* message, size_t message_len) {
- const char *color_on = "", *color_off = "";
+static bool print_multiline(
+ FILE *f,
+ unsigned prefix,
+ unsigned n_columns,
+ OutputFlags flags,
+ int priority,
+ const char* message,
+ size_t message_len,
+ size_t highlight[2]) {
+
+ const char *color_on = "", *color_off = "", *highlight_on = "";
const char *pos, *end;
bool ellipsized = false;
int line = 0;
if (priority <= LOG_ERR) {
color_on = ANSI_HIGHLIGHT_RED;
color_off = ANSI_NORMAL;
+ highlight_on = ANSI_HIGHLIGHT;
} else if (priority <= LOG_NOTICE) {
color_on = ANSI_HIGHLIGHT;
color_off = ANSI_NORMAL;
+ highlight_on = ANSI_HIGHLIGHT_RED;
}
}
if (flags & (OUTPUT_FULL_WIDTH | OUTPUT_SHOW_ALL) ||
(prefix + len + 1 < n_columns && !tail_line)) {
- fprintf(f, "%*s%s%.*s%s\n",
- continuation * prefix, "",
- color_on, len, pos, color_off);
+ if (highlight &&
+ (size_t) (pos - message) <= highlight[0] &&
+ highlight[0] < (size_t) len) {
+
+ fprintf(f, "%*s%s%.*s",
+ continuation * prefix, "",
+ color_on, (int) highlight[0], pos);
+ fprintf(f, "%s%.*s",
+ highlight_on,
+ (int) (MIN((size_t) len, highlight[1]) - highlight[0]),
+ pos + highlight[0]);
+ if ((size_t) len > highlight[1])
+ fprintf(f, "%s%.*s",
+ color_on,
+ (int) (len - highlight[1]),
+ pos + highlight[1]);
+ fprintf(f, "%s\n", color_off);
+
+ } else
+ fprintf(f, "%*s%s%.*s%s\n",
+ continuation * prefix, "",
+ color_on, len, pos, color_off);
continue;
}
sd_journal *j,
OutputMode mode,
unsigned n_columns,
- OutputFlags flags) {
+ OutputFlags flags,
+ Set *output_fields,
+ size_t highlight[2]) {
int r;
const void *data;
PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len),
PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len),
};
+ size_t highlight_shifted[] = {highlight ? highlight[0] : 0, highlight ? highlight[1] : 0};
assert(f);
assert(j);
}
if (!(flags & OUTPUT_SHOW_ALL))
- strip_tab_ansi(&message, &message_len);
+ strip_tab_ansi(&message, &message_len, highlight_shifted);
if (priority_len == 1 && *priority >= '0' && *priority <= '7')
p = *priority - '0';
} else {
fputs(": ", f);
ellipsized |=
- print_multiline(f, n + 2, n_columns, flags, p, message, message_len);
+ print_multiline(f, n + 2, n_columns, flags, p,
+ message, message_len,
+ highlight_shifted);
}
if (flags & OUTPUT_CATALOG)
sd_journal *j,
OutputMode mode,
unsigned n_columns,
- OutputFlags flags) {
+ OutputFlags flags,
+ Set *output_fields,
+ size_t highlight[2]) {
const void *data;
size_t length;
else {
_cleanup_free_ char *value = NULL;
- r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", strlen("_SOURCE_REALTIME_TIMESTAMP="), &value, NULL);
+ r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=",
+ STRLEN("_SOURCE_REALTIME_TIMESTAMP="), &value,
+ NULL);
if (r < 0)
return r;
assert(r > 0);
}
fieldlen = c - (const char*) data;
+ r = field_set_test(output_fields, data, fieldlen);
+ if (r < 0)
+ return r;
+ if (!r)
+ continue;
+
if (flags & OUTPUT_COLOR && startswith(data, "MESSAGE=")) {
on = ANSI_HIGHLIGHT;
off = ANSI_NORMAL;
(((length < PRINT_CHAR_THRESHOLD) || flags & OUTPUT_FULL_WIDTH)
&& utf8_is_printable(data, length))) {
fprintf(f, " %s%.*s=", on, fieldlen, (const char*)data);
- print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1);
+ print_multiline(f, 4 + fieldlen + 1, 0, OUTPUT_FULL_WIDTH, 0, c + 1, length - fieldlen - 1, NULL);
fputs(off, f);
} else {
char bytes[FORMAT_BYTES_MAX];
sd_journal *j,
OutputMode mode,
unsigned n_columns,
- OutputFlags flags) {
+ OutputFlags flags,
+ Set *output_fields,
+ size_t highlight[2]) {
sd_id128_t boot_id;
char sid[33];
sd_id128_to_string(boot_id, sid));
JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
+ const char *c;
/* We already printed the boot id, from the data in
* the header, hence let's suppress it here */
startswith(data, "_BOOT_ID="))
continue;
+ c = memchr(data, '=', length);
+ if (!c) {
+ log_error("Invalid field.");
+ return -EINVAL;
+ }
+
+ r = field_set_test(output_fields, data, c - (const char *) data);
+ if (r < 0)
+ return r;
+ if (!r)
+ continue;
+
if (utf8_is_printable_newline(data, length, false))
fwrite(data, length, 1, f);
else {
- const char *c;
uint64_t le64;
- c = memchr(data, '=', length);
- if (!c) {
- log_error("Invalid field.");
- return -EINVAL;
- }
-
fwrite(data, c - (const char*) data, 1, f);
fputc('\n', f);
le64 = htole64(length - (c - (const char*) data) - 1);
sd_journal *j,
OutputMode mode,
unsigned n_columns,
- OutputFlags flags) {
+ OutputFlags flags,
+ Set *output_fields,
+ size_t highlight[2]) {
uint64_t realtime, monotonic;
_cleanup_free_ char *cursor = NULL;
if (!eq)
continue;
- if (separator) {
- if (mode == OUTPUT_JSON_PRETTY)
- fputs(",\n\t", f);
- else
- fputs(", ", f);
- }
-
m = eq - (const char*) data;
n = strndup(data, m);
goto finish;
}
+ if (output_fields && !set_get(output_fields, n)) {
+ free(n);
+ continue;
+ }
+
+ if (separator) {
+ if (mode == OUTPUT_JSON_PRETTY)
+ fputs(",\n\t", f);
+ else
+ fputs(", ", f);
+ }
+
u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
if (u == 0) {
/* We already printed this, let's jump to the next */
sd_journal *j,
OutputMode mode,
unsigned n_columns,
- OutputFlags flags) {
+ OutputFlags flags,
+ Set *output_fields,
+ size_t highlight[2]) {
const void *data;
size_t l;
int r;
+ const char *highlight_on = "", *highlight_off = "";
assert(j);
assert(f);
+ if (flags & OUTPUT_COLOR) {
+ highlight_on = ANSI_HIGHLIGHT_RED;
+ highlight_off = ANSI_NORMAL;
+ }
+
sd_journal_set_data_threshold(j, 0);
r = sd_journal_get_data(j, "MESSAGE", &data, &l);
assert(l >= 8);
- fwrite((const char*) data + 8, 1, l - 8, f);
+ if (highlight && (flags & OUTPUT_COLOR)) {
+ assert(highlight[0] <= highlight[1]);
+ assert(highlight[1] <= l - 8);
+
+ fwrite((const char*) data + 8, 1, highlight[0], f);
+ fwrite(highlight_on, 1, strlen(highlight_on), f);
+ fwrite((const char*) data + 8 + highlight[0], 1, highlight[1] - highlight[0], f);
+ fwrite(highlight_off, 1, strlen(highlight_off), f);
+ fwrite((const char*) data + 8 + highlight[1], 1, l - 8 - highlight[1], f);
+ } else
+ fwrite((const char*) data + 8, 1, l - 8, f);
fputc('\n', f);
return 0;
sd_journal*j,
OutputMode mode,
unsigned n_columns,
- OutputFlags flags) = {
+ OutputFlags flags,
+ Set *output_fields,
+ size_t highlight[2]) = {
[OUTPUT_SHORT] = output_short,
[OUTPUT_SHORT_ISO] = output_short,
OutputMode mode,
unsigned n_columns,
OutputFlags flags,
+ char **output_fields,
+ size_t highlight[2],
bool *ellipsized) {
int ret;
+ _cleanup_set_free_free_ Set *fields = NULL;
assert(mode >= 0);
assert(mode < _OUTPUT_MODE_MAX);
if (n_columns <= 0)
n_columns = columns();
- ret = output_funcs[mode](f, j, mode, n_columns, flags);
+ if (output_fields) {
+ fields = set_new(&string_hash_ops);
+ if (!fields)
+ return log_oom();
+
+ ret = set_put_strdupv(fields, output_fields);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = output_funcs[mode](f, j, mode, n_columns, flags, fields, highlight);
if (ellipsized && ret > 0)
*ellipsized = true;
line++;
maybe_print_begin_newline(f, &flags);
- r = output_journal(f, j, mode, n_columns, flags, ellipsized);
+ r = output_journal(f, j, mode, n_columns, flags, NULL, NULL, ellipsized);
if (r < 0)
return r;
}
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
pid_t pid, child;
- siginfo_t si;
char buf[37];
ssize_t k;
int r;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
- child = fork();
- if (child < 0)
- return -errno;
-
- if (child == 0) {
+ r = safe_fork("(sd-bootid)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
+ if (r < 0)
+ return r;
+ if (r == 0) {
int fd;
pair[0] = safe_close(pair[0]);
pair[1] = safe_close(pair[1]);
- r = wait_for_terminate(child, &si);
- if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
- return r < 0 ? r : -EIO;
+ r = wait_for_terminate_and_check("(sd-bootid)", child, 0);
+ if (r < 0)
+ return r;
+ if (r != EXIT_SUCCESS)
+ return -EIO;
k = recv(pair[0], buf, 36, 0);
if (k != 36)
if (r < 0)
return log_error_errno(r, "Failed to add unit matches: %m");
- if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
+ if (DEBUG_LOGGING) {
_cleanup_free_ char *filter;
filter = journal_make_match_string(j);