diff options
Diffstat (limited to 'src/shared/logs-show.c')
-rw-r--r-- | src/shared/logs-show.c | 203 |
1 files changed, 122 insertions, 81 deletions
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 0626d80b19..afc3dcd219 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -48,6 +49,7 @@ #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" @@ -79,37 +81,76 @@ static int print_catalog(FILE *f, sd_journal *j) { return 0; } -static int parse_field(const void *data, size_t length, const char *field, char **target, size_t *target_size) { - size_t fl, nl; +static int parse_field(const void *data, size_t length, const char *field, size_t field_len, char **target, size_t *target_len) { + size_t nl; char *buf; assert(data); assert(field); assert(target); - fl = strlen(field); - if (length < fl) + if (length < field_len) return 0; - if (memcmp(data, field, fl)) + if (memcmp(data, field, field_len)) return 0; - nl = length - fl; + nl = length - field_len; - buf = newdup_suffix0(char, (const char*) data + fl, nl); + buf = newdup_suffix0(char, (const char*) data + field_len, nl); if (!buf) return log_oom(); free(*target); *target = buf; - if (target_size) - *target_size = nl; + if (target_len) + *target_len = nl; return 1; } +typedef struct ParseFieldVec { + const char *field; + size_t field_len; + char **target; + size_t *target_len; +} ParseFieldVec; + +#define PARSE_FIELD_VEC_ENTRY(_field, _target, _target_len) \ + { .field = _field, .field_len = strlen(_field), .target = _target, .target_len = _target_len } + +static int parse_fieldv(const void *data, size_t length, const ParseFieldVec *fields, unsigned n_fields) { + unsigned i; + + for (i = 0; i < n_fields; i++) { + const ParseFieldVec *f = &fields[i]; + int r; + + r = parse_field(data, length, f->field, f->field_len, f->target, f->target_len); + if (r < 0) + return r; + else if (r > 0) + break; + } + + 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); @@ -327,7 +368,8 @@ static int output_short( sd_journal *j, OutputMode mode, unsigned n_columns, - OutputFlags flags) { + OutputFlags flags, + Set *output_fields) { int r; const void *data; @@ -337,6 +379,17 @@ static int output_short( size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0; int p = LOG_INFO; bool ellipsized = false; + const ParseFieldVec fields[] = { + PARSE_FIELD_VEC_ENTRY("_PID=", &pid, &pid_len), + PARSE_FIELD_VEC_ENTRY("_COMM=", &comm, &comm_len), + PARSE_FIELD_VEC_ENTRY("MESSAGE=", &message, &message_len), + PARSE_FIELD_VEC_ENTRY("PRIORITY=", &priority, &priority_len), + PARSE_FIELD_VEC_ENTRY("_HOSTNAME=", &hostname, &hostname_len), + PARSE_FIELD_VEC_ENTRY("SYSLOG_PID=", &fake_pid, &fake_pid_len), + PARSE_FIELD_VEC_ENTRY("SYSLOG_IDENTIFIER=", &identifier, &identifier_len), + PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len), + PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len), + }; assert(f); assert(j); @@ -351,55 +404,7 @@ static int output_short( JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { - r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "SYSLOG_IDENTIFIER=", &identifier, &identifier_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_COMM=", &comm, &comm_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_PID=", &pid, &pid_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "SYSLOG_PID=", &fake_pid, &fake_pid_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len); - if (r < 0) - return r; - else if (r > 0) - continue; - - r = parse_field(data, length, "MESSAGE=", &message, &message_len); + r = parse_fieldv(data, length, fields, ELEMENTSOF(fields)); if (r < 0) return r; } @@ -477,7 +482,8 @@ static int output_verbose( sd_journal *j, OutputMode mode, unsigned n_columns, - OutputFlags flags) { + OutputFlags flags, + Set *output_fields) { const void *data; size_t length; @@ -500,7 +506,9 @@ static int output_verbose( else { _cleanup_free_ char *value = NULL; - r = parse_field(data, length, "_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); @@ -538,6 +546,12 @@ static int output_verbose( } 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; @@ -575,7 +589,8 @@ static int output_export( sd_journal *j, OutputMode mode, unsigned n_columns, - OutputFlags flags) { + OutputFlags flags, + Set *output_fields) { sd_id128_t boot_id; char sid[33]; @@ -612,6 +627,7 @@ static int output_export( 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 */ @@ -619,18 +635,23 @@ static int output_export( 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); @@ -706,7 +727,8 @@ static int output_json( sd_journal *j, OutputMode mode, unsigned n_columns, - OutputFlags flags) { + OutputFlags flags, + Set *output_fields) { uint64_t realtime, monotonic; _cleanup_free_ char *cursor = NULL; @@ -825,13 +847,6 @@ static int output_json( 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); @@ -840,6 +855,18 @@ static int output_json( 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 */ @@ -924,7 +951,8 @@ static int output_cat( sd_journal *j, OutputMode mode, unsigned n_columns, - OutputFlags flags) { + OutputFlags flags, + Set *output_fields) { const void *data; size_t l; @@ -957,7 +985,8 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])( sd_journal*j, OutputMode mode, unsigned n_columns, - OutputFlags flags) = { + OutputFlags flags, + Set *output_fields) = { [OUTPUT_SHORT] = output_short, [OUTPUT_SHORT_ISO] = output_short, @@ -980,16 +1009,28 @@ int output_journal( OutputMode mode, unsigned n_columns, OutputFlags flags, + char **output_fields, 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); if (ellipsized && ret > 0) *ellipsized = true; @@ -1071,7 +1112,7 @@ static int show_journal(FILE *f, 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, ellipsized); if (r < 0) return r; } |