X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogger.c;h=81196dbe00cd0e0734989d22149439bd5e040d14;hp=9d67ab6bd82074d407957cbda87ffdc44b90340c;hb=bbc732830876ce75a95c57ccf8677f74e4569efc;hpb=b00bad36414ba3acd857f8c5f3dec12ba202363a diff --git a/src/logger.c b/src/logger.c index 9d67ab6bd..81196dbe0 100644 --- a/src/logger.c +++ b/src/logger.c @@ -37,10 +37,11 @@ #include "list.h" #include "sd-daemon.h" #include "tcpwrap.h" +#include "def.h" -#define STREAMS_MAX 256 +#define STREAMS_MAX 4096 #define SERVER_FD_MAX 16 -#define TIMEOUT ((int) (10*MSEC_PER_SEC)) +#define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)) typedef struct Stream Stream; @@ -84,7 +85,8 @@ struct Stream { uid_t uid; gid_t gid; - bool prefix; + bool prefix:1; + bool tee_console:1; char buffer[LINE_MAX]; size_t length; @@ -103,20 +105,16 @@ static int stream_log(Stream *s, char *p, usec_t ts) { priority = s->priority; - if (s->prefix && - p[0] == '<' && - p[1] >= '0' && p[1] <= '7' && - p[2] == '>') { - - /* Detected priority prefix */ - priority = LOG_MAKEPRI(LOG_FAC(priority), (p[1] - '0')); - - p += 3; - } + if (s->prefix) + parse_syslog_priority(&p, &priority); if (*p == 0) return 0; + /* Patch in LOG_USER facility if necessary */ + if ((priority & LOG_FACMASK) == 0) + priority = LOG_USER | LOG_PRI(priority); + /* * The format glibc uses to talk to the syslog daemon is: * @@ -129,8 +127,7 @@ static int stream_log(Stream *s, char *p, usec_t ts) { * We extend the latter to include the process name and pid. */ - snprintf(header_priority, sizeof(header_priority), "<%i>", - s->target == STREAM_SYSLOG ? priority : LOG_PRI(priority)); + snprintf(header_priority, sizeof(header_priority), "<%i>", priority); char_array_0(header_priority); if (s->target == STREAM_SYSLOG) { @@ -174,7 +171,7 @@ static int stream_log(Stream *s, char *p, usec_t ts) { IOVEC_SET_STRING(iovec[3], header_pid); IOVEC_SET_STRING(iovec[4], p); - /* When using syslog via SOCK_STREAM seperate the messages by NUL chars */ + /* When using syslog via SOCK_STREAM separate the messages by NUL chars */ if (s->server->syslog_is_stream) iovec[4].iov_len++; @@ -187,8 +184,28 @@ static int stream_log(Stream *s, char *p, usec_t ts) { for (;;) { ssize_t n; - if ((n = sendmsg(s->server->syslog_fd, &msghdr, MSG_NOSIGNAL)) < 0) + if ((n = sendmsg(s->server->syslog_fd, &msghdr, MSG_NOSIGNAL)) < 0) { + + if (errno == ESRCH) { + pid_t our_pid; + + /* Hmm, maybe the process this + * line originates from is + * dead? Then let's patch in + * our own pid and retry, + * since we have nothing + * better */ + + our_pid = getpid(); + + if (ucred->pid != our_pid) { + ucred->pid = our_pid; + continue; + } + } + return -errno; + } if (!s->server->syslog_is_stream || (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec))) @@ -208,6 +225,20 @@ static int stream_log(Stream *s, char *p, usec_t ts) { } else assert_not_reached("Unknown log target"); + if (s->tee_console) { + int console; + + if ((console = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) >= 0) { + IOVEC_SET_STRING(iovec[0], s->process); + IOVEC_SET_STRING(iovec[1], header_pid); + IOVEC_SET_STRING(iovec[2], p); + IOVEC_SET_STRING(iovec[3], (char*) "\n"); + + writev(console, iovec, 4); + } + + } + return 0; } @@ -222,9 +253,9 @@ static int stream_line(Stream *s, char *p, usec_t ts) { switch (s->state) { case STREAM_TARGET: - if (streq(p, "syslog")) + if (streq(p, "syslog") || streq(p, "syslog+console")) s->target = STREAM_SYSLOG; - else if (streq(p, "kmsg")) { + else if (streq(p, "kmsg") || streq(p, "kmsg+console")) { if (s->server->kmsg_fd >= 0 && s->uid == 0) s->target = STREAM_KMSG; @@ -236,6 +267,10 @@ static int stream_line(Stream *s, char *p, usec_t ts) { log_warning("Failed to parse log target line."); return -EBADMSG; } + + if (endswith(p, "+console")) + s->tee_console = true; + s->state = STREAM_PRIORITY; return 0; @@ -318,7 +353,7 @@ static int stream_process(Stream *s, usec_t ts) { return 0; log_warning("Failed to read from stream: %m"); - return -1; + return -errno; } @@ -481,7 +516,7 @@ static int server_init(Server *s, unsigned n_sockets) { /* We use ev.data.ptr instead of ev.data.fd here, * since on 64bit archs fd is 32bit while a pointer is - * 64bit. To make sure we can easily distuingish fd + * 64bit. To make sure we can easily distinguish fd * values and pointer values we want to make sure to * write the full field unconditionally. */ @@ -627,7 +662,7 @@ int main(int argc, char *argv[]) { if ((k = epoll_wait(server.epoll_fd, &event, 1, - server.n_streams <= 0 ? TIMEOUT : -1)) < 0) { + server.n_streams <= 0 ? TIMEOUT_MSEC : -1)) < 0) { if (errno == EINTR) continue;