X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Flogs-show.c;h=d60e5e53081c3cdacf828dc6562ef8837f2a9390;hb=b5b46d599524341ddd7407e5dff1021af8ff5089;hp=43e42f78803cda5ca7d613514286636f5a698508;hpb=92a1fd9e95954a557d6fe27b56f5ef1b89fc2f5e;p=elogind.git diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 43e42f788..d60e5e530 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -50,12 +50,11 @@ static int parse_field(const void *data, size_t length, const char *field, char nl = length - fl; buf = malloc(nl+1); + if (!buf) + return log_oom(); + memcpy(buf, (const char*) data + fl, nl); ((char*)buf)[nl] = 0; - if (!buf) { - log_error("Out of memory"); - return -ENOMEM; - } free(*target); *target = buf; @@ -77,19 +76,27 @@ static bool shall_print(bool show_all, char *p, size_t l) { return true; } -static int output_short(sd_journal *j, unsigned line, unsigned n_columns, +static int output_short(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { int r; const void *data; size_t length; size_t n = 0; - char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL; - 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; + char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL; + 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; + const char *color_on = "", *color_off = ""; assert(j); SD_JOURNAL_FOREACH_DATA(j, data, length) { + r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); + if (r < 0) + goto finish; + else if (r > 0) + continue; + r = parse_field(data, length, "_HOSTNAME=", &hostname, &hostname_len); if (r < 0) goto finish; @@ -142,7 +149,10 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, goto finish; } - if (flags & OUTPUT_MONOTONIC_MODE) { + if (priority_len == 1 && *priority >= '0' && *priority <= '7') + p = *priority - '0'; + + if (mode == OUTPUT_SHORT_MONOTONIC) { uint64_t t; sd_id128_t boot_id; @@ -220,23 +230,33 @@ static int output_short(sd_journal *j, unsigned line, unsigned n_columns, n += fake_pid_len + 2; } + if (flags & OUTPUT_COLOR) { + if (p <= LOG_ERR) { + color_on = ANSI_HIGHLIGHT_RED_ON; + color_off = ANSI_HIGHLIGHT_OFF; + } else if (p <= LOG_NOTICE) { + color_on = ANSI_HIGHLIGHT_ON; + color_off = ANSI_HIGHLIGHT_OFF; + } + } + if (flags & OUTPUT_SHOW_ALL) - printf(": %.*s\n", (int) message_len, message); + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else if (!utf8_is_printable_n(message, message_len)) { char bytes[FORMAT_BYTES_MAX]; printf(": [%s blob data]\n", format_bytes(bytes, sizeof(bytes), message_len)); } else if ((flags & OUTPUT_FULL_WIDTH) || - (message_len + n < n_columns)) - printf(": %.*s\n", (int) message_len, message); - else if (n < n_columns) { + (message_len + n + 1 < n_columns)) + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); + else if (n < n_columns && n_columns - n - 2 >= 3) { char *e; e = ellipsize_mem(message, message_len, n_columns - n - 2, 90); if (!e) - printf(": %.*s\n", (int) message_len, message); + printf(": %s%.*s%s\n", color_on, (int) message_len, message, color_off); else - printf(": %s\n", e); + printf(": %s%s%s\n", color_on, e, color_off); free(e); } else @@ -253,21 +273,12 @@ finish: free(message); free(monotonic); free(realtime); + free(priority); return r; } -static int output_short_realtime(sd_journal *j, unsigned line, - unsigned n_columns, OutputFlags flags) { - return output_short(j, line, n_columns, flags & ~OUTPUT_MONOTONIC_MODE); -} - -static int output_short_monotonic(sd_journal *j, unsigned line, - unsigned n_columns, OutputFlags flags) { - return output_short(j, line, n_columns, flags | OUTPUT_MONOTONIC_MODE); -} - -static int output_verbose(sd_journal *j, unsigned line, +static int output_verbose(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { const void *data; size_t length; @@ -319,7 +330,7 @@ static int output_verbose(sd_journal *j, unsigned line, return 0; } -static int output_export(sd_journal *j, unsigned line, +static int output_export(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { sd_id128_t boot_id; char sid[33]; @@ -431,7 +442,7 @@ static void json_escape(const char* p, size_t l) { } } -static int output_json(sd_journal *j, unsigned line, +static int output_json(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { uint64_t realtime, monotonic; char *cursor; @@ -461,21 +472,25 @@ static int output_json(sd_journal *j, unsigned line, return r; } - if (line == 1) - fputc('\n', stdout); + if (mode == OUTPUT_JSON_PRETTY) + printf("{\n" + "\t\"__CURSOR\" : \"%s\",\n" + "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n" + "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n" + "\t\"_BOOT_ID\" : \"%s\"", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); else - fputs(",\n", stdout); - - printf("{\n" - "\t\"__CURSOR\" : \"%s\",\n" - "\t\"__REALTIME_TIMESTAMP\" : \"%llu\",\n" - "\t\"__MONOTONIC_TIMESTAMP\" : \"%llu\",\n" - "\t\"_BOOT_ID\" : \"%s\"", - cursor, - (unsigned long long) realtime, - (unsigned long long) monotonic, - sd_id128_to_string(boot_id, sid)); - + printf("{ \"__CURSOR\" : \"%s\", " + "\"__REALTIME_TIMESTAMP\" : \"%llu\", " + "\"__MONOTONIC_TIMESTAMP\" : \"%llu\", " + "\"_BOOT_ID\" : \"%s\"", + cursor, + (unsigned long long) realtime, + (unsigned long long) monotonic, + sd_id128_to_string(boot_id, sid)); free(cursor); SD_JOURNAL_FOREACH_DATA(j, data, length) { @@ -493,19 +508,25 @@ static int output_json(sd_journal *j, unsigned line, return -EINVAL; } - fputs(",\n\t", stdout); + if (mode == OUTPUT_JSON_PRETTY) + fputs(",\n\t", stdout); + else + fputs(", ", stdout); + json_escape(data, c - (const char*) data); fputs(" : ", stdout); json_escape(c + 1, length - (c - (const char*) data) - 1); } - fputs("\n}", stdout); - fflush(stdout); + if (mode == OUTPUT_JSON_PRETTY) + fputs("\n}\n", stdout); + else + fputs(" }\n", stdout); return 0; } -static int output_cat(sd_journal *j, unsigned line, +static int output_cat(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { const void *data; size_t l; @@ -527,25 +548,29 @@ static int output_cat(sd_journal *j, unsigned line, return 0; } -static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, +static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) = { - [OUTPUT_SHORT] = output_short_realtime, - [OUTPUT_SHORT_MONOTONIC] = output_short_monotonic, + [OUTPUT_SHORT] = output_short, + [OUTPUT_SHORT_MONOTONIC] = output_short, [OUTPUT_VERBOSE] = output_verbose, [OUTPUT_EXPORT] = output_export, [OUTPUT_JSON] = output_json, + [OUTPUT_JSON_PRETTY] = output_json, [OUTPUT_CAT] = output_cat }; int output_journal(sd_journal *j, OutputMode mode, unsigned line, unsigned n_columns, OutputFlags flags) { + int ret; assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); if (n_columns <= 0) n_columns = columns(); - return output_funcs[mode](j, line, n_columns, flags); + ret = output_funcs[mode](j, mode, line, n_columns, flags); + fflush(stdout); + return ret; } int show_journal_by_unit( @@ -556,7 +581,7 @@ int show_journal_by_unit( unsigned how_many, OutputFlags flags) { - char *m = NULL; + char *m1 = NULL, *m2 = NULL, *m3 = NULL; sd_journal *j = NULL; int r; unsigned line = 0; @@ -576,7 +601,9 @@ int show_journal_by_unit( if (how_many <= 0) return 0; - if (asprintf(&m, "_SYSTEMD_UNIT=%s", unit) < 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; } @@ -585,10 +612,34 @@ int show_journal_by_unit( if (r < 0) goto finish; - r = sd_journal_add_match(j, m, strlen(m)); + /* 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); if (r < 0) goto finish; @@ -671,8 +722,9 @@ int show_journal_by_unit( fputs("\n]\n", stdout); finish: - if (m) - free(m); + free(m1); + free(m2); + free(m3); if (j) sd_journal_close(j); @@ -686,6 +738,7 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { [OUTPUT_VERBOSE] = "verbose", [OUTPUT_EXPORT] = "export", [OUTPUT_JSON] = "json", + [OUTPUT_JSON_PRETTY] = "json-pretty", [OUTPUT_CAT] = "cat" };