Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package blog for openSUSE:Factory checked in 
at 2026-06-22 18:05:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/blog (Old)
 and      /work/SRC/openSUSE:Factory/.blog.new.1956 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "blog"

Mon Jun 22 18:05:38 2026 rev:26 rq:1361156 version:2.42

Changes:
--------
--- /work/SRC/openSUSE:Factory/blog/blog.changes        2026-04-25 
21:35:28.977163119 +0200
+++ /work/SRC/openSUSE:Factory/.blog.new.1956/blog.changes      2026-06-22 
18:06:08.266702816 +0200
@@ -1,0 +2,45 @@
+Mon Jun 22 13:48:12 UTC 2026 - Dr. Werner Fink <[email protected]>
+
+- Update to version 2.42
+  Fix possible memory leaks, eliminate type punning, and resolve I/O blocking
+  This update implements a series of systemic improvements to stability,
+  security, and performance:
+  1. Memory Safety & Leak Resolution:
+     - Implemented lcons_shutdown destructor to automatically purge the console
+       list and close FDs on exit.
+     - Fixed password buffer leak by using in closeIO, correctly matching
+       the mmap allocation in shm_malloc.
+     - Added cleanup for pwprompt in closeIO.
+  2. Elimination of Dangerous Type Punning:
+     - Replaced the unreliable &cons->node pattern with a type-safe list_t 
lcons
+       sentinel across the codebase.
+     - Added __attribute__((may_alias)) to list_t in listing.h to prevent
+       compiler strict aliasing optimizations from corrupting list traversals.
+  3. I/O Responsiveness & Stability:
+     - Removed tcdrain() from the high-frequency epoll_console_in path to
+       eliminate daemon freezes during heavy output.
+     - Updated consinitIO to ensure CON_SERIAL devices remain in O_NONBLOCK
+       mode, preventing freezes on slow serial lines.
+     - Extended the tcdrain skip-list in closeIO to include CON_SERIAL, 
ensuring
+       a hang-free shutdown.
+  4. Architectural Improvements:
+     - Redesigned shm_malloc to use a tiered mapping strategy: prefers
+       file-backed shared memory in /dev/shm with a graceful fallback
+       to MAP_ANONYMOUS.
+     - Optimized listing.h with always_inline attributes, __builtin_prefetch
+       for cache efficiency, and list poisoning for safer debugging.
+
+-------------------------------------------------------------------
+Fri Jun 19 12:45:28 UTC 2026 - Dr. Werner Fink <[email protected]>
+
+- Update to version 2.41
+  * The __attribute__((noreturn)) for error() in libconsole.h added
+  * The variable err with 0 initialized in thread_poll()
+  * The variable cp.parity with {0} initialized in readpw()
+  * feat(blogd): handle pending systemd password requests on coldstart
+  * Initialize console pointer list as well
+  * Check peer credentials before reading command
+  * Make isinteger() string check usable for all architectures
+  * Add some comments about warnings and translation for S390
+
+-------------------------------------------------------------------

Old:
----
  showconsole-2.40.tar.gz

New:
----
  showconsole-2.42.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ blog.spec ++++++
--- /var/tmp/diff_new_pack.RRs00r/_old  2026-06-22 18:06:09.790755992 +0200
+++ /var/tmp/diff_new_pack.RRs00r/_new  2026-06-22 18:06:09.794756131 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           blog
-Version:        2.40
+Version:        2.42
 %define sonum   2
 Release:        0
 Summary:        Boot logging

++++++ showconsole-2.40.tar.gz -> showconsole-2.42.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/Makefile 
new/showconsole-2.42/Makefile
--- old/showconsole-2.40/Makefile       2026-04-24 09:28:22.000000000 +0200
+++ new/showconsole-2.42/Makefile       2026-06-22 15:46:21.000000000 +0200
@@ -15,7 +15,7 @@
 DEBUG   =
 DESTDIR         =
 MAJOR   :=     2
-MINOR   :=     40
+MINOR   :=     42
 VERSION         :=     $(MAJOR).$(MINOR)
 DATE    =      $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]')
 COPTS    =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/blogctl.c 
new/showconsole-2.42/blogctl.c
--- old/showconsole-2.40/blogctl.c      2026-04-24 09:28:22.000000000 +0200
+++ new/showconsole-2.42/blogctl.c      2026-06-22 15:46:21.000000000 +0200
@@ -19,7 +19,7 @@
 /*
  * Cry and exit.
  */
-void error (const char *fmt, ...)
+__attribute__((noreturn)) void error (const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/blogd.c new/showconsole-2.42/blogd.c
--- old/showconsole-2.40/blogd.c        2026-04-24 09:28:22.000000000 +0200
+++ new/showconsole-2.42/blogd.c        2026-06-22 15:46:21.000000000 +0200
@@ -61,7 +61,7 @@
 /*
  * Cry and exit.
  */
-void error (const char *fmt, ...)
+__attribute__((noreturn)) void error (const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
@@ -197,7 +197,7 @@
     int ret = 0, tflags;
     int olderr = errno;
 
-    list_for_each_entry(c, &cons->node, node) {
+    list_for_each_entry(c, &lcons, node) {
        int newfd;
 
        if (!c->tty) continue;
@@ -285,7 +285,7 @@
     argc -= optind;
 
     myname = program_invocation_short_name;
-    getconsoles(&cons, 1);
+    getconsoles(1);
 
     close(0);
     close(1);
@@ -293,10 +293,12 @@
     if ((fd = open_tty(console, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC)) < 0)
        error("Can not open system console %s: %m", console);
 
-    if (fd > 0) {
+    if (fd != 0) {
        (void)ioctl(fd, TIOCNXCL);      /* Avoid EBUSY */
        dup2(fd, 0);
        close(fd);
+    } else {
+       (void)ioctl(0, TIOCNXCL);
     }
 
     dup2(0, 1);
@@ -305,7 +307,7 @@
 
     (void)ioctl(0, TIOCCONS, NULL);  /* Undo any current map if any */
 
-    list_for_each_entry(c, &cons->node, node) {
+    list_for_each_entry(c, &lcons, node) {
        speed_t ospeed;
        speed_t ispeed;
        int flags;
@@ -419,7 +421,7 @@
     (void)restart_sig(SIGTERM, 1);
     (void)restart_sig(SIGSYS,  1);
 
-    list_for_each_entry(c, &cons->node, node) {
+    list_for_each_entry(c, &lcons, node) {
        struct termios oldtio;
        speed_t ospeed;
        speed_t ispeed;
@@ -512,7 +514,7 @@
            int ret __attribute__ ((unused));
 
            if ((flags = fcntl(0, F_GETFL)) < 0)
-               list_for_each_entry(c, &cons->node, node) {
+               list_for_each_entry(c, &lcons, node) {
                    if (c->fd < 0)
                        continue;
                    ret = write(c->fd, msg, strlen(msg));
@@ -521,7 +523,7 @@
                flags &= ~(O_NONBLOCK);
                flags |=   O_NOCTTY;
                if (fcntl(0, F_SETFL, flags) < 0)
-                   list_for_each_entry(c, &cons->node, node) {
+                   list_for_each_entry(c, &lcons, node) {
                        if (c->fd < 0)
                            continue;
                        ret = write(c->fd, msg, strlen(msg));
@@ -540,7 +542,7 @@
            close(pipefd[0]);
        if (pipefd[1] >= 0)
            close(pipefd[1]);
-       list_for_each_entry(c, &cons->node, node) {
+       list_for_each_entry(c, &lcons, node) {
            const char *msg = "blogd: can not fork to become daemon: ";
            const char *err = strerror(errno);
            int ret __attribute__ ((unused));
@@ -557,7 +559,7 @@
        close(ptm);
        if (pipefd[1] >= 0)
            close(pipefd[1]);
-       list_for_each_entry(c, &cons->node, node) {
+       list_for_each_entry(c, &lcons, node) {
            if (c->fd > 0) {
                close(c->fd);
                c->fd = -1;
@@ -604,7 +606,7 @@
     if (show_status == 0 && kill (1, SIGRTMIN+20) < 0)
        warn("could not tell system to hode its status");
 
-    list_for_each_entry(c, &cons->node, node) {
+    list_for_each_entry(c, &lcons, node) {
        if (c->fd > 0) {
            if (c->tlock)       /* write back old setup  */
                tcsetattr(c->fd, TCSADRAIN, &c->otio);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/coldstart.c 
new/showconsole-2.42/libconsole/coldstart.c
--- old/showconsole-2.40/libconsole/coldstart.c 1970-01-01 01:00:00.000000000 
+0100
+++ new/showconsole-2.42/libconsole/coldstart.c 2026-06-22 15:46:21.000000000 
+0200
@@ -0,0 +1,231 @@
+/*
+ * coldstart.c
+ *
+ * Copyright 2026 Werner Fink
+ * Copyright 2026 SUSE Software Solutions Germany GmbH
+ *
+ * This source 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 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef  _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include "listing.h"
+#include "libconsole.h"
+
+extern void parse_ask_file(const char *);
+
+#define MAX_LINE 1024
+#define ASK_DIR "/run/systemd/ask-password"
+
+void send_response_to_systemd(const char *socket_path, const char *password)
+{
+    char *packet;
+    size_t pwd_len, packet_len;
+    struct sockaddr_un addr;
+
+    int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+    if (sock < 0)
+       return;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
+
+    /* systemd protocol requires: '+' + password (the \0 is optional) */
+    pwd_len = strlen(password);
+    packet_len = pwd_len + 1; /* +1 for '+' */
+    packet = (char*)malloc(packet_len);
+
+    if (!packet)
+       error("memory allocation: %m");
+
+    packet[0] = '+';
+    memcpy(packet + 1, password, pwd_len);
+
+    /* Now send the packet as one datagramm (SOCK_DGRAM) */
+    sendto(sock, packet, packet_len, 0, (struct sockaddr *)&addr, 
sizeof(addr));
+
+    free(packet);
+    close(sock);
+}
+
+
+
+/* Inintialize head node for systemd password queries */
+list_t pwd_requests = { &(pwd_requests), &(pwd_requests) };
+
+/*
+ * Data structure for single password query, compare
+ * with https://systemd.io/PASSWORD_AGENTS/
+ */
+struct request {
+    list_t node;
+    time_t notafter;
+    pid_t pid;
+    char *socket_path;
+    char *message;
+};
+
+struct request *requests = NULL;
+
+/* Helper to safely strip newlines and trailing whitespace */
+static void trim_trailing(char *str)
+{
+    size_t len = strlen(str);
+    while (len > 0 && (str[len - 1] == '\n' || str[len - 1] == '\r' || str[len 
- 1] == ' ')) {
+       str[len - 1] = '\0';
+       len--;
+    }
+}
+
+/* Parses a single ask.<id> file and adds it to the list if valid */
+void parse_ask_file(const char *filepath)
+{
+    char line[MAX_LINE];
+    int in_ask_section;
+    struct request *req;
+    list_t *head;
+
+    FILE *fp = fopen(filepath, "r");
+    if (!fp)
+       return;
+
+    in_ask_section = 0;
+
+    /* Allocate memory for our custom wrapper structure */
+    if (posix_memalign((void**)&req, sizeof(void*), alignof(struct request)) 
!= 0 || !req) {
+       fclose(fp);
+       error("memory allocation: %m");
+    }
+
+    while (fgets(line, sizeof(line), fp)) {
+       char *eq, *key, *value;
+
+       trim_trailing(line);
+
+       /* Skip empty lines or comments */
+       if (line[0] == '\0' || line[0] == '#')
+           continue;
+
+       /* Section header matching */
+       if (line[0] == '[' && line[strlen(line) - 1] == ']') {
+           if (strcmp(line, "[Ask]") == 0) {
+               in_ask_section = 1;
+           } else {
+               in_ask_section = 0; /* Left the [Ask] block */
+           }
+           continue;               /* Next line please */
+       }
+
+       if (!in_ask_section)
+           continue;               /* Only parse key=value variables if inside 
the [Ask] section */
+
+       eq = strchr(line, '=');
+       if (!eq)
+           continue;
+
+       *eq = '\0';
+       key = line;
+       value = eq + 1;
+
+       if (strcmp(key, "Message") == 0)
+           req->message = strdup(value);
+       else if (strcmp(key, "PID") == 0)
+           req->pid = (pid_t)atol(value);
+       else if (strcmp(key, "Socket") == 0)
+           req->socket_path = strdup(value);
+       else if (strcmp(key, "NotAfter") == 0)
+           req->notafter = atoll(value);
+    }
+    fclose(fp);
+
+    /* If we successfully found at least a message, commit it to our linked 
list */
+    if (req->message) {
+       if (!requests) {
+           head = &(pwd_requests);
+           requests = (struct request*)head;
+       } else
+           head = &requests->node;
+       insert(&req->node, head);
+    } else {
+       /* Clean up allocation if it wasn't a valid systemd ask file */
+       if (req->socket_path)
+           free(req->socket_path);
+       free(req);
+    }
+}
+
+/* Scans the target directory for any files prefixed with "ask." */
+void scan_ask_directory(const char *dir_path)
+{
+    struct dirent *entry;
+    char full_path[MAX_LINE];
+
+    DIR *dir = opendir(dir_path);
+    if (!dir)
+       error("Failed to open systemd ask-password directory: %m");
+
+    while ((entry = readdir(dir)) != NULL) {
+       if (entry->d_name[0] == '.')
+           continue;
+       if (entry->d_name[0] != 'a')
+           continue;
+       /* Look specifically for files starting with "ask." */
+       if (strncmp(entry->d_name, "ask.", 4) == 0) {
+           snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, 
entry->d_name);
+           parse_ask_file(full_path);
+       }
+    }
+    closedir(dir);
+}
+
+/*
+ * Pops the first systemd password request from the pending list.
+ * Transfers ownership of the allocated strings for message and socket_path 
+ * to the caller. The caller is responsible for freeing them.
+ * Returns 1 if a request was popped, 0 if the list is empty.
+ */
+int coldstart_pop_request(char **message, char **socket_path)
+{
+    struct request *req;
+
+    if (!requests)
+       return 0;
+
+    /* Check if the doubly linked list is empty */
+    if (pwd_requests.next == &pwd_requests) {
+       requests = NULL;
+       return 0;
+    }
+
+    /* Get the first entry and extract the strings */
+    req = list_entry(pwd_requests.next, struct request, node);
+
+    *message = req->message;
+    *socket_path = req->socket_path;
+    
+    /* 
+     * Defensive: clear the pointers from the struct before freeing it 
+     * to clarify that ownership has been transferred to the caller.
+     */
+    req->message = NULL;
+    req->socket_path = NULL;
+
+    /* Remove from list and free the request container */
+    delete(&req->node);
+    free(req);
+
+    return 1;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/console.c 
new/showconsole-2.42/libconsole/console.c
--- old/showconsole-2.40/libconsole/console.c   2026-04-24 09:28:22.000000000 
+0200
+++ new/showconsole-2.42/libconsole/console.c   2026-06-22 15:46:21.000000000 
+0200
@@ -153,9 +153,28 @@
 }
 
 /*
+ * Console list
+ */
+list_t lcons = { &(lcons), &(lcons) };
+
+static __attribute__((destructor)) void lcons_shutdown(void)
+{
+    struct console *c, *n;
+
+    if (list_empty(&lcons))
+       return;
+
+    list_for_each_entry_safe(c, n, &lcons, node) {
+       delete(&c->node);
+       if (c->fd >= 0)
+           close(c->fd);
+       free(c);
+    }
+}
+
+/*
  * The stdio file pointer for our log file
  */
-struct console *cons;
 FILE * flog = NULL;
 static int fdread  = -1;
 static int fdfifo  = -1;
@@ -493,6 +512,39 @@
 static       char *     ttail = temp;
 static volatile ssize_t tavail;
 
+static void ask_for_password(void) attribute((noinline));
+
+static int coldstart_active = 0;
+static char *coldstart_socket_path = NULL;
+
+static void coldstart_next(void)
+{
+    char *msg = NULL;
+    char *sock = NULL;
+
+    if (!coldstart_pop_request(&msg, &sock)) {
+       coldstart_active = 0;
+       return;
+    }
+
+    coldstart_socket_path = sock;
+    
+    if (pwprompt)
+       free(pwprompt);
+    pwprompt = msg;
+    
+    if (!password) {
+       void *tmp = shm_malloc(MAX_PASSLEN + sizeof(int32_t));
+       if (!tmp)
+           error("can not allocate string for password");
+       password = (char *)tmp;
+       pwsize = (int32_t *)(tmp + MAX_PASSLEN);
+    }
+    password[0] = '\0';
+
+    ask_for_password();
+}
+
 /*
  * Prepare I/O
  */
@@ -516,6 +568,9 @@
     fdsock  = listen;                  /* We use only ONE socket ... see also 
safeout() */
     fdread  = input;
 
+    /* Phase 1: Scan for pending systemd password queries */
+    scan_ask_directory("/run/systemd/ask-password");
+
     if (fifo_name && fdfifo < 0) {
        struct stat st;
        errno = 0;
@@ -540,13 +595,17 @@
     if (fdsock >= 0)
        epoll_addread(fdsock, &epoll_socket_accept);
 
-    list_for_each_entry(c, &cons->node, node) {
+    list_for_each_entry(c, &lcons, node) {
        if (c->fd < 0)
            continue;
        epoll_addwrite(c->fd, &epoll_write_watchdog);
     }
 
     (void)mlockall(MCL_FUTURE);
+
+    /* Phase 2: Start processing coldstart requests via epoll */
+    coldstart_active = 1;
+    coldstart_next();
 }
 
 /*
@@ -747,10 +806,10 @@
        warn("no message logging because /var file system is not accessible");
 #endif
 
-    list_for_each_entry(c, &cons->node, node) {
+    list_for_each_entry(c, &lcons, node) {
        if (c->fd < 0)
            continue;
-       if (c->flags & CON_3215)
+       if (c->flags & (CON_3215|CON_SERIAL))
            continue;
        (void)tcdrain(c->fd);           /* Hold in sync with console */
     }
@@ -793,13 +852,21 @@
     if (epfd >= 0)
        close(epfd);
 
-    if (password)
+    if (password) {
        memset(password, 0, MAX_PASSLEN);
+        munmap(password, MAX_PASSLEN+sizeof(int32_t));
+        password = NULL;
+    }
+
+    if (pwprompt) {
+       free(pwprompt);
+       pwprompt = NULL;
+    }
 
-    list_for_each_entry(c, &cons->node, node) {
+    list_for_each_entry(c, &lcons, node) {
        if (c->fd < 0)
            continue;
-       if (c->flags & CON_3215)
+       if (c->flags & (CON_3215|CON_SERIAL))
            continue;
        (void)tcdrain(c->fd);
     }
@@ -839,6 +906,9 @@
         */
        return 1;
 #endif
+    if (newc->flags & CON_SERIAL)
+       return 1;       /* Keep serial console devices non-blocking to prevent 
freezes */
+
     if ((tflags = fcntl(newc->fd, F_GETFL)) < 0)
        warn("can not get terminal flags of %s", newc->tty);
 
@@ -852,7 +922,6 @@
 }
 
 /* Allocate a console */
-static list_t lcons = { &(lcons), &(lcons) };
 static int consalloc(struct console **cons, char *name, const int cflags, 
const dev_t dev, int io)
 {
     struct console *newc;
@@ -892,7 +961,7 @@
     return 1;
 }
 
-void getconsoles(struct console **cons, int io)
+void getconsoles(int io)
 {
     static const struct {
        short flag;
@@ -915,10 +984,6 @@
 #endif
     int items;
 
-
-    if (!cons)
-       error("error: console pointer empty");
-
     fc = fopen("/proc/consoles", "re");
     if (!fc) {
        if (errno != ENOENT)
@@ -978,7 +1043,6 @@
     if (!c)
        goto err;
 
-    *cons = c;
     return;
 err:
 #ifdef TIOCGDEV
@@ -995,7 +1059,6 @@
            error("/dev/console is not a valid fallback\n");
        free(tty);
 
-       *cons = c;
        return;
     }
 fallback:
@@ -1007,8 +1070,6 @@
     if (!consalloc(&c, tty, CON_CONSDEV, makedev(TTYAUX_MAJOR, 1), io))
        error("/dev/console is not a valid fallback\n");
     free(tty);
-
-    *cons = c;
 }
 
 /*
@@ -1026,7 +1087,7 @@
        int saveerr = errno;
 
        if (fdc < 0) {
-           list_for_each_entry(c, &cons->node, node) {
+           list_for_each_entry(c, &lcons, node) {
                if (c->flags & CON_CONSDEV) {
                    fdc = c->fd;
                    break;
@@ -1044,7 +1105,7 @@
 
        parselog(trans, cnt);                           /* Parse and make copy 
of the input */
 
-       list_for_each_entry(c, &cons->node, node) {
+       list_for_each_entry(c, &lcons, node) {
            int len;
            char *mesg;
            if (c->fd < 0)
@@ -1080,7 +1141,7 @@
            if (tavail > TRANS_BUFFER_SIZE)
                len = TRANS_BUFFER_SIZE;
 
-           list_for_each_entry(c, &cons->node, node) {
+           list_for_each_entry(c, &lcons, node) {
                size_t ret;
                if (c->fd < 0)
                    continue;
@@ -1088,9 +1149,6 @@
                if (ret < 1)
                    goto flush;
                len = ret;                              /* First make write out 
all but Second? */
-               if (c->flags & CON_3215)
-                   continue;
-               (void)tcdrain(c->fd);                   /* Write copy of input 
to real tty */
            }
            thead += len;
 
@@ -1107,7 +1165,7 @@
            }
        }
 
-       list_for_each_entry(c, &cons->node, node) {
+       list_for_each_entry(c, &lcons, node) {
            size_t ret;
            if (c->fd < 0)
                continue;
@@ -1119,9 +1177,6 @@
                }
                break;
            }
-           if (c->flags & CON_3215)
-               continue;
-           (void)tcdrain(c->fd);                       /* Write copy of input 
to real tty */
        }
 flush:
        flushlog();
@@ -1225,18 +1280,29 @@
            asking = 0;         /* Success! */
 
            /* 1. Deliver the password and close the socket as well */
-           if (pwd_client_fd >= 0) {
-               (void)do_answer_password(pwd_client_fd);
-               epoll_delete(pwd_client_fd);
-               close(pwd_client_fd);
-               pwd_client_fd = -1;
+           if (coldstart_active) {
+               if (coldstart_socket_path) {
+                   password = frobnicate(password, *pwsize);
+                   send_response_to_systemd(coldstart_socket_path, password);
+                   password = frobnicate(password, *pwsize);
+                   
+                   free(coldstart_socket_path);
+                   coldstart_socket_path = NULL;
+               }
+           } else {
+               if (pwd_client_fd >= 0) {
+                   (void)do_answer_password(pwd_client_fd);
+                   epoll_delete(pwd_client_fd);
+                   close(pwd_client_fd);
+                   pwd_client_fd = -1;
+               }
            }
 
            /* 2. Enable Kernel-Logging to the console Konsole */
            klogctl(SYSLOG_ACTION_CONSOLE_ON, NULL, 0);
 
            /* 3. Close other waiting password processes */
-           list_for_each_entry(c, &cons->node, node) {
+           list_for_each_entry(c, &lcons, node) {
                if (c->pid > 0 && c->pid != info.si_pid) {
                    kill(c->pid, SIGTERM);
                }
@@ -1244,10 +1310,14 @@
                    c->pid = -1; /* we are done now */
                }
            }
+
+           /* 4. Advance coldstart */
+           if (coldstart_active)
+               coldstart_next();
        }
     } else {
        /* Clear Zombies */
-       list_for_each_entry(c, &cons->node, node) {
+       list_for_each_entry(c, &lcons, node) {
            if (c->pid == info.si_pid) {
                c->pid = -1;
            }
@@ -1272,7 +1342,7 @@
 static void socket_handler(int fd)
 {
     struct ucred cred = {};
-    unsigned char magic[2];
+    unsigned char magic[2] = {0};
     const char *enqry;
     char *arg = NULL;
     socklen_t clen;
@@ -1284,32 +1354,6 @@
        goto out;
     }
 
-    ret = safein(fd, &magic[0], sizeof(magic));
-    if (ret < 0) {
-       warn("can not read request magic from UNIX socket");
-       goto out;
-    }
-
-    if (magic[1] == '\002') {
-       unsigned char alen;
-
-       ret = safein(fd, &alen, sizeof(unsigned char));
-       if (ret < 0) {
-            warn("can not get message len from UNIX socket");
-            goto out;
-       }
-
-       arg = calloc(alen, sizeof(char));
-       if (!arg)
-           error("can not allocate memory for message from socket");
-
-       ret = safein(fd, arg, alen);
-       if (ret < 0) {
-           warn("can not get message len from UNIX socket");
-           goto out;
-       }
-    }
-
     clen = sizeof(struct ucred);
     ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &clen);
     if (ret < 0) {
@@ -1341,8 +1385,39 @@
        goto out;
     }
 
+    ret = safein(fd, &magic[0], sizeof(magic));
+    if (ret < (ssize_t)sizeof(magic)) {
+       warn("can not read request magic from UNIX socket");
+       goto out;
+    }
+
+    if (magic[1] == '\002') {
+       unsigned char alen;
+
+       ret = safein(fd, &alen, sizeof(unsigned char));
+       if (ret < (ssize_t)sizeof(unsigned char)) {
+            warn("can not get message len from UNIX socket");
+            goto out;
+       }
+
+       arg = calloc(alen, sizeof(char));
+       if (!arg)
+           error("can not allocate memory for message from socket");
+
+       ret = safein(fd, arg, alen);
+       if (ret < (ssize_t)alen) {
+           warn("can not get message len from UNIX socket");
+           goto out;
+       }
+    }
+
     switch (magic[0]) {
     case MAGIC_ASK_PWD:
+       if (magic[1] != '\002') {
+           errno = EINVAL;
+           warn("Got password invalid request for prompt");
+           goto out;
+       }
 #ifdef DEBUG
        warn("Got password request for prompt >%s<", arg);
 #endif
@@ -1381,6 +1456,11 @@
        break;
 
     case MAGIC_CHROOT:
+       if (magic[1] != '\002') {
+           errno = EINVAL;
+           warn("Got password invalid chroot request");
+           goto out;
+       }
 
        new_root(arg);
 
@@ -1419,7 +1499,7 @@
        if (fdread >= 0) {
            struct console *c;
 
-           list_for_each_entry(c, &cons->node, node) {
+           list_for_each_entry(c, &lcons, node) {
                if (c->flags & CON_CONSDEV) {
                    if (c->fd > 0) {
                        epoll_delete(fdread);
@@ -1445,7 +1525,7 @@
        if (fdread < 0) {
            struct console *c;
 
-           list_for_each_entry(c, &cons->node, node) {
+           list_for_each_entry(c, &lcons, node) {
                if (c->flags & CON_CONSDEV) {
                    if (c->fd > 0) {
                        char ptsname[NAME_MAX+1];
@@ -1565,7 +1645,7 @@
        break;
     }
 out:                   /* We are done */
-    if (fd > 0) {
+    if (fd >= 0) {
        epoll_delete(fd);
        close(fd);
        fd = -1;
@@ -1593,7 +1673,7 @@
     struct console *c;
     size_t len;
 
-    if (!pwprompt && !*pwprompt)
+    if (!pwprompt || !*pwprompt)
        return;
 
     len = strlen(pwprompt);
@@ -1611,7 +1691,7 @@
     asking = 1;                                /* Show only our question about 
password/passphrase */
 
     /* pwprompt */
-    list_for_each_entry(c, &cons->node, node) {
+    list_for_each_entry(c, &lcons, node) {
        int pfd;
        if (c->fd < 0 || !c->tty)
            continue;
@@ -1627,8 +1707,9 @@
            char *message;
            int eightbit;
            int len, fdc, tflags;
+#if defined(__s390__) || defined(__s390x__)
            int vmcpfd = -1;
-
+#endif
            if (fdfifo >= 0)
                close(fdfifo);
            if (fdsock >= 0)
@@ -1647,7 +1728,7 @@
            dup2(c->fd, 1);
            currenttty = c->tty;        /* Used in readpw() in case of an error 
*/
 
-           list_for_each_entry(d, &cons->node, node)
+           list_for_each_entry(d, &lcons, node)
                if (d->fd >= 0) {
                    close(d->fd);
                    d->fd = -1;
@@ -1839,7 +1920,7 @@
                        c->pid = -1;
                        
                        /* Terminate all other password asking children for 
syncronious mode */
-                       list_for_each_entry(d, &cons->node, node) {
+                       list_for_each_entry(d, &lcons, node) {
                            if (d->pid > 0 && d->pid != c->pid) {
                                kill(d->pid, SIGTERM);
                                /* Just wait to avoid being flooded with 
zombies */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/libconsole.h 
new/showconsole-2.42/libconsole/libconsole.h
--- old/showconsole-2.40/libconsole/libconsole.h        2026-04-24 
09:28:22.000000000 +0200
+++ new/showconsole-2.42/libconsole/libconsole.h        2026-06-22 
15:46:21.000000000 +0200
@@ -63,7 +63,7 @@
 #define weak_symbol(name)      _weak_pragma(name) _declare(name) 
__attribute__((weak))
 
 /* external function in program */
-extern void error (const char *fmt, ...);
+extern void error (const char *fmt, ...) __attribute__((noreturn));
 
 /* console.c */
 
@@ -138,13 +138,18 @@
 extern void safeIO (void);
 extern void closeIO(void);
 
-extern struct console *cons;
-extern void getconsoles(struct console **cons, int io);
+extern list_t lcons;
+extern void getconsoles(int io);
 extern void epoll_write_watchdog(int) attribute((noinline));
 
 /* chroot.c */
 extern void new_root(const char *root);
 
+/* coldstart.c */
+extern void scan_ask_directory(const char *dir_path);
+extern void send_response_to_systemd(const char *socket_path, const char 
*password);
+extern int coldstart_pop_request(char **message, char **socket_path);
+
 /* devices.c */
 extern char *charname(const char *dev);
 extern char *chardev(const dev_t cons);
@@ -212,8 +217,8 @@
 extern int request_tty(const char *tty);
 
 /* vmcp.c */
-#if defined(__s390__) || defined(__s390x__)
 extern int isinteger(const char *str);
+#if defined(__s390__) || defined(__s390x__)
 extern int openvmcp(void);
 extern void clearvmcp(void);
 extern char* queryterm(int fd);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/log.c 
new/showconsole-2.42/libconsole/log.c
--- old/showconsole-2.40/libconsole/log.c       2026-04-24 09:28:22.000000000 
+0200
+++ new/showconsole-2.42/libconsole/log.c       2026-06-22 15:46:21.000000000 
+0200
@@ -182,7 +182,7 @@
 
        if (gettimeofday(&now, NULL) == 0) {
            struct timespec abstime;
-           int err;
+           int err = 0;
 
            now.tv_usec += msec * 1000;
            while (now.tv_usec >= 1000000) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/proc.c 
new/showconsole-2.42/libconsole/proc.c
--- old/showconsole-2.40/libconsole/proc.c      2026-04-24 09:28:22.000000000 
+0200
+++ new/showconsole-2.42/libconsole/proc.c      2026-06-22 15:46:21.000000000 
+0200
@@ -68,8 +68,10 @@
        if (dr->d_name[0] == '.')
            continue;
        len = readlinkat(dirfd(dir), dr->d_name, &tmp[0], LINE_MAX);
-       tmp[len] = '\0';
-       fprintf(stderr, "/proc/%d/fd/%s %s\n", (int)pid, dr->d_name, tmp);
+       if (len >= 0) {
+           tmp[len] = '\0';
+           fprintf(stderr, "/proc/%d/fd/%s %s\n", (int)pid, dr->d_name, tmp);
+       }
     }
     closedir(dir);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/readpw.c 
new/showconsole-2.42/libconsole/readpw.c
--- old/showconsole-2.40/libconsole/readpw.c    2026-04-24 09:28:22.000000000 
+0200
+++ new/showconsole-2.42/libconsole/readpw.c    2026-06-22 15:46:21.000000000 
+0200
@@ -36,7 +36,7 @@
 ssize_t readpw(int fd, char *pass, int eightbit)
 {
     char *ptr = pass;
-    struct chardata cp;
+    struct chardata cp = {0};
     int ret;
 
     cp.eol = *ptr = '\0';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/shm.c 
new/showconsole-2.42/libconsole/shm.c
--- old/showconsole-2.40/libconsole/shm.c       2026-04-24 09:28:22.000000000 
+0200
+++ new/showconsole-2.42/libconsole/shm.c       2026-06-22 15:46:21.000000000 
+0200
@@ -76,6 +76,7 @@
     void *area;
     char *template;
     int shmfd = -1;
+    int flags = MAP_LOCKED|MAP_SHARED;
 
     if (devshm) {
        int ret;
@@ -93,7 +94,10 @@
            error("can not allocate shared memory object");
     }
 
-    area = mmap(NULL, size, PROT_READ|PROT_WRITE, 
MAP_LOCKED|MAP_SHARED|MAP_ANONYMOUS, shmfd, 0);
+    if (shmfd == -1)
+       flags |= MAP_ANONYMOUS;
+
+    area = mmap(NULL, size, PROT_READ|PROT_WRITE, flags, shmfd, 0);
     if (area == MAP_FAILED)
         error("can not map shared memory object into memory");
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/socket.c 
new/showconsole-2.42/libconsole/socket.c
--- old/showconsole-2.40/libconsole/socket.c    2026-04-24 09:28:22.000000000 
+0200
+++ new/showconsole-2.42/libconsole/socket.c    2026-06-22 15:46:21.000000000 
+0200
@@ -45,9 +45,10 @@
 
     ret = bind(fd, &su, offsetof(struct sockaddr_un, sun_path) + 1 + 
strlen(su.sun_path+1));
     if (ret < 0) {
+       int err = errno;
        close(fd);
        fd = -1;
-       if (errno != EADDRINUSE)
+       if (err != EADDRINUSE)
            warn("can not bind a name to UNIX socket");
        else
            fd = -2;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/libconsole/vmcp.c 
new/showconsole-2.42/libconsole/vmcp.c
--- old/showconsole-2.40/libconsole/vmcp.c      2026-04-24 09:28:22.000000000 
+0200
+++ new/showconsole-2.42/libconsole/vmcp.c      2026-06-22 15:46:21.000000000 
+0200
@@ -22,13 +22,6 @@
 #include <sys/ioctl.h>
 #include "libconsole.h"
 
-#if defined(__s390__) || defined(__s390x__)
-
-#define        VMCP_DEVICE_NODE        "/dev/vmcp"
-#define        VMCP_GETSIZE            _IOR(0x10, 3, int)
-#define        VMCP_SETBUF             _IOW(0x10, 2, int)
-#define        VMCP_GETCODE            _IOR(0x10, 1, int)
-
 int isinteger(const char *str)
 {
     int errs = errno, ret = 1;
@@ -54,6 +47,13 @@
     return ret;
 }
 
+#if defined(__s390__) || defined(__s390x__)
+
+#define        VMCP_DEVICE_NODE        "/dev/vmcp"
+#define        VMCP_GETSIZE            _IOR(0x10, 3, int)
+#define        VMCP_SETBUF             _IOW(0x10, 2, int)
+#define        VMCP_GETCODE            _IOR(0x10, 1, int)
+
 static char *more, *hold;
 static int spooling;
 
@@ -224,6 +224,13 @@
 
 void warning3215(int fd)
 {
+    /*
+     * Warning: Do not translate this test as it might inlude then so called
+     * umlauts which in fact can not be encoded for the 3215 console interface.
+     * The 3215 console driver work in fact with EBCDIC codepage and the
+     * kernel has to translate such umlauts (multi or single bytes) with the
+     * correct EBCDIC character table (for german e.g. IBM-1141 or IBM-273).
+     */
     (void) writevmcp(fd, "MESSAGE * WARNING: 3215 mode. Password visible!");
     (void) writevmcp(fd, "MESSAGE * Ensure nobody is watching the screen.");
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/listing.h 
new/showconsole-2.42/listing.h
--- old/showconsole-2.40/listing.h      2026-04-24 09:28:22.000000000 +0200
+++ new/showconsole-2.42/listing.h      2026-06-22 15:46:21.000000000 +0200
@@ -11,6 +11,9 @@
 
 #ifndef _LISTING_H_
 #define _LISTING_H_
+#ifdef DEBUG
+# include <assert.h>
+#endif
 
 #ifndef offsetof
 # define offsetof(type,memb)   __builtin_offsetof(type,memb)
@@ -18,13 +21,17 @@
 
 typedef struct list_struct {
     struct list_struct * next, * prev;
-} list_t;
+} __attribute__((may_alias)) list_t;
 
 /*
  * Insert new entry as next member.
  */
-static inline void insert (list_t * new, list_t * here)
+static inline __attribute__((always_inline)) void insert (list_t * new, list_t 
* here)
 {
+#ifdef DEBUG
+    assert(new != NULL && here != NULL);
+    assert(here->next != NULL && here->prev != NULL);
+#endif
     list_t * prev = here;
     list_t * next = here->next;
 
@@ -45,16 +52,26 @@
 /*
  * Remove entries, note that the pointer its self remains.
  */
-static inline void delete (list_t * entry)
+#define LIST_POISON1   ((void *) 0x100)
+#define LIST_POISON2   ((void *) 0x200)
+
+static inline __attribute__((always_inline)) void delete (list_t * entry)
 {
+#ifdef DEBUG
+    assert(entry != NULL);
+    assert(entry->next != LIST_POISON1 && entry->prev != LIST_POISON2);
+#endif
     list_t * prev = entry->prev;
     list_t * next = entry->next;
 
     next->prev = prev;
     prev->next = next;
+
+    entry->next = (list_t *)LIST_POISON1;
+    entry->prev = (list_t *)LIST_POISON2;
 }
 
-static inline void join(list_t *list, list_t *head)
+static inline __attribute__((always_inline)) void join(list_t *list, list_t 
*head)
 {
     list_t *first = list->next;
 
@@ -70,7 +87,7 @@
     }
 }
 
-static inline int list_empty(list_t *head)
+static inline __attribute__((always_inline)) int list_empty(list_t *head)
 {
         return head->next == head;
 }
@@ -79,7 +96,7 @@
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        ((type *)( (char *)(__mptr) - offsetof(type,member) )); }))
 #define list_for_each(pos, head)       \
-       for (pos = (head)->next; pos != (head); pos = pos->next)
+       for (pos = (head)->next; __builtin_prefetch(pos->next, 0, 3), pos != 
(head); pos = pos->next)
 #define list_for_each_prev(pos, head)  \
        for (pos = (head)->prev; pos != (head); pos = pos->prev)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.40/showconsole.c 
new/showconsole-2.42/showconsole.c
--- old/showconsole-2.40/showconsole.c  2026-04-24 09:28:22.000000000 +0200
+++ new/showconsole-2.42/showconsole.c  2026-06-22 15:46:21.000000000 +0200
@@ -83,6 +83,9 @@
        if (opt && *opt++ == '-' && *opt++ == 'r' && *opt == '\0')
            goto out;
 
+       if (!argv[1])
+           goto out;
+
        if ((fd = open(argv[1], O_WRONLY|O_NOCTTY)) < 0)
            error("can not open %s: %m", argv[1]);
 
@@ -103,8 +106,8 @@
     } else if (argc > 2)
        error("Usage: %s [-n]", myname);
 
-    getconsoles(&cons, 0);
-    list_for_each_entry(c, &cons->node, node) {
+    getconsoles(0);
+    list_for_each_entry(c, &lcons, node) {
                if (c->flags & CON_CONSDEV) {
            if (numeric)
                printf("%u %u\n", major(c->dev), minor(c->dev));

Reply via email to