1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <selinux/selinux.h>
29 #include "sd-daemon.h"
32 #include "alloc-util.h"
33 #include "dirent-util.h"
38 #include "journald-console.h"
39 #include "journald-kmsg.h"
40 #include "journald-server.h"
41 #include "journald-stream.h"
42 #include "journald-syslog.h"
43 #include "journald-wall.h"
45 #include "parse-util.h"
46 #include "selinux-util.h"
47 #include "socket-util.h"
48 #include "stdio-util.h"
49 #include "string-util.h"
50 #include "syslog-util.h"
52 #define STDOUT_STREAMS_MAX 4096
54 typedef enum StdoutStreamState
{
55 STDOUT_STREAM_IDENTIFIER
,
56 STDOUT_STREAM_UNIT_ID
,
57 STDOUT_STREAM_PRIORITY
,
58 STDOUT_STREAM_LEVEL_PREFIX
,
59 STDOUT_STREAM_FORWARD_TO_SYSLOG
,
60 STDOUT_STREAM_FORWARD_TO_KMSG
,
61 STDOUT_STREAM_FORWARD_TO_CONSOLE
,
67 StdoutStreamState state
;
77 bool forward_to_syslog
:1;
78 bool forward_to_kmsg
:1;
79 bool forward_to_console
:1;
82 bool in_notify_queue
:1;
84 char buffer
[LINE_MAX
+1];
87 sd_event_source
*event_source
;
91 LIST_FIELDS(StdoutStream
, stdout_stream
);
92 LIST_FIELDS(StdoutStream
, stdout_stream_notify_queue
);
95 void stdout_stream_free(StdoutStream
*s
) {
100 assert(s
->server
->n_stdout_streams
> 0);
101 s
->server
->n_stdout_streams
--;
102 LIST_REMOVE(stdout_stream
, s
->server
->stdout_streams
, s
);
104 if (s
->in_notify_queue
)
105 LIST_REMOVE(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
108 if (s
->event_source
) {
109 sd_event_source_set_enabled(s
->event_source
, SD_EVENT_OFF
);
110 s
->event_source
= sd_event_source_unref(s
->event_source
);
122 DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream
*, stdout_stream_free
);
124 static void stdout_stream_destroy(StdoutStream
*s
) {
129 (void) unlink(s
->state_file
);
131 stdout_stream_free(s
);
134 static int stdout_stream_save(StdoutStream
*s
) {
135 _cleanup_free_
char *temp_path
= NULL
;
136 _cleanup_fclose_
FILE *f
= NULL
;
141 if (s
->state
!= STDOUT_STREAM_RUNNING
)
144 if (!s
->state_file
) {
147 r
= fstat(s
->fd
, &st
);
149 return log_warning_errno(errno
, "Failed to stat connected stream: %m");
151 /* We use device and inode numbers as identifier for the stream */
152 if (asprintf(&s
->state_file
, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st
.st_dev
, (unsigned long) st
.st_ino
) < 0)
156 mkdir_p("/run/systemd/journal/streams", 0755);
158 r
= fopen_temporary(s
->state_file
, &f
, &temp_path
);
163 "# This is private data. Do not parse\n"
166 "FORWARD_TO_SYSLOG=%i\n"
167 "FORWARD_TO_KMSG=%i\n"
168 "FORWARD_TO_CONSOLE=%i\n",
171 s
->forward_to_syslog
,
173 s
->forward_to_console
);
175 if (!isempty(s
->identifier
)) {
176 _cleanup_free_
char *escaped
;
178 escaped
= cescape(s
->identifier
);
184 fprintf(f
, "IDENTIFIER=%s\n", escaped
);
187 if (!isempty(s
->unit_id
)) {
188 _cleanup_free_
char *escaped
;
190 escaped
= cescape(s
->unit_id
);
196 fprintf(f
, "UNIT=%s\n", escaped
);
199 r
= fflush_and_check(f
);
203 if (rename(temp_path
, s
->state_file
) < 0) {
208 if (!s
->fdstore
&& !s
->in_notify_queue
) {
209 LIST_PREPEND(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
210 s
->in_notify_queue
= true;
212 if (s
->server
->notify_event_source
) {
213 r
= sd_event_source_set_enabled(s
->server
->notify_event_source
, SD_EVENT_ON
);
215 log_warning_errno(r
, "Failed to enable notify event source: %m");
222 (void) unlink(s
->state_file
);
225 (void) unlink(temp_path
);
227 return log_error_errno(r
, "Failed to save stream data %s: %m", s
->state_file
);
230 static int stdout_stream_log(StdoutStream
*s
, const char *p
) {
231 struct iovec iovec
[N_IOVEC_META_FIELDS
+ 5];
233 char syslog_priority
[] = "PRIORITY=\0";
234 char syslog_facility
[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1];
235 _cleanup_free_
char *message
= NULL
, *syslog_identifier
= NULL
;
242 priority
= s
->priority
;
245 syslog_parse_priority(&p
, &priority
, false);
250 if (s
->forward_to_syslog
|| s
->server
->forward_to_syslog
)
251 server_forward_syslog(s
->server
, syslog_fixup_facility(priority
), s
->identifier
, p
, &s
->ucred
, NULL
);
253 if (s
->forward_to_kmsg
|| s
->server
->forward_to_kmsg
)
254 server_forward_kmsg(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
256 if (s
->forward_to_console
|| s
->server
->forward_to_console
)
257 server_forward_console(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
259 if (s
->server
->forward_to_wall
)
260 server_forward_wall(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
262 IOVEC_SET_STRING(iovec
[n
++], "_TRANSPORT=stdout");
264 syslog_priority
[strlen("PRIORITY=")] = '0' + LOG_PRI(priority
);
265 IOVEC_SET_STRING(iovec
[n
++], syslog_priority
);
267 if (priority
& LOG_FACMASK
) {
268 xsprintf(syslog_facility
, "SYSLOG_FACILITY=%i", LOG_FAC(priority
));
269 IOVEC_SET_STRING(iovec
[n
++], syslog_facility
);
273 syslog_identifier
= strappend("SYSLOG_IDENTIFIER=", s
->identifier
);
274 if (syslog_identifier
)
275 IOVEC_SET_STRING(iovec
[n
++], syslog_identifier
);
278 message
= strappend("MESSAGE=", p
);
280 IOVEC_SET_STRING(iovec
[n
++], message
);
282 label_len
= s
->label
? strlen(s
->label
) : 0;
283 server_dispatch_message(s
->server
, iovec
, n
, ELEMENTSOF(iovec
), &s
->ucred
, NULL
, s
->label
, label_len
, s
->unit_id
, priority
, 0);
287 static int stdout_stream_line(StdoutStream
*s
, char *p
) {
299 case STDOUT_STREAM_IDENTIFIER
:
301 s
->identifier
= NULL
;
303 s
->identifier
= strdup(p
);
308 s
->state
= STDOUT_STREAM_UNIT_ID
;
311 case STDOUT_STREAM_UNIT_ID
:
312 if (s
->ucred
.uid
== 0) {
316 s
->unit_id
= strdup(p
);
322 s
->state
= STDOUT_STREAM_PRIORITY
;
325 case STDOUT_STREAM_PRIORITY
:
326 r
= safe_atoi(p
, &s
->priority
);
327 if (r
< 0 || s
->priority
< 0 || s
->priority
> 999) {
328 log_warning("Failed to parse log priority line.");
332 s
->state
= STDOUT_STREAM_LEVEL_PREFIX
;
335 case STDOUT_STREAM_LEVEL_PREFIX
:
336 r
= parse_boolean(p
);
338 log_warning("Failed to parse level prefix line.");
342 s
->level_prefix
= !!r
;
343 s
->state
= STDOUT_STREAM_FORWARD_TO_SYSLOG
;
346 case STDOUT_STREAM_FORWARD_TO_SYSLOG
:
347 r
= parse_boolean(p
);
349 log_warning("Failed to parse forward to syslog line.");
353 s
->forward_to_syslog
= !!r
;
354 s
->state
= STDOUT_STREAM_FORWARD_TO_KMSG
;
357 case STDOUT_STREAM_FORWARD_TO_KMSG
:
358 r
= parse_boolean(p
);
360 log_warning("Failed to parse copy to kmsg line.");
364 s
->forward_to_kmsg
= !!r
;
365 s
->state
= STDOUT_STREAM_FORWARD_TO_CONSOLE
;
368 case STDOUT_STREAM_FORWARD_TO_CONSOLE
:
369 r
= parse_boolean(p
);
371 log_warning("Failed to parse copy to console line.");
375 s
->forward_to_console
= !!r
;
376 s
->state
= STDOUT_STREAM_RUNNING
;
378 /* Try to save the stream, so that journald can be restarted and we can recover */
379 (void) stdout_stream_save(s
);
382 case STDOUT_STREAM_RUNNING
:
383 return stdout_stream_log(s
, orig
);
386 assert_not_reached("Unknown stream state");
389 static int stdout_stream_scan(StdoutStream
*s
, bool force_flush
) {
397 remaining
= s
->length
;
402 end
= memchr(p
, '\n', remaining
);
405 else if (remaining
>= sizeof(s
->buffer
) - 1) {
406 end
= p
+ sizeof(s
->buffer
) - 1;
413 r
= stdout_stream_line(s
, p
);
421 if (force_flush
&& remaining
> 0) {
423 r
= stdout_stream_line(s
, p
);
432 memmove(s
->buffer
, p
, remaining
);
433 s
->length
= remaining
;
439 static int stdout_stream_process(sd_event_source
*es
, int fd
, uint32_t revents
, void *userdata
) {
440 StdoutStream
*s
= userdata
;
446 if ((revents
|EPOLLIN
|EPOLLHUP
) != (EPOLLIN
|EPOLLHUP
)) {
447 log_error("Got invalid event from epoll for stdout stream: %"PRIx32
, revents
);
451 l
= read(s
->fd
, s
->buffer
+s
->length
, sizeof(s
->buffer
)-1-s
->length
);
457 log_warning_errno(errno
, "Failed to read from stream: %m");
462 stdout_stream_scan(s
, true);
467 r
= stdout_stream_scan(s
, false);
474 stdout_stream_destroy(s
);
478 static int stdout_stream_install(Server
*s
, int fd
, StdoutStream
**ret
) {
479 _cleanup_(stdout_stream_freep
) StdoutStream
*stream
= NULL
;
485 stream
= new0(StdoutStream
, 1);
490 stream
->priority
= LOG_INFO
;
492 r
= getpeercred(fd
, &stream
->ucred
);
494 return log_error_errno(r
, "Failed to determine peer credentials: %m");
496 if (mac_selinux_have()) {
497 r
= getpeersec(fd
, &stream
->label
);
498 if (r
< 0 && r
!= -EOPNOTSUPP
)
499 (void) log_warning_errno(r
, "Failed to determine peer security context: %m");
502 (void) shutdown(fd
, SHUT_WR
);
504 r
= sd_event_add_io(s
->event
, &stream
->event_source
, fd
, EPOLLIN
, stdout_stream_process
, stream
);
506 return log_error_errno(r
, "Failed to add stream to event loop: %m");
508 r
= sd_event_source_set_priority(stream
->event_source
, SD_EVENT_PRIORITY_NORMAL
+5);
510 return log_error_errno(r
, "Failed to adjust stdout event source priority: %m");
515 LIST_PREPEND(stdout_stream
, s
->stdout_streams
, stream
);
516 s
->n_stdout_streams
++;
526 static int stdout_stream_new(sd_event_source
*es
, int listen_fd
, uint32_t revents
, void *userdata
) {
527 _cleanup_close_
int fd
= -1;
528 Server
*s
= userdata
;
533 if (revents
!= EPOLLIN
) {
534 log_error("Got invalid event from epoll for stdout server fd: %"PRIx32
, revents
);
538 fd
= accept4(s
->stdout_fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
543 return log_error_errno(errno
, "Failed to accept stdout connection: %m");
546 if (s
->n_stdout_streams
>= STDOUT_STREAMS_MAX
) {
547 log_warning("Too many stdout streams, refusing connection.");
551 r
= stdout_stream_install(s
, fd
, NULL
);
559 static int stdout_stream_load(StdoutStream
*stream
, const char *fname
) {
562 *level_prefix
= NULL
,
563 *forward_to_syslog
= NULL
,
564 *forward_to_kmsg
= NULL
,
565 *forward_to_console
= NULL
;
571 if (!stream
->state_file
) {
572 stream
->state_file
= strappend("/run/systemd/journal/streams/", fname
);
573 if (!stream
->state_file
)
577 r
= parse_env_file(stream
->state_file
, NEWLINE
,
578 "PRIORITY", &priority
,
579 "LEVEL_PREFIX", &level_prefix
,
580 "FORWARD_TO_SYSLOG", &forward_to_syslog
,
581 "FORWARD_TO_KMSG", &forward_to_kmsg
,
582 "FORWARD_TO_CONSOLE", &forward_to_console
,
583 "IDENTIFIER", &stream
->identifier
,
584 "UNIT", &stream
->unit_id
,
587 return log_error_errno(r
, "Failed to read: %s", stream
->state_file
);
592 p
= log_level_from_string(priority
);
594 stream
->priority
= p
;
598 r
= parse_boolean(level_prefix
);
600 stream
->level_prefix
= r
;
603 if (forward_to_syslog
) {
604 r
= parse_boolean(forward_to_syslog
);
606 stream
->forward_to_syslog
= r
;
609 if (forward_to_kmsg
) {
610 r
= parse_boolean(forward_to_kmsg
);
612 stream
->forward_to_kmsg
= r
;
615 if (forward_to_console
) {
616 r
= parse_boolean(forward_to_console
);
618 stream
->forward_to_console
= r
;
624 static int stdout_stream_restore(Server
*s
, const char *fname
, int fd
) {
625 StdoutStream
*stream
;
632 if (s
->n_stdout_streams
>= STDOUT_STREAMS_MAX
) {
633 log_warning("Too many stdout streams, refusing restoring of stream.");
637 r
= stdout_stream_install(s
, fd
, &stream
);
641 stream
->state
= STDOUT_STREAM_RUNNING
;
642 stream
->fdstore
= true;
644 /* Ignore all parsing errors */
645 (void) stdout_stream_load(stream
, fname
);
650 int server_restore_streams(Server
*s
, FDSet
*fds
) {
651 _cleanup_closedir_
DIR *d
= NULL
;
655 d
= opendir("/run/systemd/journal/streams");
660 return log_warning_errno(errno
, "Failed to enumerate /run/systemd/journal/streams: %m");
663 FOREACH_DIRENT(de
, d
, goto fail
) {
664 unsigned long st_dev
, st_ino
;
669 if (sscanf(de
->d_name
, "%lu:%lu", &st_dev
, &st_ino
) != 2)
672 FDSET_FOREACH(fd
, fds
, i
) {
675 if (fstat(fd
, &st
) < 0)
676 return log_error_errno(errno
, "Failed to stat %s: %m", de
->d_name
);
678 if (S_ISSOCK(st
.st_mode
) && st
.st_dev
== st_dev
&& st
.st_ino
== st_ino
) {
685 /* No file descriptor? Then let's delete the state file */
686 log_debug("Cannot restore stream file %s", de
->d_name
);
687 unlinkat(dirfd(d
), de
->d_name
, 0);
691 fdset_remove(fds
, fd
);
693 r
= stdout_stream_restore(s
, de
->d_name
, fd
);
701 return log_error_errno(errno
, "Failed to read streams directory: %m");
704 int server_open_stdout_socket(Server
*s
) {
709 if (s
->stdout_fd
< 0) {
710 union sockaddr_union sa
= {
711 .un
.sun_family
= AF_UNIX
,
712 .un
.sun_path
= "/run/systemd/journal/stdout",
715 s
->stdout_fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
716 if (s
->stdout_fd
< 0)
717 return log_error_errno(errno
, "socket() failed: %m");
719 unlink(sa
.un
.sun_path
);
721 r
= bind(s
->stdout_fd
, &sa
.sa
, offsetof(union sockaddr_union
, un
.sun_path
) + strlen(sa
.un
.sun_path
));
723 return log_error_errno(errno
, "bind(%s) failed: %m", sa
.un
.sun_path
);
725 (void) chmod(sa
.un
.sun_path
, 0666);
727 if (listen(s
->stdout_fd
, SOMAXCONN
) < 0)
728 return log_error_errno(errno
, "listen(%s) failed: %m", sa
.un
.sun_path
);
730 fd_nonblock(s
->stdout_fd
, 1);
732 r
= sd_event_add_io(s
->event
, &s
->stdout_event_source
, s
->stdout_fd
, EPOLLIN
, stdout_stream_new
, s
);
734 return log_error_errno(r
, "Failed to add stdout server fd to event source: %m");
736 r
= sd_event_source_set_priority(s
->stdout_event_source
, SD_EVENT_PRIORITY_NORMAL
+5);
738 return log_error_errno(r
, "Failed to adjust priority of stdout server event source: %m");
743 void stdout_stream_send_notify(StdoutStream
*s
) {
744 struct iovec iovec
= {
745 .iov_base
= (char*) "FDSTORE=1",
746 .iov_len
= strlen("FDSTORE=1"),
748 struct msghdr msghdr
= {
752 struct cmsghdr
*cmsg
;
757 assert(s
->in_notify_queue
);
759 assert(s
->server
->notify_fd
>= 0);
761 /* Store the connection fd in PID 1, so that we get it passed
762 * in again on next start */
764 msghdr
.msg_controllen
= CMSG_SPACE(sizeof(int));
765 msghdr
.msg_control
= alloca0(msghdr
.msg_controllen
);
767 cmsg
= CMSG_FIRSTHDR(&msghdr
);
768 cmsg
->cmsg_level
= SOL_SOCKET
;
769 cmsg
->cmsg_type
= SCM_RIGHTS
;
770 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
772 memcpy(CMSG_DATA(cmsg
), &s
->fd
, sizeof(int));
774 l
= sendmsg(s
->server
->notify_fd
, &msghdr
, MSG_DONTWAIT
|MSG_NOSIGNAL
);
779 log_error_errno(errno
, "Failed to send stream file descriptor to service manager: %m");
781 log_debug("Successfully sent stream file descriptor to service manager.");
785 LIST_REMOVE(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
786 s
->in_notify_queue
= false;