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 is Martin Buck.)
This commit is contained in:
parent
f52d703c8e
commit
986bee63c0
126
src/bootlogd.c
126
src/bootlogd.c
@ -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);
|
||||
@ -68,6 +69,11 @@ int didnl = 1;
|
||||
int createlogfile = 0;
|
||||
int syncalot = 0;
|
||||
|
||||
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
|
||||
@ -230,10 +236,10 @@ int isconsole(char *s, char *res, int rlen)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
@ -242,34 +248,9 @@ int consolename(char *res, int rlen)
|
||||
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__
|
||||
/*
|
||||
@ -278,7 +259,7 @@ int consolename(char *res, int rlen)
|
||||
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) {
|
||||
@ -288,21 +269,21 @@ int consolename(char *res, int rlen)
|
||||
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.
|
||||
@ -310,21 +291,32 @@ int consolename(char *res, int rlen)
|
||||
*/
|
||||
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;
|
||||
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
|
||||
|
||||
/*
|
||||
@ -332,12 +324,12 @@ int consolename(char *res, int rlen)
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
@ -479,7 +471,6 @@ int main(int argc, char **argv)
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
char buf[1024];
|
||||
char realcons[1024];
|
||||
char *p;
|
||||
char *logfile;
|
||||
char *pidfile;
|
||||
@ -492,6 +483,9 @@ int main(int argc, char **argv)
|
||||
#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;
|
||||
@ -538,6 +532,7 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Open console device directly.
|
||||
*/
|
||||
/*
|
||||
if (consolename(realcons, sizeof(realcons)) < 0)
|
||||
return 1;
|
||||
|
||||
@ -550,6 +545,25 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "bootlogd: %s: %s\n", realcons, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
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.
|
||||
@ -633,12 +647,14 @@ int main(int argc, char **argv)
|
||||
if ((n = read(ptm, inptr, endptr - inptr)) >= 0) {
|
||||
/*
|
||||
* Write data (in chunks if needed)
|
||||
* to the real output device.
|
||||
* to the real output devices.
|
||||
*/
|
||||
for (considx = 0; considx < num_consoles; considx++) {
|
||||
if (cons[considx].fd < 0) continue;
|
||||
m = n;
|
||||
p = inptr;
|
||||
while (m > 0) {
|
||||
i = write(realfd, p, m);
|
||||
i = write(cons[considx].fd, p, m);
|
||||
if (i >= 0) {
|
||||
m -= i;
|
||||
p += i;
|
||||
@ -648,12 +664,18 @@ int main(int argc, char **argv)
|
||||
* Handle EIO (somebody hung
|
||||
* up our filedescriptor)
|
||||
*/
|
||||
realfd = write_err(pts, realfd,
|
||||
realcons, errno);
|
||||
if (realfd >= 0) continue;
|
||||
got_signal = 1; /* Not really */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment buffer position. Handle
|
||||
@ -698,7 +720,9 @@ int main(int argc, char **argv)
|
||||
|
||||
close(pts);
|
||||
close(ptm);
|
||||
close(realfd);
|
||||
for (considx = 0; considx < num_consoles; considx++) {
|
||||
close(cons[considx].fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user