1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2012 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include "logs-show.h"
30 #define PRINT_THRESHOLD 128
32 static bool contains_unprintable(const void *p, size_t l) {
35 for (j = p; j < (const char *) p + l; j++)
36 if (*j < ' ' || *j >= 127)
42 static int output_short(sd_journal *j, unsigned line, bool show_all) {
54 r = sd_journal_get_realtime_usec(j, &realtime);
56 log_error("Failed to get realtime: %s", strerror(-r));
60 t = (time_t) (realtime / USEC_PER_SEC);
61 if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm)) <= 0) {
62 log_error("Failed to format time.");
69 if (sd_journal_get_data(j, "_HOSTNAME", &data, &length) >= 0 &&
70 (show_all || (!contains_unprintable(data, length) &&
71 length < PRINT_THRESHOLD))) {
72 printf(" %.*s", (int) length - 10, ((const char*) data) + 10);
76 if (sd_journal_get_data(j, "MESSAGE", &data, &length) >= 0) {
78 printf(" %.*s", (int) length - 8, ((const char*) data) + 8);
79 else if (contains_unprintable(data, length))
80 fputs(" [blob data]", stdout);
81 else if (length - 8 + n < columns())
82 printf(" %.*s", (int) length - 8, ((const char*) data) + 8);
83 else if (n < columns()) {
86 e = ellipsize_mem((const char *) data + 8, length - 8, columns() - n - 2, 90);
89 printf(" %.*s", (int) length - 8, ((const char*) data) + 8);
102 static int output_verbose(sd_journal *j, unsigned line, bool show_all) {
107 char ts[FORMAT_TIMESTAMP_MAX];
112 r = sd_journal_get_realtime_usec(j, &realtime);
114 log_error("Failed to get realtime timestamp: %s", strerror(-r));
118 r = sd_journal_get_cursor(j, &cursor);
120 log_error("Failed to get cursor: %s", strerror(-r));
125 format_timestamp(ts, sizeof(ts), realtime),
130 SD_JOURNAL_FOREACH_DATA(j, data, length) {
131 if (!show_all && (length > PRINT_THRESHOLD ||
132 contains_unprintable(data, length))) {
135 c = memchr(data, '=', length);
137 log_error("Invalid field.");
141 printf("\t%.*s=[blob data]\n",
142 (int) (c - (const char*) data),
145 printf("\t%.*s\n", (int) length, (const char*) data);
151 static int output_export(sd_journal *j, unsigned line, bool show_all) {
155 usec_t realtime, monotonic;
162 r = sd_journal_get_realtime_usec(j, &realtime);
164 log_error("Failed to get realtime timestamp: %s", strerror(-r));
168 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
170 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
174 r = sd_journal_get_cursor(j, &cursor);
176 log_error("Failed to get cursor: %s", strerror(-r));
180 printf(".cursor=%s\n"
185 (unsigned long long) realtime,
186 (unsigned long long) monotonic,
187 sd_id128_to_string(boot_id, sid));
191 SD_JOURNAL_FOREACH_DATA(j, data, length) {
193 if (contains_unprintable(data, length)) {
197 c = memchr(data, '=', length);
199 log_error("Invalid field.");
203 fwrite(data, c - (const char*) data, 1, stdout);
205 le64 = htole64(length - (c - (const char*) data) - 1);
206 fwrite(&le64, sizeof(le64), 1, stdout);
207 fwrite(c + 1, length - (c - (const char*) data) - 1, 1, stdout);
209 fwrite(data, length, 1, stdout);
219 static void json_escape(const char* p, size_t l) {
221 if (contains_unprintable(p, l)) {
222 bool not_first = false;
228 printf(", %u", (uint8_t) *p);
231 printf("%u", (uint8_t) *p);
243 if (*p == '"' || *p == '\\') {
257 static int output_json(sd_journal *j, unsigned line, bool show_all) {
258 uint64_t realtime, monotonic;
268 r = sd_journal_get_realtime_usec(j, &realtime);
270 log_error("Failed to get realtime timestamp: %s", strerror(-r));
274 r = sd_journal_get_monotonic_usec(j, &monotonic, &boot_id);
276 log_error("Failed to get monotonic timestamp: %s", strerror(-r));
280 r = sd_journal_get_cursor(j, &cursor);
282 log_error("Failed to get cursor: %s", strerror(-r));
289 fputs(",\n", stdout);
292 "\t\".cursor\" : \"%s\",\n"
293 "\t\".realtime\" : %llu,\n"
294 "\t\".monotonic\" : %llu,\n"
295 "\t\".boot_id\" : \"%s\"",
297 (unsigned long long) realtime,
298 (unsigned long long) monotonic,
299 sd_id128_to_string(boot_id, sid));
303 SD_JOURNAL_FOREACH_DATA(j, data, length) {
306 c = memchr(data, '=', length);
308 log_error("Invalid field.");
312 fputs(",\n\t", stdout);
313 json_escape(data, c - (const char*) data);
314 fputs(" : ", stdout);
315 json_escape(c + 1, length - (c - (const char*) data) - 1);
318 fputs("\n}", stdout);
324 static int (*output_funcs[_OUTPUT_MODE_MAX])(sd_journal*j, unsigned line, bool show_all) = {
325 [OUTPUT_SHORT] = output_short,
326 [OUTPUT_VERBOSE] = output_verbose,
327 [OUTPUT_EXPORT] = output_export,
328 [OUTPUT_JSON] = output_json
331 int output_journal(sd_journal *j, output_mode mode, unsigned line, bool show_all) {
332 assert(mode < _OUTPUT_MODE_MAX);
334 return output_funcs[mode](j, line, show_all);
337 int show_journal_by_service(
354 n_columns = columns();
362 if (asprintf(&m, "_SYSTEMD_SERVICE=%s", service) < 0) {
367 r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY|SD_JOURNAL_SYSTEM_ONLY);
371 r = sd_journal_add_match(j, m, strlen(m));
375 r = sd_journal_seek_tail(j);
379 for (i = 0; i < how_many; i++)
380 sd_journal_previous(j);
382 for (i = 0; i < how_many; i++) {
384 r = sd_journal_next(j);
391 r = output_journal(j, mode, i+1, show_all);