journald-stream.c revision 7b77ed8cf36e8eca6017791626044b61ae2d68e7
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen This file is part of systemd.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Copyright 2011 Lennart Poettering
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen systemd is free software; you can redistribute it and/or modify it
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen under the terms of the GNU Lesser General Public License as published by
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen (at your option) any later version.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen systemd is distributed in the hope that it will be useful, but
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen Lesser General Public License for more details.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen You should have received a copy of the GNU Lesser General Public License
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int stdout_stream_log(StdoutStream *s, const char *p) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen char syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(priority)];
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen _cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen unsigned n = 0;
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (s->forward_to_syslog || s->server->forward_to_syslog)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (s->forward_to_kmsg || s->server->forward_to_kmsg)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (s->forward_to_console || s->server->forward_to_console)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen server_forward_console(s->server, priority, s->identifier, p, &s->ucred);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=stdout");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen syslog_priority[strlen("PRIORITY=")] = '0' + LOG_PRI(priority);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen IOVEC_SET_STRING(iovec[n++], syslog_priority);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen snprintf(syslog_facility, sizeof(syslog_facility), "SYSLOG_FACILITY=%i", LOG_FAC(priority));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen IOVEC_SET_STRING(iovec[n++], syslog_facility);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen syslog_identifier = strappend("SYSLOG_IDENTIFIER=", s->identifier);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen IOVEC_SET_STRING(iovec[n++], syslog_identifier);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen label_len = strlen((char*) s->security_context);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority, 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int stdout_stream_line(StdoutStream *s, char *p) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen switch (s->state) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (r < 0 || s->priority < 0 || s->priority > 999) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_warning("Failed to parse log priority line.");
52d629010db73a9466c359201916494bd55186d1Tom Gundersen log_warning("Failed to parse level prefix line.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_warning("Failed to parse forward to syslog line.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_warning("Failed to parse copy to kmsg line.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_warning("Failed to parse copy to console line.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int stdout_stream_scan(StdoutStream *s, bool force_flush) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen else if (remaining >= sizeof(s->buffer) - 1) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (p > s->buffer) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen l = read(s->fd, s->buffer+s->length, sizeof(s->buffer)-1-s->length);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_warning("Failed to read from stream: %m");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (l == 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen s->event_source = sd_event_source_unref(s->event_source);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (s->fd >= 0)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersenstatic int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Got invalid event from epoll for stdout server fd: %"PRIx32, revents);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to accept stdout connection: %m");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_warning("Too many stdout streams, refusing connection.");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &stream->ucred, &len) < 0) {
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to determine peer credentials: %m");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen if (getpeercon(fd, &stream->security_context) < 0 && errno != ENOPROTOOPT)
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to determine peer security context: %m");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to shutdown writing side of socket: %m");
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_event_add_io(s->event, fd, EPOLLIN, stdout_stream_process, stream, &stream->event_source);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to add stream to event loop: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to adjust stdout event source priority: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_event_add_io(s->event, s->stdout_fd, EPOLLIN, stdout_stream_new, s, &s->stdout_event_source);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to add stdout server fd to event source: %s", strerror(-r));
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+10);
57fa1d094cd2c5ac68970526ad0a0754c548e75dTom Gundersen log_error("Failed to adjust priority of stdout server event source: %s", strerror(-r));