[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