X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogger.c;h=9d67ab6bd82074d407957cbda87ffdc44b90340c;hp=a590bb84fdd1aa39e63acd4affbf82ddce40e6ed;hb=aa5939a3ba4a0004ced1be4d8f9b0eb7521e4cef;hpb=22f4096ca96acd504ac74e7dfad96f07edb6da51 diff --git a/src/logger.c b/src/logger.c index a590bb84f..9d67ab6bd 100644 --- a/src/logger.c +++ b/src/logger.c @@ -51,6 +51,8 @@ typedef struct Server { unsigned n_server_fd; + bool syslog_is_stream; + LIST_HEAD(Stream, streams); unsigned n_streams; } Server; @@ -172,14 +174,28 @@ 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 */ + if (s->server->syslog_is_stream) + iovec[4].iov_len++; + zero(msghdr); msghdr.msg_iov = iovec; msghdr.msg_iovlen = ELEMENTSOF(iovec); msghdr.msg_control = &control; msghdr.msg_controllen = control.cmsghdr.cmsg_len; - if (sendmsg(s->server->syslog_fd, &msghdr, MSG_NOSIGNAL) < 0) - return -errno; + for (;;) { + ssize_t n; + + if ((n = sendmsg(s->server->syslog_fd, &msghdr, MSG_NOSIGNAL)) < 0) + return -errno; + + if (!s->server->syslog_is_stream || + (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec))) + break; + + IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n); + } } else if (s->target == STREAM_KMSG) { IOVEC_SET_STRING(iovec[1], s->process); @@ -479,22 +495,35 @@ static int server_init(Server *s, unsigned n_sockets) { } } - if ((s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { - r = -errno; - log_error("Failed to create log fd: %m"); - goto fail; - } - zero(sa); sa.un.sun_family = AF_UNIX; strncpy(sa.un.sun_path, "/dev/log", sizeof(sa.un.sun_path)); - if (connect(s->syslog_fd, &sa.sa, sizeof(sa)) < 0) { + if ((s->syslog_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) { r = -errno; - log_error("Failed to connect log socket to /dev/log: %m"); + log_error("Failed to create log fd: %m"); goto fail; } + if (connect(s->syslog_fd, &sa.sa, sizeof(sa)) < 0) { + close_nointr_nofail(s->syslog_fd); + + if ((s->syslog_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0)) < 0) { + r = -errno; + log_error("Failed to create log fd: %m"); + goto fail; + } + + if (connect(s->syslog_fd, &sa.sa, sizeof(sa)) < 0) { + r = -errno; + log_error("Failed to connect log socket to /dev/log: %m"); + goto fail; + } + + s->syslog_is_stream = true; + } else + s->syslog_is_stream = false; + /* /dev/kmsg logging is strictly optional */ if ((s->kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) log_warning("Failed to open /dev/kmsg for logging, disabling kernel log buffer support: %m"); @@ -514,7 +543,7 @@ static int process_event(Server *s, struct epoll_event *ev) { /* Yes, this is a bit ugly, we assume that that valid pointers * are > SD_LISTEN_FDS_START+SERVER_FD_MAX. Which is certainly * true on Linux (and probably most other OSes, too, since the - * first 4k usually are part of a seperate null pointer + * first 4k usually are part of a separate null pointer * dereference page. */ if (PTR_TO_INT(ev->data.ptr) >= SD_LISTEN_FDS_START &&