Description: Allow multiple console output
 When booting a kernel with multiple serial console support, or multuiple
 console arguments ala "console=tty1 console=ttyS0,9600" the kernel will output
 messages to all consoles, init however will not. It will only send output to,
 and accept input from, the last of the consoles.
 .
 This patch fixes it.
Author: Martin Buck <m@rtin-buck.de>
Origin: other, https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=181756
Bug-Debian: https://bugs.debian.org/181756
Forwarded: no
Last-Update: 2014-07-20

Index: sysvinit-2.88dsf/src/bootlogd.c
===================================================================
--- sysvinit-2.88dsf.orig/src/bootlogd.c	2010-03-23 15:37:01.000000000 +0100
+++ sysvinit-2.88dsf/src/bootlogd.c	2013-07-15 09:56:55.953975300 +0200
@@ -57,6 +57,7 @@
 char *Version = "@(#) bootlogd 2.86 03-Jun-2004 miquels@cistron.nl";
 
 #define LOGFILE	"/var/log/boot"
+#define MAX_CONSOLES 16
 
 char ringbuf[32768];
 char *endptr = ringbuf + sizeof(ringbuf);
@@ -73,6 +74,11 @@
 	int pos;
 } line;
 
+struct real_cons {
+	char name[1024];
+	int fd;
+};
+
 /*
  *	Console devices as listed on the kernel command line and
  *	the mapping to actual devices in /dev
@@ -235,10 +241,10 @@
 }
 
 /*
- *	Find out the _real_ console. Assume that stdin is connected to
+ *	Find out the _real_ console(s). Assume that stdin is connected to
  *	the console device (/dev/console).
  */
-int consolename(char *res, int rlen)
+int consolenames(struct real_cons *cons, int max_consoles)
 {
 #ifdef TIOCGDEV
 	unsigned int	kdev;
@@ -247,34 +253,9 @@
 	char		buf[256];
 	char		*p;
 	int		didmount = 0;
-	int		n, r;
+	int		n;
 	int		fd;
-
-	fstat(0, &st);
-	if (major(st.st_rdev) != 5 || minor(st.st_rdev) != 1) {
-		/*
-		 *	Old kernel, can find real device easily.
-		 */
-		int r = findtty(res, "/dev", rlen, st.st_rdev);
-		if (0 != r)
-			fprintf(stderr, "bootlogd: cannot find console device "
-				"%d:%d under /dev\n", major(st.st_rdev), minor(st.st_rdev));
-		return r;
-	}
-
-#ifdef TIOCGDEV
-# ifndef  ENOIOCTLCMD
-#  define ENOIOCTLCMD	515
-# endif
-	if (ioctl(0, TIOCGDEV, &kdev) == 0) {
-		int r = findtty(res, "/dev", rlen, (dev_t)kdev);
-		if (0 != r)
-			fprintf(stderr, "bootlogd: cannot find console device "
-				"%d:%d under /dev\n", major(kdev), minor(kdev));
-		return r;
-	}
-	if (errno != ENOIOCTLCMD) return -1;
-#endif
+	int		considx, num_consoles = 0;
 
 #ifdef __linux__
 	/*
@@ -283,7 +264,7 @@
 	stat("/", &st);
 	if (stat("/proc", &st2) < 0) {
 		perror("bootlogd: /proc");
-		return -1;
+		return 0;
 	}
 	if (st.st_dev == st2.st_dev) {
 		if (mount("proc", "/proc", "proc", 0, NULL) < 0) {
@@ -293,21 +274,21 @@
 		didmount = 1;
 	}
 
-	n = 0;
-	r = -1;
+	n = -1;
 	if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) {
 		perror("bootlogd: /proc/cmdline");
 	} else {
 		buf[0] = 0;
-		if ((n = read(fd, buf, sizeof(buf) - 1)) >= 0)
-			r = 0;
-		else
+		if ((n = read(fd, buf, sizeof(buf) - 1)) < 0)
 			perror("bootlogd: /proc/cmdline");
 		close(fd);
 	}
 	if (didmount) umount("/proc");
+                
+
+	if (n < 0) return 0;
+
 
-	if (r < 0) return r;
 
 	/*
 	 *	OK, so find console= in /proc/cmdline.
@@ -315,21 +296,32 @@
 	 */
 	p = buf + n;
 	*p-- = 0;
-	r = -1;
 	while (p >= buf) {
 		if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
 			*p-- = 0;
 			continue;
 		}
 		if (strncmp(p, "console=", 8) == 0 &&
-		    isconsole(p + 8, res, rlen)) {
-			r = 0;
-			break;
+			isconsole(p + 8, cons[num_consoles].name, sizeof(cons[num_consoles].name))) {
+				/*
+				 *	Suppress duplicates
+				 */
+				for (considx = 0; considx < num_consoles; considx++) {
+					if (!strcmp(cons[num_consoles].name, cons[considx].name)) {
+						goto dontuse;
+					}
+				}
+			
+			num_consoles++;
+			if (num_consoles >= max_consoles) {
+				break;
+			}
 		}
+dontuse:
 		p--;
 	}
 
-	if (r == 0) return r;
+	if (num_consoles > 0) return num_consoles;
 #endif
 
 	/*
@@ -337,12 +329,12 @@
 	 *	guess the default console.
 	 */
 	for (n = 0; defcons[n]; n++)
-		if (isconsole(defcons[n], res, rlen))
-			return 0;
+		if (isconsole(defcons[n], cons[0].name, sizeof(cons[0].name))) 
+			return 1;
 
 	fprintf(stderr, "bootlogd: cannot deduce real console device\n");
 
-	return -1;
+	return 0;
 }
 
 
@@ -472,7 +464,6 @@
 	struct timeval	tv;
 	fd_set		fds;
 	char		buf[1024];
-	char		realcons[1024];
 	char		*p;
 	char		*logfile;
 	char		*pidfile;
@@ -485,6 +476,9 @@
 #ifndef __linux__	/* BSD-style ioctl needs an argument. */
 	int		on = 1;
 #endif
+	int		considx;
+	struct real_cons cons[MAX_CONSOLES];
+	int		num_consoles, consoles_left;
 
 	fp = NULL;
 	logfile = LOGFILE;
@@ -531,18 +525,22 @@
 	/*
 	 *	Open console device directly.
 	 */
-	if (consolename(realcons, sizeof(realcons)) < 0)
-		return 1;
-
-	if (strcmp(realcons, "/dev/tty0") == 0)
-		strcpy(realcons, "/dev/tty1");
-	if (strcmp(realcons, "/dev/vc/0") == 0)
-		strcpy(realcons, "/dev/vc/1");
-
-	if ((realfd = open_nb(realcons)) < 0) {
-		fprintf(stderr, "bootlogd: %s: %s\n", buf, strerror(errno));
+	if ((num_consoles = consolenames(cons, MAX_CONSOLES)) <= 0)
 		return 1;
+	consoles_left = num_consoles;
+	for (considx = 0; considx < num_consoles; considx++) {
+		if (strcmp(cons[considx].name, "/dev/tty0") == 0)
+			strcpy(cons[considx].name, "/dev/tty1");
+		if (strcmp(cons[considx].name, "/dev/vc/0") == 0)
+			strcpy(cons[considx].name, "/dev/vc/1");
+
+		if ((cons[considx].fd = open_nb(cons[considx].name)) < 0) {
+			fprintf(stderr, "bootlogd: %s: %s\n", cons[considx].name, strerror(errno));
+			consoles_left--;
+		}
 	}
+	if (!consoles_left)
+		return 1;
 
 	/*
 	 *	Grab a pty, and redirect console messages to it.
@@ -626,26 +624,34 @@
 			if ((n = read(ptm, inptr, endptr - inptr)) >= 0) {
 				/*
 				 *	Write data (in chunks if needed)
-				 *	to the real output device.
+				 *	to the real output devices.
 				 */
-				m = n;
-				p = inptr;
-				while (m > 0) {
-					i = write(realfd, p, m);
-					if (i >= 0) {
-						m -= i;
-						p += i;
-						continue;
-					}
-					/*
-					 *	Handle EIO (somebody hung
-					 *	up our filedescriptor)
-					 */
-					realfd = write_err(pts, realfd,
-						realcons, errno);
-					if (realfd >= 0) continue;
-					got_signal = 1; /* Not really */
-					break;
+				for (considx = 0; considx < num_consoles; considx++) {
+					if (cons[considx].fd < 0) continue;
+					m = n;
+					p = inptr;
+					while (m > 0) {
+						i = write(cons[considx].fd, p, m);
+						if (i >= 0) {
+							m -= i;
+							p += i;
+							continue;
+						}
+						/*
+						 *	Handle EIO (somebody hung
+						 *	up our filedescriptor)
+						 */
+						cons[considx].fd = write_err(pts,
+							cons[considx].fd,
+							cons[considx].name, errno);
+						if (cons[considx].fd >= 0) continue;
+						/*	
+						 *	If this was the last console,
+						 *	generate a fake signal
+						 */
+						if (--consoles_left <= 0) got_signal = 1;
+						break;
+ 					}
 				}
 
 				/*
@@ -691,7 +697,9 @@
 
 	close(pts);
 	close(ptm);
-	close(realfd);
+	for (considx = 0; considx < num_consoles; considx++) {
+		close(cons[considx].fd);
+	}
 
 	return 0;
 }
