1 Description: Allow multiple console output
2 When booting a kernel with multiple serial console support, or multuiple
3 console arguments ala "console=tty1 console=ttyS0,9600" the kernel will output
4 messages to all consoles, init however will not. It will only send output to,
5 and accept input from, the last of the consoles.
8 Author: Martin Buck <m@rtin-buck.de>
9 Origin: other, https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=181756
10 Bug-Debian: https://bugs.debian.org/181756
12 Last-Update: 2014-07-20
14 Index: sysvinit-2.88dsf/src/bootlogd.c
15 ===================================================================
16 --- sysvinit-2.88dsf.orig/src/bootlogd.c 2010-03-23 15:37:01.000000000 +0100
17 +++ sysvinit-2.88dsf/src/bootlogd.c 2013-07-15 09:56:55.953975300 +0200
19 char *Version = "@(#) bootlogd 2.86 03-Jun-2004 miquels@cistron.nl";
21 #define LOGFILE "/var/log/boot"
22 +#define MAX_CONSOLES 16
25 char *endptr = ringbuf + sizeof(ringbuf);
36 * Console devices as listed on the kernel command line and
37 * the mapping to actual devices in /dev
42 - * Find out the _real_ console. Assume that stdin is connected to
43 + * Find out the _real_ console(s). Assume that stdin is connected to
44 * the console device (/dev/console).
46 -int consolename(char *res, int rlen)
47 +int consolenames(struct real_cons *cons, int max_consoles)
60 - if (major(st.st_rdev) != 5 || minor(st.st_rdev) != 1) {
62 - * Old kernel, can find real device easily.
64 - int r = findtty(res, "/dev", rlen, st.st_rdev);
66 - fprintf(stderr, "bootlogd: cannot find console device "
67 - "%d:%d under /dev\n", major(st.st_rdev), minor(st.st_rdev));
73 -# define ENOIOCTLCMD 515
75 - if (ioctl(0, TIOCGDEV, &kdev) == 0) {
76 - int r = findtty(res, "/dev", rlen, (dev_t)kdev);
78 - fprintf(stderr, "bootlogd: cannot find console device "
79 - "%d:%d under /dev\n", major(kdev), minor(kdev));
82 - if (errno != ENOIOCTLCMD) return -1;
84 + int considx, num_consoles = 0;
90 if (stat("/proc", &st2) < 0) {
91 perror("bootlogd: /proc");
95 if (st.st_dev == st2.st_dev) {
96 if (mount("proc", "/proc", "proc", 0, NULL) < 0) {
104 if ((fd = open("/proc/cmdline", O_RDONLY)) < 0) {
105 perror("bootlogd: /proc/cmdline");
108 - if ((n = read(fd, buf, sizeof(buf) - 1)) >= 0)
111 + if ((n = read(fd, buf, sizeof(buf) - 1)) < 0)
112 perror("bootlogd: /proc/cmdline");
115 if (didmount) umount("/proc");
118 + if (n < 0) return 0;
121 - if (r < 0) return r;
124 * OK, so find console= in /proc/cmdline.
125 @@ -315,21 +296,32 @@
131 if (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
135 if (strncmp(p, "console=", 8) == 0 &&
136 - isconsole(p + 8, res, rlen)) {
139 + isconsole(p + 8, cons[num_consoles].name, sizeof(cons[num_consoles].name))) {
141 + * Suppress duplicates
143 + for (considx = 0; considx < num_consoles; considx++) {
144 + if (!strcmp(cons[num_consoles].name, cons[considx].name)) {
150 + if (num_consoles >= max_consoles) {
158 - if (r == 0) return r;
159 + if (num_consoles > 0) return num_consoles;
163 @@ -337,12 +329,12 @@
164 * guess the default console.
166 for (n = 0; defcons[n]; n++)
167 - if (isconsole(defcons[n], res, rlen))
169 + if (isconsole(defcons[n], cons[0].name, sizeof(cons[0].name)))
172 fprintf(stderr, "bootlogd: cannot deduce real console device\n");
183 - char realcons[1024];
188 #ifndef __linux__ /* BSD-style ioctl needs an argument. */
192 + struct real_cons cons[MAX_CONSOLES];
193 + int num_consoles, consoles_left;
197 @@ -531,18 +525,22 @@
199 * Open console device directly.
201 - if (consolename(realcons, sizeof(realcons)) < 0)
204 - if (strcmp(realcons, "/dev/tty0") == 0)
205 - strcpy(realcons, "/dev/tty1");
206 - if (strcmp(realcons, "/dev/vc/0") == 0)
207 - strcpy(realcons, "/dev/vc/1");
209 - if ((realfd = open_nb(realcons)) < 0) {
210 - fprintf(stderr, "bootlogd: %s: %s\n", buf, strerror(errno));
211 + if ((num_consoles = consolenames(cons, MAX_CONSOLES)) <= 0)
213 + consoles_left = num_consoles;
214 + for (considx = 0; considx < num_consoles; considx++) {
215 + if (strcmp(cons[considx].name, "/dev/tty0") == 0)
216 + strcpy(cons[considx].name, "/dev/tty1");
217 + if (strcmp(cons[considx].name, "/dev/vc/0") == 0)
218 + strcpy(cons[considx].name, "/dev/vc/1");
220 + if ((cons[considx].fd = open_nb(cons[considx].name)) < 0) {
221 + fprintf(stderr, "bootlogd: %s: %s\n", cons[considx].name, strerror(errno));
225 + if (!consoles_left)
229 * Grab a pty, and redirect console messages to it.
230 @@ -626,26 +624,34 @@
231 if ((n = read(ptm, inptr, endptr - inptr)) >= 0) {
233 * Write data (in chunks if needed)
234 - * to the real output device.
235 + * to the real output devices.
240 - i = write(realfd, p, m);
247 - * Handle EIO (somebody hung
248 - * up our filedescriptor)
250 - realfd = write_err(pts, realfd,
252 - if (realfd >= 0) continue;
253 - got_signal = 1; /* Not really */
255 + for (considx = 0; considx < num_consoles; considx++) {
256 + if (cons[considx].fd < 0) continue;
260 + i = write(cons[considx].fd, p, m);
267 + * Handle EIO (somebody hung
268 + * up our filedescriptor)
270 + cons[considx].fd = write_err(pts,
272 + cons[considx].name, errno);
273 + if (cons[considx].fd >= 0) continue;
275 + * If this was the last console,
276 + * generate a fake signal
278 + if (--consoles_left <= 0) got_signal = 1;
289 + for (considx = 0; considx < num_consoles; considx++) {
290 + close(cons[considx].fd);