journald-stream.c revision e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2011 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <stddef.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/epoll.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_SELINUX
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <selinux/selinux.h>
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "socket-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "selinux-util.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "journald-server.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "journald-stream.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "journald-syslog.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "journald-kmsg.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "journald-console.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define STDOUT_STREAMS_MAX 4096
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringtypedef enum StdoutStreamState {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STDOUT_STREAM_IDENTIFIER,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STDOUT_STREAM_UNIT_ID,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STDOUT_STREAM_PRIORITY,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STDOUT_STREAM_LEVEL_PREFIX,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STDOUT_STREAM_FORWARD_TO_SYSLOG,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STDOUT_STREAM_FORWARD_TO_KMSG,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STDOUT_STREAM_FORWARD_TO_CONSOLE,
d3e84ddb885e9d5f0ae9930eb905910e3a81f157Lennart Poettering STDOUT_STREAM_RUNNING
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering} StdoutStreamState;
d3e84ddb885e9d5f0ae9930eb905910e3a81f157Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstruct StdoutStream {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering Server *server;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering StdoutStreamState state;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
afc6adb5ec7e73bc13156c43f52fb015cd80cc68Lennart Poettering int fd;
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct ucred ucred;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_SELINUX
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering security_context_t security_context;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
cde93897cdefdd7c7f66c400a61e42ceee5f6a46Lennart Poettering
cde93897cdefdd7c7f66c400a61e42ceee5f6a46Lennart Poettering char *identifier;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *unit_id;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int priority;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool level_prefix:1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool forward_to_syslog:1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool forward_to_kmsg:1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool forward_to_console:1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char buffer[LINE_MAX+1];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t length;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering LIST_FIELDS(StdoutStream, stdout_stream);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d3e84ddb885e9d5f0ae9930eb905910e3a81f157Lennart Poetteringstatic int stdout_stream_log(StdoutStream *s, const char *p) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct iovec iovec[N_IOVEC_META_FIELDS + 5];
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int priority;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering char syslog_priority[] = "PRIORITY=\0";
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering char syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(priority)];
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering unsigned n = 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering char *label = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t label_len = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (isempty(p))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering priority = s->priority;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->level_prefix)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering syslog_parse_priority(&p, &priority, false);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->forward_to_syslog || s->server->forward_to_syslog)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->forward_to_kmsg || s->server->forward_to_kmsg)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->forward_to_console || s->server->forward_to_console)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_forward_console(s->server, priority, s->identifier, p, &s->ucred);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=stdout");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
b87633c4b20e3221748d6c98336cf6c85123cd66Lennart Poettering syslog_priority[strlen("PRIORITY=")] = '0' + LOG_PRI(priority);
b87633c4b20e3221748d6c98336cf6c85123cd66Lennart Poettering IOVEC_SET_STRING(iovec[n++], syslog_priority);
b87633c4b20e3221748d6c98336cf6c85123cd66Lennart Poettering
b87633c4b20e3221748d6c98336cf6c85123cd66Lennart Poettering if (priority & LOG_FACMASK) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering snprintf(syslog_facility, sizeof(syslog_facility), "SYSLOG_FACILITY=%i", LOG_FAC(priority));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iovec[n++], syslog_facility);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->identifier) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering syslog_identifier = strappend("SYSLOG_IDENTIFIER=", s->identifier);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (syslog_identifier)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iovec[n++], syslog_identifier);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering message = strappend("MESSAGE=", p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (message)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering IOVEC_SET_STRING(iovec[n++], message);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_SELINUX
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->security_context) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering label = (char*) s->security_context;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering label_len = strlen((char*) s->security_context);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
76b543756ef69ce69784d571aefe8de65eaeb331Lennart Poetteringstatic int stdout_stream_line(StdoutStream *s, char *p) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(s);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering p = strstrip(p);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering switch (s->state) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case STDOUT_STREAM_IDENTIFIER:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (isempty(p))
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering s->identifier = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering else {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->identifier = strdup(p);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!s->identifier)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return log_oom();
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->state = STDOUT_STREAM_UNIT_ID;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case STDOUT_STREAM_UNIT_ID:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->ucred.uid == 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (isempty(p))
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering s->unit_id = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering else {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->unit_id = strdup(p);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!s->unit_id)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return log_oom();
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->state = STDOUT_STREAM_PRIORITY;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case STDOUT_STREAM_PRIORITY:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = safe_atoi(p, &s->priority);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0 || s->priority < 0 || s->priority > 999) {
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering log_warning("Failed to parse log priority line.");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EINVAL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->state = STDOUT_STREAM_LEVEL_PREFIX;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case STDOUT_STREAM_LEVEL_PREFIX:
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = parse_boolean(p);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to parse level prefix line.");
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering return -EINVAL;
943aca8efb39453e3994ccdd1e08534b788c5aeeLennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering s->level_prefix = !!r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case STDOUT_STREAM_FORWARD_TO_SYSLOG:
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = parse_boolean(p);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to parse forward to syslog line.");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EINVAL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->forward_to_syslog = !!r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
19befb2d5fc087f96e40ddc432b2cc9385666209Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case STDOUT_STREAM_FORWARD_TO_KMSG:
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = parse_boolean(p);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_warning("Failed to parse copy to kmsg line.");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EINVAL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->forward_to_kmsg = !!r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering return 0;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case STDOUT_STREAM_FORWARD_TO_CONSOLE:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = parse_boolean(p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_warning("Failed to parse copy to console line.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->forward_to_console = !!r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->state = STDOUT_STREAM_RUNNING;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case STDOUT_STREAM_RUNNING:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return stdout_stream_log(s, p);
5bb658a1784a0fd4f0f32adb4b1fb636ff503f7dKay Sievers }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert_not_reached("Unknown stream state");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int stdout_stream_scan(StdoutStream *s, bool force_flush) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering char *p;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering size_t remaining;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering p = s->buffer;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering remaining = s->length;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (;;) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *end;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering size_t skip;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering end = memchr(p, '\n', remaining);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (end)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering skip = end - p + 1;
71fda00f320379f5cbee8e118848de98caaa229dLennart Poettering else if (remaining >= sizeof(s->buffer) - 1) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering end = p + sizeof(s->buffer) - 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering skip = remaining;
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering } else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *end = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = stdout_stream_line(s, p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering remaining -= skip;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering p += skip;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (force_flush && remaining > 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering p[remaining] = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = stdout_stream_line(s, p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering p += remaining;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering remaining = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p > s->buffer) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering memmove(s->buffer, p, remaining);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->length = remaining;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint stdout_stream_process(StdoutStream *s) {
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering ssize_t l;
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering l = read(s->fd, s->buffer+s->length, sizeof(s->buffer)-1-s->length);
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering if (l < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering if (errno == EAGAIN)
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering log_warning("Failed to read from stream: %m");
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering return -errno;
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering }
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering if (l == 0) {
d9e34bfda3d34dcde00a876cb052e7de0655e1cbLennart Poettering r = stdout_stream_scan(s, true);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->length += l;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = stdout_stream_scan(s, false);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid stdout_stream_free(StdoutStream *s) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->server) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s->server->n_stdout_streams > 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->server->n_stdout_streams --;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->fd >= 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->server)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering epoll_ctl(s->server->epoll_fd, EPOLL_CTL_DEL, s->fd, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(s->fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_SELINUX
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (s->security_context)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering freecon(s->security_context);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(s->identifier);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(s->unit_id);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint stdout_stream_new(Server *s) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering StdoutStream *stream;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int fd, r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering socklen_t len;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering struct epoll_event ev;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (errno == EAGAIN)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_error("Failed to accept stdout connection: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
log_warning("Too many stdout streams, refusing connection.");
close_nointr_nofail(fd);
return 0;
}
stream = new0(StdoutStream, 1);
if (!stream) {
close_nointr_nofail(fd);
return log_oom();
}
stream->fd = fd;
len = sizeof(stream->ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &stream->ucred, &len) < 0) {
log_error("Failed to determine peer credentials: %m");
r = -errno;
goto fail;
}
#ifdef HAVE_SELINUX
if (use_selinux()) {
if (getpeercon(fd, &stream->security_context) < 0 && errno != ENOPROTOOPT)
log_error("Failed to determine peer security context: %m");
}
#endif
if (shutdown(fd, SHUT_WR) < 0) {
log_error("Failed to shutdown writing side of socket: %m");
r = -errno;
goto fail;
}
zero(ev);
ev.data.ptr = stream;
ev.events = EPOLLIN;
if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
log_error("Failed to add stream to event loop: %m");
r = -errno;
goto fail;
}
stream->server = s;
LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
s->n_stdout_streams ++;
return 0;
fail:
stdout_stream_free(stream);
return r;
}
int server_open_stdout_socket(Server *s) {
int r;
struct epoll_event ev = { .events = EPOLLIN };
assert(s);
if (s->stdout_fd < 0) {
union sockaddr_union sa = {
.un.sun_family = AF_UNIX,
.un.sun_path = "/run/systemd/journal/stdout",
};
s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (s->stdout_fd < 0) {
log_error("socket() failed: %m");
return -errno;
}
unlink(sa.un.sun_path);
r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
if (r < 0) {
log_error("bind() failed: %m");
return -errno;
}
chmod(sa.un.sun_path, 0666);
if (listen(s->stdout_fd, SOMAXCONN) < 0) {
log_error("listen() failed: %m");
return -errno;
}
} else
fd_nonblock(s->stdout_fd, 1);
ev.data.fd = s->stdout_fd;
if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->stdout_fd, &ev) < 0) {
log_error("Failed to add stdout server fd to epoll object: %m");
return -errno;
}
return 0;
}