From 7ba741a50a04e8e72861e90132394996f2d82006 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Sat, 30 Oct 2021 15:56:14 +0100
Subject: [PATCH] login: Restore tty size after calling vhangup()

If login receives the tty to work on via stdin, stdout and stderr,
login might end up closing the remaining open file descriptors to
the tty just before it calls vhangup(). When the last open file
descriptors to a tty are closed, it's configured size is reset to
0x0. To avoid this from happening, save the size before closing
the stdin, stdout and stderr file descriptors and reapply the size
after the tty is re-opened.

Fixes #1484
---
 login-utils/login.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/login-utils/login.c b/login-utils/login.c
index 3657f04..c9f6d59 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -513,6 +513,7 @@ static void init_tty(struct login_context *cxt)
 {
 	struct stat st;
 	struct termios tt, ttt;
+	struct winsize ws;
 
 	cxt->tty_mode = (mode_t) getlogindefs_num("TTYPERM", TTY_MODE);
 
@@ -543,6 +544,12 @@ static void init_tty(struct login_context *cxt)
 	}
 #endif
 
+	/* The TTY size might be reset to 0x0 by the kernel when we close the stdin/stdout/stderr file
+	 * descriptors so let's save the size now so we can reapply it later */
+	memset(&ws, 0, sizeof(struct winsize));
+	if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0)
+		syslog(LOG_WARNING, _("TIOCGWINSZ ioctl failed: %m"));
+
 	tcgetattr(0, &tt);
 	ttt = tt;
 	ttt.c_cflag &= ~HUPCL;
@@ -574,6 +581,11 @@ static void init_tty(struct login_context *cxt)
 
 	/* restore tty modes */
 	tcsetattr(0, TCSAFLUSH, &tt);
+
+	/* Restore tty size */
+	if (ws.ws_row > 0 || ws.ws_col > 0)
+		if (ioctl(STDIN_FILENO, TIOCSWINSZ, &ws) < 0)
+			syslog(LOG_WARNING, _("TIOCSWINSZ ioctl failed: %m"));
 }
 
 /*
-- 
1.8.3.1

