-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
+/* SPDX-License-Identifier: LGPL-2.1+ */
#include <stddef.h>
#include <unistd.h>
#include "stdio-util.h"
#include "string-util.h"
#include "syslog-util.h"
+#include "tmpfile-util.h"
#include "unit-name.h"
#define STDOUT_STREAMS_MAX 4096
LIST_FIELDS(StdoutStream, stdout_stream);
LIST_FIELDS(StdoutStream, stdout_stream_notify_queue);
- char id_field[sizeof("_STREAM_ID=")-1 + SD_ID128_STRING_MAX];
+ char id_field[STRLEN("_STREAM_ID=") + SD_ID128_STRING_MAX];
};
void stdout_stream_free(StdoutStream *s) {
DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);
-static void stdout_stream_destroy(StdoutStream *s) {
+void stdout_stream_destroy(StdoutStream *s) {
if (!s)
return;
s->forward_to_syslog,
s->forward_to_kmsg,
s->forward_to_console,
- s->id_field + strlen("_STREAM_ID="));
+ s->id_field + STRLEN("_STREAM_ID="));
if (!isempty(s->identifier)) {
_cleanup_free_ char *escaped;
struct iovec *iovec;
int priority;
char syslog_priority[] = "PRIORITY=\0";
- char syslog_facility[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1];
+ char syslog_facility[STRLEN("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int) + 1];
_cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
size_t n = 0, m;
int r;
iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=stdout");
iovec[n++] = IOVEC_MAKE_STRING(s->id_field);
- syslog_priority[strlen("PRIORITY=")] = '0' + LOG_PRI(priority);
+ syslog_priority[STRLEN("PRIORITY=")] = '0' + LOG_PRI(priority);
iovec[n++] = IOVEC_MAKE_STRING(syslog_priority);
if (priority & LOG_FACMASK) {
return -EINVAL;
}
- s->level_prefix = !!r;
+ s->level_prefix = r;
s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
return 0;
return -EINVAL;
}
- s->forward_to_syslog = !!r;
+ s->forward_to_syslog = r;
s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
return 0;
return -EINVAL;
}
- s->forward_to_kmsg = !!r;
+ s->forward_to_kmsg = r;
s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
return 0;
return -EINVAL;
}
- s->forward_to_console = !!r;
+ s->forward_to_console = r;
s->state = STDOUT_STREAM_RUNNING;
/* Try to save the stream, so that journald can be restarted and we can recover */
return 0;
}
-static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
+int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
_cleanup_(stdout_stream_freep) StdoutStream *stream = NULL;
sd_id128_t id;
int r;
assert(s);
- if (revents != EPOLLIN) {
- log_error("Got invalid event from epoll for stdout server fd: %"PRIx32, revents);
- return -EIO;
- }
+ if (revents != EPOLLIN)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO),
+ "Got invalid event from epoll for stdout server fd: %" PRIx32,
+ revents);
fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (fd < 0) {
}
if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
- log_warning("Too many stdout streams, refusing connection.");
+ struct ucred u;
+
+ r = getpeercred(fd, &u);
+
+ /* By closing fd here we make sure that the client won't wait too long for journald to
+ * gather all the data it adds to the error message to find out that the connection has
+ * just been refused.
+ */
+ fd = safe_close(fd);
+
+ server_driver_message(s, r < 0 ? 0 : u.pid, NULL, LOG_MESSAGE("Too many stdout streams, refusing connection."), NULL);
return 0;
}
return log_oom();
}
- r = parse_env_file(stream->state_file, NEWLINE,
+ r = parse_env_file(NULL, stream->state_file,
"PRIORITY", &priority,
"LEVEL_PREFIX", &level_prefix,
"FORWARD_TO_SYSLOG", &forward_to_syslog,
"FORWARD_TO_CONSOLE", &forward_to_console,
"IDENTIFIER", &stream->identifier,
"UNIT", &stream->unit_id,
- "STREAM_ID", &stream_id,
- NULL);
+ "STREAM_ID", &stream_id);
if (r < 0)
return log_error_errno(r, "Failed to read: %s", stream->state_file);
if (!found) {
/* No file descriptor? Then let's delete the state file */
log_debug("Cannot restore stream file %s", de->d_name);
- unlinkat(dirfd(d), de->d_name, 0);
+ if (unlinkat(dirfd(d), de->d_name, 0) < 0)
+ log_warning_errno(errno, "Failed to remove /run/systemd/journal/streams/%s: %m",
+ de->d_name);
continue;
}
if (s->stdout_fd < 0)
return log_error_errno(errno, "socket() failed: %m");
- (void) unlink(sa.un.sun_path);
+ (void) sockaddr_un_unlink(&sa.un);
r = bind(s->stdout_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
if (r < 0)
if (listen(s->stdout_fd, SOMAXCONN) < 0)
return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path);
} else
- fd_nonblock(s->stdout_fd, 1);
+ (void) fd_nonblock(s->stdout_fd, true);
r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLIN, stdout_stream_new, s);
if (r < 0)
void stdout_stream_send_notify(StdoutStream *s) {
struct iovec iovec = {
.iov_base = (char*) "FDSTORE=1",
- .iov_len = strlen("FDSTORE=1"),
+ .iov_len = STRLEN("FDSTORE=1"),
};
struct msghdr msghdr = {
.msg_iov = &iovec,