X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Flogs-show.c;h=034fde6624793de677ebd45b56e98444bd90eb91;hb=e3ded78be7df143ba780dd55ca8897fdddd67460;hp=36cce73550f45b4dd18a00ad42a299ccae108934;hpb=d99ae53a7327e1520ea4b9a3408c2d7f938c4b37;p=elogind.git diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 36cce7355..034fde662 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -34,6 +34,26 @@ #define PRINT_THRESHOLD 128 #define JSON_THRESHOLD 4096 +static int print_catalog(FILE *f, sd_journal *j) { + int r; + _cleanup_free_ char *t = NULL, *z = NULL; + + + r = sd_journal_get_catalog(j, &t); + if (r < 0) + return r; + + z = strreplace(strstrip(t), "\n", "\n-- "); + if (!z) + return log_oom(); + + fputs("-- ", f); + fputs(z, f); + fputc('\n', f); + + 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; void *buf; @@ -71,7 +91,7 @@ static bool shall_print(const char *p, size_t l, OutputFlags flags) { if (flags & OUTPUT_SHOW_ALL) return true; - if (l > PRINT_THRESHOLD) + if (l >= PRINT_THRESHOLD) return false; if (!utf8_is_printable_n(p, l)) @@ -99,6 +119,8 @@ static int output_short( assert(f); assert(j); + sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : PRINT_THRESHOLD); + SD_JOURNAL_FOREACH_DATA(j, data, length) { r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); @@ -157,6 +179,9 @@ static int output_short( if (!message) return 0; + if (!(flags & OUTPUT_SHOW_ALL)) + strip_tab_ansi(&message, &message_len); + if (priority_len == 1 && *priority >= '0' && *priority <= '7') p = *priority - '0'; @@ -252,7 +277,7 @@ static int output_short( } else if ((flags & OUTPUT_FULL_WIDTH) || (message_len + n + 1 < n_columns)) fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else if (n < n_columns && n_columns - n - 2 >= 3) { - char *e; + char _cleanup_free_ *e; e = ellipsize_mem(message, message_len, n_columns - n - 2, 90); @@ -260,11 +285,12 @@ static int output_short( fprintf(f, ": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else fprintf(f, ": %s%s%s\n", color_on, e, color_off); - - free(e); } else fputs("\n", f); + if (flags & OUTPUT_CATALOG) + print_catalog(f, j); + return 0; } @@ -277,7 +303,7 @@ static int output_verbose( const void *data; size_t length; - char *cursor; + char _cleanup_free_ *cursor = NULL; uint64_t realtime; char ts[FORMAT_TIMESTAMP_MAX]; int r; @@ -285,6 +311,8 @@ static int output_verbose( assert(f); assert(j); + sd_journal_set_data_threshold(j, 0); + r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) { log_error("Failed to get realtime timestamp: %s", strerror(-r)); @@ -301,8 +329,6 @@ static int output_verbose( format_timestamp(ts, sizeof(ts), realtime), cursor); - free(cursor); - SD_JOURNAL_FOREACH_DATA(j, data, length) { if (!shall_print(data, length, flags)) { const char *c; @@ -322,6 +348,9 @@ static int output_verbose( fprintf(f, "\t%.*s\n", (int) length, (const char*) data); } + if (flags & OUTPUT_CATALOG) + print_catalog(f, j); + return 0; } @@ -336,12 +365,14 @@ static int output_export( char sid[33]; int r; usec_t realtime, monotonic; - char *cursor; + char _cleanup_free_ *cursor = NULL; const void *data; size_t length; assert(j); + sd_journal_set_data_threshold(j, 0); + r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) { log_error("Failed to get realtime timestamp: %s", strerror(-r)); @@ -370,8 +401,6 @@ static int output_export( (unsigned long long) monotonic, sd_id128_to_string(boot_id, sid)); - free(cursor); - SD_JOURNAL_FOREACH_DATA(j, data, length) { /* We already printed the boot id, from the data in @@ -415,7 +444,7 @@ void json_escape( assert(f); assert(p); - if (!(flags & OUTPUT_SHOW_ALL) && l > JSON_THRESHOLD) + if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD) fputs("null", f); @@ -465,17 +494,19 @@ static int output_json( OutputFlags flags) { uint64_t realtime, monotonic; - char *cursor, *k; + char _cleanup_free_ *cursor = NULL; const void *data; size_t length; sd_id128_t boot_id; - char sid[33]; + char sid[33], *k; int r; Hashmap *h = NULL; bool done, separator; assert(j); + sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD); + r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) { log_error("Failed to get realtime timestamp: %s", strerror(-r)); @@ -519,7 +550,6 @@ static int output_json( (unsigned long long) monotonic, sd_id128_to_string(boot_id, sid)); } - free(cursor); h = hashmap_new(string_hash_func, string_compare_func); if (!h) @@ -688,6 +718,8 @@ static int output_cat( assert(j); assert(f); + sd_journal_set_data_threshold(j, 0); + r = sd_journal_get_data(j, "MESSAGE", &data, &l); if (r < 0) { /* An entry without MESSAGE=? */ @@ -742,72 +774,22 @@ int output_journal( return ret; } -int show_journal_by_unit( - FILE *f, - const char *unit, - OutputMode mode, - unsigned n_columns, - usec_t not_before, - unsigned how_many, - OutputFlags flags) { +static int show_journal(FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + OutputFlags flags) { - _cleanup_free_ char *m1 = NULL, *m2 = NULL, *m3 = NULL; - sd_journal *j = NULL; int r; unsigned line = 0; bool need_seek = false; int warn_cutoff = flags & OUTPUT_WARN_CUTOFF; + assert(j); assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); - assert(unit); - - if (!endswith(unit, ".service") && - !endswith(unit, ".socket") && - !endswith(unit, ".mount") && - !endswith(unit, ".swap")) - return 0; - - if (how_many <= 0) - return 0; - - if (asprintf(&m1, "_SYSTEMD_UNIT=%s", unit) < 0 || - asprintf(&m2, "COREDUMP_UNIT=%s", unit) < 0 || - asprintf(&m3, "UNIT=%s", unit) < 0) { - r = -ENOMEM; - goto finish; - } - - r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY); - if (r < 0) - goto finish; - - /* Look for messages from the service itself */ - r = sd_journal_add_match(j, m1, 0); - if (r < 0) - goto finish; - - /* Look for coredumps of the service */ - r = sd_journal_add_disjunction(j); - if (r < 0) - goto finish; - r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0); - if (r < 0) - goto finish; - r = sd_journal_add_match(j, m2, 0); - if (r < 0) - goto finish; - - /* Look for messages from PID 1 about this service */ - r = sd_journal_add_disjunction(j); - if (r < 0) - goto finish; - r = sd_journal_add_match(j, "_PID=1", 0); - if (r < 0) - goto finish; - r = sd_journal_add_match(j, m3, 0); - if (r < 0) - goto finish; /* Seek to end */ r = sd_journal_seek_tail(j); @@ -883,6 +865,145 @@ int show_journal_by_unit( } +finish: + return r; +} + +int show_journal_by_unit( + FILE *f, + const char *unit, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + OutputFlags flags) { + + _cleanup_free_ char *m1 = NULL, *m2 = NULL, *m3 = NULL; + sd_journal *j = NULL; + int r; + + assert(mode >= 0); + assert(mode < _OUTPUT_MODE_MAX); + assert(unit); + + if (!endswith(unit, ".service") && + !endswith(unit, ".socket") && + !endswith(unit, ".mount") && + !endswith(unit, ".swap")) + return 0; + + if (how_many <= 0) + return 0; + + if (asprintf(&m1, "_SYSTEMD_UNIT=%s", unit) < 0 || + asprintf(&m2, "COREDUMP_UNIT=%s", unit) < 0 || + asprintf(&m3, "UNIT=%s", unit) < 0) { + r = -ENOMEM; + goto finish; + } + + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY); + if (r < 0) + goto finish; + + /* Look for messages from the service itself */ + r = sd_journal_add_match(j, m1, 0); + if (r < 0) + goto finish; + + /* Look for coredumps of the service */ + r = sd_journal_add_disjunction(j); + if (r < 0) + goto finish; + r = sd_journal_add_match(j, "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1", 0); + if (r < 0) + goto finish; + r = sd_journal_add_match(j, m2, 0); + if (r < 0) + goto finish; + + /* Look for messages from PID 1 about this service */ + r = sd_journal_add_disjunction(j); + if (r < 0) + goto finish; + r = sd_journal_add_match(j, "_PID=1", 0); + if (r < 0) + goto finish; + r = sd_journal_add_match(j, m3, 0); + if (r < 0) + goto finish; + + r = show_journal(f, j, mode, n_columns, not_before, how_many, flags); + if (r < 0) + goto finish; + +finish: + if (j) + sd_journal_close(j); + + return r; +} + +int show_journal_by_user_unit( + FILE *f, + const char *unit, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + uid_t uid, + OutputFlags flags) { + + _cleanup_free_ char *m1 = NULL, *m2 = NULL, *m3 = NULL; + sd_journal *j = NULL; + int r; + + assert(mode >= 0); + assert(mode < _OUTPUT_MODE_MAX); + assert(unit); + + if (!endswith(unit, ".service") && + !endswith(unit, ".socket")) + + return 0; + + if (how_many <= 0) + return 0; + + if (asprintf(&m1, "_SYSTEMD_USER_UNIT=%s", unit) < 0 || + asprintf(&m2, "USER_UNIT=%s", unit) < 0 || + asprintf(&m3, "_UID=%d", uid) < 0) { + r = -ENOMEM; + goto finish; + } + + r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); + if (r < 0) + goto finish; + + /* Look for messages from the user service itself */ + r = sd_journal_add_match(j, m1, 0); + if (r < 0) + goto finish; + r = sd_journal_add_match(j, m3, 0); + if (r < 0) + goto finish; + + /* Look for messages from systemd about this service */ + r = sd_journal_add_disjunction(j); + if (r < 0) + goto finish; + r = sd_journal_add_match(j, m2, 0); + if (r < 0) + goto finish; + r = sd_journal_add_match(j, m3, 0); + if (r < 0) + goto finish; + + r = show_journal(f, j, mode, n_columns, not_before, how_many, flags); + if (r < 0) + goto finish; + finish: if (j) sd_journal_close(j);