diff --git a/showconsole-1.13.dif b/showconsole-1.13.dif index e8c27cd..5841532 100644 --- a/showconsole-1.13.dif +++ b/showconsole-1.13.dif @@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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]\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 /* Defines the macros major and minor */ + #include + #include ++#ifndef TIOCGDEV ++# include ++# include ++# include ++#endif ++#include + #include + #include + #include +@@ -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 diff --git a/sysvinit.changes b/sysvinit.changes index fdb1f9f..428ffc7 100644 --- a/sysvinit.changes +++ b/sysvinit.changes @@ -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