Dr. Werner Fink 2011-03-25 11:16:47 +00:00 committed by Git OBS Bridge
parent a85735fc32
commit 655b7a0468
2 changed files with 585 additions and 19 deletions

View File

@ -1,6 +1,157 @@
--- blogd.8
+++ blogd.8 2011-03-25 11:08:46.268426518 +0000
@@ -40,7 +40,7 @@ will not hold the real character device
.I /dev/console
as its controlling tty (would hangup any running
getty on that character device).
-\."
+.\"
.SH SIGNALS
.B blogd
knows a few signal to contol its behavior.
--- blogd.c
+++ blogd.c 2011-03-02 11:25:01.151926991 +0000
@@ -301,9 +301,16 @@ int main(int argc, char *argv[])
+++ blogd.c 2011-03-25 11:08:46.284426810 +0000
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include <stropts.h>
#include <dirent.h>
#include <fcntl.h>
#include <termios.h>
@@ -41,6 +42,8 @@
#endif
extern volatile sig_atomic_t nsigsys;
+static const char console[] = "/dev/console";
+
/*
* Internal logger
*/
@@ -91,7 +94,7 @@ static void rmfpid()
/*
* Write pidfile
*/
-static void pidfile()
+static void attribute((noinline)) pidfile()
{
char buf[strlen(_PATH_VARRUN)+strlen(myname)+1+3+1];
FILE * fpid;
@@ -207,26 +210,55 @@ static void reconnect(int fd)
}
}
+
+static volatile int cntrtty = 1;
+static volatile pid_t pid = -1;
+static volatile pid_t ppid;
+
+static void flush_handler (void) attribute((noinline));
+static void exit_handler (void) attribute((noinline));
+
/*
* Now do the job
*/
int main(int argc, char *argv[])
{
- int fd, flags;
- int ptm, pts, cntrtty = 1;
- const pid_t ppid = getppid();
- const pid_t pgrp = getpgid(ppid);
char ptsname[NAME_MAX+1];
struct console *c;
struct termios o;
struct winsize w;
struct stat st;
- pid_t pid;
+ speed_t ospeed;
+ speed_t ispeed;
+ int ptm, pts;
+ int flags;
+ pid_t pgrp;
time_t tt;
- char *tty, *stt, *name = ttyname(0);
+ char *tty, *stt;
+ ppid = getppid();
+ pgrp = getpgid(ppid);
myname = basename(*argv);
+ if (stat(console, &st) < 0)
+ error("No system console %s: %m\n", console);
+ else {
+ dev_t sysconsole = st.st_rdev;
+ int fd0;
+
+ if (stat("/proc/self/fd/0", &st) < 0)
+ error("No standard input: %m\n");
+ if (sysconsole != st.st_rdev) {
+ close(0);
+ if ((fd0 = open(console, O_WRONLY|O_NONBLOCK|O_NOCTTY)) < 0)
+ error("Can not open system console %s: %m\n", console);
+ if (fd0 > 0) {
+ dup2(fd0, 0);
+ close(fd0);
+ }
+ }
+ }
+
if (argc > 2)
error("Too many args; usage: %s [/dev/tty<X>]\n", myname);
@@ -238,14 +270,8 @@ int main(int argc, char *argv[])
if (!tty || !*tty)
error("can not discover real system console tty, boot logging disabled.\n");
- if (!name || !*name) {
- name = strdup("(no tty)");
- if (!name)
- error("strdup(): %s\n", strerror(errno));
- }
-
- if (strcmp(tty, name) == 0)
- error("console=%s, stdin=%s, must differ, boot logging disabled\n", tty, name);
+ if (strcmp(tty, console) == 0)
+ error("console=%s, stdin=%s, must differ, boot logging disabled\n", tty, console);
if (posix_memalign((void*)&cons, sizeof(void*), alignof(typeof(struct console))) != 0)
error("memory allocation: %s\n", strerror(errno));
@@ -266,10 +292,14 @@ int main(int argc, char *argv[])
if (tcgetattr(cons->fd, &cons->otio) < 0)
error("can not get terminal parameters of %s: %s\n", tty, strerror(errno));
- if (fstat(cons->fd, &st) == 0 && major(st.st_rdev) == TTY_MAJOR) {
- cfsetispeed(&cons->otio, B38400);
- cfsetospeed(&cons->otio, B38400);
+ ispeed = B38400;
+ ospeed = B38400;
+ if (ioctl(cons->fd, TIOCMGET, &flags) == 0) {
+ ispeed = cfgetispeed(&cons->otio);
+ ospeed = cfgetospeed(&cons->otio);
}
+ cfsetispeed(&cons->otio, ispeed);
+ cfsetospeed(&cons->otio, ospeed);
if (tcgetpgrp(cons->fd) < 0)
cntrtty = 0;
@@ -286,6 +316,8 @@ int main(int argc, char *argv[])
memcpy(&o, &cons->otio, sizeof(o));
cfmakeraw(&o);
+ cfsetispeed(&o, ispeed);
+ cfsetospeed(&o, ospeed);
if (openpty(&ptm, &pts, ptsname, &o, &w) < 0)
error("can not open pty/tty pair: %s\n", strerror(errno));
@@ -298,13 +330,22 @@ int main(int argc, char *argv[])
(void)ioctl(pts, TIOCSLCKTRMIOS, &lock);
}
+ if (isastream(1) < 0 && errno == EBADF)
+ dup2(0, 1);
+ if (isastream(2) < 0 && errno == EBADF)
+ dup2(0, 2);
+
secondtty(cons, st.st_rdev);
(void)ioctl(0, TIOCCONS, NULL); /* Undo any current map if any */
@ -8,27 +159,61 @@
+
if (ioctl(pts, TIOCCONS, NULL) < 0)
error("can not set console device to %s: %s\n", ptsname, strerror(errno));
+ close(pts);
+ dup2(pts, 1);
+ dup2(pts, 2);
+ if (pts > 2)
+ close(pts);
+
for (c = cons; c; c = c->next) {
+ int iflag, oflag;
#ifdef _PC_MAX_CANON
if ((c->max_canon = (ssize_t)fpathconf(c->fd, _PC_MAX_CANON)) <= 0)
@@ -356,21 +363,16 @@ int main(int argc, char *argv[])
close(cons->fd);
cons->fd = 1; /* Choose stdout */
}
#endif
@@ -313,6 +354,19 @@ int main(int argc, char *argv[])
if (tcgetattr(cons->fd, &cons->otio) < 0)
continue;
c->tlock = 1;
+#if 1
+ iflag = c->otio.c_iflag;
+ oflag = c->otio.c_oflag;
+
+ c->otio.c_iflag |= (ICRNL | IGNBRK);
+ c->otio.c_iflag &= ~(INLCR | IGNCR | BRKINT);
+ c->otio.c_oflag |= (ONLCR | OPOST);
+ c->otio.c_oflag &= ~(OCRNL | ONLRET);
+ (void)tcsetattr(cons->fd, TCSADRAIN, &cons->otio);
+
+ c->otio.c_iflag = iflag;
+ c->otio.c_oflag = oflag;
+#endif
if ((c->otio.c_lflag & ICANON) == 0) {
c->otio.c_lflag |= ICANON | IEXTEN | ISIG | ECHO|ECHOE|ECHOK|ECHOKE;
c->otio.c_oflag |= OPOST;
@@ -344,6 +398,8 @@ int main(int argc, char *argv[])
(void)siginterrupt(SIGTERM, 0);
(void)siginterrupt(SIGSYS, 0);
+ atexit(exit_handler); /* Register main exit handler */
+
switch ((pid = fork())) {
case 0:
/* Get our own session */
@@ -352,55 +408,56 @@ int main(int argc, char *argv[])
dup2(ptm, 0);
dup2(cons->fd, 1);
dup2(cons->fd, 2);
- if (cons->fd > 2) {
- close(cons->fd);
- cons->fd = 1; /* Choose stdout */
- }
- close(pts);
+ if (cons->fd > 2)
+ dup2(1, cons->fd); /* Choose stdout */
close(ptm);
break;
case -1:
- close(pts);
close(ptm);
warn("can not fork to become daemon: %s\n", strerror(errno));
goto err;
- warn("can not fork to become daemon: %s\n", strerror(errno));
- goto err;
+ error("can not fork to become daemon: %s\n", strerror(errno));
default:
time(&tt);
stt = ctime(&tt);
@ -39,9 +224,172 @@
for (c = cons; c; c = c->next) {
if (c->fd > 0) {
close(c->fd);
c->fd = -1;
}
}
- fprintf(stdout, "\rBoot logging started on %s(%s) at %.24s\n", tty, name, stt);
+ fprintf(stdout, "\rBoot logging started on %s(%s) at %.24s\n", tty, console, stt);
fflush(stdout);
- exit(0);
+ _exit(0); /* NEVER rise exit handlers here */
}
+ atexit(flush_handler); /* Register flush exit handler */
+
prepareIO(reconnect, pidfile, pgrp, 0);
while (!signaled)
safeIO();
+ exit(0); /* Raise exit handlers */
+}
+
+static void flush_handler (void)
+{
(void)tcdrain(1);
(void)tcdrain(2);
- if (!cntrtty)
- kill(ppid, SIGSTOP);
+ if (!cntrtty) kill(ppid, SIGSTOP);
closeIO();
- if (!cntrtty)
- kill(ppid, SIGCONT);
+ if (!cntrtty) kill(ppid, SIGCONT);
+}
+
+static void exit_handler (void)
+{
+ struct console *c;
+ int fd;
- (void)ioctl(0, TIOCSLCKTRMIOS, &o);
-err:
for (c = cons; c; c = c->next) {
if (c->fd > 0) {
if (c->tlock) /* write back old setup */
- tcsetattr(c->fd, TCSANOW, &c->otio);
+ tcsetattr(c->fd, TCSADRAIN, &c->otio);
if (c->tlock > 1) /* write back lock if any */
(void)ioctl(c->fd, TIOCSLCKTRMIOS, &c->ltio);
c->tlock = 0;
@@ -410,20 +467,15 @@ err:
}
errno = 0;
- if ((fd = open("/dev/console", O_RDWR|O_NOCTTY)) >= 0) {
+ if ((fd = open(console, O_RDWR|O_NOCTTY)) >= 0) {
(void)ioctl(fd, TIOCCONS, NULL); /* Restore old console mapping */
close(fd);
}
- if (pid > 0) {
- (void)tcflush(1, TCOFLUSH);
- close(1);
- (void)tcflush(2, TCOFLUSH);
- close(2);
- (void)tcflush(0, TCIFLUSH);
- close(0);
- rmfpid();
- }
+ close(1);
+ close(2);
+ (void)tcflush(0, TCIFLUSH);
+ close(0);
reset_signal(SIGTTIN, &saved_sigttin);
reset_signal(SIGTTOU, &saved_sigttou);
@@ -433,6 +485,4 @@ err:
reset_signal(SIGQUIT, &saved_sigquit);
reset_signal(SIGTERM, &saved_sigterm);
reset_signal(SIGSYS, &saved_sigsys);
-
- return 0;
}
--- libconsole.c
+++ libconsole.c 2011-03-02 10:33:17.032457114 +0000
@@ -707,11 +707,12 @@ static void parselog(unsigned char *buf,
+++ libconsole.c 2011-03-25 11:11:22.040426359 +0000
@@ -29,6 +29,12 @@
#include <sys/types.h> /* Defines the macros major and minor */
#include <sys/stat.h>
#include <sys/ioctl.h>
+#ifndef TIOCGDEV
+# include <sys/vt.h>
+# include <sys/kd.h>
+# include <linux/serial.h>
+#endif
+#include <linux/major.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/param.h>
@@ -52,9 +58,6 @@
#include "libconsole.h"
#include "listing.h"
-extern void error (const char *fmt, ...);
-extern void warn (const char *fmt, ...);
-
/*
* push and popd direcotry changes
*/
@@ -110,12 +113,12 @@ static int rlstat(char ** file, struct s
{
int ret = -1;
unsigned int deep = 0;
- static ino_t iprev; // Recurive loop detection
+ static ino_t iprev; /* Recurive loop detection */
if (lstat(*file, st) < 0)
goto out;
- if (iprev && iprev == st->st_ino) // We're run on the previous
+ if (iprev && iprev == st->st_ino) /* We're run on the previous */
goto out;
iprev = st->st_ino;
@@ -123,7 +126,7 @@ static int rlstat(char ** file, struct s
const char *prev_file;
ssize_t cnt;
- if (!S_ISLNK(st->st_mode)) // Not a symlink
+ if (!S_ISLNK(st->st_mode)) /* Not a symlink */
break;
if (deep++ > MAXSYMLINKS) {
@@ -175,7 +178,7 @@ static inline void safeout (int fd, cons
static int eiocount;
while (s > 0) {
- ssize_t p = write (fd, ptr, (max < 0) ? s : ((s < (size_t)max) ? s : (size_t)max));
+ ssize_t p = write (fd, ptr, (max < 1) ? 1 : ((s < (size_t)max) ? s : (size_t)max));
if (p < 0) {
if (errno == EPIPE) {
warn("error on writing to fd %d: %s\n", fd, strerror(errno));
@@ -238,6 +241,7 @@ static inline ssize_t safein (int fd, ch
if (s > SSIZE_MAX)
s = SSIZE_MAX;
+ t=0;
if ((ioctl(fd, FIONREAD, &t) < 0) || (t == 0)) {
fd_set check;
struct timeval zero = {0, 0};
@@ -258,6 +262,8 @@ static inline ssize_t safein (int fd, ch
if (r < 0 && errno != EPIPE) {
if (noerr)
goto out;
+ if (fd == 0 && errno == EIO)
+ warn("\e[31m\e[1msystem console stolen at line %d!\e[m\n", __LINE__);
error("Can not read from fd %d: %s\n", fd, strerror(errno));
}
@@ -279,6 +285,8 @@ static inline ssize_t safein (int fd, ch
}
if (noerr)
goto out;
+ if (fd == 0 && errno == EIO)
+ warn("\e[31m\e[1msystem console stolen at line %d!\e[m\n", __LINE__);
error("Can not read from fd %d: %s\n", fd, strerror(errno));
}
repeated = 0;
@@ -707,11 +715,12 @@ static void parselog(unsigned char *buf,
static void copylog(const unsigned char *buf, const size_t s)
{
lock(&llock);
@ -57,7 +405,7 @@
unlock(&llock);
}
@@ -770,7 +771,7 @@ void prepareIO(void (*rfunc)(int), void
@@ -770,7 +779,7 @@ void prepareIO(void (*rfunc)(int), void
(void)mkfifo(fifo_name, 0600);
errno = 0;
if (!stat(fifo_name, &st) && S_ISFIFO(st.st_mode)) {
@ -66,7 +414,63 @@
warn("can not open named fifo %s: %s\n", fifo_name, strerror(errno));
}
}
@@ -1266,7 +1267,7 @@ char * fetchtty(const pid_t pid, const p
@@ -1141,6 +1150,15 @@ static int checkdev(char ** retname, con
if (!strncmp(name, "ram", 3))
continue;
+ if (!strncmp(name, "rtc", 3))
+ continue;
+
+ if (!strncmp(name, "card", 4))
+ continue;
+
+ if (!strncmp(name, "vboxguest", 9))
+ continue;
+
if (!strcmp(name, "cciss"))
continue;
@@ -1183,8 +1201,23 @@ static int checkdev(char ** retname, con
if (!strcmp(name, "block"))
continue;
+ if (!strcmp(name, "cgroup"))
+ continue;
+
if (!strcmp(name, "disk"))
continue;
+
+ if (!strcmp(name, "bus"))
+ continue;
+
+ if (!strcmp(name, "bsg"))
+ continue;
+
+ if (!strcmp(name, "cpu"))
+ continue;
+
+ if (!strcmp(name, "char"))
+ continue;
}
if (rlstat(&name, &st) < 0) {
@@ -1251,37 +1284,50 @@ static int checkdev(char ** retname, con
/* main routine to fetch tty */
char * fetchtty(const pid_t pid, const pid_t ppid, dev_t * tty)
{
-#ifdef TIOCGDEV
- unsigned int mjmi = 0;
-#endif
char * name = NULL;
dev_t dev = 0;
int found = 0;
DIR * ddev;
FILE * fc;
- if ((fc = fopen("/proc/tty/consoles", "r"))) {
+ if ((fc = fopen("/proc/consoles", "r"))) {
char fbuf[16];
int maj, min;
while ((fscanf(fc, "%*s %*s (%[^)]) %d:%d", &fbuf[0], &maj, &min) == 3)) {
if (!strchr(fbuf, 'E'))
continue;
@ -75,7 +479,43 @@
dev = makedev(maj, min);
break;
}
@@ -1327,8 +1328,9 @@ void secondtty(struct console *restrict
}
fclose(fc);
- }
+ } else {
#ifdef TIOCGDEV
- else {
- if (ioctl (0, TIOCGDEV, &mjmi) < 0) {
+ unsigned int devnum = 0;
+ if (ioctl (0, TIOCGDEV, &devnum) < 0) {
if (errno == EINVAL && !getenv("NOTIOCGDEV"))
warn("Warning: the ioctl TIOCGDEV is not known by the kernel\n");
}
- dev = (dev_t)mjmi;
- }
+ dev = (dev_t)devnum;
+#else
+ struct stat st;
+ if (fstat(0, &st) == 0 && (major(st.st_rdev) == TTYAUX_MAJOR || st.st_rdev == makedev(TTY_MAJOR, 0))) {
+ unsigned int arg;
+ if (ioctl(0, TIOCMGET, &arg) == 0) { /* serial line */
+# if 0
+ dev = makedev(TTY_MAJOR, 64); /* 8250/16450/16550(A) ports */
+# else
+ dev = 0;
+# endif
+ } else if (ioctl(0, KDGKBTYPE, &arg) == 0) { /* virtual console */
+ struct vt_stat vt;
+ if (ioctl(0, VT_GETSTATE, &vt) == 0)
+ dev = makedev(TTY_MAJOR, (int)vt.v_active);
+ }
+ }
#endif
+ }
if (!dev) {
if (!(name = ttyname(0)) || !strcmp(name, "/dev/console"))
dev = fallback(pid, ppid);
@@ -1327,8 +1373,9 @@ void secondtty(struct console *restrict
tail = cons;
@ -87,7 +527,7 @@
struct stat st;
char fbuf[16];
@@ -1341,13 +1343,13 @@ void secondtty(struct console *restrict
@@ -1341,13 +1388,13 @@ void secondtty(struct console *restrict
error("can not opendir(/dev): %s\n", strerror(errno));
pushd("/dev");
@ -103,6 +543,125 @@
continue;
dev = makedev(maj, min);
@@ -1379,14 +1426,14 @@ void secondtty(struct console *restrict
if ((flags = fcntl(newc->fd, F_GETFL)) < 0) {
warn("can not get terminal flags of %s: %s\n", newc->tty, strerror(errno));
+ free(newc);
continue;
}
flags &= ~(O_NONBLOCK);
flags |= O_NOCTTY;
- if (fcntl(newc->fd, F_SETFL, flags) < 0) {
+ if (fcntl(newc->fd, F_SETFL, flags) < 0)
warn("can not set terminal flags of %s: %s\n", newc->tty, strerror(errno));
- }
}
popd();
@@ -1433,7 +1480,12 @@ void secondtty(struct console *restrict
struct console *restrict newc;
char *res = (char*)0;
struct stat st;
- int flags;
+#ifdef TIOCGDEV
+ unsigned int devnum;
+#else
+ struct vt_stat vt;
+#endif
+ int fd, flags;
if (*ptr == ',' || *ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') {
*ptr-- = 0;
@@ -1461,14 +1513,47 @@ void secondtty(struct console *restrict
if (!res)
continue;
- if (stat(res, &st) < 0) {
- warn("can not stat /dev/%s: %s\n", res, strerror(errno));
+ /* Open second console e.g. /dev/tty0 */
+ if ((fd = open(res, O_RDWR|O_NONBLOCK|O_NOCTTY)) < 0)
+ continue;
+
+ /*
+ * We do this because if we would write out the buffered
+ * messages to e.g. /dev/tty0 after this we would (re)read
+ * those and buffer them again which leads to an endless loop.
+ */
+#ifdef TIOCGDEV
+ if (ioctl (fd, TIOCGDEV, &devnum) < 0) {
+ if (errno == EINVAL && !getenv("NOTIOCGDEV"))
+ warn("Warning: the ioctl TIOCGDEV is not known by the kernel\n");
+ close(fd);
+ continue;
+ }
+ st.st_rdev = (dev_t)devnum;
+#else
+ if (fstat(fd, &st) < 0) {
+ close(fd);
continue;
}
+ if (st.st_rdev == makedev(TTY_MAJOR, 0)) {
+ if (ioctl(fd, VT_GETSTATE, &vt) < 0) {
+ if (errno == EINVAL)
+ warn("Warning: the ioctl VT_GETSTATE is not known by the kernel\n");
+ close(fd);
+ continue;
+ }
+ st.st_rdev = makedev(TTY_MAJOR, (int)vt.v_active);
+ }
+#endif
+ close(fd);
+
if (st.st_rdev == tty)
continue;
+ if (st.st_rdev == makedev(TTY_MAJOR, 0)) /* Avoid endless loop */
+ continue;
+
if (!checkdev(&name, st.st_rdev, ddev) || !name) {
if (name) {
free(name);
@@ -1492,14 +1577,14 @@ void secondtty(struct console *restrict
if ((flags = fcntl(newc->fd, F_GETFL)) < 0) {
warn("can not get terminal flags of %s: %s\n", newc->tty, strerror(errno));
+ free(newc);
continue;
}
flags &= ~(O_NONBLOCK);
flags |= O_NOCTTY;
- if (fcntl(newc->fd, F_SETFL, flags) < 0) {
+ if (fcntl(newc->fd, F_SETFL, flags) < 0)
warn("can not set terminal flags of %s: %s\n", newc->tty, strerror(errno));
- }
}
popd();
--- libconsole.h
+++ libconsole.h 2011-03-25 11:08:46.344426335 +0000
@@ -27,6 +27,9 @@
# ifndef extension
# define extension __extension__
# endif
+# ifndef typeof
+# define typeof __typeof__
+# endif
#endif
#ifndef attribute
# define attribute(attr) __attribute__(attr)
@@ -38,6 +41,8 @@ struct console {
struct termios ltio, otio;
struct console *restrict next;
};
+extern void error (const char *fmt, ...) attribute((__noreturn__, __format__(__printf__, 1, 2)));
+extern void warn (const char *fmt, ...) attribute((__format__(__printf__, 1, 2)));
extern void pushd(const char *);
extern void popd(void);
extern char * fetchtty(const pid_t, const pid_t, dev_t *);
--- showconsole.8
+++ showconsole.8 2010-11-09 15:26:29.038362757 +0000
@@ -22,8 +22,7 @@ Setconsole \- redirect system console ou

View File

@ -1,3 +1,10 @@
-------------------------------------------------------------------
Fri Mar 25 12:13:30 CET 2011 - werner@suse.de
- Fix triggered endless loop in blogd (bnc#642289)
* Writing on tty0 caused blogd to re-read its own messages
* The usage of ttyname(3) on /dev/console can fail
-------------------------------------------------------------------
Tue Mar 15 16:01:22 CET 2011 - werner@suse.de