On Fri, Mar 11, 2011 at 8:35 PM, Lennart Poettering
<lenn...@poettering.net> wrote:
> On Fri, 11.03.11 19:41, Andrey Borzenkov (arvidj...@mail.ru) wrote:
>
>> Well ... the problem really is that format is supposed to be single
>> printable character, which does not really support bit operations and
>> such. What about attached (completely untested) path - which adds <u>
>> marker to anything written into /dev/kmsg?
>
> Please don't do this. Let's not invent new interfaces here. Let's just
> stick to traditional syslog which is perfectly capable of handling this,
> because it allows for a full 8bit number between < and > which is 3 bits
> priority plus 5 bits facility.
>
> Then, let's fix the kernel side of kmsg to implicitly add in LOG_USER as
> facility for everything coming in from /dev/kmsg that has has facility=0
> set.
>
> Basically what Kay suggested.
>
> Facilities might not be the most powerful idea ever invented, but they
> are useful to distuingish kernel from userspace messages, as there is
> LOG_KERNEL for the former and all other facilities for the latter.
>

Attached patch preserves full syslog facility marker and simply emits
it back. So userspace is free to feed any facility it deems
appropriate, not only LOG_USER.

Compile tested only.

read_priority shamelessly borrowed from systemd :)
From: Andrey Borzenkov <arvidj...@gmail.com>
Subject: [PATCH] support full syslog facility+priority in printk

Add support for parsing full syslog facility+priority marker.
This allows early boot userspace to inject log messages with
correct facility so that these can be later processed by syslog
according to real source, and not misinterpreted as originated in kernel.

---
 kernel/printk.c |  106 +++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 79 insertions(+), 27 deletions(-)

diff --git a/kernel/printk.c b/kernel/printk.c
index 3623152..7534158 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -515,6 +515,54 @@ static void _call_console_drivers(unsigned start,
 }
 
 /*
+ * Parse full syslog prefix and extract priority. Returns length of prefix
+ * or 0 if prefix is invalid
+ */
+static int read_priority(const char *buf, int *priority) {
+	const char *p = buf;
+	int a = 0, b = 0, c = 0;
+	int r, len;
+
+	if (*p++ != '<')
+		return 0;
+
+	if ((*p == 'd' || *p == 'c') && p[1] == '>') {
+		r = *p;
+		len = 3;
+		goto out;
+	}
+
+	if (*p >= '0' && *p <= '9')
+		c = *p++ - '0';
+	else
+		return 0;
+
+	if (*p >= '0' && *p <= '9') {
+		b = c;
+		c = *p++ - '0';
+	} else
+		return 0;
+
+	if (*p >= '0' && *p <= '9') {
+		a = b;
+		b = c;
+		c = *p++ - '0';
+	} else
+		return 0;
+
+	if (*p++ != '>')
+		return 0;
+
+	r = '0' + ((100*a + 10*b + c) & 7);
+	len = p - buf;
+
+out:
+	if (priority)
+		*priority = r;
+	return len;
+}
+
+/*
  * Call the console drivers, asking them to write out
  * log_buf[start] to log_buf[end - 1].
  * The console_lock must be held.
@@ -529,13 +577,12 @@ static void call_console_drivers(unsigned start, unsigned end)
 	cur_index = start;
 	start_print = start;
 	while (cur_index != end) {
-		if (msg_level < 0 && ((end - cur_index) > 2) &&
-				LOG_BUF(cur_index + 0) == '<' &&
-				LOG_BUF(cur_index + 1) >= '0' &&
-				LOG_BUF(cur_index + 1) <= '7' &&
-				LOG_BUF(cur_index + 2) == '>') {
-			msg_level = LOG_BUF(cur_index + 1) - '0';
-			cur_index += 3;
+		int plen, prio;
+
+		plen = read_priority(&LOG_BUF(cur_index), &prio);
+		if (plen && prio != 'd' && prio != 'c') {
+			msg_level = prio - '0';
+			cur_index += plen;
 			start_print = cur_index;
 		}
 		while (cur_index != end) {
@@ -733,6 +780,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 	unsigned long flags;
 	int this_cpu;
 	char *p;
+	int plen, prio;
 
 	boot_delay_msec();
 	printk_delay();
@@ -777,24 +825,21 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 	p = printk_buf;
 
 	/* Do we have a loglevel in the string? */
-	if (p[0] == '<') {
-		unsigned char c = p[1];
-		if (c && p[2] == '>') {
-			switch (c) {
-			case '0' ... '7': /* loglevel */
-				current_log_level = c - '0';
-			/* Fallthrough - make sure we're on a new line */
-			case 'd': /* KERN_DEFAULT */
-				if (!new_text_line) {
-					emit_log_char('\n');
-					new_text_line = 1;
-				}
-			/* Fallthrough - skip the loglevel */
-			case 'c': /* KERN_CONT */
-				p += 3;
-				break;
+	if ((plen = read_priority(p, &prio))) {
+		switch (prio) {
+		case '0' ... '7': /* loglevel */
+			current_log_level = prio - '0';
+		/* Fallthrough - make sure we're on a new line */
+		case 'd': /* KERN_DEFAULT */
+			if (!new_text_line) {
+				emit_log_char('\n');
+				new_text_line = 1;
 			}
+		/* Fallthrough - skip the loglevel */
+		case 'c': /* KERN_CONT */
+			break;
 		}
+		p += plen;
 	}
 
 	/*
@@ -804,10 +849,17 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 	for ( ; *p; p++) {
 		if (new_text_line) {
 			/* Always output the token */
-			emit_log_char('<');
-			emit_log_char(current_log_level + '0');
-			emit_log_char('>');
-			printed_len += 3;
+			if (plen && prio != 'd' && prio != 'c') {
+				int i;
+				for (i = 0; i < plen; i++)
+					emit_log_char(printk_buf[i]);
+				printed_len += plen;
+			} else {
+				emit_log_char('<');
+				emit_log_char(current_log_level + '0');
+				emit_log_char('>');
+				printed_len += 3;
+			}
 			new_text_line = 0;
 
 			if (printk_time) {
-- 
tg: (9179746..) u/user-printk (depends on: origin/master)
_______________________________________________
systemd-devel mailing list
systemd-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/systemd-devel

Reply via email to