util-linux/backport-sulogin-ignore-none-existing-console-devices.patch
zhangyao f63973e5e5 sync community patches
(cherry picked from commit 1efe7bf26406dfed2dc9304835801f62f5e8a558)
2023-06-06 09:47:09 +08:00

228 lines
5.6 KiB
Diff

From 0d092db5c40b94e1ea9529f3f1c384a74eca19f8 Mon Sep 17 00:00:00 2001
From: Werner Fink <werner@suse.de>
Date: Mon, 17 May 2021 17:20:32 +0200
Subject: [PATCH] sulogin: ignore none-existing console devices
and also none-functional console devices. Redirect the error
messages to the appropiate console device.
Signed-off-by: Werner Fink <werner@suse.de>
---
login-utils/sulogin-consoles.h | 1 +
login-utils/sulogin.c | 92 ++++++++++++++++++++++++++++------
2 files changed, 79 insertions(+), 14 deletions(-)
diff --git a/login-utils/sulogin-consoles.h b/login-utils/sulogin-consoles.h
index 0bfbc38..12032c9 100644
--- a/login-utils/sulogin-consoles.h
+++ b/login-utils/sulogin-consoles.h
@@ -40,6 +40,7 @@ struct console {
int fd, id;
#define CON_SERIAL 0x0001
#define CON_NOTTY 0x0002
+#define CON_EIO 0x0004
pid_t pid;
struct chardata cp;
struct termios tio;
diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index 4d48943..df27896 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -52,6 +52,7 @@
#ifdef __linux__
# include <sys/kd.h>
# include <sys/param.h>
+# include <linux/serial.h>
#endif
#include "c.h"
@@ -106,6 +107,9 @@ static void tcinit(struct console *con)
int flags = 0, mode = 0;
struct termios *tio = &con->tio;
const int fd = con->fd;
+#if defined(TIOCGSERIAL)
+ struct serial_struct serinfo;
+#endif
#ifdef USE_PLYMOUTH_SUPPORT
struct termios lock;
int i = (plymouth_command(MAGIC_PING)) ? PLYMOUTH_TERMIOS_FLAGS_DELAY : 0;
@@ -125,27 +129,72 @@ static void tcinit(struct console *con)
}
memset(&lock, 0, sizeof(struct termios));
ioctl(fd, TIOCSLCKTRMIOS, &lock);
+ errno = 0;
#endif
+
+#if defined(TIOCGSERIAL)
+ if (ioctl(fd, TIOCGSERIAL, &serinfo) >= 0)
+ con->flags |= CON_SERIAL;
+ errno = 0;
+#else
+# if defined(KDGKBMODE)
+ if (ioctl(fd, KDGKBMODE, &mode) < 0)
+ con->flags |= CON_SERIAL;
errno = 0;
+# endif
+#endif
if (tcgetattr(fd, tio) < 0) {
- warn(_("tcgetattr failed"));
- con->flags |= CON_NOTTY;
- return;
+ int saveno = errno;
+#if defined(KDGKBMODE) || defined(TIOCGSERIAL)
+ if (con->flags & CON_SERIAL) { /* Try to recover this */
+
+# if defined(TIOCGSERIAL)
+ serinfo.flags |= ASYNC_SKIP_TEST; /* Skip test of UART */
+
+ if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0)
+ goto tcgeterr;
+ if (ioctl(fd, TIOCSERCONFIG) < 0) /* Try to autoconfigure */
+ goto tcgeterr;
+ if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0)
+ goto tcgeterr; /* Ouch */
+# endif
+ if (tcgetattr(fd, tio) < 0) /* Retry to get tty attributes */
+ saveno = errno;
+ }
+# if defined(TIOCGSERIAL)
+ tcgeterr:
+# endif
+ if (saveno)
+#endif
+ {
+ FILE *fcerr = fdopen(fd, "w");
+ if (fcerr) {
+ fprintf(fcerr, _("tcgetattr failed"));
+ fclose(fcerr);
+ }
+ warn(_("tcgetattr failed"));
+
+ con->flags &= ~CON_SERIAL;
+ if (saveno != EIO)
+ con->flags |= CON_NOTTY;
+ else
+ con->flags |= CON_EIO;
+
+ errno = 0;
+ return;
+ }
}
/* Handle lines other than virtual consoles here */
-#if defined(KDGKBMODE)
- if (ioctl(fd, KDGKBMODE, &mode) < 0)
+#if defined(KDGKBMODE) || defined(TIOCGSERIAL)
+ if (con->flags & CON_SERIAL)
#endif
{
speed_t ispeed, ospeed;
struct winsize ws;
errno = 0;
- /* this is a modem line */
- con->flags |= CON_SERIAL;
-
/* Flush input and output queues on modem lines */
tcflush(fd, TCIOFLUSH);
@@ -222,6 +271,8 @@ static void tcfinal(struct console *con)
struct termios *tio = &con->tio;
const int fd = con->fd;
+ if (con->flags & CON_EIO)
+ return;
if ((con->flags & CON_SERIAL) == 0) {
xsetenv("TERM", "linux", 1);
return;
@@ -559,12 +610,16 @@ err:
static void setup(struct console *con)
{
int fd = con->fd;
- const pid_t pid = getpid(), pgrp = getpgid(0), ppgrp =
- getpgid(getppid()), ttypgrp = tcgetpgrp(fd);
+ const pid_t pid = getpid(), pgrp = getpgid(0), ppgrp = getpgid(getppid());
+ pid_t ttypgrp;
if (con->flags & CON_NOTTY)
+ goto notty;
+ if (con->flags & CON_EIO)
return;
+ ttypgrp = tcgetpgrp(fd);
+
/*
* Only go through this trouble if the new
* tty doesn't fall in this process group.
@@ -587,6 +642,7 @@ static void setup(struct console *con)
ioctl(fd, TIOCSCTTY, (char *)1);
tcsetpgrp(fd, ppgrp);
}
+notty:
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
@@ -616,15 +672,19 @@ static char *getpasswd(struct console *con)
int eightbit;
const int fd = con->fd;
- if (con->flags & CON_NOTTY)
+ if (con->flags & CON_EIO)
goto out;
+
cp = &con->cp;
tty = con->tio;
+ tc = 0;
ret = pass;
tty.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY);
tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP|ISIG);
- tc = (tcsetattr(fd, TCSAFLUSH, &tty) == 0);
+
+ if ((con->flags & CON_NOTTY) == 0)
+ tc = (tcsetattr(fd, TCSAFLUSH, &tty) == 0);
sigemptyset(&sa.sa_mask);
sa.sa_handler = alrm_handler;
@@ -650,11 +710,12 @@ static char *getpasswd(struct console *con)
}
ret = NULL;
switch (errno) {
- case 0:
case EIO:
+ con->flags |= CON_EIO;
case ESRCH:
case EINVAL:
case ENOENT:
+ case 0:
break;
default:
warn(_("cannot read %s"), con->tty);
@@ -976,10 +1037,13 @@ int main(int argc, char **argv)
con = list_entry(ptr, struct console, entry);
if (con->id >= CONMAX)
break;
+ if (con->flags & CON_EIO)
+ goto next;
switch ((con->pid = fork())) {
case 0:
mask_signal(SIGCHLD, SIG_DFL, NULL);
+ dup2(con->fd, STDERR_FILENO);
nofork:
setup(con);
while (1) {
@@ -1040,7 +1104,7 @@ int main(int argc, char **argv)
default:
break;
}
-
+ next:
ptr = ptr->next;
} while (ptr != &consoles);
--
2.33.0