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;
83 char buffer
[LINE_MAX
+1];
86 sd_event_source
*event_source
;
90 LIST_FIELDS(StdoutStream
, stdout_stream
);
93 void stdout_stream_free(StdoutStream
*s
) {
98 assert(s
->server
->n_stdout_streams
> 0);
99 s
->server
->n_stdout_streams
--;
100 LIST_REMOVE(stdout_stream
, s
->server
->stdout_streams
, s
);
103 if (s
->event_source
) {
104 sd_event_source_set_enabled(s
->event_source
, SD_EVENT_OFF
);
105 s
->event_source
= sd_event_source_unref(s
->event_source
);
117 DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream
*, stdout_stream_free
);
119 static void stdout_stream_destroy(StdoutStream
*s
) {
124 unlink(s
->state_file
);
126 stdout_stream_free(s
);
129 static int stdout_stream_save(StdoutStream
*s
) {
130 _cleanup_free_
char *temp_path
= NULL
;
131 _cleanup_fclose_
FILE *f
= NULL
;
136 if (s
->state
!= STDOUT_STREAM_RUNNING
)
139 if (!s
->state_file
) {
142 r
= fstat(s
->fd
, &st
);
144 return log_warning_errno(errno
, "Failed to stat connected stream: %m");
146 /* We use device and inode numbers as identifier for the stream */
147 if (asprintf(&s
->state_file
, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st
.st_dev
, (unsigned long) st
.st_ino
) < 0)
151 mkdir_p("/run/systemd/journal/streams", 0755);
153 r
= fopen_temporary(s
->state_file
, &f
, &temp_path
);
158 "# This is private data. Do not parse\n"
161 "FORWARD_TO_SYSLOG=%i\n"
162 "FORWARD_TO_KMSG=%i\n"
163 "FORWARD_TO_CONSOLE=%i\n",
166 s
->forward_to_syslog
,
168 s
->forward_to_console
);
170 if (!isempty(s
->identifier
)) {
171 _cleanup_free_
char *escaped
;
173 escaped
= cescape(s
->identifier
);
179 fprintf(f
, "IDENTIFIER=%s\n", escaped
);
182 if (!isempty(s
->unit_id
)) {
183 _cleanup_free_
char *escaped
;
185 escaped
= cescape(s
->unit_id
);
191 fprintf(f
, "UNIT=%s\n", escaped
);
194 r
= fflush_and_check(f
);
198 if (rename(temp_path
, s
->state_file
) < 0) {
203 /* Store the connection fd in PID 1, so that we get it passed
204 * in again on next start */
206 sd_pid_notify_with_fds(0, false, "FDSTORE=1", &s
->fd
, 1);
213 (void) unlink(s
->state_file
);
216 (void) unlink(temp_path
);
218 return log_error_errno(r
, "Failed to save stream data %s: %m", s
->state_file
);
221 static int stdout_stream_log(StdoutStream
*s
, const char *p
) {
222 struct iovec iovec
[N_IOVEC_META_FIELDS
+ 5];
224 char syslog_priority
[] = "PRIORITY=\0";
225 char syslog_facility
[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1];
226 _cleanup_free_
char *message
= NULL
, *syslog_identifier
= NULL
;
236 priority
= s
->priority
;
239 syslog_parse_priority(&p
, &priority
, false);
241 if (s
->forward_to_syslog
|| s
->server
->forward_to_syslog
)
242 server_forward_syslog(s
->server
, syslog_fixup_facility(priority
), s
->identifier
, p
, &s
->ucred
, NULL
);
244 if (s
->forward_to_kmsg
|| s
->server
->forward_to_kmsg
)
245 server_forward_kmsg(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
247 if (s
->forward_to_console
|| s
->server
->forward_to_console
)
248 server_forward_console(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
250 if (s
->server
->forward_to_wall
)
251 server_forward_wall(s
->server
, priority
, s
->identifier
, p
, &s
->ucred
);
253 IOVEC_SET_STRING(iovec
[n
++], "_TRANSPORT=stdout");
255 syslog_priority
[strlen("PRIORITY=")] = '0' + LOG_PRI(priority
);
256 IOVEC_SET_STRING(iovec
[n
++], syslog_priority
);
258 if (priority
& LOG_FACMASK
) {
259 xsprintf(syslog_facility
, "SYSLOG_FACILITY=%i", LOG_FAC(priority
));
260 IOVEC_SET_STRING(iovec
[n
++], syslog_facility
);
264 syslog_identifier
= strappend("SYSLOG_IDENTIFIER=", s
->identifier
);
265 if (syslog_identifier
)
266 IOVEC_SET_STRING(iovec
[n
++], syslog_identifier
);
269 message
= strappend("MESSAGE=", p
);
271 IOVEC_SET_STRING(iovec
[n
++], message
);
273 label_len
= s
->label
? strlen(s
->label
) : 0;
274 server_dispatch_message(s
->server
, iovec
, n
, ELEMENTSOF(iovec
), &s
->ucred
, NULL
, s
->label
, label_len
, s
->unit_id
, priority
, 0);
278 static int stdout_stream_line(StdoutStream
*s
, char *p
) {
288 case STDOUT_STREAM_IDENTIFIER
:
290 s
->identifier
= NULL
;
292 s
->identifier
= strdup(p
);
297 s
->state
= STDOUT_STREAM_UNIT_ID
;
300 case STDOUT_STREAM_UNIT_ID
:
301 if (s
->ucred
.uid
== 0) {
305 s
->unit_id
= strdup(p
);
311 s
->state
= STDOUT_STREAM_PRIORITY
;
314 case STDOUT_STREAM_PRIORITY
:
315 r
= safe_atoi(p
, &s
->priority
);
316 if (r
< 0 || s
->priority
< 0 || s
->priority
> 999) {
317 log_warning("Failed to parse log priority line.");
321 s
->state
= STDOUT_STREAM_LEVEL_PREFIX
;
324 case STDOUT_STREAM_LEVEL_PREFIX
:
325 r
= parse_boolean(p
);
327 log_warning("Failed to parse level prefix line.");
331 s
->level_prefix
= !!r
;
332 s
->state
= STDOUT_STREAM_FORWARD_TO_SYSLOG
;
335 case STDOUT_STREAM_FORWARD_TO_SYSLOG
:
336 r
= parse_boolean(p
);
338 log_warning("Failed to parse forward to syslog line.");
342 s
->forward_to_syslog
= !!r
;
343 s
->state
= STDOUT_STREAM_FORWARD_TO_KMSG
;
346 case STDOUT_STREAM_FORWARD_TO_KMSG
:
347 r
= parse_boolean(p
);
349 log_warning("Failed to parse copy to kmsg line.");
353 s
->forward_to_kmsg
= !!r
;
354 s
->state
= STDOUT_STREAM_FORWARD_TO_CONSOLE
;
357 case STDOUT_STREAM_FORWARD_TO_CONSOLE
:
358 r
= parse_boolean(p
);
360 log_warning("Failed to parse copy to console line.");
364 s
->forward_to_console
= !!r
;
365 s
->state
= STDOUT_STREAM_RUNNING
;
367 /* Try to save the stream, so that journald can be restarted and we can recover */
368 (void) stdout_stream_save(s
);
371 case STDOUT_STREAM_RUNNING
:
372 return stdout_stream_log(s
, p
);
375 assert_not_reached("Unknown stream state");
378 static int stdout_stream_scan(StdoutStream
*s
, bool force_flush
) {
386 remaining
= s
->length
;
391 end
= memchr(p
, '\n', remaining
);
394 else if (remaining
>= sizeof(s
->buffer
) - 1) {
395 end
= p
+ sizeof(s
->buffer
) - 1;
402 r
= stdout_stream_line(s
, p
);
410 if (force_flush
&& remaining
> 0) {
412 r
= stdout_stream_line(s
, p
);
421 memmove(s
->buffer
, p
, remaining
);
422 s
->length
= remaining
;
428 static int stdout_stream_process(sd_event_source
*es
, int fd
, uint32_t revents
, void *userdata
) {
429 StdoutStream
*s
= userdata
;
435 if ((revents
|EPOLLIN
|EPOLLHUP
) != (EPOLLIN
|EPOLLHUP
)) {
436 log_error("Got invalid event from epoll for stdout stream: %"PRIx32
, revents
);
440 l
= read(s
->fd
, s
->buffer
+s
->length
, sizeof(s
->buffer
)-1-s
->length
);
446 log_warning_errno(errno
, "Failed to read from stream: %m");
451 stdout_stream_scan(s
, true);
456 r
= stdout_stream_scan(s
, false);
463 stdout_stream_destroy(s
);
467 static int stdout_stream_install(Server
*s
, int fd
, StdoutStream
**ret
) {
468 _cleanup_(stdout_stream_freep
) StdoutStream
*stream
= NULL
;
474 stream
= new0(StdoutStream
, 1);
479 stream
->priority
= LOG_INFO
;
481 r
= getpeercred(fd
, &stream
->ucred
);
483 return log_error_errno(r
, "Failed to determine peer credentials: %m");
485 if (mac_selinux_use()) {
486 r
= getpeersec(fd
, &stream
->label
);
487 if (r
< 0 && r
!= -EOPNOTSUPP
)
488 (void) log_warning_errno(r
, "Failed to determine peer security context: %m");
491 (void) shutdown(fd
, SHUT_WR
);
493 r
= sd_event_add_io(s
->event
, &stream
->event_source
, fd
, EPOLLIN
, stdout_stream_process
, stream
);
495 return log_error_errno(r
, "Failed to add stream to event loop: %m");
497 r
= sd_event_source_set_priority(stream
->event_source
, SD_EVENT_PRIORITY_NORMAL
+5);
499 return log_error_errno(r
, "Failed to adjust stdout event source priority: %m");
504 LIST_PREPEND(stdout_stream
, s
->stdout_streams
, stream
);
505 s
->n_stdout_streams
++;
515 static int stdout_stream_new(sd_event_source
*es
, int listen_fd
, uint32_t revents
, void *userdata
) {
516 _cleanup_close_
int fd
= -1;
517 Server
*s
= userdata
;
522 if (revents
!= EPOLLIN
) {
523 log_error("Got invalid event from epoll for stdout server fd: %"PRIx32
, revents
);
527 fd
= accept4(s
->stdout_fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
532 log_error_errno(errno
, "Failed to accept stdout connection: %m");
536 if (s
->n_stdout_streams
>= STDOUT_STREAMS_MAX
) {
537 log_warning("Too many stdout streams, refusing connection.");
541 r
= stdout_stream_install(s
, fd
, NULL
);
549 static int stdout_stream_load(StdoutStream
*stream
, const char *fname
) {
552 *level_prefix
= NULL
,
553 *forward_to_syslog
= NULL
,
554 *forward_to_kmsg
= NULL
,
555 *forward_to_console
= NULL
;
561 if (!stream
->state_file
) {
562 stream
->state_file
= strappend("/run/systemd/journal/streams/", fname
);
563 if (!stream
->state_file
)
567 r
= parse_env_file(stream
->state_file
, NEWLINE
,
568 "PRIORITY", &priority
,
569 "LEVEL_PREFIX", &level_prefix
,
570 "FORWARD_TO_SYSLOG", &forward_to_syslog
,
571 "FORWARD_TO_KMSG", &forward_to_kmsg
,
572 "FORWARD_TO_CONSOLE", &forward_to_console
,
573 "IDENTIFIER", &stream
->identifier
,
574 "UNIT", &stream
->unit_id
,
577 return log_error_errno(r
, "Failed to read: %s", stream
->state_file
);
582 p
= log_level_from_string(priority
);
584 stream
->priority
= p
;
588 r
= parse_boolean(level_prefix
);
590 stream
->level_prefix
= r
;
593 if (forward_to_syslog
) {
594 r
= parse_boolean(forward_to_syslog
);
596 stream
->forward_to_syslog
= r
;
599 if (forward_to_kmsg
) {
600 r
= parse_boolean(forward_to_kmsg
);
602 stream
->forward_to_kmsg
= r
;
605 if (forward_to_console
) {
606 r
= parse_boolean(forward_to_console
);
608 stream
->forward_to_console
= r
;
614 static int stdout_stream_restore(Server
*s
, const char *fname
, int fd
) {
615 StdoutStream
*stream
;
622 if (s
->n_stdout_streams
>= STDOUT_STREAMS_MAX
) {
623 log_warning("Too many stdout streams, refusing restoring of stream.");
627 r
= stdout_stream_install(s
, fd
, &stream
);
631 stream
->state
= STDOUT_STREAM_RUNNING
;
632 stream
->fdstore
= true;
634 /* Ignore all parsing errors */
635 (void) stdout_stream_load(stream
, fname
);
640 int server_restore_streams(Server
*s
, FDSet
*fds
) {
641 _cleanup_closedir_
DIR *d
= NULL
;
645 d
= opendir("/run/systemd/journal/streams");
650 return log_warning_errno(errno
, "Failed to enumerate /run/systemd/journal/streams: %m");
653 FOREACH_DIRENT(de
, d
, goto fail
) {
654 unsigned long st_dev
, st_ino
;
659 if (sscanf(de
->d_name
, "%lu:%lu", &st_dev
, &st_ino
) != 2)
662 FDSET_FOREACH(fd
, fds
, i
) {
665 if (fstat(fd
, &st
) < 0)
666 return log_error_errno(errno
, "Failed to stat %s: %m", de
->d_name
);
668 if (S_ISSOCK(st
.st_mode
) && st
.st_dev
== st_dev
&& st
.st_ino
== st_ino
) {
675 /* No file descriptor? Then let's delete the state file */
676 log_debug("Cannot restore stream file %s", de
->d_name
);
677 unlinkat(dirfd(d
), de
->d_name
, 0);
681 fdset_remove(fds
, fd
);
683 r
= stdout_stream_restore(s
, de
->d_name
, fd
);
691 return log_error_errno(errno
, "Failed to read streams directory: %m");
694 int server_open_stdout_socket(Server
*s
) {
699 if (s
->stdout_fd
< 0) {
700 union sockaddr_union sa
= {
701 .un
.sun_family
= AF_UNIX
,
702 .un
.sun_path
= "/run/systemd/journal/stdout",
705 s
->stdout_fd
= socket(AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
|SOCK_NONBLOCK
, 0);
706 if (s
->stdout_fd
< 0)
707 return log_error_errno(errno
, "socket() failed: %m");
709 unlink(sa
.un
.sun_path
);
711 r
= bind(s
->stdout_fd
, &sa
.sa
, offsetof(union sockaddr_union
, un
.sun_path
) + strlen(sa
.un
.sun_path
));
713 return log_error_errno(errno
, "bind(%s) failed: %m", sa
.un
.sun_path
);
715 (void) chmod(sa
.un
.sun_path
, 0666);
717 if (listen(s
->stdout_fd
, SOMAXCONN
) < 0)
718 return log_error_errno(errno
, "listen(%s) failed: %m", sa
.un
.sun_path
);
720 fd_nonblock(s
->stdout_fd
, 1);
722 r
= sd_event_add_io(s
->event
, &s
->stdout_event_source
, s
->stdout_fd
, EPOLLIN
, stdout_stream_new
, s
);
724 return log_error_errno(r
, "Failed to add stdout server fd to event source: %m");
726 r
= sd_event_source_set_priority(s
->stdout_event_source
, SD_EVENT_PRIORITY_NORMAL
+10);
728 return log_error_errno(r
, "Failed to adjust priority of stdout server event source: %m");