]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
Introduce ply-kmsg-reader to read kernel log messages from /dev/kmsg
authorn3rdopolis <bluescreen_avenger@verizon.net>
Mon, 20 Mar 2023 02:38:26 +0000 (22:38 -0400)
committernerdopolis <bluescreen_avenger@verizon.net>
Wed, 31 May 2023 23:43:49 +0000 (19:43 -0400)
src/libply-splash-core/meson.build
src/libply-splash-core/ply-kmsg-reader.c [new file with mode: 0644]
src/libply-splash-core/ply-kmsg-reader.h [new file with mode: 0644]

index 69636b1338393562fd90af9c3034bdbf9c14e07e..bced940d3c4f074bc66c29bb14791329ef9045c0 100644 (file)
@@ -2,6 +2,7 @@ libply_splash_core_sources = files(
   'ply-boot-splash.c',
   'ply-device-manager.c',
   'ply-input-device.c',
+  'ply-kmsg-reader.c',
   'ply-keyboard.c',
   'ply-pixel-buffer.c',
   'ply-pixel-display.c',
@@ -54,6 +55,7 @@ libply_splash_core_headers = files(
   'ply-boot-splash.h',
   'ply-device-manager.h',
   'ply-input-device.h',
+  'ply-kmsg-reader.h',
   'ply-keyboard.h',
   'ply-pixel-buffer.h',
   'ply-pixel-display.h',
diff --git a/src/libply-splash-core/ply-kmsg-reader.c b/src/libply-splash-core/ply-kmsg-reader.c
new file mode 100644 (file)
index 0000000..c368ca0
--- /dev/null
@@ -0,0 +1,134 @@
+/* ply-kmsg-reader.c - kernel log message reader
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#include "ply-list.h"
+#include "ply-kmsg-reader.h"
+#include "ply-event-loop.h"
+#include "ply-logger.h"
+#include "ply-utils.h"
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+#include <ctype.h>
+
+#ifndef LOG_LINE_MAX
+#define LOG_LINE_MAX 8192
+#endif
+
+#define from_hex(c)             (isdigit (c) ? c - '0' : tolower (c) - 'a' + 10)
+
+size_t
+unhexmangle_to_buffer (const char *s,
+                       char       *buf,
+                       size_t      len)
+{
+        size_t sz = 0;
+        const char *buf0 = buf;
+
+        if (!s)
+                return 0;
+
+        while (*s && sz < len - 1) {
+                if (*s == '\\' && sz + 3 < len - 1 && s[1] == 'x' &&
+                    isxdigit (s[2]) && isxdigit (s[3])) {
+                        *buf++ = from_hex (s[2]) << 4 | from_hex (s[3]);
+                        s += 4;
+                        sz += 4;
+                } else {
+                        *buf++ = *s++;
+                        sz++;
+                }
+        }
+        *buf = '\0';
+        return buf - buf0 + 1;
+}
+
+int
+handle_kmsg_message (ply_kmsg_reader_t *kmsg_reader,
+                     int                fd)
+{
+        ssize_t bytes_read;
+        char read_buffer[LOG_LINE_MAX] = "";
+
+        bytes_read = read (fd, read_buffer, sizeof(read_buffer) - 1);
+        if (bytes_read > 0) {
+                char *fields, *field_prefix, *field_sequence, *field_timestamp, *message, *message_substr, *msgptr, *saveptr;
+                int prefix, priority, facility;
+                uint64_t sequence;
+                unsigned long long timestamp;
+                kmsg_message_t *kmsg_message;
+
+                fields = strtok_r (read_buffer, ";", &message);
+
+                /* Messages end in \n, any following lines are machine readable. Actual multiline messages are expanded with unhexmangle_to_buffer*/
+                msgptr = strchr (message, '\n');
+                if (*msgptr && *msgptr != '\n')
+                        msgptr--;
+
+                unhexmangle_to_buffer (message, (char *) message, msgptr - message + 1);
+
+                field_prefix = strtok_r (fields, ",", &fields);
+                field_sequence = strtok_r (fields, ",", &fields);
+                field_timestamp = strtok_r (fields, ",", &fields);
+
+                prefix = atoi (field_prefix);
+                sequence = strtoull (field_sequence, NULL, 0);
+                timestamp = strtoull (field_timestamp, NULL, 0);
+
+                if (prefix > 0) {
+                        priority = prefix & 7;
+                        facility = prefix >> 3;
+                } else {
+                        priority = LOG_INFO;
+                        facility = LOG_USER;
+                }
+
+                message_substr = strtok_r (message, "\n", &saveptr);
+                while (message_substr != NULL) {
+                        kmsg_message = calloc (1, sizeof(kmsg_message_t));
+
+                        kmsg_message->priority = priority;
+                        kmsg_message->facility = facility;
+                        kmsg_message->sequence = sequence;
+                        kmsg_message->timestamp = timestamp;
+                        kmsg_message->message = strndup (message_substr, strlen (message_substr));
+
+                        ply_trigger_pull (kmsg_reader->kmsg_trigger, kmsg_message);
+
+                        message_substr = strtok_r (NULL, "\n", &saveptr);
+                }
+
+                return 0;
+        } else {
+                ply_event_loop_stop_watching_fd (ply_event_loop_get_default (), kmsg_reader->fd_watch);
+                close (kmsg_reader->kmsg_fd);
+                return -1;
+        }
+}
+
+void
+ply_kmsg_reader_start (ply_kmsg_reader_t *kmsg_reader)
+{
+        kmsg_reader->fd_watch = ply_event_loop_watch_fd (ply_event_loop_get_default (), kmsg_reader->kmsg_fd, PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
+                                                         (ply_event_handler_t) handle_kmsg_message,
+                                                         NULL,
+                                                         kmsg_reader);
+}
diff --git a/src/libply-splash-core/ply-kmsg-reader.h b/src/libply-splash-core/ply-kmsg-reader.h
new file mode 100644 (file)
index 0000000..236a785
--- /dev/null
@@ -0,0 +1,52 @@
+/* ply-kmsg-reader.h - kernel log message reader
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+#ifndef PLY_KMSG_READER_H
+#define PLY_KMSG_READER_H
+
+#include "ply-boot-splash.h"
+#include <sys/syslog.h>
+
+typedef struct _ply_kmsg_reader ply_kmsg_reader_t;
+
+struct dmesg_name
+{
+        const char *name;
+};
+
+typedef struct
+{
+        int                priority;
+        int                facility;
+        unsigned long      sequence;
+        unsigned long long timestamp;
+        char              *message;
+} kmsg_message_t;
+
+struct _ply_kmsg_reader
+{
+        int             kmsg_fd;
+        ply_fd_watch_t *fd_watch;
+        ply_trigger_t  *kmsg_trigger;
+};
+
+#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+void ply_kmsg_reader_start (ply_kmsg_reader_t *kmsg_reader);
+#endif //PLY_HIDE_FUNCTION_DECLARATIONS
+
+#endif //PLY_KMSG_READER_H