Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package blog for openSUSE:Factory checked in at 2025-04-29 16:39:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/blog (Old) and /work/SRC/openSUSE:Factory/.blog.new.30101 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "blog" Tue Apr 29 16:39:44 2025 rev:21 rq:1273161 version:2.35 Changes: -------- --- /work/SRC/openSUSE:Factory/blog/blog.changes 2025-04-20 19:50:21.696861330 +0200 +++ /work/SRC/openSUSE:Factory/.blog.new.30101/blog.changes 2025-04-29 16:39:48.280739083 +0200 @@ -1,0 +2,13 @@ +Mon Apr 28 13:42:43 UTC 2025 - Dr. Werner Fink <wer...@suse.de> + +- Update to version 2.35 + * Make s390 3215 console work that is use EPOLLOUT|EPOLLONESHOT + to control if we can write to ttyS0 in nonblocking mode and if + not reenable EPOLLOUT|EPOLLONESHOT. + * At boot set for ttyS0 via vmcp API nonblocking MORE mode with + `0 0'. It beeps but boots. +- Remove patches now upstream + * blog-3215.patch + * blog-install.patch + +------------------------------------------------------------------- Old: ---- blog-3215.patch blog-install.patch showconsole-2.34.tar.gz New: ---- showconsole-2.35.tar.gz BETA DEBUG BEGIN: Old:- Remove patches now upstream * blog-3215.patch * blog-install.patch Old: * blog-3215.patch * blog-install.patch BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ blog.spec ++++++ --- /var/tmp/diff_new_pack.6SEkPR/_old 2025-04-29 16:39:49.048771342 +0200 +++ /var/tmp/diff_new_pack.6SEkPR/_new 2025-04-29 16:39:49.052771511 +0200 @@ -17,7 +17,7 @@ Name: blog -Version: 2.34 +Version: 2.35 %define sonum 2 Release: 0 Summary: Boot logging @@ -26,8 +26,6 @@ URL: https://github.com/bitstreamout/showconsole Source: https://github.com/bitstreamout/showconsole/archive/v%{version}.tar.gz#/showconsole-%{version}.tar.gz Source1: blog-rpmlintrc -Patch0: blog-install.patch -Patch1: blog-3215.patch BuildRequires: bash %if 0%{suse_version} >= 1550 # regenerate_initrd_post moved to rpm-config-SUSE:initrd.macros @@ -89,8 +87,6 @@ %prep %setup -q -n showconsole-%version -%patch -P0 -%patch -P1 for l in rt util pthread do ln -sf %{_libdir}/lib${l}.so.[0-9] lib${l}.so ++++++ showconsole-2.34.tar.gz -> showconsole-2.35.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/Makefile new/showconsole-2.35/Makefile --- old/showconsole-2.34/Makefile 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/Makefile 2025-04-28 15:35:31.000000000 +0200 @@ -15,7 +15,7 @@ DEBUG = DESTDIR = MAJOR := 2 -MINOR := 34 +MINOR := 35 VERSION := $(MAJOR).$(MINOR) DATE = $(shell date +'%d%b%y' | tr '[:lower:]' '[:upper:]') COPTS = @@ -83,7 +83,7 @@ $(SED) '$(SEDOPTS)' $< > $@ $(libfiles): $(L)libconsole.h listing.h -libconsole.a: $(patsubst %.c,%.o,$(libfiles)) +libconsole.a: $(patsubst %.c,%.o,$(libfiles)) $(L)libconsole.h listing.h $(AR) rusv $@ $^ libblogger.o: libconsole.a @@ -137,50 +137,28 @@ $(INSTSCR) module-setup.sh $(DESTDIR)$(DRACUTMOD)/ $(LINK) libblogger.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libblogger.so.$(MAJOR) $(LINK) libblogger.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libblogger.so - for unit in blog blog-final blog-quit blog-store-messages blog-switch-root blog-switch-initramfs blog-umount ; do \ - $(INSTCON) $${unit}.service $(DESTDIR)$(SYSDUNITS)/ ; \ - done - for unit in systemd-ask-password-blog.path systemd-ask-password-blog.service ; do \ - $(INSTCON) $${unit} $(DESTDIR)$(SYSDUNITS)/ ; \ - done - for target in default sysinit basic local-fs-pre halt rescue shutdown reboot poweroff kexec emergency initrd-switch-root; do \ - $(MKDIR) $(DESTDIR)$(SYSDUNITS)/$${target}.target.wants ; \ - done - for service in systemd-ask-password-blog ; do \ - $(MKDIR) $(DESTDIR)$(SYSDUNITS)/$${target}.service.wants ; \ - done - for unit in blog-quit.service ; do \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/default.target.wants/$${unit} ; \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/rescue.target.wants/$${unit} ; \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/emergency.target.wants/$${unit} ; \ - done - for unit in blog.service ; do \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/basic.target.wants/$${unit} ; \ - done - for unit in blog-store-messages.service systemd-ask-password-blog.path ; do \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/sysinit.target.wants/$${unit} ; \ - done - for unit in blog-umount.service ; do \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/local-fs-pre.target.wants/$${unit} ; \ - done - for unit in blog-switch-initramfs.service ; do \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/reboot.target.wants/$${unit} ; \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/poweroff.target.wants/$${unit} ; \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/kexec.target.wants/$${unit} ; \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/halt.target.wants/$${unit} ; \ - done - for unit in reboot poweroff kexec halt ; do \ - $(LINK) ../blog-$${unit}.service $(DESTDIR)$(SYSDUNITS)/$${unit}.target.wants/blog-$${unit}.service ; \ - done - for target in systemd-ask-password-blog.service ; do \ - $(MKDIR) $(DESTDIR)$(SYSDUNITS)/$${target}.wants ; \ - done - for unit in blog.service blog-switch-root.service ; do \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/initrd-switch-root.target.wants/$${unit} ; \ - done - for unit in systemd-vconsole-setup.service ; do \ - $(LINK) ../$${unit} $(DESTDIR)$(SYSDUNITS)/systemd-ask-password-blog.service.wants/$${unit} ; \ - done + @set +x; \ + export initdir=$(DESTDIR); \ + export systemdsystemunitdir=$(SYSDUNITS); \ + inst_multiple () { \ + if test $$1 = -o; then \ + shift; \ + for o; do \ + test -e $${o##*/} && command install -vp -m 0644 $${o##*/} $${initdir}$${o} || : ; \ + done; \ + else \ + command install -vp -m 0755 $${1##*/} $${initdir}$(SBINDIR)/; \ + fi; \ + }; \ + ln_r () { \ + local rel="$$(realpath -m --relative-to=$${2%/*}/ $${1%/*}/)"; \ + ln -sf $${rel}/$${1##*/} $${initdir}$${2}; }; \ + . ./module-setup.sh ; \ + set -xe; install + $(MKDIR) $(DESTDIR)$(SYSDUNITS)/local-fs-pre.target.wants + $(MKDIR) $(DESTDIR)$(SYSDUNITS)/default.target.wants + $(LINK) ../blog-umount.service $(DESTDIR)$(SYSDUNITS)/local-fs-pre.target.wants/ + $(LINK) ../blog-quit.service $(DESTDIR)$(SYSDUNITS)/default.target.wants/ # # Make distribution @@ -205,8 +183,11 @@ isserial.c \ isserial.8 \ blog.service \ - blog-final.service \ + blog-halt.service \ + blog-kexec.service \ + blog-poweroff.service \ blog-quit.service \ + blog-reboot.service \ blog-store-messages.service.in \ blog-switch-root.service \ blog-switch-initramfs.service \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/blog-store-messages.service.in new/showconsole-2.35/blog-store-messages.service.in --- old/showconsole-2.34/blog-store-messages.service.in 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/blog-store-messages.service.in 2025-04-28 15:35:31.000000000 +0200 @@ -1,9 +1,13 @@ [Unit] Description=Tell blogd about writable boot log DefaultDependencies=no +RequiresMountsFor=/var/log/boot.log +Conflicts=shutdown.target +After=systemd-remount-fs.service systemd-tmpfiles-setup.service auditd.service After=local-fs.target Before=sysinit.target ConditionPathExists=!/etc/initrd-release +ConditionPathIsReadWrite=/var/log [Service] Type=oneshot diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/blog.service new/showconsole-2.35/blog.service --- old/showconsole-2.34/blog.service 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/blog.service 2025-04-28 15:35:31.000000000 +0200 @@ -6,6 +6,7 @@ Before=systemd-ask-password-blog.service ConditionKernelCommandLine=!blog.enable=0 ConditionVirtualization=!container +ConditionPathExists=/dev/console IgnoreOnIsolate=true RefuseManualStart=true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/blogd.c new/showconsole-2.35/blogd.c --- old/showconsole-2.34/blogd.c 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/blogd.c 2025-04-28 15:35:31.000000000 +0200 @@ -191,9 +191,11 @@ /* * To be able to reconnect to real tty on EIO */ -static void reconnect(int fd) +static int reconnect(int fd) { struct console * c; + int ret = 0, tflags; + int olderr = errno; list_for_each_entry(c, &cons->node, node) { int newfd; @@ -209,12 +211,27 @@ default: /* IO of system consoles */ if ((newfd = open_tty(c->tty, O_WRONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC)) < 0) error("can not open %s: %m", c->tty); + epoll_delete(c->fd); dup2(newfd, c->fd); if (newfd != c->fd) close(newfd); + epoll_addwrite(c->fd, &epoll_write_watchdog); + ret = 1; +#if defined(__s390__) || defined(__s390x__) + if (major(c->dev) == 4 && minor(c->dev) == 64) + break; +#endif + if ((tflags = fcntl(c->fd, F_GETFL)) < 0) + warn("can not get terminal flags of %s", c->tty); + tflags &= ~(O_NONBLOCK); + if (fcntl(c->fd, F_SETFL, tflags) < 0) + warn("can not set terminal flags of %s", c->tty); break; } } + errno = olderr; + + return ret; } @@ -222,6 +239,9 @@ static void flush_handler (void) attribute((noinline)); static void exit_handler (void) attribute((noinline)); +#if defined(__s390__) || defined(__s390x__) +static void vmcp_handler (void) attribute((noinline)); +#endif /* * Now do the job @@ -325,8 +345,22 @@ o.c_cc[VMIN] = CMIN; } #if defined(__s390__) || defined(__s390x__) - if (major(c->dev) == 4 && minor(c->dev) == 65) { - ioctl(c->fd, TIOCSBRK); + 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); + } + close(vmcp); + atexit(vmcp_handler); /* Register vmcp restore exit handler */ + } + ioctl(c->fd, TIOCCBRK); usleep(1000); } #endif @@ -605,3 +639,13 @@ reset_signal(SIGTERM, &saved_sigterm); reset_signal(SIGSYS, &saved_sigsys); } + +#if defined(__s390__) || defined(__s390x__) +static void vmcp_handler (void) +{ + int vmcp = openvmcp(); + if (vmcp >= 0) + restoreterm(vmcp); + close(vmcp); +} +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/libconsole/console.c new/showconsole-2.35/libconsole/console.c --- old/showconsole-2.34/libconsole/console.c 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/libconsole/console.c 2025-04-28 15:35:31.000000000 +0200 @@ -26,6 +26,7 @@ #include <sys/klog.h> #include <sys/mman.h> #include <sys/prctl.h> +#include <sys/select.h> /* declares fd_set */ #include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> @@ -69,6 +70,13 @@ volatile sig_atomic_t asking; /* + * One of the device for console are blocked if true. + */ +static fd_set blocked; +static const fd_set empty; +#define FD_BUSY(arg) (memcmp(arg, &empty, sizeof(fd_set)) != 0) + +/* * Move log file to old file */ int final = 0; @@ -117,23 +125,29 @@ } /* + * The stdio file pointer for our log file + */ +struct console *cons; +static FILE * flog = NULL; +static int fdread = -1; +static int fdfifo = -1; + +static int fdsock = -1; +static char *pwprompt; +static char *password; +static int32_t *pwsize; + +/* * Arg used: safe out */ -static void (*vc_reconnect)(int fd); +static int (*vc_reconnect)(int fd); void safeout (int fd, const void *ptr, size_t s, ssize_t max) { int saveerr = errno; - int issocket = 0; - struct stat st; - - if (fstat(fd, &st) < 0) - goto out; - if (S_ISSOCK(st.st_mode)) - issocket++; while (s > 0) { ssize_t p; - if (issocket) { + if (fdsock == fd) { /* We use only ONE socket, no fstat() required */ int flags = MSG_NOSIGNAL; if (s > max) flags |= MSG_MORE; @@ -142,7 +156,7 @@ p = write (fd, ptr, (max < 1) ? 1 : ((s < (size_t)max) ? s : (size_t)max)); if (p < 0) { if (errno == EPIPE) - break; + break; /* Drop the rest of the message */ if (errno == EINTR) { errno = 0; @@ -150,15 +164,19 @@ } if (errno == EAGAIN || errno == EWOULDBLOCK) { - /* Avoid high load: wait upto two seconds if system is not ready */ - if (can_write(fd, 2)) + /* Avoid high load: wait upto 100 milli seconds if system is not ready */ + if (can_write(fd, 100)) continue; + + FD_SET(fd, &blocked); + epoll_reenable(fd); + break; /* Drop the rest of the message */ } if (errno == EIO) { if (!vc_reconnect) lerror("can not write to fd %d", fd); - - (*vc_reconnect)(fd); + if (!(*vc_reconnect)(fd)) + lerror("can not write to fd %d", fd); errno = 0; continue; } @@ -172,6 +190,51 @@ } /* + * Arg used: copy out + */ +static ssize_t copyout (int fd, const void *ptr, size_t s, ssize_t max) +{ + int saveerr = errno; + ssize_t r = 0, p; + do { + p = write (fd, ptr, (max < 1) ? 1 : ((s < (size_t)max) ? s : (size_t)max)); + if (p < 0) { + if (errno == EINTR) { + errno = 0; + continue; + } + if (errno == EAGAIN || errno == EWOULDBLOCK) { + FD_SET(fd, &blocked); + epoll_reenable(fd); + if (r == 0) + r = -1; + break; + } + if (errno == EIO) { + if (!vc_reconnect) { + warn("can not write to fd %d", fd); + break; + } + if (!(*vc_reconnect)(fd)) { + warn("can not write to fd %d", fd); + break; + } + errno = 0; + continue; + } + warn("can not write to fd %d", fd); + break; + } + ptr += p; + s -= p; + r += p; + } while (s > 0); + + errno = saveerr; + return r; +} + +/* * Twice used: safe in */ @@ -241,19 +304,6 @@ } /* - * The stdio file pointer for our log file - */ -struct console *cons; -static FILE * flog = NULL; -static int fdread = -1; -static int fdfifo = -1; - -static int fdsock = -1; -static char *pwprompt; -static char *password; -static int32_t *pwsize; - -/* * Signal control for writing on log file */ volatile sig_atomic_t nsigsys; @@ -276,7 +326,11 @@ /* * Our temporary buffer during asking a password/passphrase */ +#if defined(__s390__) || defined(__s390x__) +static char temp[8*TRANS_BUFFER_SIZE]; +#else static char temp[4*TRANS_BUFFER_SIZE]; +#endif static const char *const tend = temp + sizeof(temp); static char * thead = temp; static char * ttail = temp; @@ -289,9 +343,12 @@ static void epoll_console_in(int) attribute((noinline)); static void epoll_fifo_in(int) attribute((noinline)); static void epoll_socket_accept(int) attribute((noinline)); +void epoll_write_watchdog(int) attribute((noinline)); -void prepareIO(void (*rfunc)(int), const int listen, const int input) +void prepareIO(int (*rfunc)(int), const int listen, const int input) { + struct console *c; + (void)sigfillset(&omask); (void)sigdelset(&omask, SIGQUIT); (void)sigdelset(&omask, SIGTERM); @@ -299,7 +356,7 @@ (void)sigdelset(&omask, SIGIO); vc_reconnect = rfunc; - fdsock = listen; + fdsock = listen; /* We use only ONE socket ... see also safeout() */ fdread = input; if (fifo_name && fdfifo < 0) { @@ -326,6 +383,12 @@ if (fdsock >= 0) epoll_addread(fdsock, &epoll_socket_accept); + list_for_each_entry(c, &cons->node, node) { + if (c->fd < 0) + continue; + epoll_addwrite(c->fd, &epoll_write_watchdog); + } + (void)mlockall(MCL_FUTURE); } @@ -352,26 +415,22 @@ safein_noexit = noerr; /* Do or do not not exit on unexpected errors */ for (n = 0; n < nfds; n++) { - if (evlist[n].events & (EPOLLIN|EPOLLPRI)) { - void (*efunc)(int); - int fd; - efunc = epoll_handle(evlist[n].data.ptr, &fd); - if (!efunc) - continue; + void (*efunc)(int); + int fd; + efunc = epoll_handle(evlist[n].data.ptr, &fd); + if (!efunc) + continue; + ret = 1; + if (evlist[n].events & (EPOLLIN|EPOLLOUT)) { efunc(fd); - ret = 1; + continue; } - } - - for (n = 0; n < nfds; n++) { - if (evlist[n].events & (EPOLLOUT)) { - void (*efunc)(int); - int fd; - efunc = epoll_handle(evlist[n].data.ptr, &fd); - if (!efunc) - continue; - efunc(fd); + if (evlist[n].events & (EPOLLRDHUP|EPOLLHUP)) { + warn("epoll returns RDHUP or HUP"); + continue; } + if (evlist[n].events & EPOLLERR) + warn("epoll returns error"); } safein_noexit = 0; @@ -598,11 +657,17 @@ 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) + return 1; +#endif if ((tflags = fcntl(newc->fd, F_GETFL)) < 0) warn("can not get terminal flags of %s", newc->tty); tflags &= ~(O_NONBLOCK); tflags |= O_NOCTTY; + if (fcntl(newc->fd, F_SETFL, tflags) < 0) warn("can not set terminal flags of %s", newc->tty); @@ -788,18 +853,36 @@ parselog(trans, cnt); /* Parse and make copy of the input */ + list_for_each_entry(c, &cons->node, node) { + int len; + char *mesg; + if (c->fd < 0) + continue; + if (FD_ISSET(c->fd, &blocked)) + break; /* Let's wait on epoll event */ + if (can_write(c->fd, 50)) + continue; + FD_SET(c->fd, &blocked); + epoll_reenable(c->fd); + len = asprintf(&mesg, "blogd: console device %s is blocked", c->tty); + if (len < 0) + error("can not allocate string"); + copylog(mesg, len); + free(mesg); + } + /* * During asking a password/passphrase we are temporary * buffer console output to release it if we've got an answer. */ - if (asking) { + if (asking || FD_BUSY(&blocked)) { if (cnt <= (size_t)(tend - ttail)) { memcpy(ttail, trans, cnt); tavail = (ttail += cnt) - thead; } - goto flush; /* Temporary silent as waiting on passphrase */ - + goto flush; /* Temporary silent as waiting on + passphrase or console device */ } else while (tavail > 0) { /* Empty temporary buffer if any */ size_t len = (size_t)tavail; @@ -807,9 +890,13 @@ len = TRANS_BUFFER_SIZE; list_for_each_entry(c, &cons->node, node) { + size_t ret; if (c->fd < 0) continue; - safeout(c->fd, thead, len, c->max_canon); + ret = copyout(c->fd, thead, len, c->max_canon); + if (ret < 1) + goto flush; + len = ret; /* First make write out all but Second? */ (void)tcdrain(c->fd); /* Write copy of input to real tty */ } thead += len; @@ -828,9 +915,17 @@ } list_for_each_entry(c, &cons->node, node) { + size_t ret; if (c->fd < 0) continue; - safeout(c->fd, trans, cnt, c->max_canon); + ret = copyout(c->fd, trans, cnt, c->max_canon); + if (ret < 1) { + if (cnt <= (size_t)(tend - ttail)) { + memcpy(ttail, trans, cnt); + tavail = (ttail += cnt) - thead; + } + break; + } (void)tcdrain(c->fd); /* Write copy of input to real tty */ } flush: @@ -1213,6 +1308,14 @@ } /* + * The watch dog for all outgoing terminals + */ +void epoll_write_watchdog(int fd) +{ + FD_CLR(fd, &blocked); +} + +/* * Do handle the connection in data */ char* currenttty; @@ -1243,7 +1346,7 @@ wait = 200; while (wait > 0 && (len = klogctl(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0)) > 0) { usleep(1000); - wait--; + wait--; } wait = 0; @@ -1278,6 +1381,8 @@ epoll_close_fd(); close(epfd); } + FD_ZERO(&blocked); + vc_reconnect = NULL; dup2(1, 2); dup2(c->fd, 0); @@ -1286,7 +1391,6 @@ list_for_each_entry(d, &cons->node, node) if (d->fd >= 0) { - (void)tcdrain(d->fd); close(d->fd); d->fd = -1; } @@ -1296,6 +1400,7 @@ set_signal(SIGHUP, NULL, SIG_DFL); prctl(PR_SET_PDEATHSIG, SIGHUP); + prctl(PR_SET_NAME, "login"); set_signal(SIGCHLD, NULL, SIG_DFL); set_signal(SIGINT, NULL, SIG_DFL); @@ -1319,7 +1424,7 @@ (major(c->dev) == 227 && minor(c->dev) >= 1)) len = asprintf(&message, BOLD RED "\n\r%s: " NORM, pwprompt); else - len = asprintf(&message, "\n\r>> %s: ", pwprompt); + len = asprintf(&message, "\n\r===>> %s: ", pwprompt); #else if (c->flags & CON_SERIAL) len = asprintf(&message, BOLD RED "\n\r%s: " NORM, pwprompt); @@ -1349,8 +1454,8 @@ tcsetattr(0, TCSANOW, &c->ctio); safeout(1, "\n", 1, c->max_canon); - if (*pwsize == 0) - goto again; + if (*pwsize == 0) + goto again; if (*pwsize < 0) warn("can not read password"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/libconsole/epoll.c new/showconsole-2.35/libconsole/epoll.c --- old/showconsole-2.34/libconsole/epoll.c 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/libconsole/epoll.c 2025-04-28 15:35:31.000000000 +0200 @@ -28,14 +28,14 @@ int fd; } *epolls; -void epoll_addread(int fd, void *fptr) +static inline void epoll_addition(int fd, void *fptr, uint32_t flags) { struct epoll_event ev = {}; struct epolls *ep; list_t *head; int ret; - ev.events = EPOLLIN|EPOLLPRI; + ev.events = flags; if (posix_memalign((void**)&ep, sizeof(void*), alignof(struct epolls)) != 0 || !ep) error("memory allocation"); @@ -58,6 +58,16 @@ error("can not add %d file descriptor on epoll file descriptor", fd); } +void epoll_addread(int fd, void *fptr) +{ + epoll_addition(fd, fptr, EPOLLIN|EPOLLPRI|EPOLLRDHUP); +} + +void epoll_addwrite(int fd, void *fptr) +{ + epoll_addition(fd, fptr, EPOLLOUT|EPOLLONESHOT|EPOLLPRI|EPOLLERR); +} + void epoll_answer_once(int fd, void *fptr) { struct epoll_event ev = {}; @@ -88,6 +98,26 @@ error("can not add %d file descriptor on epoll file descriptor", fd); } +void epoll_reenable(int fd) +{ + struct epoll_event ev = {}; + struct epolls *ep; + + ev.events = EPOLLOUT|EPOLLONESHOT; + + list_for_each_entry(ep, &lpolls, watch) { + if (ep->fd == fd) { + int ret; + ev.data.ptr = (void*)ep; + ret = epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev); + if (ret < 0) + error("can not add %d file descriptor on epoll file descriptor", fd); + break; + } + } + +} + void epoll_delete(int fd) { struct epolls *ep, *n; @@ -95,8 +125,6 @@ list_for_each_entry_safe(ep, n, &lpolls, watch) { if (ep->fd == fd) { - if (isatty(fd)) - tcdrain(fd); delete(&ep->watch); free(ep); break; @@ -118,8 +146,6 @@ if (ep == ptr) { handle = ep->handle; *fd = ep->fd; - if (isatty(ep->fd)) - tcdrain(ep->fd); break; } } @@ -132,9 +158,6 @@ { struct epolls *ep; - list_for_each_entry(ep, &lpolls, watch) { - if (isatty(ep->fd)) - tcdrain(ep->fd); + list_for_each_entry(ep, &lpolls, watch) close(ep->fd); - } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/libconsole/io.c new/showconsole-2.35/libconsole/io.c --- old/showconsole-2.34/libconsole/io.c 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/libconsole/io.c 2025-04-28 15:35:31.000000000 +0200 @@ -21,7 +21,7 @@ * The sigset_t omask is given in console.c * */ -int can_read(int fd, const long timeout) +int can_read(int fd, const time_t msec) { struct pollfd fds = { .fd = fd, @@ -29,19 +29,19 @@ .revents = 0, }; struct timespec ts = { - .tv_sec = (time_t)(timeout/1000), - .tv_nsec = (timeout % 1000) * 1000000, + .tv_sec = (time_t)(msec/1000), + .tv_nsec = (msec % 1000) * 1000000, }; int ret; do { - ret = ppoll(&fds, 1, (timeout < 0) ? NULL : &ts, &omask); + ret = ppoll(&fds, 1, (msec < 0) ? NULL : &ts, &omask); } while ((ret < 0) && (errno == EINTR)); return (ret == 1) && (fds.revents & (POLLIN|POLLPRI)); } -int can_write(int fd, const int timeout) +int can_write(int fd, const time_t msec) { struct pollfd fds = { .fd = fd, @@ -49,13 +49,13 @@ .revents = 0, }; struct timespec ts = { - .tv_sec = (time_t)(timeout/1000), - .tv_nsec = (timeout % 1000) * 1000000, + .tv_sec = (time_t)(msec/1000), + .tv_nsec = (msec % 1000) * 1000000, }; int ret; do { - ret = ppoll(&fds, 1, (timeout < 0) ? NULL : &ts, &omask); + ret = ppoll(&fds, 1, (msec < 0) ? NULL : &ts, &omask); } while ((ret < 0) && (errno == EINTR)); return (ret == 1) && (fds.revents & (POLLOUT|POLLWRBAND)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/libconsole/libconsole.h new/showconsole-2.35/libconsole/libconsole.h --- old/showconsole-2.34/libconsole/libconsole.h 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/libconsole/libconsole.h 2025-04-28 15:35:31.000000000 +0200 @@ -127,12 +127,13 @@ extern ssize_t safein (int fd, void *ptr, size_t s); extern void safeout (int fd, const void *ptr, size_t s, ssize_t max); -extern void prepareIO(void (*rfunc)(int), const int listen, const int in); +extern void prepareIO(int (*rfunc)(int), const int listen, const int in); extern void safeIO (void); extern void closeIO(void); extern struct console *cons; extern void getconsoles(struct console **cons, int io); +extern void epoll_write_watchdog(int) attribute((noinline)); /* chroot.c */ extern void new_root(const char *root); @@ -147,7 +148,9 @@ /* epoll.c */ extern void epoll_addread(int fd, void *fptr); +extern void epoll_addwrite(int fd, void *fptr); extern void epoll_answer_once(int fd, void *fptr); +extern void epoll_reenable(int fd); extern void epoll_delete(int fd); extern void (*epoll_handle(void *ptr, int *fd))(int); extern void epoll_close_fd(void); @@ -156,8 +159,8 @@ extern void *frobnicate(void *in, const size_t len); /* io.c */ -extern int can_read(int fd, const long timeout); -extern int can_write(int fd, const int timeout); +extern int can_read(int fd, const time_t msec); +extern int can_write(int fd, const time_t msec); extern void clear_input(int fd); /* log.c */ @@ -198,6 +201,15 @@ extern int open_tty(const char *name, int mode); extern int request_tty(const char *tty); +/* 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); +#endif + #define MAX_PASSLEN LINE_MAX /* Some shorthands for control characters. */ #define CTL(x) ((x) ^ 0100) /* Assumes ASCII dialect */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/libconsole/tty.c new/showconsole-2.35/libconsole/tty.c --- old/showconsole-2.34/libconsole/tty.c 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/libconsole/tty.c 2025-04-28 15:35:31.000000000 +0200 @@ -15,6 +15,7 @@ #include <signal.h> #include <sys/inotify.h> #include <sys/ioctl.h> +#include <sys/sysmacros.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -52,6 +53,9 @@ { struct sigaction saved_sighup; int fd = -1, nd, wd; +#if defined(__s390__) || defined(__s390x__) + struct stat sb; +#endif fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); if (fd >= 0) { @@ -95,9 +99,16 @@ break; } +#if defined(__s390__) || defined(__s390x__) + if (fstat(fd, &sb) == 0 && major(sb.st_dev) == 4 && minor(sb.st_dev) == 64) + goto noblock; +#endif flags = fcntl(fd, F_GETFL); flags &= ~O_NONBLOCK; fcntl(fd, F_SETFL, flags); +#if defined(__s390__) || defined(__s390x__) + noblock: +#endif if (ret >= 0) break; /* Success */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/libconsole/vmcp.c new/showconsole-2.35/libconsole/vmcp.c --- old/showconsole-2.34/libconsole/vmcp.c 1970-01-01 01:00:00.000000000 +0100 +++ new/showconsole-2.35/libconsole/vmcp.c 2025-04-28 15:35:31.000000000 +0200 @@ -0,0 +1,154 @@ +/* + * vmcp.c + * + * Based on: + * + * Copyright IBM Corp. 2018 + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + * + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#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 openvmcp(void) +{ + return open(VMCP_DEVICE_NODE, O_RDWR|O_NOCTTY); +} + +char* queryterm(int fd) +{ + const char* question = "QUERY TERMINAL"; + long pagesize = sysconf(_SC_PAGESIZE); + int rc = 0, num, buffersize; + char* ret = NULL; + + num = (strlen(question) + pagesize - 1)/pagesize; + buffersize = num * pagesize; + + if (ioctl(fd, VMCP_SETBUF, &buffersize) == -1) + goto out; + do { + rc = write(fd, question, strlen(question)); + if (rc < 0) { + if (errno != EINTR) + goto out; + } + } while (rc < 0); + if (ioctl(fd, VMCP_GETCODE, &rc) == -1) + goto out; + if (ioctl(fd, VMCP_GETSIZE, &buffersize) == -1) + goto out; + ret = (char*)malloc(buffersize); + if (!ret) + goto out; + do { + rc = read(fd, ret, buffersize); + if (rc < 0) { + if (errno != EINTR) + goto out; + } + } while (rc < 0); +out: + return ret; +} + +int setterm(int fd) +{ + const char* instruction = "TERMINAL MORE 0 0 HOLD OFF"; + long pagesize = sysconf(_SC_PAGESIZE); + int rc = 0, num, buffersize; + int ret = -1; + + num = (strlen(instruction) + pagesize - 1)/pagesize; + buffersize = num * pagesize; + + if (ioctl(fd, VMCP_SETBUF, &buffersize) == -1) + goto out; + do { + rc = write(fd, instruction, strlen(instruction)); + if (rc < 0) { + if (errno != EINTR) + goto out; + } + } while (rc < 0); + if (ioctl(fd, VMCP_GETCODE, &rc) == -1) + goto out; + if (ioctl(fd, VMCP_GETSIZE, &buffersize) == -1) + goto out; + if (rc == 0 && buffersize == 0) + ret = 0; +out: + return ret; +} + +static char *more, *hold; + +int restoreterm(int fd) +{ + char* instruction; + long pagesize = sysconf(_SC_PAGESIZE); + int rc = 0, num, buffersize; + int ret = -1; + + if (!more || !hold) + goto out; + if (asprintf(&instruction, "TERMINAL %s %s", more, hold) == -1) + goto out; + + num = (strlen(instruction) + pagesize - 1)/pagesize; + buffersize = num * pagesize; + + if (ioctl(fd, VMCP_SETBUF, &buffersize) == -1) + goto out; + do { + rc = write(fd, instruction, strlen(instruction)); + if (rc < 0) { + if (errno != EINTR) + goto out; + } + } while (rc < 0); + free(instruction); + if (ioctl(fd, VMCP_GETCODE, &rc) == -1) + goto out; + if (ioctl(fd, VMCP_GETSIZE, &buffersize) == -1) + goto out; + if (rc == 0 && buffersize == 0) + ret = 0; +out: + return ret; +} + +void parseterm(char *msg) +{ + int n; + char *token, *ptr; + for (n = 1, ptr = msg; ; n++, ptr = NULL) { + token = strtok(ptr, ",\n"); + if (!token) + break; + if (hold && more) + break; + while (*token == ' ') + token++; + if (strncmp("MORE ", token, 5) == 0) + more = strdup(token); + if (strncmp("HOLD ", token, 5) == 0) + hold = strdup(token); + } +} +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/module-setup.sh new/showconsole-2.35/module-setup.sh --- old/showconsole-2.34/module-setup.sh 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/module-setup.sh 2025-04-28 15:35:31.000000000 +0200 @@ -34,14 +34,14 @@ ln_r "${systemdsystemunitdir}/${s}" "${systemdsystemunitdir}/rescue.target.wants/${s}" ln_r "${systemdsystemunitdir}/${s}" "${systemdsystemunitdir}/emergency.target.wants/${s}" done - for s in blog.service systemd-ask-password-blog.path + for s in blog.service blog-store-messages.service do ln_r "${systemdsystemunitdir}/${s}" "${systemdsystemunitdir}/sysinit.target.wants/${s}" done for u in reboot poweroff kexec halt do ln_r "${systemdsystemunitdir}/blog-${u}.service" "${systemdsystemunitdir}/${u}.target.wants/blog-${u}.service" - ln_r "${systemdsystemunitdir}/blog-switch-initramfs.service" "${systemdsystemunitdir}/${u}.target.wants/blog-switch-initramfs" + ln_r "${systemdsystemunitdir}/blog-switch-initramfs.service" "${systemdsystemunitdir}/${u}.target.wants/blog-switch-initramfs.service" done for t in systemd-ask-password-blog.service do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/systemd-ask-password-blog.path new/showconsole-2.35/systemd-ask-password-blog.path --- old/showconsole-2.34/systemd-ask-password-blog.path 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/systemd-ask-password-blog.path 2025-04-28 15:35:31.000000000 +0200 @@ -2,9 +2,12 @@ Description=Forward Password Requests to Plymouth Directory Watch Documentation=http://www.freedesktop.org/wiki/Software/systemd/PasswordAgents DefaultDependencies=no -Conflicts=shutdown.target After=blog.service -Before=basic.target shutdown.target +Before=paths.target cryptsetup.target +Conflicts=emergency.service +Before=emergency.service +Conflicts=shutdown.target +Before=shutdown.target ConditionKernelCommandLine=!blog.enable=0 ConditionPathExists=/run/blogd.pid ConditionVirtualization=!container diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/showconsole-2.34/systemd-ask-password-blog.service new/showconsole-2.35/systemd-ask-password-blog.service --- old/showconsole-2.34/systemd-ask-password-blog.service 2025-04-16 14:56:56.000000000 +0200 +++ new/showconsole-2.35/systemd-ask-password-blog.service 2025-04-28 15:35:31.000000000 +0200 @@ -2,12 +2,15 @@ Description=Forward Password Requests to Blogd as a Plymouth agent Documentation=http://www.freedesktop.org/wiki/Software/systemd/PasswordAgents DefaultDependencies=no -Conflicts=shutdown.target -After=blog.service -Before=shutdown.target +After=blog.service systemd-vconsole-setup.service +Conflicts=emergency.service +Before=emergency.service +Conflicts=shutdown.target initrd-switch-root.target +Before=shutdown.target initrd-switch-root.target ConditionKernelCommandLine=!blog.enable=0 ConditionVirtualization=!container ConditionPathExists=/run/blogd.pid [Service] ExecStart=/usr/bin/systemd-tty-ask-password-agent --watch --plymouth +SystemCallArchitectures=native