--- blogd.8 +++ blogd.8 2011-04-19 11:59:52.704425678 +0000 @@ -65,7 +65,7 @@ says that it should stop writing to disk but continue to repeat messages to the old devices of the system console. -\." +.\" .SH BUGS .B blogd needs a mounted --- blogd.c +++ blogd.c 2011-04-20 11:13:46.799926099 +0000 @@ -41,6 +41,7 @@ # define _POSIX_MAX_CANON 255 #endif extern volatile sig_atomic_t nsigsys; +extern volatile sig_atomic_t signaled; static const char console[] = "/dev/console"; @@ -66,7 +67,7 @@ void error (const char *fmt, ...) _logger(fmt, ap); va_end(ap); popd(); - exit (1); + exit(EXIT_FAILURE); } /* @@ -122,7 +123,6 @@ static struct sigaction saved_sigint; static struct sigaction saved_sigquit; static struct sigaction saved_sigterm; static struct sigaction saved_sigsys; -static volatile sig_atomic_t signaled = 0; static void sighandle(int sig) { @@ -318,6 +318,10 @@ int main(int argc, char *argv[]) cfmakeraw(&o); cfsetispeed(&o, ispeed); cfsetospeed(&o, ospeed); + o.c_lflag &= ~ECHO; + o.c_lflag |= ISIG; + o.c_cc[VTIME] = 0; + o.c_cc[VMIN] = CMIN; if (openpty(&ptm, &pts, ptsname, &o, &w) < 0) error("can not open pty/tty pair: %m\n"); @@ -336,7 +340,7 @@ int main(int argc, char *argv[]) dup2(0, 2); secondtty(cons, st.st_rdev); -exit(0); + (void)ioctl(0, TIOCCONS, NULL); /* Undo any current map if any */ close(0); @@ -344,6 +348,20 @@ exit(0); error("can not set console device to %s: %m\n", ptsname); close(pts); + signaled = nsigsys = 0; + set_signal(SIGTTIN, &saved_sigttin, SIG_IGN); + set_signal(SIGTTOU, &saved_sigttou, SIG_IGN); + set_signal(SIGTSTP, &saved_sigtstp, SIG_IGN); + set_signal(SIGHUP, &saved_sighup, SIG_IGN); + set_signal(SIGINT, &saved_sigint, sighandle); + set_signal(SIGQUIT, &saved_sigquit, sighandle); + set_signal(SIGTERM, &saved_sigterm, sighandle); + set_signal(SIGSYS, &saved_sigsys, sigsys); + (void)siginterrupt(SIGINT, 0); + (void)siginterrupt(SIGQUIT, 0); + (void)siginterrupt(SIGTERM, 0); + (void)siginterrupt(SIGSYS, 0); + for (c = cons; c; c = c->next) { int iflag, oflag; #ifdef _PC_MAX_CANON @@ -351,22 +369,34 @@ exit(0); #endif c->max_canon = _POSIX_MAX_CANON; c->tlock = 0; - if (tcgetattr(cons->fd, &cons->otio) < 0) + if (tcgetattr(c->fd, &c->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); + if (ioctl(c->fd, TIOCMGET, &flags) == 0) { + ispeed = cfgetispeed(&c->otio); + ospeed = cfgetospeed(&c->otio); + + c->otio.c_iflag = c->otio.c_lflag = 0; + c->otio.c_oflag = (ONLCR | OPOST); + c->otio.c_cflag = CREAD | CS8 | HUPCL | (c->otio.c_cflag & CLOCAL); + + cfsetispeed(&c->otio, ispeed); + cfsetospeed(&c->otio, ospeed); + } else { + 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(c->fd, TCSADRAIN, &c->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; @@ -384,20 +414,6 @@ exit(0); } } - nsigsys = 0; - set_signal(SIGTTIN, &saved_sigttin, SIG_IGN); - set_signal(SIGTTOU, &saved_sigttou, SIG_IGN); - set_signal(SIGTSTP, &saved_sigtstp, SIG_IGN); - set_signal(SIGHUP, &saved_sighup, SIG_IGN); - set_signal(SIGINT, &saved_sigint, sighandle); - set_signal(SIGQUIT, &saved_sigquit, sighandle); - set_signal(SIGTERM, &saved_sigterm, sighandle); - set_signal(SIGSYS, &saved_sigsys, sigsys); - (void)siginterrupt(SIGINT, 0); - (void)siginterrupt(SIGQUIT, 0); - (void)siginterrupt(SIGTERM, 0); - (void)siginterrupt(SIGSYS, 0); - atexit(exit_handler); /* Register main exit handler */ switch ((pid = fork())) { @@ -427,7 +443,7 @@ exit(0); } fprintf(stdout, "\rBoot logging started on %s(%s) at %.24s\n", tty, console, stt); fflush(stdout); - _exit(0); /* NEVER rise exit handlers here */ + _exit(EXIT_SUCCESS); /* NEVER rise exit handlers here */ } atexit(flush_handler); /* Register flush exit handler */ @@ -436,7 +452,7 @@ exit(0); while (!signaled) safeIO(); - exit(0); /* Raise exit handlers */ + exit(EXIT_SUCCESS); /* Raise exit handlers */ } static void flush_handler (void) --- isserial.8 +++ isserial.8 2011-04-19 11:59:52.772425964 +0000 @@ -32,7 +32,7 @@ is if .B stdin is a serial line otherwise not. -\." +.\" .SH FILES .TP .I /dev/console --- libblogger.c +++ libblogger.c 2011-08-01 14:32:47.599926864 +0000 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -40,9 +41,58 @@ #define ESNS "skipped" /* Skipped */ #define ESNU "unused" /* Unused */ +static struct sigaction saved_sigpipe; +static volatile sig_atomic_t broken = 0; static int fdfifo = -1; static char * fifo_name = _PATH_BLOG_FIFO; +static void sigpipe(int sig __attribute__((__unused__))) +{ + broken++; +} + +static void set_signal(int sig, struct sigaction *old, sighandler_t handler) +{ + do { + if (sigaction(sig, NULL, old) == 0) + break; + } while (errno == EINTR); + + if (old && old->sa_handler != handler) { + struct sigaction new; + sigset_t sigset; + + new.sa_handler = handler; + sigemptyset(&new.sa_mask); + new.sa_flags = SA_RESTART; + do { + if (sigaction(sig, &new, NULL) == 0) + break; + } while (errno == EINTR); + + sigemptyset(&sigset); + sigaddset(&sigset, sig); + sigprocmask(SIG_UNBLOCK, &sigset, NULL); + } +} + +static void reset_signal(int sig, struct sigaction *old) +{ + struct sigaction cur; + + do { + if (sigaction(sig, NULL, &cur) == 0) + break; + } while (errno == EINTR); + + if (old && old->sa_handler == cur.sa_handler) { + do { + if (sigaction(sig, old, NULL) == 0) + break; + } while (errno == EINTR); + } +} + static int bootlog_init(const int lvl __attribute__((__unused__))) { int ret = -1; @@ -57,6 +107,8 @@ static int bootlog_init(const int lvl __ if ((fdfifo = open(fifo_name, O_WRONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC)) < 0) goto out; + set_signal(SIGPIPE, &saved_sigpipe, sigpipe); + ret = 0; out: return ret; @@ -66,6 +118,9 @@ void closeblog() { if (fdfifo < 0) goto out; + + reset_signal(SIGPIPE, &saved_sigpipe); + (void)close(fdfifo); out: return; @@ -77,6 +132,7 @@ int bootlog(const int lvl, const char *f int ret = -1; char * head = ESNN; char buf[4096]; + sigset_t blockpipe, oldpipe; if (fdfifo < 0 && bootlog_init(lvl) < 0) goto out; @@ -106,6 +162,9 @@ int bootlog(const int lvl, const char *f break; } + sigprocmask(SIG_BLOCK, &blockpipe, &oldpipe); + if (broken) + goto pipe; if (head) { const struct tm *local; struct timeval now; @@ -124,6 +183,8 @@ int bootlog(const int lvl, const char *f vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); write(fdfifo, buf, strlen(buf)); +pipe: + sigprocmask(SIG_SETMASK, &oldpipe, NULL); out: return ret; } --- libconsole.c +++ libconsole.c 2011-08-01 14:00:51.311926463 +0000 @@ -59,6 +59,27 @@ #include "listing.h" /* + * Used to ignore some signals during pselect(2) + */ +static sigset_t omask; + +/* + * Remember if we're signaled. + */ +volatile sig_atomic_t signaled; + +/* + * Error raised in exit handler should not call exit(3) its self + */ +#define lerror(fmt, args...) \ + do { \ + if (signaled) { \ + warn(fmt, args); \ + goto out; \ + } error(fmt, args); \ + } while (0) + +/* * push and popd direcotry changes */ @@ -182,7 +203,9 @@ static inline void safeout (int fd, cons if (p < 0) { if (errno == EPIPE) { warn("error on writing to fd %d: %m\n", fd); - exit (0); + if (signaled) + goto out; + exit(EXIT_SUCCESS); } if (errno == EINTR) { errno = 0; @@ -192,8 +215,9 @@ static inline void safeout (int fd, cons int ret; fd_set check; - if (repeated++ > 1000) - error("repeated error on writing to fd %d: %m\n", fd); + if (repeated++ > 1000) { + lerror("repeated error on writing to fd %d: %m\n", fd); + } FD_ZERO (&check); FD_SET (fd, &check); @@ -201,30 +225,33 @@ static inline void safeout (int fd, cons /* Avoid high load: wait upto two seconds if system is not ready */ errno = 0; do { - struct timeval two = {2, 0}; - ret = select(fd + 1, (fd_set*)0, &check, (fd_set*)0, &two); + struct timespec two = {2, 0}; + ret = pselect(fd + 1, (fd_set*)0, &check, (fd_set*)0, &two, &omask); } while ((ret < 0) && (errno == EINTR)); - if (ret < 0) - error("can not write to fd %d: %m\n", fd); + if (ret < 0) { + lerror("can not write to fd %d: %m\n", fd); + } errno = 0; continue; } if (errno == EIO) { - if ((eiocount++ > 10) || !vc_reconnect) - error("can not write to fd %d: %m\n", fd); + if ((eiocount++ > 10) || !vc_reconnect) { + lerror("can not write to fd %d: %m\n", fd); + } (*vc_reconnect)(fd); errno = 0; continue; } - error("can not write to fd %d: %m\n", fd); + lerror("can not write to fd %d: %m\n", fd); } repeated = 0; ptr += p; s -= p; } +out: errno = saveerr; } @@ -244,14 +271,14 @@ static inline ssize_t safein (int fd, ch t=0; if ((ioctl(fd, FIONREAD, &t) < 0) || (t == 0)) { fd_set check; - struct timeval zero = {0, 0}; + struct timespec zero = {0, 0}; do { FD_ZERO (&check); FD_SET (fd, &check); /* Avoid deadlock: do not read if nothing is in there */ - if (select(fd + 1, &check, (fd_set*)0, (fd_set*)0, &zero) <= 0) + if (pselect(fd + 1, &check, (fd_set*)0, (fd_set*)0, &zero, &omask) <= 0) break; r = read (fd, ptr, s); @@ -260,11 +287,11 @@ static inline ssize_t safein (int fd, ch /* Do not exit on a broken FIFO */ if (r < 0 && errno != EPIPE) { - if (noerr) + if (noerr || signaled) 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: %m\n", fd); + lerror("Can not read from fd %d: %m\n", fd); } goto out; @@ -277,17 +304,18 @@ static inline ssize_t safein (int fd, ch while (t > 0) { ssize_t p = read (fd, ptr, t); if (p < 0) { - if (repeated++ > 1000) - error("Repeated error on reading from fd %d: %m\n", fd); + if (repeated++ > 1000) { + lerror("Repeated error on reading from fd %d: %m\n", fd); + } if (errno == EINTR || errno == EAGAIN) { errno = 0; continue; } - if (noerr) + if (noerr || signaled) 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: %m\n", fd); + lerror("Can not read from fd %d: %m\n", fd); } repeated = 0; ptr += p; @@ -302,7 +330,7 @@ out: /* * The stdio file pointer for our log file */ -struct console *restrict cons; +struct console *cons; static FILE * flog = NULL; static int fdread = -1; static int fdfifo = -1; @@ -310,7 +338,7 @@ static int fdfifo = -1; /* * Signal control for writing on log file */ -volatile sig_atomic_t nsigsys = 0; +volatile sig_atomic_t nsigsys; static volatile sig_atomic_t nsigio = -1; static sigset_t save_oldset; @@ -402,7 +430,7 @@ xout: static inline void writelog(void) { if (!flog) - goto xout; + return; clearerr(flog); lock(&llock); while (avail > 0) { @@ -411,8 +439,8 @@ static inline void writelog(void) if (avail > TRANS_BUFFER_SIZE) ret = TRANS_BUFFER_SIZE; - if (!flog) - goto xout;; + if (!flog || nsigsys) + break; ret = fwrite(head, sizeof(unsigned char), ret, flog); if (!ret && ferror(flog)) break; @@ -429,12 +457,10 @@ static inline void writelog(void) } } unlock(&llock); - if (!flog) - goto xout;; - fflush(flog); - fdatasync(fileno(flog)); -xout: - return; + if (flog) { + fflush(flog); + fdatasync(fileno(flog)); + } } static inline void flushlog(void) @@ -771,6 +797,12 @@ void prepareIO(void (*rfunc)(int), void pgroup = pgrp; fdread = in; + (void)sigfillset(&omask); + (void)sigdelset(&omask, SIGQUIT); + (void)sigdelset(&omask, SIGTERM); + (void)sigdelset(&omask, SIGSYS); + (void)sigdelset(&omask, SIGIO); + if (fifo_name && fdfifo < 0) { struct stat st; errno = 0; @@ -789,7 +821,7 @@ void prepareIO(void (*rfunc)(int), void /* * Seek for input, more input ... */ -static void more_input (struct timeval *timeout, const int noerr) +static void more_input (struct timespec *timeout, const int noerr) { fd_set watch; int nfds, wfds; @@ -803,19 +835,16 @@ static void more_input (struct timeval * } else wfds = fdread + 1; - nfds = select(wfds, &watch, (fd_set*)0, (fd_set*)0, timeout); + nfds = pselect(wfds, &watch, (fd_set*)0, (fd_set*)0, timeout, &omask); - if (nfds < 0) { + if (nfds <= 0) { timeout->tv_sec = 0; - timeout->tv_usec = 0; - if (errno != EINTR) - error ("select(): %m\n"); + timeout->tv_nsec = 0; + if (nfds < 0 && errno != EINTR && !signaled) + error ("pselect(): %m\n"); goto nothing; } - if (!nfds) - goto nothing; - if (FD_ISSET(fdread, &watch)) { const ssize_t cnt = safein(fdread, (char*)trans, sizeof(trans), noerr); static struct winsize owz; @@ -863,7 +892,7 @@ nothing: */ void safeIO (void) { - struct timeval timeout; + struct timespec timeout; static int log = -1; if (!nsigio) /* signal handler set but no signal recieved */ @@ -898,8 +927,12 @@ void safeIO (void) (*vr_access)(); vr_access = NULL; } - if ((flog = fdopen (log, "a")) == NULL) - error("Can not open %s: %m\n", BOOT_LOGFILE); + lock(&llock); + if ((flog = fdopen (log, "a")) == NULL) { + unlock(&llock); + error("Can not open %s: %m\n", BOOT_LOGFILE); + } + unlock(&llock); nsigio = SIGIO; /* We do not need a signal handler */ (void)signal(SIGIO, SIG_IGN); @@ -927,7 +960,7 @@ skip: } timeout.tv_sec = 5; - timeout.tv_usec = 0; + timeout.tv_nsec = 0; more_input(&timeout, 0); if (flog && !running) { @@ -958,7 +991,7 @@ skip: */ void closeIO(void) { - struct timeval timeout; + struct timespec timeout; struct console * c; int n = 240; @@ -983,12 +1016,12 @@ void closeIO(void) n--; timeout.tv_sec = 0; - timeout.tv_usec = 25*1000; + timeout.tv_nsec = 25*1000*1000; more_input(&timeout, 1); (void)tcdrain(fdread); - } while (timeout.tv_sec || timeout.tv_usec); + } while (timeout.tv_sec || timeout.tv_nsec); if (running) { lock(&ljoin); @@ -998,20 +1031,16 @@ void closeIO(void) pthread_cancel(lthread); } - if (!flog) - goto xout; - - writelog(); - - if (!nl) - fputc('\n', flog); - - if (!flog) - goto xout; - - (void)fclose(flog); + if (flog) { + writelog(); + if (!nl) + fputc('\n', flog); + (void)fclose(flog); + } + lock(&llock); flog = NULL; -xout: + unlock(&llock); + if (fdfifo >= 0) { close(fdfifo); fdfifo = -1; @@ -1101,7 +1130,7 @@ static dev_t fallback(const pid_t pid, c printf("|%u|%u|", tty, ttypgrp); /* stdout to pipe synchronize ... */ - exit(0); + exit(EXIT_SUCCESS); } break; case -1: error("can not execute: %m\n"); @@ -1463,6 +1492,10 @@ static void consalloc(struct console *re return; } tail->next = newc; + tail->tlock = 0; + tail->max_canon = _POSIX_MAX_CANON; + memset(&tail->ltio, 0, sizeof(tail->ltio)); + memset(&tail->otio, 0, sizeof(tail->otio)); tail = tail->next; if ((flags = fcntl(newc->fd, F_GETFL)) < 0) --- libconsole.h +++ libconsole.h 2011-03-31 14:47:22.755926508 +0000 @@ -39,7 +39,7 @@ struct console { int fd, tlock; ssize_t max_canon; struct termios ltio, otio; - struct console *restrict next; + struct console * next; }; extern void error (const char *fmt, ...) attribute((__noreturn__, __format__(__printf__, 1, 2))); extern void warn (const char *fmt, ...) attribute((__format__(__printf__, 1, 2))); @@ -50,6 +50,6 @@ extern void secondtty(struct console *re extern void prepareIO(void (*rfunc)(int), void (*pfunc)(void), const pid_t, const int); extern void safeIO (void); extern void closeIO(void); -extern struct console *restrict cons; +extern struct console *cons; #define alignof(type) ((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1)) #define strsize(string) ((strlen(string)+1)*sizeof(char)) --- showconsole.8 +++ showconsole.8 2011-04-19 11:59:52.844425538 +0000 @@ -41,7 +41,7 @@ Without any argument or the option the .B setconsole undo any redirection. -\." +.\" .SH OPTIONS .TP .B \-n @@ -50,7 +50,7 @@ the device file name. This can be used kernel for the major and minor device numbers of a not existing device file in .IR /dev . -\." +.\" .SH BUGS .B showconsole needs a mounted