X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fjournal%2Fjournald-syslog.c;h=d3e0f6f6c11868e4dcf5a9bd8c88f4d063a170c0;hb=178cc7700c23ac088cd7190d7854282075028d91;hp=91664762e64a2706ead10ffdbb9343fc329bd286;hpb=35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9;p=elogind.git diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index 91664762e..d3e0f6f6c 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -20,12 +20,18 @@ ***/ #include +#include #include +#include "systemd/sd-messages.h" #include "socket-util.h" #include "journald.h" #include "journald-syslog.h" #include "journald-kmsg.h" +#include "journald-console.h" + +/* Warn once every 30s if we missed syslog message */ +#define WARN_FORWARD_SYSLOG_MISSED_USEC (30 * USEC_PER_SEC) static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, struct ucred *ucred, struct timeval *tv) { struct msghdr msghdr; @@ -72,8 +78,10 @@ static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned /* The socket is full? I guess the syslog implementation is * too slow, and we shouldn't wait for that... */ - if (errno == EAGAIN) + if (errno == EAGAIN) { + s->n_forward_syslog_missed++; return; + } if (ucred && errno == ESRCH) { struct ucred u; @@ -89,8 +97,10 @@ static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0) return; - if (errno == EAGAIN) + if (errno == EAGAIN) { + s->n_forward_syslog_missed++; return; + } } if (errno != ENOENT) @@ -175,7 +185,7 @@ int syslog_fixup_facility(int priority) { return priority; } -void syslog_read_identifier(const char **buf, char **identifier, char **pid) { +void syslog_parse_identifier(const char **buf, char **identifier, char **pid) { const char *p; char *t; size_t l, e; @@ -225,6 +235,112 @@ void syslog_read_identifier(const char **buf, char **identifier, char **pid) { *buf += strspn(*buf, WHITESPACE); } +void syslog_parse_priority(char **p, int *priority) { + int a = 0, b = 0, c = 0; + int k; + + assert(p); + assert(*p); + assert(priority); + + if ((*p)[0] != '<') + return; + + if (!strchr(*p, '>')) + return; + + if ((*p)[2] == '>') { + c = undecchar((*p)[1]); + k = 3; + } else if ((*p)[3] == '>') { + b = undecchar((*p)[1]); + c = undecchar((*p)[2]); + k = 4; + } else if ((*p)[4] == '>') { + a = undecchar((*p)[1]); + b = undecchar((*p)[2]); + c = undecchar((*p)[3]); + k = 5; + } else + return; + + if (a < 0 || b < 0 || c < 0) + return; + + *priority = a*100+b*10+c; + *p += k; +} + +static void syslog_skip_date(char **buf) { + enum { + LETTER, + SPACE, + NUMBER, + SPACE_OR_NUMBER, + COLON + } sequence[] = { + LETTER, LETTER, LETTER, + SPACE, + SPACE_OR_NUMBER, NUMBER, + SPACE, + SPACE_OR_NUMBER, NUMBER, + COLON, + SPACE_OR_NUMBER, NUMBER, + COLON, + SPACE_OR_NUMBER, NUMBER, + SPACE + }; + + char *p; + unsigned i; + + assert(buf); + assert(*buf); + + p = *buf; + + for (i = 0; i < ELEMENTSOF(sequence); i++, p++) { + + if (!*p) + return; + + switch (sequence[i]) { + + case SPACE: + if (*p != ' ') + return; + break; + + case SPACE_OR_NUMBER: + if (*p == ' ') + break; + + /* fall through */ + + case NUMBER: + if (*p < '0' || *p > '9') + return; + + break; + + case LETTER: + if (!(*p >= 'A' && *p <= 'Z') && + !(*p >= 'a' && *p <= 'z')) + return; + + break; + + case COLON: + if (*p != ':') + return; + break; + + } + } + + *buf = p; +} + void server_process_syslog_message( Server *s, const char *buf, @@ -250,7 +366,7 @@ void server_process_syslog_message( forward_syslog_raw(s, priority, orig, ucred, tv); syslog_skip_date((char**) &buf); - syslog_read_identifier(&buf, &identifier, &pid); + syslog_parse_identifier(&buf, &identifier, &pid); if (s->forward_to_kmsg) server_forward_kmsg(s, priority, identifier, buf, ucred); @@ -356,3 +472,20 @@ int server_open_syslog_socket(Server *s) { return 0; } + +void server_maybe_warn_forward_syslog_missed(Server *s) { + usec_t n; + assert(s); + + if (s->n_forward_syslog_missed <= 0) + return; + + n = now(CLOCK_MONOTONIC); + if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n) + return; + + server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, "Forwarding to syslog missed %u messages.", s->n_forward_syslog_missed); + + s->n_forward_syslog_missed = 0; + s->last_warn_forward_syslog_missed = n; +}