Backport.
From ddbb3067b676ad040302ad6ccd6b5d41ff536e83 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 11 Oct 2018 13:12:02 +0200
Subject: [PATCH 04/14] agetty: move all issue variables to struct

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 term-utils/agetty.c | 180 +++++++++++++++++++++++++-------------------
 1 file changed, 101 insertions(+), 79 deletions(-)

Index: util-linux-2.28/term-utils/agetty.c
===================================================================
--- util-linux-2.28.orig/term-utils/agetty.c
+++ util-linux-2.28/term-utils/agetty.c
@@ -143,6 +143,18 @@ static __u32 netlink_groups;
 #define AGETTY_PLYMOUTH		"/usr/bin/plymouth"
 #define AGETTY_PLYMOUTH_FDFILE	"/dev/null"
 
+struct issue {
+	FILE *output;
+	char *mem;
+	size_t mem_sz;
+
+#ifdef AGETTY_RELOAD
+	char *mem_old;
+#endif
+	unsigned int do_tcsetattr : 1,
+		     do_tcrestore : 1;
+};
+
 /*
  * When multiple baud rates are specified on the command line, the first one
  * we will try is the first one specified.
@@ -293,11 +305,11 @@ static void open_tty(char *tty, struct t
 static void termio_init(struct options *op, struct termios *tp);
 static void reset_vc (const struct options *op, struct termios *tp);
 static void auto_baud(struct termios *tp);
-static void output_special_char (unsigned char c, struct options *op,
+static void output_special_char (struct issue *ie, unsigned char c, struct options *op,
 		struct termios *tp, FILE *fp);
-static void do_prompt(struct options *op, struct termios *tp);
+static void do_prompt(struct issue *ie, struct options *op, struct termios *tp);
 static void next_speed(struct options *op, struct termios *tp);
-static char *get_logname(struct options *op,
+static char *get_logname(struct issue *ie, struct options *op,
 			 struct termios *tp, struct chardata *cp);
 static void termio_final(struct options *op,
 			 struct termios *tp, struct chardata *cp);
@@ -313,8 +325,8 @@ static void check_username (const char*
 static void login_options_to_argv(char *argv[], int *argc, char *str, char *username);
 static int plymouth_command(const char* arg);
 static void reload_agettys(void);
-static void print_issue_file(struct options *op, struct termios *tp);
-static void eval_issue_file(struct options *op, struct termios *tp);
+static void print_issue_file(struct issue *ie, struct options *op, struct termios *tp);
+static void eval_issue_file(struct issue *ie, struct options *op, struct termios *tp);
 
 /* Fake hostname for ut_host specified on command line. */
 static char *fakehost;
@@ -341,6 +353,9 @@ int main(int argc, char **argv)
 		.tty    = "tty1",		/* default tty line */
 		.issue  =  ISSUE		/* default issue file */
 	};
+	struct issue issue = {
+		.mem = NULL,
+	};
 	char *login_argv[LOGIN_ARGV_MAX + 1];
 	int login_argc = 0;
 	struct sigaction sa, sa_hup, sa_quit, sa_int;
@@ -453,14 +468,14 @@ int main(int argc, char **argv)
 	if ((options.flags & F_NOPROMPT) == 0) {
 		if (options.autolog) {
 			/* Autologin prompt */
-			eval_issue_file(&options, &termios);
-			do_prompt(&options, &termios);
+			eval_issue_file(&issue, &options, &termios);
+			do_prompt(&issue, &options, &termios);
 			printf(_("%s%s (automatic login)\n"), LOGIN, options.autolog);
 		} else {
 			/* Read the login name. */
 			debug("reading login name\n");
 			while ((username =
-				get_logname(&options, &termios, &chardata)) == NULL)
+				get_logname(&issue, &options, &termios, &chardata)) == NULL)
 				if ((options.flags & F_VCONSOLE) == 0 && options.numspeed)
 					next_speed(&options, &termios);
 		}
@@ -1689,20 +1704,13 @@ static int wait_for_term_input(int fd)
 }
 #endif  /* AGETTY_RELOAD */
 #ifdef	ISSUE
-static FILE *issue_f;
-static char *issue_mem = NULL;
-static size_t issue_mem_sz;
-static bool do_tcsetattr;
-static bool do_tcrestore;
-#ifdef AGETTY_RELOAD
-static char *issue_mem_old = NULL;
-#endif
-static bool cmp_issue_file(void) {
-	if (issue_mem_old && issue_mem) {
-		if (!strcmp(issue_mem_old, issue_mem)) {
-			free(issue_mem_old);
-			issue_mem_old = issue_mem;
-			issue_mem = NULL;
+static bool cmp_issue_file(struct issue *ie)
+{
+	if (ie->mem_old && ie->mem) {
+		if (!strcmp(ie->mem_old, ie->mem)) {
+			free(ie->mem_old);
+			ie->mem_old = ie->mem;
+			ie->mem = NULL;
 			return false;
 		}
 	} else
@@ -1710,7 +1718,10 @@ static bool cmp_issue_file(void) {
 	return true;
 }
 #endif
-static void print_issue_file(struct options *op, struct termios *tp)
+
+static void print_issue_file(struct issue *ie,
+			     struct options *op,
+			     struct termios *tp)
 {
 	int oflag = tp->c_oflag;	    /* Save current setting. */
 
@@ -1719,7 +1730,7 @@ static void print_issue_file(struct opti
 		write_all(STDOUT_FILENO, "\r\n", 2);
 	}
 
-	if (do_tcsetattr) {
+	if (ie->do_tcsetattr) {
 		if ((op->flags & F_VCONSOLE) == 0) {
 			/* Map new line in output to carriage return & new line. */
 			tp->c_oflag |= (ONLCR | OPOST);
@@ -1727,24 +1738,26 @@ static void print_issue_file(struct opti
 		}
 	}
 
-	write_all(STDOUT_FILENO, issue_mem, issue_mem_sz);
-	if (do_tcrestore) {
+	write_all(STDOUT_FILENO, ie->mem, ie->mem_sz);
+	if (ie->do_tcrestore) {
 		/* Restore settings. */
 		tp->c_oflag = oflag;
 		/* Wait till output is gone. */
 		tcsetattr(STDIN_FILENO, TCSADRAIN, tp);
 	}
 #ifdef AGETTY_RELOAD
-	free(issue_mem_old);
-	issue_mem_old = issue_mem;
-	issue_mem = NULL;
+	free(ie->mem_old);
+	ie->mem_old = ie->mem;
+	ie->mem = NULL;
 #else
-	free(issue_mem);
-	issue_mem = NULL;
+	free(ie->mem);
+	ie->mem = NULL;
 #endif
 }
 
-static void eval_issue_file(struct options *op, struct termios *tp)
+static void eval_issue_file(struct issue *ie,
+			    struct options *op,
+			    struct termios *tp)
 {
 #ifdef	ISSUE
 	FILE *fd;
@@ -1754,44 +1767,44 @@ static void eval_issue_file(struct optio
 #endif
 
 #ifdef	ISSUE
-	issue_f = open_memstream(&issue_mem, &issue_mem_sz);
+	ie->output = open_memstream(&ie->mem, &ie->mem_sz);
 	if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) {
 		int c;
 
-		do_tcsetattr = true;
+		ie->do_tcsetattr = true;
 
 		while ((c = getc(fd)) != EOF) {
 			if (c == '\\')
-				output_special_char(getc(fd), op, tp, fd);
+				output_special_char(ie, getc(fd), op, tp, fd);
 			else
-				putc(c, issue_f);
+				putc(c, ie->output);
 		}
 		fflush(stdout);
 
 		if ((op->flags & F_VCONSOLE) == 0)
-			do_tcrestore = true;
+			ie->do_tcrestore = true;
 		fclose(fd);
 	}
 #ifdef AGETTY_RELOAD
 	if (netlink_groups != 0)
 		open_netlink();
 #endif
-	fclose(issue_f);
+	fclose(ie->output);
 #endif	/* ISSUE */
 }
 
 /* Show login prompt, optionally preceded by /etc/issue contents. */
-static void do_prompt(struct options *op, struct termios *tp)
+static void do_prompt(struct issue *ie, struct options *op, struct termios *tp)
 {
 again:
-	print_issue_file(op, tp);
+	print_issue_file(ie, op, tp);
 
 	if (op->flags & F_LOGINPAUSE) {
 		puts(_("[press ENTER to login]"));
 #ifdef AGETTY_RELOAD
 		if (!wait_for_term_input(STDIN_FILENO)) {
-			eval_issue_file(op, tp);
-			if (cmp_issue_file()) {
+			eval_issue_file(ie, op, tp);
+			if (cmp_issue_file(ie)) {
 				if (op->flags & F_VCONSOLE)
 					termio_clear(STDOUT_FILENO);
 				goto again;
@@ -1887,7 +1900,7 @@ static void next_speed(struct options *o
 }
 
 /* Get user name, establish parity, speed, erase, kill & eol. */
-static char *get_logname(struct options *op, struct termios *tp, struct chardata *cp)
+static char *get_logname(struct issue *ie, struct options *op, struct termios *tp, struct chardata *cp)
 {
 	static char logname[BUFSIZ];
 	char *bp;
@@ -1910,8 +1923,8 @@ static char *get_logname(struct options
 	 */
 	if ((op->flags & F_VCONSOLE) == 0)
 		sleep(1);
-	eval_issue_file(op, tp);
-	if (!cmp_issue_file())
+	eval_issue_file(ie, op, tp);
+	if (!cmp_issue_file(ie))
 		goto no_reload;
 	tcflush(STDIN_FILENO, TCIFLUSH);
 
@@ -1919,11 +1932,11 @@ static char *get_logname(struct options
 	bp = logname;
 	*bp = '\0';
 
-	eval_issue_file(op, tp);
+	eval_issue_file(ie, op, tp);
 	while (*logname == '\0') {
 
 		/* Write issue file and prompt */
-		do_prompt(op, tp);
+		do_prompt(ie, op, tp);
 
 #ifdef AGETTY_RELOAD
 	no_reload:
@@ -2282,12 +2295,12 @@ static void log_warn(const char *fmt, ..
 	va_end(ap);
 }
 
-static void print_addr(sa_family_t family, void *addr)
+static void print_addr(struct issue *ie, sa_family_t family, void *addr)
 {
 	char buff[INET6_ADDRSTRLEN + 1];
 
 	inet_ntop(family, addr, buff, sizeof(buff));
-	fprintf(issue_f, "%s", buff);
+	fprintf(ie->output, "%s", buff);
 }
 
 /*
@@ -2295,7 +2308,8 @@ static void print_addr(sa_family_t famil
  * specified then prints the "best" one (UP, RUNNING, non-LOOPBACK). If not
  * found the "best" interface then prints at least host IP.
  */
-static void output_iface_ip(struct ifaddrs *addrs,
+static void output_iface_ip(struct issue *ie,
+			    struct ifaddrs *addrs,
 			    const char *iface,
 			    sa_family_t family)
 {
@@ -2337,7 +2351,7 @@ static void output_iface_ip(struct ifadd
 		}
 
 		if (addr) {
-			print_addr(family, addr);
+			print_addr(ie, family, addr);
 			return;
 		}
 	}
@@ -2362,7 +2376,7 @@ static void output_iface_ip(struct ifadd
 			break;
 		}
 		if (addr)
-			print_addr(family, addr);
+			print_addr(ie, family, addr);
 
 		freeaddrinfo(info);
 	}
@@ -2396,8 +2410,11 @@ static char *get_escape_argument(FILE *f
 	return buf;
 }
 
-static void output_special_char(unsigned char c, struct options *op,
-				struct termios *tp, FILE *fp)
+static void output_special_char(struct issue *ie,
+				unsigned char c,
+				struct options *op,
+				struct termios *tp,
+				FILE *fp)
 {
 	struct utsname uts;
 
@@ -2411,31 +2428,31 @@ static void output_special_char(unsigned
 		if (get_escape_argument(fp, escname, sizeof(escname))) {
 			const char *esc = color_sequence_from_colorname(escname);
 			if (esc)
-				fputs(esc, issue_f);
+				fputs(esc, ie->output);
 		} else
-			fputs("\033", issue_f);
+			fputs("\033", ie->output);
 		break;
 	}
 	case 's':
-		fprintf(issue_f, "%s", uts.sysname);
+		fprintf(ie->output, "%s", uts.sysname);
 		break;
 	case 'n':
-		fprintf(issue_f, "%s", uts.nodename);
+		fprintf(ie->output, "%s", uts.nodename);
 		break;
 	case 'r':
-		fprintf(issue_f, "%s", uts.release);
+		fprintf(ie->output, "%s", uts.release);
 		break;
 	case 'v':
-		fprintf(issue_f, "%s", uts.version);
+		fprintf(ie->output, "%s", uts.version);
 		break;
 	case 'm':
-		fprintf(issue_f, "%s", uts.machine);
+		fprintf(ie->output, "%s", uts.machine);
 		break;
 	case 'o':
 	{
 		char *dom = xgetdomainname();
 
-		fputs(dom ? dom : "unknown_domain", issue_f);
+		fputs(dom ? dom : "unknown_domain", ie->output);
 		free(dom);
 		break;
 	}
@@ -2455,7 +2472,7 @@ static void output_special_char(unsigned
 			    (canon = strchr(info->ai_canonname, '.')))
 				dom = canon + 1;
 		}
-		fputs(dom ? dom : "unknown_domain", issue_f);
+		fputs(dom ? dom : "unknown_domain", ie->output);
 		if (info)
 			freeaddrinfo(info);
 		free(host);
@@ -2474,19 +2491,19 @@ static void output_special_char(unsigned
 			break;
 
 		if (c == 'd') /* ISO 8601 */
-			fprintf(issue_f, "%s %s %d  %d",
+			fprintf(ie->output, "%s %s %d  %d",
 				      nl_langinfo(ABDAY_1 + tm->tm_wday),
 				      nl_langinfo(ABMON_1 + tm->tm_mon),
 				      tm->tm_mday,
 				      tm->tm_year < 70 ? tm->tm_year + 2000 :
 				      tm->tm_year + 1900);
 		else
-			fprintf(issue_f, "%02d:%02d:%02d",
+			fprintf(ie->output, "%02d:%02d:%02d",
 				      tm->tm_hour, tm->tm_min, tm->tm_sec);
 		break;
 	}
 	case 'l':
-		fprintf (issue_f, "%s", op->tty);
+		fprintf (ie->output, "%s", op->tty);
 		break;
 	case 'b':
 	{
@@ -2495,7 +2512,7 @@ static void output_special_char(unsigned
 
 		for (i = 0; speedtab[i].speed; i++) {
 			if (speedtab[i].code == speed) {
-				fprintf(issue_f, "%ld", speedtab[i].speed);
+				fprintf(ie->output, "%ld", speedtab[i].speed);
 				break;
 			}
 		}
@@ -2511,9 +2528,9 @@ static void output_special_char(unsigned
 			var = uts.sysname;
 		if (var) {
 			if (strcmp(varname, "ANSI_COLOR") == 0)
-				fprintf(issue_f, "\033[%sm", var);
+				fprintf(ie->output, "\033[%sm", var);
 			else
-				fprintf(issue_f, "%s", var);
+				fprintf(ie->output, "%s", var);
 			if (var != uts.sysname)
 				free(var);
 		}
@@ -2530,9 +2547,9 @@ static void output_special_char(unsigned
 				users++;
 		endutent();
 		if (c == 'U')
-			fprintf(issue_f, P_("%d user", "%d users", users), users);
+			fprintf(ie->output, P_("%d user", "%d users", users), users);
 		else
-			fprintf (issue_f, "%d ", users);
+			fprintf (ie->output, "%d ", users);
 		break;
 	}
 	case '4':
@@ -2547,9 +2564,9 @@ static void output_special_char(unsigned
 			break;
 
 		if (get_escape_argument(fp, iface, sizeof(iface)))
-			output_iface_ip(addrs, iface, family);
+			output_iface_ip(ie, addrs, iface, family);
 		else
-			output_iface_ip(addrs, NULL, family);
+			output_iface_ip(ie, addrs, NULL, family);
 
 		freeifaddrs(addrs);
 		break;
