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-04-16 17:25:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/blog (Old)
 and      /work/SRC/openSUSE:Factory/.blog.new.11940 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "blog"

Thu Apr 16 17:25:12 2026 rev:24 rq:1346447 version:2.38

Changes:
--------
--- /work/SRC/openSUSE:Factory/blog/blog.changes        2026-03-20 
21:19:43.501298343 +0100
+++ /work/SRC/openSUSE:Factory/.blog.new.11940/blog.changes     2026-04-16 
17:25:22.639497950 +0200
@@ -1,0 +2,12 @@
+Mon Apr 13 12:47:36 UTC 2026 - Dr. Werner Fink <[email protected]>
+
+- Update to version 2.38
+  * Silent debugging messages in epoll algorithm (boo#1261699)
+  * Make it work on 3215 console of s390
+    means no tcdrain() for 3215, no blocking writes, not more then
+    130 characters per line, no \r, finalize lines with \n.
+    Nevertheless use a blocking read for password requests.
+    Make automatic CLEAR an kernel command line option with
+    the parameter blog.timeout=0 (boo#1261697)
+
+-------------------------------------------------------------------

Old:
----
  showconsole-2.37.tar.gz

New:
----
  showconsole-2.38.tar.gz

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

Other differences:
------------------
++++++ blog.spec ++++++
--- /var/tmp/diff_new_pack.aE9dPV/_old  2026-04-16 17:25:23.263523659 +0200
+++ /var/tmp/diff_new_pack.aE9dPV/_new  2026-04-16 17:25:23.267523824 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           blog
-Version:        2.37
+Version:        2.38
 %define sonum   2
 Release:        0
 Summary:        Boot logging

++++++ showconsole-2.37.tar.gz -> showconsole-2.38.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/Makefile 
new/showconsole-2.38/Makefile
--- old/showconsole-2.37/Makefile       2026-03-18 12:18:33.000000000 +0100
+++ new/showconsole-2.38/Makefile       2026-04-13 14:11:49.000000000 +0200
@@ -15,7 +15,7 @@
 DEBUG   =
 DESTDIR         =
 MAJOR   :=     2
-MINOR   :=     37
+MINOR   :=     38
 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.37/blogd.8.in 
new/showconsole-2.38/blogd.8.in
--- old/showconsole-2.37/blogd.8.in     2026-03-18 12:18:33.000000000 +0100
+++ new/showconsole-2.38/blogd.8.in     2026-04-13 14:11:49.000000000 +0200
@@ -45,6 +45,24 @@
 .B \-f
 This option is used at shutdown, that is reboot, halt, and poweroff
 but also for kexec.
+.SH BOOT PARAMETERS
+On 
+.B s390x
+(64-bit IBM System/390) and
+.B z/Architecture
+the
+.B blogd
+knows currently one kernel command line parameter
+.BI blog\&.timeout= <integer>
+with
+.I <integer>
+the timeout for the
+.B MORE
+prompt on
+.I 3215
+console.  If set to
+.I 0
+the boot process does not need manual support.
 .SH SIGNALS
 .B blogd
 knows a few signal to contol its behavior.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/blogd.c new/showconsole-2.38/blogd.c
--- old/showconsole-2.37/blogd.c        2026-03-18 12:18:33.000000000 +0100
+++ new/showconsole-2.38/blogd.c        2026-04-13 14:11:49.000000000 +0200
@@ -216,7 +216,7 @@
            if (newfd != c->fd)
                close(newfd);
            epoll_addwrite(c->fd, &epoll_write_watchdog);
-            ret = 1;
+           ret = 1;
 #if defined(__s390__) || defined(__s390x__)
            if (major(c->dev) == 4 && minor(c->dev) == 64)
                break;
@@ -345,23 +345,29 @@
            o.c_cc[VMIN]  = CMIN;
        }
 #if defined(__s390__) || defined(__s390x__)
-       if (major(c->dev) == 4 && minor(c->dev) == 64 && final == 0) {
-           char *msg;
-           int vmcp;
-
-           vmcp = openvmcp();
-           if (vmcp) {
-               msg = queryterm(vmcp);
-               if (msg) {
-                   parseterm(msg);
-                   free(msg);
-                   setterm(vmcp);
+       if ((c->flags & CON_3215) && final == 0) {
+           char *timeout;
+
+           parse_cmdline();    /* Parse the kernel command line for 
blog.<key>=<val> */
+           timeout = value_cmdline("timeout");
+
+           if (timeout && isinteger(timeout)) {
+               int vmcp = openvmcp();
+               if (vmcp) {
+                   char *msg = queryterm(vmcp);
+                   if (msg) {
+                       parseterm(msg);
+                       free(msg);
+                       setterm(vmcp, timeout);
+                   }
+                   close(vmcp);
+                   atexit(vmcp_handler);       /* Register vmcp restore exit 
handler */
                }
-               close(vmcp);
-               atexit(vmcp_handler);   /* Register vmcp restore exit handler */
+               ioctl(c->fd, TIOCCBRK);
+               usleep(1000);
            }
-           ioctl(c->fd, TIOCCBRK);
-           usleep(1000);
+
+           free_cmdline();
        }
 #endif
     }
@@ -513,7 +519,7 @@
                }
            else {
                flags &= ~(O_NONBLOCK);
-               flags |=   O_NOCTTY;
+               flags |=   O_NOCTTY;
                if (fcntl(0, F_SETFL, flags) < 0)
                    list_for_each_entry(c, &cons->node, node) {
                        if (c->fd < 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/libconsole/console.c 
new/showconsole-2.38/libconsole/console.c
--- old/showconsole-2.37/libconsole/console.c   2026-03-18 12:18:33.000000000 
+0100
+++ new/showconsole-2.38/libconsole/console.c   2026-04-13 14:11:49.000000000 
+0200
@@ -1,8 +1,9 @@
 /*
  * console.c
  *
- * Copyright 2000,2015,2025 Werner Fink, 2000 SuSE GmbH Nuernberg, Germany.
- * Copyright 2015 SuSE Linux GmbH.
+ * Copyright 2000,2015,2025,2026 Werner Fink, 2000 SUSE GmbH Nuernberg, 
Germany.
+ * Copyright 2015 SUSE Linux GmbH.
+ * 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
@@ -155,7 +156,7 @@
  * The stdio file pointer for our log file
  */
 struct console *cons;
-static FILE * flog = NULL;
+FILE * flog = NULL;
 static int fdread  = -1;
 static int fdfifo  = -1;
 
@@ -261,6 +262,135 @@
     return r;
 }
 
+#if defined(__s390__) || defined(__s390x__)
+static ssize_t copyout3215 (int fd, const void *ptr, size_t cnt, ssize_t max)
+{
+    /*
+     * Workaround for s390x console mode 3215:
+     * 1. 3215 can not handle carriage return (\r). Instead of just dropping 
it,
+     * we translate it to a newline (\n) if the line is not empty, to simulate
+     * overwriting without concatenating strings indefinitely.
+     * 2. Be sure that there is a \n after 130 chars to flush the device 3215 
driver.
+     */
+    const char *conbuf = (const char *)ptr;
+    /*
+     * Missing: detect lines across chunks
+     */
+    size_t line_start = 0;
+    size_t i = 0;
+    ssize_t ret, total_written = 0;
+    static int skip_next_lf = 0;       /* It remembers \r\n across chunk 
boundaries. */
+
+    while (i < cnt) {
+       size_t current_line_len;
+       char linebuf[132];              /* For atomar write: 130 char max + \n 
+ rest */
+
+       /* 0. Catch CRLF across chunks */
+       if (skip_next_lf && conbuf[i] == '\n') {
+           skip_next_lf = 0;
+           line_start = i+1;
+           i++;
+           continue;
+       }
+       skip_next_lf = 0;
+
+       current_line_len = i - line_start;
+
+       /* 1. Search for end of line (could be \n, \r or 130 char limit 
reached) */
+       if (conbuf[i] == '\n' || conbuf[i] == '\r') {
+           if (current_line_len > 0) {
+               memcpy(linebuf, &conbuf[line_start], current_line_len);
+               linebuf[current_line_len] = '\n';
+
+               ret = copyout(fd, linebuf, current_line_len + 1, max);
+               if (ret < 0)
+                   goto error;
+               total_written += ret;
+           } else if (conbuf[i] == '\n') {
+               /*
+                * Only create a blank line with a true \n!
+                * An isolated \r at the beginning of a line will be silently 
ignored.
+                */
+               ret = copyout(fd, "\n", 1, max);
+               if (ret < 0)
+                   goto error;
+               total_written += ret;
+           }
+
+           if (conbuf[i] == '\r') {
+               if ((i+1 < cnt) && conbuf[i+1] == '\n') {
+                   i++;                /* Ignore CRLF in the same chunk */
+               } else if (i+1 == cnt) {
+                   skip_next_lf = 1;   /* Set marker for the next chunk at 0. 
*/
+               }
+           }
+
+           line_start = i+1;
+           i = line_start;
+           continue;
+       }
+
+       /* 2. Ouch: Reached 130 without any newline */
+       if (current_line_len >= 130) {
+           /* Are there any spaces in the last 130 characters? */
+           size_t last_space = i;
+           int found_space = 0;
+
+           for (size_t s = i; s > line_start; s--) {
+               if (conbuf[s] == ' ') {
+                   last_space = s;
+                   found_space = 1;
+                   break;
+               }
+           }
+
+           if (found_space) {
+               /* Copy up to the spaces */
+               size_t write_len = last_space - line_start;
+               memcpy(linebuf, &conbuf[line_start], write_len);
+               linebuf[write_len] = '\n';
+
+               ret = copyout(fd, &conbuf[line_start], write_len + 1, max);
+               if (ret < 0)
+                   goto error;
+               total_written += ret;
+
+               line_start = last_space + 1; /* continue after the space */
+           } else {
+               /* No space found -> hard newline at 130 chars */
+               memcpy(linebuf, &conbuf[line_start], 130);
+               linebuf[130] = '\n';
+
+               ret = copyout(fd, &conbuf[line_start], 130 + 1, max);
+               if (ret < 0)
+                   goto error;
+               total_written += ret;
+
+               line_start = line_start + 130;
+           }
+           i = line_start;
+           continue;
+       }
+       i++;
+    }
+
+    /* 3. final write out the rest */
+    if (line_start < cnt) {
+       ret = copyout(fd, &conbuf[line_start], cnt - line_start, max);
+       if (ret < 0)
+           goto error;
+       total_written += ret;
+    }
+
+    if (total_written != cnt)  /* We might not return more or less then we got 
from the outer ringbuffer */
+       total_written = cnt;
+
+    return total_written;
+error:
+    return -1;
+}
+#endif
+
 /*
  * Twice used: safe in
  */
@@ -452,9 +582,11 @@
        ret = 1;
 
        if (evlist[n].events & (EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLHUP | 
EPOLLERR)) {
+#ifdef DEBUG
            if (evlist[n].events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)) {
                warn("epoll returned RDHUP, HUP or ERR on fd %d", fd);
            }
+#endif
            efunc(fd);
            continue;
        }
@@ -609,13 +741,17 @@
     struct console *c;
     int ret, n = 20;
 
+#ifdef DEBUG
     /* Maybe we've catched a signal, therefore */
     if (!flog && !nsigsys)
        warn("no message logging because /var file system is not accessible");
+#endif
 
     list_for_each_entry(c, &cons->node, node) {
        if (c->fd < 0)
            continue;
+       if (c->flags & CON_3215)
+           continue;
        (void)tcdrain(c->fd);           /* Hold in sync with console */
     }
 
@@ -663,6 +799,8 @@
     list_for_each_entry(c, &cons->node, node) {
        if (c->fd < 0)
            continue;
+       if (c->flags & CON_3215)
+           continue;
        (void)tcdrain(c->fd);
     }
     return;
@@ -680,13 +818,25 @@
        return 0;
     }
     newc->tlock = 0;
-    newc->max_canon = _POSIX_MAX_CANON;
+#if defined(__s390__) || defined(__s390x__)
+    if (newc->flags & CON_3215)
+       newc->max_canon = 130;
+    else
+#endif
+       newc->max_canon = _POSIX_MAX_CANON;
     memset(&newc->ltio, 0, sizeof(newc->ltio));
     memset(&newc->otio, 0, sizeof(newc->otio));
     memset(&newc->ctio, 0, sizeof(newc->ctio));
 
 #if defined(__s390__) || defined(__s390x__)
-    if (major(newc->dev) == 4 && minor(newc->dev) == 64)
+    if (newc->flags & CON_3215)
+       /*
+        * WARNING: Do not remove this early return!
+        * The s390x 3215 console MUST remain in O_NONBLOCK mode.
+        * Since blogd is single-threaded, setting this half-duplex device
+        * to blocking would completely freeze the daemon as soon as the
+        * kernel buffer fills up (e.g. during heavy \r floods from fsck).
+        */
        return 1;
 #endif
     if ((tflags = fcntl(newc->fd, F_GETFL)) < 0)
@@ -720,6 +870,13 @@
     newc->dev = dev;
     newc->pid = -1;
 
+#if defined(__s390__) || defined(__s390x__)
+    if (newc->flags & CON_3215)
+       newc->out = copyout3215;
+    else
+#endif
+    newc->out = copyout;
+
     if (io && !consinitIO(newc)) {
        free(newc);
        return 0;
@@ -804,7 +961,14 @@
 
        if (sscanf(dev, "%u:%u", &maj, &min) != 2)
            error("can not determine device numbers for %s: %m", tty);
-
+#if defined(__s390__) || defined(__s390x__)
+       if (maj == 4 && min == 64)
+           flags |= CON_3215;
+       if (maj == 4 && min >= 65)
+           flags |= CON_SCLP;
+       else if (maj == 227 && min >= 1)
+           flags |= CON_3270;
+#endif
        consalloc(&c, tty, flags, makedev(maj, min), io);
        free(tty);
     }
@@ -920,10 +1084,12 @@
                size_t ret;
                if (c->fd < 0)
                    continue;
-               ret = copyout(c->fd, thead, len, c->max_canon);
+               ret = c->out(c->fd, thead, len, c->max_canon);
                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;
@@ -945,7 +1111,7 @@
            size_t ret;
            if (c->fd < 0)
                continue;
-           ret = copyout(c->fd, trans, cnt, c->max_canon);
+           ret = c->out(c->fd, trans, cnt, c->max_canon);
            if (ret < 1) {
                if (cnt <= (size_t)(tend - ttail)) {
                    memcpy(ttail, trans, cnt);
@@ -953,6 +1119,8 @@
                }
                break;
            }
+           if (c->flags & CON_3215)
+               continue;
            (void)tcdrain(c->fd);                       /* Write copy of input 
to real tty */
        }
 flush:
@@ -1458,7 +1626,7 @@
            struct console *d;
            char *message;
            int eightbit;
-           int len, fdc;
+           int len, fdc, tflags;
 
            if (fdfifo >= 0)
                close(fdfifo);
@@ -1506,6 +1674,15 @@
            if (fdc > 1)
                close(fdc);
 
+           /*
+            * Mandatory: Remove none blocking mode for reading
+            * For mainframes console required to enforce the
+            * driver to READ CCW on 3215.
+            */
+           tflags = fcntl(0, F_GETFL);
+           if (tflags >= 0)
+               fcntl(0, F_SETFL, tflags & ~O_NONBLOCK);
+
            if (c->flags & CON_CONSDEV) {
                int wait = 200;
                while (wait > 0 && (len = klogctl(SYSLOG_ACTION_SIZE_UNREAD, 
NULL, 0)) > 0) {
@@ -1517,11 +1694,22 @@
        again:
            clear_input(0);
 #if defined(__s390__) || defined(__s390x__)
-           if ((major(c->dev) == 4 && minor(c->dev) >= 65) ||
-               (major(c->dev) == 227 && minor(c->dev) >= 1))
+           if (c->flags & CON_3215) {
+               /*
+                * The 3215 console MUST have a trailing newline.
+                * Otherwise the half-duplex driver won't flush the write buffer
+                * and blocks the subsequent readpw() call forever.
+                */
+               len = asprintf(&message, "\n===>> %s:\n", pwprompt);
+           } else if (c->flags & (CON_SCLP|CON_3270)) {
+               /*
+                * The 3270 console can do ANSI colouring and carriage returns,
+                * as well as the sclp consoles which are a full featured ttys.
+                */
                len = asprintf(&message, BOLD RED "\n\r%s: " NORM, pwprompt);
-           else
-               len = asprintf(&message, "\n\r===>> %s: ", pwprompt);
+           } else {
+               len = asprintf(&message, "\n===>> %s: ", pwprompt);
+           }
 #else
            if (c->flags & CON_SERIAL)
                len = asprintf(&message, BOLD RED "\n\r%s: " NORM, pwprompt);
@@ -1532,12 +1720,48 @@
                warn("can not set password prompt");
                _exit(1);
            }
-           safeout(1, message, len, c->max_canon);
+           /*
+            * Do not use safeout() here! safeout() drops the message
+            * after 100ms on EAGAIN. We MUST wait and insist on writing the 
prompt.
+            */
+           {
+               size_t written = 0;
+               while (written < len) {
+                   ssize_t p = write(1, message + written, len - written);
+                   if (p < 0) {
+                       if (errno == EINTR)
+                           continue;
+                       if (errno == EAGAIN || errno == EWOULDBLOCK) {
+                           /* * Driver buffer is full (e.g. fsck traffic jam).
+                            * Use io.c helper to wait efficiently via ppoll()
+                            * until the terminal accepts data again.
+                            */
+                           can_write(1, 100);
+                           continue;
+                       }
+                       warn("can not set password prompt on %s: %m", c->tty);
+                       break; /* Hard error */
+                   }
+                   written += p;
+               }
+           }
            free(message);
 
            /* We read byte for byte */
            newtio = c->ctio;
+#if defined(__s390__) || defined(__s390x__)
+           if (c->flags & CON_3270)
+               /*
+                * ONLY the 3270 block-mode terminal MUST keep ICANON enabled!
+                * Otherwise the tty3270 driver switches to raw mode and fails
+                * to apply the non-display hardware attribute to the input 
field.
+                */
+               newtio.c_lflag &= ~(ECHO);
+           else
+               newtio.c_lflag &= ~(ECHO|ICANON);
+#else
            newtio.c_lflag &= ~(ECHO|ICANON);
+#endif
            newtio.c_lflag |= ECHONL;
            newtio.c_cc[VTIME] = 0;
            newtio.c_cc[VMIN] = 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/libconsole/dir.c 
new/showconsole-2.38/libconsole/dir.c
--- old/showconsole-2.37/libconsole/dir.c       2026-03-18 12:18:33.000000000 
+0100
+++ new/showconsole-2.38/libconsole/dir.c       2026-04-13 14:11:49.000000000 
+0200
@@ -15,7 +15,7 @@
 #include "libconsole.h"
 
 /*
- * push and popd direcotry changes
+ * push and popd directory changes
  */
 
 typedef struct pwd_struct {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/libconsole/libconsole.h 
new/showconsole-2.38/libconsole/libconsole.h
--- old/showconsole-2.37/libconsole/libconsole.h        2026-03-18 
12:18:33.000000000 +0100
+++ new/showconsole-2.38/libconsole/libconsole.h        2026-04-13 
14:11:49.000000000 +0200
@@ -40,6 +40,9 @@
 # ifndef  typeof
 #  define typeof               __typeof__
 # endif
+# ifndef  unused
+#  define unused               __unused__
+# endif
 #endif
 #ifndef  attribute
 # define attribute(attr)       __attribute__(attr)
@@ -104,6 +107,7 @@
     int flags;
     int fd, tlock;
     ssize_t max_canon;
+    ssize_t (*out)(int, const void *, size_t, ssize_t);
     struct termios ltio, otio, ctio;
 };
 
@@ -114,6 +118,9 @@
 #define CON_ANYTIME    (16)    /* Safe to call when cpu is offline */
 #define CON_BRL                (32)    /* Used for a braille device */
 #define CON_SERIAL     (64)    /* Serial line */
+#define CON_3215       (128)   /* s390x 3215 halfduplex console */
+#define CON_3270       (256)   /* s390x 3270 console */
+#define CON_SCLP       (512)   /* s390x sclp terminals */
 
 extern sigset_t omask;
 extern int final;
@@ -178,6 +185,9 @@
 /* proc.c */
 extern char *proc2exe(const pid_t pid);
 extern void list_fd(const pid_t pid);
+extern void parse_cmdline(void);
+extern char* value_cmdline(const char*);
+void free_cmdline(void);
 
 /* readpw.c */
 extern ssize_t readpw(int fd, char *pass, int eightbit);
@@ -203,11 +213,12 @@
 
 /* vmcp.c */
 #if defined(__s390__) || defined(__s390x__)
-int openvmcp(void);
-char* queryterm(int fd);
-int setterm(int fd);
-int restoreterm(int fd);
-void parseterm(char *msg);
+extern int isinteger(const char *str);
+extern int openvmcp(void);
+extern char* queryterm(int fd);
+extern int setterm(int fd, char *tout);
+extern int restoreterm(int fd);
+extern void parseterm(char *msg);
 #endif
 
 #define MAX_PASSLEN    LINE_MAX
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/libconsole/log.c 
new/showconsole-2.38/libconsole/log.c
--- old/showconsole-2.37/libconsole/log.c       2026-03-18 12:18:33.000000000 
+0100
+++ new/showconsole-2.38/libconsole/log.c       2026-04-13 14:11:49.000000000 
+0200
@@ -36,7 +36,7 @@
 /*
  * The stdio file pointer for our log file
  */
-static FILE *flog = NULL;
+extern FILE *flog;
 
 /*
  * Signal control for writing on log file
@@ -634,15 +634,17 @@
 
 FILE *open_logging(int fd)
 {
+    FILE *log;
+
     lock(&llock);
-    flog = fdopen(fd, "a");
-    if (!flog) {
+    log = fdopen(fd, "a");
+    if (!log) {
        unlock(&llock);
-       error("Can not open boot loggin file");
+       error("Can not open boot logging file");
     }
     unlock(&llock);
 
-    return flog;
+    return log;
 }
 
 FILE *close_logging(void)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/libconsole/proc.c 
new/showconsole-2.38/libconsole/proc.c
--- old/showconsole-2.37/libconsole/proc.c      2026-03-18 12:18:33.000000000 
+0100
+++ new/showconsole-2.38/libconsole/proc.c      2026-04-13 14:11:49.000000000 
+0200
@@ -13,7 +13,9 @@
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
+#include "listing.h"
 #include "libconsole.h"
 
 /*
@@ -71,3 +73,139 @@
     }
     closedir(dir);
 }
+
+/*
+ * Parse kernel command line for our entries
+ */
+static list_t lparameter = { &(lparameter), &(lparameter) };
+typedef struct parameter_s {
+    list_t     handle;
+    char       *val;
+    char       *key;
+} parameter_t;
+static parameter_t *parameter = (parameter_t*)0;
+
+void parse_cmdline(void) {
+    char buf[4096];
+    list_t *head;
+    FILE *fp;
+
+#ifdef DEBUG_PROC
+    fp = fopen("cmdline", "r");
+#else
+    fp = fopen("/proc/cmdline", "r");
+#endif
+    if (!fp)
+       return;
+
+    if (fgets(buf, sizeof(buf), fp)) {
+       char *saveptr;
+       char *token = strtok_r(buf, " \n", &saveptr);
+
+       while (token) {
+           const char *prefix = "blog.";
+           const size_t plen = strlen(prefix);
+
+           if (strncmp(token, prefix , plen) == 0) {
+               char *kv = token + plen;
+               char *eq = strchr(kv, '=');
+
+               if (eq) {
+                   parameter_t *pm;
+                   int exists = 0;
+
+                   *eq = '\0';
+                   char *key = kv;
+                   char *val = eq + 1;
+
+                    if (*val == '\0' || *val == ' ') {
+                        *eq = '='; /* restore token for strtok_r */
+                        token = strtok_r(NULL, " \n", &saveptr);
+                        continue;
+                    }
+
+                   list_for_each_entry(pm, &lparameter, handle) {
+                       if (strcmp(pm->key, key) == 0) {
+                           free(pm->val);
+                           pm->val = strdup(val);
+                           exists++;
+                       }
+                   }
+                   if (!exists) {
+                       if (posix_memalign((void**)&pm, sizeof(void*), 
alignof(parameter_t)+strlen(key)+1) != 0 || !pm)
+                           error("memory allocation");
+                       pm->key = ((char*)pm)+alignof(parameter_t);
+                       strcpy(pm->key, key);
+                       pm->val = strdup(val);
+
+                       if (!parameter) {
+                           head = &lparameter;
+                           parameter = (parameter_t *)head;
+                       } else
+                           head = &(parameter)->handle;
+                       insert(&pm->handle, head);
+                   }
+                   *eq = '='; /* restore token for strtok_r */
+               }
+           }
+           token = strtok_r(NULL, " \n", &saveptr);
+       }
+    }
+    fclose(fp);
+}
+
+char* value_cmdline(const char* key) {
+    parameter_t *pm;
+    list_for_each_entry(pm, &lparameter, handle) {
+       if (strcmp(pm->key, key) == 0) {
+            return pm->val;
+        }
+    }
+    return (char*)0;
+}
+
+void free_cmdline(void) {
+    parameter_t *pm, *n;
+    list_for_each_entry_safe(pm, n, &lparameter, handle) {
+        free(pm->val);
+        delete(&pm->handle);
+        free(pm);
+    }
+}
+#ifdef DEBUG_PROC
+static int _isinteger(const char *str)
+{
+    int errs = errno, ret = 1;
+    char *endptr;
+
+    errno = 0;
+    long attribute((unused)) val = strtol(str, &endptr, 10);
+
+    /* Check if no digits were found at all */
+    if (str == endptr)
+        ret = 0;
+
+    /* Check for overflow or underflow */
+    if (errno == ERANGE)
+        ret = 0;
+
+    /* Check for trailing non-numeric characters (e.g., "123abc") */
+    if (*endptr != '\0')
+        ret = 0;
+
+    errno = errs;
+    return ret;
+}
+int main(void)
+{
+    parameter_t *pm;
+    char *key;
+    parse_cmdline();
+    list_for_each_entry(pm, &lparameter, handle) {
+        printf("key %s = val %s\n", pm->key, pm->val);
+    }
+    key = value_cmdline("timeout");
+    if (key)
+        printf("%s %d\n", key, _isinteger(key));
+}
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/libconsole/readpw.c 
new/showconsole-2.38/libconsole/readpw.c
--- old/showconsole-2.37/libconsole/readpw.c    2026-03-18 12:18:33.000000000 
+0100
+++ new/showconsole-2.38/libconsole/readpw.c    2026-04-13 14:11:49.000000000 
+0200
@@ -39,15 +39,32 @@
     struct chardata cp;
     int ret;
 
-    cp.eol = *ptr = '\0'; 
+    cp.eol = *ptr = '\0';
 
     while (cp.eol == '\0') {
        char ascval, c;
        errno = 0;
-
+#if 0
+       /*
+        * Sidemark: DO NOT USE THIS ON 3215 OF S390
+        * Wait in input without busy waiting.
+        * If we use a negative timeout the ppoll() blocks
+        * up to the point where even a halfduplex 3215
+        * console provides input data.
+        */
+       if (!can_read(fd, -1)) {
+           if (errno == EINTR)
+               continue;
+           warn("can_read failed on %s: %m", currenttty);
+           return -1;
+       }
+#endif
        ret = read(fd, &c, 1);
        if (ret < 0) {
            if (errno == EINTR || errno == EAGAIN) {
+               /*
+                * Due to can_read() EAGAIN should not happen.
+                */
                usleep(250000);
                continue;
            }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/showconsole-2.37/libconsole/vmcp.c 
new/showconsole-2.38/libconsole/vmcp.c
--- old/showconsole-2.37/libconsole/vmcp.c      2026-03-18 12:18:33.000000000 
+0100
+++ new/showconsole-2.38/libconsole/vmcp.c      2026-04-13 14:11:49.000000000 
+0200
@@ -25,6 +25,31 @@
 #define        VMCP_SETBUF             _IOW(0x10, 2, int)
 #define        VMCP_GETCODE            _IOR(0x10, 1, int)
 
+int isinteger(const char *str)
+{
+    int errs = errno, ret = 1;
+    long attribute((unused)) val;
+    char *endptr;
+
+    errno = 0;
+    val = strtol(str, &endptr, 10);
+
+    /* Check if no digits were found at all */
+    if (str == endptr)
+       ret = 0;
+
+    /* Check for overflow or underflow */
+    if (errno == ERANGE)
+       ret = 0;
+
+    /* Check for trailing non-numeric characters (e.g., "123abc") */
+    if (*endptr != '\0')
+       ret = 0;
+
+    errno = errs;
+    return ret;
+}
+
 int openvmcp(void)
 {
     return open(VMCP_DEVICE_NODE, O_RDWR|O_NOCTTY);
@@ -41,55 +66,59 @@
     buffersize = num * pagesize;
 
     if (ioctl(fd, VMCP_SETBUF, &buffersize) == -1)
-        goto out;
+       goto out;
     do {
        rc = write(fd, question, strlen(question));
-        if (rc < 0) {
+       if (rc < 0) {
            if (errno != EINTR)
                goto out;
-        }
+       }
     } while (rc < 0);
     if (ioctl(fd, VMCP_GETCODE, &rc) == -1)
-        goto out;
+       goto out;
     if (ioctl(fd, VMCP_GETSIZE, &buffersize) == -1)
-        goto out;
+       goto out;
     ret = (char*)malloc(buffersize);
     if (!ret)
-        goto out;
+       goto out;
     do {
        rc = read(fd, ret, buffersize);
-        if (rc < 0) {
+       if (rc < 0) {
            if (errno != EINTR)
                goto out;
-        }
+       }
     } while (rc < 0);
 out:
     return ret;
 }
 
-int setterm(int fd)
+int setterm(int fd, char *tout)
 {
-    const char* instruction = "TERMINAL MORE 0 0 HOLD OFF";
+    char *instruction;
     long pagesize = sysconf(_SC_PAGESIZE);
     int rc = 0, num, buffersize;
     int ret = -1;
 
+    if (asprintf(&instruction, "TERMINAL MORE %s 0 HOLD OFF", tout) == -1)
+       goto out;
+
     num = (strlen(instruction) + pagesize - 1)/pagesize;
     buffersize = num * pagesize;
 
     if (ioctl(fd, VMCP_SETBUF, &buffersize) == -1)
-        goto out;
+       goto out;
     do {
        rc = write(fd, instruction, strlen(instruction));
-        if (rc < 0) {
+       if (rc < 0) {
            if (errno != EINTR)
                goto out;
-        }
+       }
     } while (rc < 0);
+    free(instruction);
     if (ioctl(fd, VMCP_GETCODE, &rc) == -1)
-        goto out;
+       goto out;
     if (ioctl(fd, VMCP_GETSIZE, &buffersize) == -1)
-        goto out;
+       goto out;
     if (rc == 0 && buffersize == 0)
        ret = 0;
 out:
@@ -114,19 +143,19 @@
     buffersize = num * pagesize;
 
     if (ioctl(fd, VMCP_SETBUF, &buffersize) == -1)
-        goto out;
+       goto out;
     do {
        rc = write(fd, instruction, strlen(instruction));
-        if (rc < 0) {
+       if (rc < 0) {
            if (errno != EINTR)
                goto out;
-        }
+       }
     } while (rc < 0);
     free(instruction);
     if (ioctl(fd, VMCP_GETCODE, &rc) == -1)
-        goto out;
+       goto out;
     if (ioctl(fd, VMCP_GETSIZE, &buffersize) == -1)
-        goto out;
+       goto out;
     if (rc == 0 && buffersize == 0)
        ret = 0;
 out:

Reply via email to