From 46537bc28d48acb9ae5cac76535262e6b2ec48a2 Mon Sep 17 00:00:00 2001
From: Werner Fink <werner@suse.de>
Date: Thu, 8 May 2014 12:09:25 +0200
Subject: [PATCH 80/84] sulogin: (and agetty) virtual consoles support, xvc and
 hvc device

For this approach do not use the ioctl TIOCMGET anymore as this
is for real serial lines only. But switch over to use the ioctl
KDGKBMODE as this is unique to the virtual console lines only.

Upstream: http://github.com/karelzak/util-linux/commit/b9c7390948c7850db2bee82ad64624930962cc14
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1029385
Signed-off-by: Werner Fink <werner@suse.de>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/sulogin.c | 17 ++++++++++++-----
 term-utils/agetty.c   | 23 +++++++++++------------
 2 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index 32ae9a2..bbd67b3 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -49,6 +49,11 @@
 # include <selinux/get_context_list.h>
 #endif

+#ifdef __linux__
+# include <sys/kd.h>
+# include <sys/param.h>
+#endif
+
 #include "c.h"
 #include "closestream.h"
 #include "nls.h"
@@ -93,10 +98,14 @@ static void tcinit(struct console *con)
		return;
	}

-	/* Handle serial lines here */
-	if (ioctl(fd, TIOCMGET, (char *) &mode) == 0) {
+	/* Handle lines other than virtual consoles here */
+#if defined(KDGKBMODE)
+	if (ioctl(fd, KDGKBMODE, &mode) < 0)
+#endif
+	{
		speed_t ispeed, ospeed;
		struct winsize ws;
+		errno = 0;

		/* this is a modem line */
		con->flags |= CON_SERIAL;
@@ -142,9 +151,7 @@ static void tcinit(struct console *con)
		goto setattr;
	}
 #if defined(IUTF8) && defined(KDGKBMODE)
-	/* Detect mode of current keyboard setup, e.g. for UTF-8 */
-	if (ioctl(fd, KDGKBMODE, &mode) < 0)
-		mode = K_RAW;
+	/* Handle mode of current keyboard setup, e.g. for UTF-8 */
	switch(mode) {
	case K_UNICODE:
		setlocale(LC_CTYPE, "C.UTF-8");
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index c7af154..5692126 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -134,6 +134,7 @@ struct options {
	int nice;			/* Run login with this priority */
	int numspeed;			/* number of baud rates to try */
	int clocal;			/* CLOCAL_MODE_* */
+	int kbmode;			/* Keyboard mode if virtual console */
	speed_t speeds[MAX_SPEED];	/* baud rates to be tried */
 };

@@ -886,7 +887,7 @@ static void update_utmp(struct options *op)
 static void open_tty(char *tty, struct termios *tp, struct options *op)
 {
	const pid_t pid = getpid();
-	int serial, closed = 0;
+	int closed = 0;

	/* Set up new standard input, unless we are given an already opened port. */

@@ -1016,15 +1017,18 @@ static void open_tty(char *tty, struct termios *tp, struct options *op)

	/*
	 * Detect if this is a virtual console or serial/modem line.
-	 * In case of a virtual console the ioctl TIOCMGET fails and
-	 * the error number will be set to EINVAL.
+	 * In case of a virtual console the ioctl KDGKBMODE succeeds
+	 * whereas on other lines it will fails.
	 */
-	if (ioctl(STDIN_FILENO, TIOCMGET, &serial) < 0 && (errno == EINVAL)) {
+	if (ioctl(STDIN_FILENO, KDGKBMODE, &op->kbmode) == 0) {
		op->flags |= F_VCONSOLE;
		if (!op->term)
			op->term = DEFAULT_VCTERM;
-	} else if (!op->term)
-		op->term = DEFAULT_STERM;
+	} else {
+		op->kbmode = K_RAW;
+		if (!op->term)
+			op->term = DEFAULT_STERM;
+	}

	setenv("TERM", op->term, 1);
 }
@@ -1037,12 +1041,7 @@ static void termio_init(struct options *op, struct termios *tp)

	if (op->flags & F_VCONSOLE) {
 #if defined(IUTF8) && defined(KDGKBMODE)
-		int mode;
-
-		/* Detect mode of current keyboard setup, e.g. for UTF-8 */
-		if (ioctl(STDIN_FILENO, KDGKBMODE, &mode) < 0)
-			mode = K_RAW;
-		switch(mode) {
+		switch(op->kbmode) {
		case K_UNICODE:
			setlocale(LC_CTYPE, "C.UTF-8");
			op->flags |= F_UTF8;
--
2.7.4
