2 This file is part of systemd.
4 Copyright 2011 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <selinux/selinux.h>
27 #include "sd-daemon.h"
30 #include "alloc-util.h"
31 #include "dirent-util.h"
36 #include "journald-console.h"
37 #include "journald-kmsg.h"
38 #include "journald-server.h"
39 #include "journald-stream.h"
40 #include "journald-syslog.h"
41 #include "journald-wall.h"
43 #include "parse-util.h"
44 #include "selinux-util.h"
45 #include "socket-util.h"
46 #include "stdio-util.h"
47 #include "string-util.h"
48 #include "syslog-util.h"
49 #include "unit-name.h"
51 #define STDOUT_STREAMS_MAX 4096
53 typedef enum StdoutStreamState
{
54 STDOUT_STREAM_IDENTIFIER
,
55 STDOUT_STREAM_UNIT_ID
,
56 STDOUT_STREAM_PRIORITY
,
57 STDOUT_STREAM_LEVEL_PREFIX
,
58 STDOUT_STREAM_FORWARD_TO_SYSLOG
,
59 STDOUT_STREAM_FORWARD_TO_KMSG
,
60 STDOUT_STREAM_FORWARD_TO_CONSOLE
,
66 StdoutStreamState state
;
76 bool forward_to_syslog
:1;
77 bool forward_to_kmsg
:1;
78 bool forward_to_console
:1;
81 bool in_notify_queue
:1;
83 char buffer
[LINE_MAX
+1];
86 sd_event_source
*event_source
;
90 LIST_FIELDS(StdoutStream
, stdout_stream
);
91 LIST_FIELDS(StdoutStream
, stdout_stream_notify_queue
);
94 void stdout_stream_free(StdoutStream
*s
) {
99 assert(s
->server
->n_stdout_streams
> 0);
100 s
->server
->n_stdout_streams
--;
101 LIST_REMOVE(stdout_stream
, s
->server
->stdout_streams
, s
);
103 if (s
->in_notify_queue
)
104 LIST_REMOVE(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
107 if (s
->event_source
) {
108 sd_event_source_set_enabled(s
->event_source
, SD_EVENT_OFF
);
109 s
->event_source
= sd_event_source_unref(s
->event_source
);
121 DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream
*, stdout_stream_free
);
123 static void stdout_stream_destroy(StdoutStream
*s
) {
128 (void) unlink(s
->state_file
);
130 stdout_stream_free(s
);
133 static int stdout_stream_save(StdoutStream
*s
) {
134 _cleanup_free_
char *temp_path
= NULL
;
135 _cleanup_fclose_
FILE *f
= NULL
;
140 if (s
->state
!= STDOUT_STREAM_RUNNING
)
143 if (!s
->state_file
) {
146 r
= fstat(s
->fd
, &st
);
148 return log_warning_errno(errno
, "Failed to stat connected stream: %m");
150 /* We use device and inode numbers as identifier for the stream */
151 if (asprintf(&s
->state_file
, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st
.st_dev
, (unsigned long) st
.st_ino
) < 0)
155 mkdir_p("/run/systemd/journal/streams", 0755);
157 r
= fopen_temporary(s
->state_file
, &f
, &temp_path
);
162 "# This is private data. Do not parse\n"
165 "FORWARD_TO_SYSLOG=%i\n"
166 "FORWARD_TO_KMSG=%i\n"
167 "FORWARD_TO_CONSOLE=%i\n",
170 s
->forward_to_syslog
,
172 s
->forward_to_console
);
174 if (!isempty(s
->identifier
)) {
175 _cleanup_free_
char *escaped
;
177 escaped
= cescape(s
->identifier
);
183 fprintf(f
, "IDENTIFIER=%s\n", escaped
);
186 if (!isempty(s
->unit_id
)) {
187 _cleanup_free_
char *escaped
;
189 escaped
= cescape(s
->unit_id
);
195 fprintf(f
, "UNIT=%s\n", escaped
);
198 r
= fflush_and_check(f
);
202 if (rename(temp_path
, s
->state_file
) < 0) {
207 if (!s
->fdstore
&& !s
->in_notify_queue
) {
208 LIST_PREPEND(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
209 s
->in_notify_queue
= true;
211 if (s
->server
->notify_event_source
) {
212 r
= sd_event_source_set_enabled(s
->server
->notify_event_source
, SD_EVENT_ON
);
214 log_warning_errno(r
, "Failed to enable notify event source: %m");
221 (void) unlink(s
->state_file
);
224 (void) unlink(temp_path
);
226 return log_error_errno(r
, "Failed to save stream data %s: %m", s
->state_file
);
229 static int stdout_stream_log(StdoutStream
*s
, const char *p
) {
230 struct iovec iovec
[N_IOVEC_META_FIELDS
+ 5];
232 char syslog_priority
[] = "PRIORITY=\0";
233 char syslog_facility
[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1];
234 _cleanup_free_
char *message
= NULL
, *syslog_identifier
= NULL
;
241 priority
= s
->priority
;
244 syslog_parse_priority(&p
, &priority
, false);
249 if (s
->forward_to_syslog
|| s
->server
->forward_to_syslog
)
250 server_forward_syslog(s
->server
, syslog_fixup_facility(priority
), s
->identifier
, p
, &s
->ucred
, NULL
);
252 if (s
->forward_to_kmsg
|| s
->server
->forward_to_kmsg
)
253 server_forward_kmsg(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
255 if (s
->forward_to_console
|| s
->server
->forward_to_console
)
256 server_forward_console(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
258 if (s
->server
->forward_to_wall
)
259 server_forward_wall(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
261 IOVEC_SET_STRING(iovec
[n
++], "_TRANSPORT=stdout");
263 syslog_priority
[strlen("PRIORITY=")] = '0' + LOG_PRI(priority
);
264 IOVEC_SET_STRING(iovec
[n
++], syslog_priority
);
266 if (priority
& LOG_FACMASK
) {
267 xsprintf(syslog_facility
, "SYSLOG_FACILITY=%i", LOG_FAC(priority
));
268 IOVEC_SET_STRING(iovec
[n
++], syslog_facility
);
272 syslog_identifier
= strappend("SYSLOG_IDENTIFIER=", s
->identifier
);
273 if (syslog_identifier
)
274 IOVEC_SET_STRING(iovec
[n
++], syslog_identifier
);
277 message
= strappend("MESSAGE=", p
);
279 IOVEC_SET_STRING(iovec
[n
++], message
);
281 label_len
= s
->label
? strlen(s
->label
) : 0;
282 server_dispatch_message(s
->server
, iovec
, n
, ELEMENTSOF(iovec
), &s
->ucred
, NULL
, s
->label
, label_len
, s
->unit_id
, priority
, 0);
286 static int stdout_stream_line(StdoutStream
*s
, char *p
) {
298 case STDOUT_STREAM_IDENTIFIER
:
300 s
->identifier
= strdup(p
);
305 s
->state
= STDOUT_STREAM_UNIT_ID
;
308 case STDOUT_STREAM_UNIT_ID
:
309 if (s
->ucred
.uid
== 0 &&
310 unit_name_is_valid(p
, UNIT_NAME_PLAIN
|UNIT_NAME_INSTANCE
)) {
312 s
->unit_id
= strdup(p
);
317 s
->state
= STDOUT_STREAM_PRIORITY
;
320 case STDOUT_STREAM_PRIORITY
:
321 r
= safe_atoi(p
, &s
->priority
);
322 if (r
< 0 || s
->priority
< 0 || s
->priority
> 999) {
323 log_warning("Failed to parse log priority line.");
327 s
->state
= STDOUT_STREAM_LEVEL_PREFIX
;
330 case STDOUT_STREAM_LEVEL_PREFIX
:
331 r
= parse_boolean(p
);
333 log_warning("Failed to parse level prefix line.");
337 s
->level_prefix
= !!r
;
338 s
->state
= STDOUT_STREAM_FORWARD_TO_SYSLOG
;
341 case STDOUT_STREAM_FORWARD_TO_SYSLOG
:
342 r
= parse_boolean(p
);
344 log_warning("Failed to parse forward to syslog line.");
348 s
->forward_to_syslog
= !!r
;
349 s
->state
= STDOUT_STREAM_FORWARD_TO_KMSG
;
352 case STDOUT_STREAM_FORWARD_TO_KMSG
:
353 r
= parse_boolean(p
);
355 log_warning("Failed to parse copy to kmsg line.");
359 s
->forward_to_kmsg
= !!r
;
360 s
->state
= STDOUT_STREAM_FORWARD_TO_CONSOLE
;
363 case STDOUT_STREAM_FORWARD_TO_CONSOLE
:
364 r
= parse_boolean(p
);
366 log_warning("Failed to parse copy to console line.");
370 s
->forward_to_console
= !!r
;
371 s
->state
= STDOUT_STREAM_RUNNING
;
373 /* Try to save the stream, so that journald can be restarted and we can recover */
374 (void) stdout_stream_save(s
);
377 case STDOUT_STREAM_RUNNING
:
378 return stdout_stream_log(s
, orig
);
381 assert_not_reached("Unknown stream state");
384 static int stdout_stream_scan(StdoutStream
*s
, bool force_flush
) {
392 remaining
= s
->length
;
394 /* XXX: This function does nothing if (s->length == 0) */
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
) {
703 static const union sockaddr_union sa
= {
704 .un
.sun_family
= AF_UNIX
,
705 .un
.sun_path
= "/run/systemd/journal/stdout",
711 if (s
->stdout_fd
< 0) {
712 s
->stdout_fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
713 if (s
->stdout_fd
< 0)
714 return log_error_errno(errno
, "socket() failed: %m");
716 (void) unlink(sa
.un
.sun_path
);
718 r
= bind(s
->stdout_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
));
720 return log_error_errno(errno
, "bind(%s) failed: %m", sa
.un
.sun_path
);
722 (void) chmod(sa
.un
.sun_path
, 0666);
724 if (listen(s
->stdout_fd
, SOMAXCONN
) < 0)
725 return log_error_errno(errno
, "listen(%s) failed: %m", sa
.un
.sun_path
);
727 fd_nonblock(s
->stdout_fd
, 1);
729 r
= sd_event_add_io(s
->event
, &s
->stdout_event_source
, s
->stdout_fd
, EPOLLIN
, stdout_stream_new
, s
);
731 return log_error_errno(r
, "Failed to add stdout server fd to event source: %m");
733 r
= sd_event_source_set_priority(s
->stdout_event_source
, SD_EVENT_PRIORITY_NORMAL
+5);
735 return log_error_errno(r
, "Failed to adjust priority of stdout server event source: %m");
740 void stdout_stream_send_notify(StdoutStream
*s
) {
741 struct iovec iovec
= {
742 .iov_base
= (char*) "FDSTORE=1",
743 .iov_len
= strlen("FDSTORE=1"),
745 struct msghdr msghdr
= {
749 struct cmsghdr
*cmsg
;
754 assert(s
->in_notify_queue
);
756 assert(s
->server
->notify_fd
>= 0);
758 /* Store the connection fd in PID 1, so that we get it passed
759 * in again on next start */
761 msghdr
.msg_controllen
= CMSG_SPACE(sizeof(int));
762 msghdr
.msg_control
= alloca0(msghdr
.msg_controllen
);
764 cmsg
= CMSG_FIRSTHDR(&msghdr
);
765 cmsg
->cmsg_level
= SOL_SOCKET
;
766 cmsg
->cmsg_type
= SCM_RIGHTS
;
767 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
769 memcpy(CMSG_DATA(cmsg
), &s
->fd
, sizeof(int));
771 l
= sendmsg(s
->server
->notify_fd
, &msghdr
, MSG_DONTWAIT
|MSG_NOSIGNAL
);
776 log_error_errno(errno
, "Failed to send stream file descriptor to service manager: %m");
778 log_debug("Successfully sent stream file descriptor to service manager.");
782 LIST_REMOVE(stdout_stream_notify_queue
, s
->server
->stdout_streams_notify_queue
, s
);
783 s
->in_notify_queue
= false;