[Pkg-sysvinit-devel] Bug#181756: bootlogd patch

Martin Buck m at rtin-buck.de
Mon Oct 30 17:58:43 CET 2006


tags 181756 patch
thanks

Even though this is not mentioned anywhere in the bug report, I assume this
bug is about bootlogd (since init itself doesn't produce any particularly
interesting boot messages). If so, the following patch should fix the bug
by implementing multiple console support in bootlogd. With this patch,
bootlogd will send its output to up to 16 consoles specified on the kernel
command line using console=...

Please note that I've tested this patch only with the sarge version of
sysvinit (2.86.ds1-1), but it applied cleanly to 2.86.ds1-33 as well, so I
don't see a reason why it shouldn't work there.

Martin


--- sysvinit-2.86.ds1/src/bootlogd.c.orig	2004-06-09 14:47:45.000000000 +0200
+++ sysvinit-2.86.ds1/src/bootlogd.c	2006-10-30 17:30:50.000000000 +0100
@@ -48,6 +48,7 @@
 char *Version = "@(#) bootlogd 2.86 03-Jun-2004 miquels at cistron.nl";
 
 #define LOGFILE	"/var/log/boot"
+#define MAX_CONSOLES 16
 
 char ringbuf[32768];
 char *endptr = ringbuf + sizeof(ringbuf);
@@ -62,6 +63,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
@@ -204,10 +210,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;
@@ -216,21 +222,25 @@
 	char		buf[256];
 	char		*p;
 	int		didmount = 0;
-	int		n, r;
+	int		n;
 	int		fd;
+	int		considx, num_consoles = 0;
 
 	fstat(0, &st);
 	if (major(st.st_rdev) != 5 || minor(st.st_rdev) != 1) {
 		/*
 		 *	Old kernel, can find real device easily.
 		 */
-		return findtty(res, rlen, st.st_rdev);
+		cons[0].fd = findtty(cons[0].name, sizeof(cons[0].name), st.st_rdev);
+		return (cons[0].fd >= 0) ? 1 : 0;
 	}
 
 #ifdef TIOCGDEV
-	if (ioctl(0, TIOCGDEV, &kdev) == 0)
-		return findtty(res, rlen, (dev_t)kdev);
-	if (errno != ENOIOCTLCMD) return -1;
+	if (ioctl(0, TIOCGDEV, &kdev) == 0) {
+		cons[0].fd = findtty(cons[0].name, sizeof(cons[0].name), (dev_t)kdev);
+		return (cons[0].fd >= 0) ? 1 : 0;
+	}
+	if (errno != ENOIOCTLCMD) return 0;
 #endif
 
 #ifdef __linux__
@@ -240,31 +250,28 @@
 	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) {
 			perror("bootlogd: mount /proc");
-			return -1;
+			return 0;
 		}
 		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 (r < 0) return r;
+	if (n < 0) return 0;
 
 	/*
 	 *	OK, so find console= in /proc/cmdline.
@@ -274,21 +281,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
 
 	/*
@@ -296,12 +314,13 @@
 	 *	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;
 }
 
 
@@ -429,16 +448,17 @@
 	struct timeval	tv;
 	fd_set		fds;
 	char		buf[1024];
-	char		realcons[1024];
 	char		*p;
 	char		*logfile;
 	char		*pidfile;
 	int		rotate;
 	int		dontfork;
 	int		ptm, pts;
-	int		realfd;
 	int		n, m, i;
 	int		todo;
+	int		considx;
+	struct real_cons	cons[MAX_CONSOLES];
+	int		num_consoles, consoles_left;
 
 	fp = NULL;
 	logfile = LOGFILE;
@@ -479,18 +499,23 @@
 	/*
 	 *	Open console device directly.
 	 */
-	if (consolename(realcons, sizeof(realcons)) < 0)
+	if ((num_consoles = consolenames(cons, MAX_CONSOLES)) <= 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));
-		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.
@@ -558,26 +583,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;
+				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;
 					}
-					/*
-					 *	Handle EIO (somebody hung
-					 *	up our filedescriptor)
-					 */
-					realfd = write_err(pts, realfd,
-						realcons, errno);
-					if (realfd >= 0) continue;
-					got_signal = 1; /* Not really */
-					break;
 				}
 
 				/*
@@ -619,7 +652,9 @@
 
 	close(pts);
 	close(ptm);
-	close(realfd);
+	for (considx = 0; considx < num_consoles; considx++) {
+		close(cons[considx].fd);
+	}
 
 	return 0;
 }




More information about the Pkg-sysvinit-devel mailing list