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=5a28c2197fd3c0d9a36f604e453e5afe8e6b31e6;hb=f6943caa53ac486cc8de580160954ba2b8ffd504;hpb=addab137cd8d318e4f543ca56018ee23d51aaca9 diff --git a/src/logger.c b/src/logger.c index 5a28c2197..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 && @@ -557,16 +586,16 @@ static int process_event(Server *s, struct epoll_event *ev) { int main(int argc, char *argv[]) { Server server; - int r = 3, n; + int r = EXIT_FAILURE, n; if (getppid() != 1) { log_error("This program should be invoked by init only."); - return 1; + return EXIT_FAILURE; } if (argc > 1) { log_error("This program does not take arguments."); - return 1; + return EXIT_FAILURE; } log_set_target(LOG_TARGET_SYSLOG_OR_KMSG); @@ -575,16 +604,16 @@ int main(int argc, char *argv[]) { if ((n = sd_listen_fds(true)) < 0) { log_error("Failed to read listening file descriptors from environment: %s", strerror(-r)); - return 1; + return EXIT_FAILURE; } if (n <= 0 || n > SERVER_FD_MAX) { log_error("No or too many file descriptors passed."); - return 2; + return EXIT_FAILURE; } if (server_init(&server, (unsigned) n) < 0) - return 3; + return EXIT_FAILURE; log_debug("systemd-logger running as pid %lu", (unsigned long) getpid()); @@ -614,7 +643,7 @@ int main(int argc, char *argv[]) { goto fail; } - r = 0; + r = EXIT_SUCCESS; log_debug("systemd-logger stopped as pid %lu", (unsigned long) getpid());