#include #include #include #include #include #include enum log_flags { LOG_NOCONS = 1, /* already flushed, do not print to console */ LOG_NEWLINE = 2, /* text ended with a newline */ LOG_PREFIX = 4, /* text started with a prefix */ LOG_CONT = 8, /* text is a fragment of a continuation line */ }; struct log { uint64_t ts_nsec; /* timestamp in nanoseconds */ uint16_t len; /* length of entire record */ uint16_t text_len; /* length of text buffer */ uint16_t dict_len; /* length of dictionary buffer */ uint8_t facility; /* syslog facility */ union { struct { uint8_t flags:5; /* internal record flags */ uint8_t level:3; /* syslog level */ } normal; struct { uint8_t level:3; /* syslog level */ uint8_t flags:5; /* internal record flags */ } swapped; } fl; }; static size_t print_time(uint64_t ts) { unsigned long rem_nsec; rem_nsec = ts / 1000000000; return printf("[%5lu.%06lu] ", (unsigned long)ts, rem_nsec / 1000); } static size_t print_prefix(const struct log *msg, unsigned int level) { size_t len = 0; unsigned int prefix = (msg->facility << 3) | level; len += printf("<%u>", prefix); len += print_time(msg->ts_nsec); return len; } int main(int argc, char **argv) { bool swap = false; unsigned int prev = 0; FILE *f = stdin; /* Use getopt !!! */ argv++; argc--; while(argc) { if (!strcmp(argv[0], "--byteswap")) swap = 1; else if (!strcmp(argv[0], "--file") && (argc > 1)) { f = fopen(argv[1], "r"); argv++; argc--; } else { printf("usage: kmsg_dump [--byteswap] [--file ]\n"); exit(1); } argv++; argc--; } for (;;) { size_t sz; struct log l; unsigned int flags, level; uint8_t buf[0x10000]; bool prefix = true; bool newline = true; const char *text; unsigned int text_size; sz = fread(&l, sizeof(struct log), 1, f); if (sz != 1) exit(0); if (swap) { l.ts_nsec = bswap_64(l.ts_nsec); l.len = bswap_16(l.len); l.text_len = bswap_16(l.text_len); l.dict_len = bswap_16(l.dict_len); flags = l.fl.swapped.flags; level = l.fl.swapped.level; } else { flags = l.fl.normal.flags; level = l.fl.normal.level; } if (l.len == 0) break; sz = fread(buf, l.len - sizeof(struct log), 1, f); if (sz != 1) break; if ((prev & LOG_CONT) && !(flags & LOG_PREFIX)) prefix = false; if (flags & LOG_CONT) { if ((prev & LOG_CONT) && !(prev & LOG_NEWLINE)) prefix = false; if (!(flags & LOG_NEWLINE)) newline = false; } text = buf; text_size = l.text_len; do { char *next = memchr(text, '\n', text_size); size_t text_len; if (next) { text_len = next - text; next++; text_size -= next - text; } else { text_len = text_size; } if (prefix) print_prefix(&l, level); fwrite(text, text_len, 1, stdout); if (next || newline) printf("\n"); prefix = true; text = next; } while (text); } return 0; }