summaryrefslogtreecommitdiffstats
path: root/sys-utils/dmesg.c
diff options
context:
space:
mode:
authorKarel Zak2011-07-13 15:00:49 +0200
committerKarel Zak2011-07-13 15:00:49 +0200
commitb8300c0a1e744a4f958e2edd1ab2208c13fbbec2 (patch)
treef28382d8625afae902f5e87da6710acd165ac9fd /sys-utils/dmesg.c
parentbuild-sys: fix spaces versus tabs conflict (diff)
downloadkernel-qcow2-util-linux-b8300c0a1e744a4f958e2edd1ab2208c13fbbec2.tar.gz
kernel-qcow2-util-linux-b8300c0a1e744a4f958e2edd1ab2208c13fbbec2.tar.xz
kernel-qcow2-util-linux-b8300c0a1e744a4f958e2edd1ab2208c13fbbec2.zip
dmesg: don't print non-printable chars, parse records
All non-printable chars, non-printable multibyte sequences or invalid multibyte sequences will be replaced with \x<hex> strings. Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/dmesg.c')
-rw-r--r--sys-utils/dmesg.c111
1 files changed, 99 insertions, 12 deletions
diff --git a/sys-utils/dmesg.c b/sys-utils/dmesg.c
index 94309fd59..6be07afe6 100644
--- a/sys-utils/dmesg.c
+++ b/sys-utils/dmesg.c
@@ -23,6 +23,8 @@
#include "nls.h"
#include "strutils.h"
#include "xalloc.h"
+#include "widechar.h"
+#include "writeall.h"
/* Close the log. Currently a NOP. */
#define SYSLOG_ACTION_CLOSE 0
@@ -68,7 +70,9 @@ static const struct dmesg_name level_names[] =
};
/* dmesg flags */
-#define DMESG_FL_RAW (1 << 1)
+#define DMESG_FL_RAW (1 << 1)
+#define DMESG_FL_LEVEL (1 << 2)
+#define DMESG_FL_FACILITY (1 << 3)
static void __attribute__((__noreturn__)) usage(FILE *out)
{
@@ -152,25 +156,108 @@ static int read_buffer(char **buf, size_t bufsize, int clear)
return rc;
}
+static int fwrite_hex(const char *buf, size_t size, FILE *out)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ int rc = fprintf(out, "\\x%02x", buf[i]);
+ if (rc < 0)
+ return rc;
+ }
+ return 0;
+}
+
+static void safe_fwrite(const char *buf, size_t size, FILE *out)
+{
+ int i;
+#ifdef HAVE_WIDECHAR
+ mbstate_t s;
+ memset(&s, 0, sizeof (s));
+#endif
+ for (i = 0; i < size; i++) {
+ const char *p = buf + i;
+ int rc, hex = 0;
+
+#ifdef HAVE_WIDECHAR
+ wchar_t wc;
+ size_t len = mbrtowc(&wc, p, size - i, &s);
+
+ if (len == 0) /* L'\0' */
+ return;
+
+ if (len < 0) { /* invalid sequence */
+ memset(&s, 0, sizeof (s));
+ len = hex = 1;
+
+ } else if (len > 1 && !iswprint(wc)) { /* non-printable multibyte */
+ hex = 1;
+ } else
+#endif
+ {
+ if (!isprint((unsigned int) *p) &&
+ !isspace((unsigned int) *p)) /* non-printable */
+ hex = 1;
+ }
+ if (hex)
+ rc = fwrite_hex(p, len, out);
+ else
+ rc = write_all(fileno(out), p, len);
+ if (rc != 0)
+ err(EXIT_FAILURE, _("write failed"));
+ }
+}
+
static void print_buffer(const char *buf, size_t size, int flags)
{
- int lastc = '\n';
int i;
+ const char *begin = NULL;
+
+ if (flags & DMESG_FL_RAW) {
+ /* print whole buffer */
+ safe_fwrite(buf, size, stdout);
+ if (buf[size - 1] != '\n')
+ putchar('\n');
+ return;
+ }
for (i = 0; i < size; i++) {
- if (!(flags & DMESG_FL_RAW) &&
- (i == 0 || buf[i - 1] == '\n') && buf[i] == '<') {
+ const char *p = buf + i, *end = NULL;
+
+ if (!begin)
+ begin = p;
+ if (*p == '\n')
+ end = p;
+ if (i + 1 == size) {
+ end = p + 1;
i++;
- while (isdigit(buf[i]))
- i++;
- if (buf[i] == '>')
- i++;
}
- lastc = buf[i];
- putchar(lastc);
+ if (!begin || !end)
+ continue;
+ if (end <= begin)
+ continue; /* error or empty line? */
+
+ if ((flags & DMESG_FL_LEVEL) || (flags & DMESG_FL_FACILITY)) {
+ /* parse facility and level */
+ ;
+ } else if (*begin == '<') {
+ /* ignore facility and level */
+ while (begin < end) {
+ begin++;
+ if (*(begin - 1) == '>')
+ break;
+ }
+ }
+
+ if (begin < end) {
+ size_t sz = end - begin;
+
+ safe_fwrite(begin, sz, stdout);
+ if (*(begin + sz - 1) != '\n')
+ putchar('\n');
+ }
+ begin = NULL;
}
- if (lastc != '\n')
- putchar('\n');
}
int main(int argc, char *argv[])