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
;
245 priority
= s
->priority
;
248 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
) {
297 case STDOUT_STREAM_IDENTIFIER
:
299 s
->identifier
= NULL
;
301 s
->identifier
= strdup(p
);
306 s
->state
= STDOUT_STREAM_UNIT_ID
;
309 case STDOUT_STREAM_UNIT_ID
:
310 if (s
->ucred
.uid
== 0) {
314 s
->unit_id
= strdup(p
);
320 s
->state
= STDOUT_STREAM_PRIORITY
;
323 case STDOUT_STREAM_PRIORITY
:
324 r
= safe_atoi(p
, &s
->priority
);
325 if (r
< 0 || s
->priority
< 0 || s
->priority
> 999) {
326 log_warning("Failed to parse log priority line.");
330 s
->state
= STDOUT_STREAM_LEVEL_PREFIX
;
333 case STDOUT_STREAM_LEVEL_PREFIX
:
334 r
= parse_boolean(p
);
336 log_warning("Failed to parse level prefix line.");
340 s
->level_prefix
= !!r
;
341 s
->state
= STDOUT_STREAM_FORWARD_TO_SYSLOG
;
344 case STDOUT_STREAM_FORWARD_TO_SYSLOG
:
345 r
= parse_boolean(p
);
347 log_warning("Failed to parse forward to syslog line.");
351 s
->forward_to_syslog
= !!r
;
352 s
->state
= STDOUT_STREAM_FORWARD_TO_KMSG
;
355 case STDOUT_STREAM_FORWARD_TO_KMSG
:
356 r
= parse_boolean(p
);
358 log_warning("Failed to parse copy to kmsg line.");
362 s
->forward_to_kmsg
= !!r
;
363 s
->state
= STDOUT_STREAM_FORWARD_TO_CONSOLE
;
366 case STDOUT_STREAM_FORWARD_TO_CONSOLE
:
367 r
= parse_boolean(p
);
369 log_warning("Failed to parse copy to console line.");
373 s
->forward_to_console
= !!r
;
374 s
->state
= STDOUT_STREAM_RUNNING
;
376 /* Try to save the stream, so that journald can be restarted and we can recover */
377 (void) stdout_stream_save(s
);
380 case STDOUT_STREAM_RUNNING
:
381 return stdout_stream_log(s
, p
);
384 assert_not_reached("Unknown stream state");
387 static int stdout_stream_scan(StdoutStream
*s
, bool force_flush
) {
395 remaining
= s
->length
;
400 end
= memchr(p
, '\n', remaining
);
403 else if (remaining
>= sizeof(s
->buffer
) - 1) {
404 end
= p
+ sizeof(s
->buffer
) - 1;
411 r
= stdout_stream_line(s
, p
);
419 if (force_flush
&& remaining
> 0) {
421 r
= stdout_stream_line(s
, p
);
430 memmove(s
->buffer
, p
, remaining
);
431 s
->length
= remaining
;
437 static int stdout_stream_process(sd_event_source
*es
, int fd
, uint32_t revents
, void *userdata
) {
438 StdoutStream
*s
= userdata
;
444 if ((revents
|EPOLLIN
|EPOLLHUP
) != (EPOLLIN
|EPOLLHUP
)) {
445 log_error("Got invalid event from epoll for stdout stream: %"PRIx32
, revents
);
449 l
= read(s
->fd
, s
->buffer
+s
->length
, sizeof(s
->buffer
)-1-s
->length
);
455 log_warning_errno(errno
, "Failed to read from stream: %m");
460 stdout_stream_scan(s
, true);
465 r
= stdout_stream_scan(s
, false);
472 stdout_stream_destroy(s
);
476 static int stdout_stream_install(Server
*s
, int fd
, StdoutStream
**ret
) {
477 _cleanup_(stdout_stream_freep
) StdoutStream
*stream
= NULL
;
483 stream
= new0(StdoutStream
, 1);
488 stream
->priority
= LOG_INFO
;
490 r
= getpeercred(fd
, &stream
->ucred
);
492 return log_error_errno(r
, "Failed to determine peer credentials: %m");
494 if (mac_selinux_use()) {
495 r
= getpeersec(fd
, &stream
->label
);
496 if (r
< 0 && r
!= -EOPNOTSUPP
)
497 (void) log_warning_errno(r
, "Failed to determine peer security context: %m");
500 (void) shutdown(fd
, SHUT_WR
);
502 r
= sd_event_add_io(s
->event
, &stream
->event_source
, fd
, EPOLLIN
, stdout_stream_process
, stream
);
504 return log_error_errno(r
, "Failed to add stream to event loop: %m");
506 r
= sd_event_source_set_priority(stream
->event_source
, SD_EVENT_PRIORITY_NORMAL
+5);
508 return log_error_errno(r
, "Failed to adjust stdout event source priority: %m");
513 LIST_PREPEND(stdout_stream
, s
->stdout_streams
, stream
);
514 s
->n_stdout_streams
++;
524 static int stdout_stream_new(sd_event_source
*es
, int listen_fd
, uint32_t revents
, void *userdata
) {
525 _cleanup_close_
int fd
= -1;
526 Server
*s
= userdata
;
531 if (revents
!= EPOLLIN
) {
532 log_error("Got invalid event from epoll for stdout server fd: %"PRIx32
, revents
);
536 fd
= accept4(s
->stdout_fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
541 return log_error_errno(errno
, "Failed to accept stdout connection: %m");
544 if (s
->n_stdout_streams
>= STDOUT_STREAMS_MAX
) {
545 log_warning("Too many stdout streams, refusing connection.");
549 r
= stdout_stream_install(s
, fd
, NULL
);
557 static int stdout_stream_load(StdoutStream
*stream
, const char *fname
) {
560 *level_prefix
= NULL
,
561 *forward_to_syslog
= NULL
,
562 *forward_to_kmsg
= NULL
,
563 *forward_to_console
= NULL
;
569 if (!stream
->state_file
) {
570 stream
->state_file
= strappend("/run/systemd/journal/streams/", fname
);
571 if (!stream
->state_file
)
575 r
= parse_env_file(stream
->state_file
, NEWLINE
,
576 "PRIORITY", &priority
,
577 "LEVEL_PREFIX", &level_prefix
,
578 "FORWARD_TO_SYSLOG", &forward_to_syslog
,
579 "FORWARD_TO_KMSG", &forward_to_kmsg
,
580 "FORWARD_TO_CONSOLE", &forward_to_console
,
581 "IDENTIFIER", &stream
->identifier
,
582 "UNIT", &stream
->unit_id
,
585 return log_error_errno(r
, "Failed to read: %s", stream
->state_file
);
590 p
= log_level_from_string(priority
);
592 stream
->priority
= p
;
596 r
= parse_boolean(level_prefix
);
598 stream
->level_prefix
= r
;
601 if (forward_to_syslog
) {
602 r
= parse_boolean(forward_to_syslog
);
604 stream
->forward_to_syslog
= r
;
607 if (forward_to_kmsg
) {
608 r
= parse_boolean(forward_to_kmsg
);
610 stream
->forward_to_kmsg
= r
;
613 if (forward_to_console
) {
614 r
= parse_boolean(forward_to_console
);
616 stream
->forward_to_console
= r
;
622 static int stdout_stream_restore(Server
*s
, const char *fname
, int fd
) {
623 StdoutStream
*stream
;
630 if (s
->n_stdout_streams
>= STDOUT_STREAMS_MAX
) {
631 log_warning("Too many stdout streams, refusing restoring of stream.");
635 r
= stdout_stream_install(s
, fd
, &stream
);
639 stream
->state
= STDOUT_STREAM_RUNNING
;
640 stream
->fdstore
= true;
642 /* Ignore all parsing errors */
643 (void) stdout_stream_load(stream
, fname
);
648 int server_restore_streams(Server
*s
, FDSet
*fds
) {
649 _cleanup_closedir_
DIR *d
= NULL
;
653 d
= opendir("/run/systemd/journal/streams");
658 return log_warning_errno(errno
, "Failed to enumerate /run/systemd/journal/streams: %m");
661 FOREACH_DIRENT(de
, d
, goto fail
) {
662 unsigned long st_dev
, st_ino
;
667 if (sscanf(de
->d_name
, "%lu:%lu", &st_dev
, &st_ino
) != 2)
670 FDSET_FOREACH(fd
, fds
, i
) {
673 if (fstat(fd
, &st
) < 0)
674 return log_error_errno(errno
, "Failed to stat %s: %m", de
->d_name
);
676 if (S_ISSOCK(st
.st_mode
) && st
.st_dev
== st_dev
&& st
.st_ino
== st_ino
) {
683 /* No file descriptor? Then let's delete the state file */
684 log_debug("Cannot restore stream file %s", de
->d_name
);
685 unlinkat(dirfd(d
), de
->d_name
, 0);
689 fdset_remove(fds
, fd
);
691 r
= stdout_stream_restore(s
, de
->d_name
, fd
);
699 return log_error_errno(errno
, "Failed to read streams directory: %m");
702 int server_open_stdout_socket(Server
*s
) {
707 if (s
->stdout_fd
< 0) {
708 union sockaddr_union sa
= {
709 .un
.sun_family
= AF_UNIX
,
710 .un
.sun_path
= "/run/systemd/journal/stdout",
713 s
->stdout_fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
714 if (s
->stdout_fd
< 0)
715 return log_error_errno(errno
, "socket() failed: %m");
717 unlink(sa
.un
.sun_path
);
719 r
= bind(s
->stdout_fd
, &sa
.sa
, offsetof(union sockaddr_union
, un
.sun_path
) + strlen(sa
.un
.sun_path
));
721 return log_error_errno(errno
, "bind(%s) failed: %m", sa
.un
.sun_path
);
723 (void) chmod(sa
.un
.sun_path
, 0666);
725 if (listen(s
->stdout_fd
, SOMAXCONN
) < 0)
726 return log_error_errno(errno
, "listen(%s) failed: %m", sa
.un
.sun_path
);
728 fd_nonblock(s
->stdout_fd
, 1);
730 r
= sd_event_add_io(s
->event
, &s
->stdout_event_source
, s
->stdout_fd
, EPOLLIN
, stdout_stream_new
, s
);
732 return log_error_errno(r
, "Failed to add stdout server fd to event source: %m");
734 r
= sd_event_source_set_priority(s
->stdout_event_source
, SD_EVENT_PRIORITY_NORMAL
+10);
736 return log_error_errno(r
, "Failed to adjust priority of stdout server event source: %m");
741 void stdout_stream_send_notify(StdoutStream
*s
) {
742 struct iovec iovec
= {
743 .iov_base
= (char*) "FDSTORE=1",
744 .iov_len
= strlen("FDSTORE=1"),
746 struct msghdr msghdr
= {
750 struct cmsghdr
*cmsg
;
755 assert(s
->in_notify_queue
);
757 assert(s
->server
->notify_fd
>= 0);
759 /* Store the connection fd in PID 1, so that we get it passed
760 * in again on next start */
762 msghdr
.msg_controllen
= CMSG_SPACE(sizeof(int));
763 msghdr
.msg_control
= alloca0(msghdr
.msg_controllen
);
765 cmsg
= CMSG_FIRSTHDR(&msghdr
);
766 cmsg
->cmsg_level
= SOL_SOCKET
;
767 cmsg
->cmsg_type
= SCM_RIGHTS
;
768 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
770 memcpy(CMSG_DATA(cmsg
), &s
->fd
, sizeof(int));
772 l
= sendmsg(s
->server
->notify_fd
, &msghdr
, MSG_DONTWAIT
|MSG_NOSIGNAL
);
777 log_error_errno(errno
, "Failed to send stream file descriptor to service manager: %m");
779 log_debug("Successfully sent stream file descriptor to service manager.");
783 LIST_REMOVE(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
784 s
->in_notify_queue
= false;