]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/journald-stream.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / journal / journald-stream.c
CommitLineData
a45b9fca
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
4871690d 22#include <stddef.h>
07630cea 23#include <unistd.h>
a45b9fca
LP
24
25#ifdef HAVE_SELINUX
26#include <selinux/selinux.h>
27#endif
28
13790add 29#include "sd-daemon.h"
4f5dd394
LP
30#include "sd-event.h"
31
32#include "escape.h"
13790add 33#include "fileio.h"
4f5dd394
LP
34#include "journald-console.h"
35#include "journald-kmsg.h"
d025f1e4 36#include "journald-server.h"
a45b9fca 37#include "journald-syslog.h"
40b71e89 38#include "journald-wall.h"
4f5dd394
LP
39#include "mkdir.h"
40#include "selinux-util.h"
41#include "socket-util.h"
07630cea 42#include "string-util.h"
4f5dd394 43#include "journald-stream.h"
a45b9fca
LP
44
45#define STDOUT_STREAMS_MAX 4096
46
47typedef enum StdoutStreamState {
48 STDOUT_STREAM_IDENTIFIER,
49 STDOUT_STREAM_UNIT_ID,
50 STDOUT_STREAM_PRIORITY,
51 STDOUT_STREAM_LEVEL_PREFIX,
52 STDOUT_STREAM_FORWARD_TO_SYSLOG,
53 STDOUT_STREAM_FORWARD_TO_KMSG,
54 STDOUT_STREAM_FORWARD_TO_CONSOLE,
55 STDOUT_STREAM_RUNNING
56} StdoutStreamState;
57
58struct StdoutStream {
59 Server *server;
60 StdoutStreamState state;
61
62 int fd;
63
64 struct ucred ucred;
2de56f70 65 char *label;
a45b9fca
LP
66 char *identifier;
67 char *unit_id;
68 int priority;
69 bool level_prefix:1;
70 bool forward_to_syslog:1;
71 bool forward_to_kmsg:1;
72 bool forward_to_console:1;
73
13790add
LP
74 bool fdstore:1;
75
a45b9fca
LP
76 char buffer[LINE_MAX+1];
77 size_t length;
78
f9a810be
LP
79 sd_event_source *event_source;
80
13790add
LP
81 char *state_file;
82
a45b9fca
LP
83 LIST_FIELDS(StdoutStream, stdout_stream);
84};
85
13790add
LP
86void stdout_stream_free(StdoutStream *s) {
87 if (!s)
88 return;
89
90 if (s->server) {
91 assert(s->server->n_stdout_streams > 0);
92 s->server->n_stdout_streams --;
93 LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
94 }
95
96 if (s->event_source) {
97 sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF);
98 s->event_source = sd_event_source_unref(s->event_source);
99 }
100
101 safe_close(s->fd);
2de56f70 102 free(s->label);
13790add
LP
103 free(s->identifier);
104 free(s->unit_id);
105 free(s->state_file);
106
107 free(s);
108}
109
110DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);
111
112static void stdout_stream_destroy(StdoutStream *s) {
113 if (!s)
114 return;
115
116 if (s->state_file)
117 unlink(s->state_file);
118
119 stdout_stream_free(s);
120}
121
122static int stdout_stream_save(StdoutStream *s) {
123 _cleanup_free_ char *temp_path = NULL;
124 _cleanup_fclose_ FILE *f = NULL;
125 int r;
126
127 assert(s);
128
129 if (s->state != STDOUT_STREAM_RUNNING)
130 return 0;
131
132 if (!s->state_file) {
133 struct stat st;
134
135 r = fstat(s->fd, &st);
136 if (r < 0)
137 return log_warning_errno(errno, "Failed to stat connected stream: %m");
138
139 /* We use device and inode numbers as identifier for the stream */
140 if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0)
141 return log_oom();
142 }
143
144 mkdir_p("/run/systemd/journal/streams", 0755);
145
146 r = fopen_temporary(s->state_file, &f, &temp_path);
147 if (r < 0)
dacd6cee 148 goto fail;
13790add
LP
149
150 fprintf(f,
151 "# This is private data. Do not parse\n"
152 "PRIORITY=%i\n"
153 "LEVEL_PREFIX=%i\n"
154 "FORWARD_TO_SYSLOG=%i\n"
155 "FORWARD_TO_KMSG=%i\n"
156 "FORWARD_TO_CONSOLE=%i\n",
157 s->priority,
158 s->level_prefix,
159 s->forward_to_syslog,
160 s->forward_to_kmsg,
161 s->forward_to_console);
162
163 if (!isempty(s->identifier)) {
164 _cleanup_free_ char *escaped;
165
166 escaped = cescape(s->identifier);
167 if (!escaped) {
168 r = -ENOMEM;
dacd6cee 169 goto fail;
13790add
LP
170 }
171
172 fprintf(f, "IDENTIFIER=%s\n", escaped);
173 }
174
175 if (!isempty(s->unit_id)) {
176 _cleanup_free_ char *escaped;
177
178 escaped = cescape(s->unit_id);
179 if (!escaped) {
180 r = -ENOMEM;
dacd6cee 181 goto fail;
13790add
LP
182 }
183
184 fprintf(f, "UNIT=%s\n", escaped);
185 }
186
187 r = fflush_and_check(f);
188 if (r < 0)
dacd6cee 189 goto fail;
13790add
LP
190
191 if (rename(temp_path, s->state_file) < 0) {
192 r = -errno;
dacd6cee 193 goto fail;
13790add
LP
194 }
195
13790add
LP
196 /* Store the connection fd in PID 1, so that we get it passed
197 * in again on next start */
198 if (!s->fdstore) {
199 sd_pid_notify_with_fds(0, false, "FDSTORE=1", &s->fd, 1);
200 s->fdstore = true;
201 }
202
dacd6cee 203 return 0;
13790add 204
dacd6cee
LP
205fail:
206 (void) unlink(s->state_file);
207
208 if (temp_path)
209 (void) unlink(temp_path);
13790add 210
dacd6cee 211 return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file);
13790add
LP
212}
213
a45b9fca
LP
214static int stdout_stream_log(StdoutStream *s, const char *p) {
215 struct iovec iovec[N_IOVEC_META_FIELDS + 5];
a45b9fca 216 int priority;
e3bfb7be 217 char syslog_priority[] = "PRIORITY=\0";
5ffa8c81 218 char syslog_facility[sizeof("SYSLOG_FACILITY=")-1 + DECIMAL_STR_MAX(int) + 1];
e3bfb7be
ZJS
219 _cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
220 unsigned n = 0;
2de56f70 221 size_t label_len;
a45b9fca
LP
222
223 assert(s);
224 assert(p);
225
226 if (isempty(p))
227 return 0;
228
229 priority = s->priority;
230
231 if (s->level_prefix)
e3bfb7be 232 syslog_parse_priority(&p, &priority, false);
a45b9fca
LP
233
234 if (s->forward_to_syslog || s->server->forward_to_syslog)
235 server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
236
237 if (s->forward_to_kmsg || s->server->forward_to_kmsg)
238 server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred);
239
240 if (s->forward_to_console || s->server->forward_to_console)
241 server_forward_console(s->server, priority, s->identifier, p, &s->ucred);
242
40b71e89
ST
243 if (s->server->forward_to_wall)
244 server_forward_wall(s->server, priority, s->identifier, p, &s->ucred);
245
a45b9fca
LP
246 IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=stdout");
247
e3bfb7be
ZJS
248 syslog_priority[strlen("PRIORITY=")] = '0' + LOG_PRI(priority);
249 IOVEC_SET_STRING(iovec[n++], syslog_priority);
a45b9fca 250
e3bfb7be 251 if (priority & LOG_FACMASK) {
5ffa8c81 252 xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority));
e3bfb7be
ZJS
253 IOVEC_SET_STRING(iovec[n++], syslog_facility);
254 }
a45b9fca
LP
255
256 if (s->identifier) {
257 syslog_identifier = strappend("SYSLOG_IDENTIFIER=", s->identifier);
258 if (syslog_identifier)
259 IOVEC_SET_STRING(iovec[n++], syslog_identifier);
260 }
261
262 message = strappend("MESSAGE=", p);
263 if (message)
264 IOVEC_SET_STRING(iovec[n++], message);
265
2de56f70
ZJS
266 label_len = s->label ? strlen(s->label) : 0;
267 server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, s->label, label_len, s->unit_id, priority, 0);
a45b9fca
LP
268 return 0;
269}
270
271static int stdout_stream_line(StdoutStream *s, char *p) {
272 int r;
273
274 assert(s);
275 assert(p);
276
277 p = strstrip(p);
278
279 switch (s->state) {
280
281 case STDOUT_STREAM_IDENTIFIER:
282 if (isempty(p))
283 s->identifier = NULL;
284 else {
285 s->identifier = strdup(p);
286 if (!s->identifier)
287 return log_oom();
288 }
289
290 s->state = STDOUT_STREAM_UNIT_ID;
291 return 0;
292
293 case STDOUT_STREAM_UNIT_ID:
294 if (s->ucred.uid == 0) {
295 if (isempty(p))
296 s->unit_id = NULL;
297 else {
298 s->unit_id = strdup(p);
299 if (!s->unit_id)
300 return log_oom();
301 }
302 }
303
304 s->state = STDOUT_STREAM_PRIORITY;
305 return 0;
306
307 case STDOUT_STREAM_PRIORITY:
308 r = safe_atoi(p, &s->priority);
41891700 309 if (r < 0 || s->priority < 0 || s->priority > 999) {
a45b9fca
LP
310 log_warning("Failed to parse log priority line.");
311 return -EINVAL;
312 }
313
314 s->state = STDOUT_STREAM_LEVEL_PREFIX;
315 return 0;
316
317 case STDOUT_STREAM_LEVEL_PREFIX:
318 r = parse_boolean(p);
319 if (r < 0) {
320 log_warning("Failed to parse level prefix line.");
321 return -EINVAL;
322 }
323
324 s->level_prefix = !!r;
325 s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
326 return 0;
327
328 case STDOUT_STREAM_FORWARD_TO_SYSLOG:
329 r = parse_boolean(p);
330 if (r < 0) {
331 log_warning("Failed to parse forward to syslog line.");
332 return -EINVAL;
333 }
334
335 s->forward_to_syslog = !!r;
336 s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
337 return 0;
338
339 case STDOUT_STREAM_FORWARD_TO_KMSG:
340 r = parse_boolean(p);
341 if (r < 0) {
342 log_warning("Failed to parse copy to kmsg line.");
343 return -EINVAL;
344 }
345
346 s->forward_to_kmsg = !!r;
347 s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
348 return 0;
349
350 case STDOUT_STREAM_FORWARD_TO_CONSOLE:
351 r = parse_boolean(p);
352 if (r < 0) {
353 log_warning("Failed to parse copy to console line.");
354 return -EINVAL;
355 }
356
357 s->forward_to_console = !!r;
358 s->state = STDOUT_STREAM_RUNNING;
13790add
LP
359
360 /* Try to save the stream, so that journald can be restarted and we can recover */
361 (void) stdout_stream_save(s);
a45b9fca
LP
362 return 0;
363
364 case STDOUT_STREAM_RUNNING:
365 return stdout_stream_log(s, p);
366 }
367
368 assert_not_reached("Unknown stream state");
369}
370
371static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
372 char *p;
373 size_t remaining;
374 int r;
375
376 assert(s);
377
378 p = s->buffer;
379 remaining = s->length;
380 for (;;) {
381 char *end;
382 size_t skip;
383
384 end = memchr(p, '\n', remaining);
385 if (end)
386 skip = end - p + 1;
387 else if (remaining >= sizeof(s->buffer) - 1) {
388 end = p + sizeof(s->buffer) - 1;
389 skip = remaining;
390 } else
391 break;
392
393 *end = 0;
394
395 r = stdout_stream_line(s, p);
396 if (r < 0)
397 return r;
398
399 remaining -= skip;
400 p += skip;
401 }
402
403 if (force_flush && remaining > 0) {
404 p[remaining] = 0;
405 r = stdout_stream_line(s, p);
406 if (r < 0)
407 return r;
408
409 p += remaining;
410 remaining = 0;
411 }
412
413 if (p > s->buffer) {
414 memmove(s->buffer, p, remaining);
415 s->length = remaining;
416 }
417
418 return 0;
419}
420
f9a810be
LP
421static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
422 StdoutStream *s = userdata;
a45b9fca
LP
423 ssize_t l;
424 int r;
425
426 assert(s);
427
f9a810be
LP
428 if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
429 log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents);
91bf3b3e 430 goto terminate;
f9a810be
LP
431 }
432
a45b9fca
LP
433 l = read(s->fd, s->buffer+s->length, sizeof(s->buffer)-1-s->length);
434 if (l < 0) {
435
436 if (errno == EAGAIN)
437 return 0;
438
56f64d95 439 log_warning_errno(errno, "Failed to read from stream: %m");
91bf3b3e 440 goto terminate;
a45b9fca
LP
441 }
442
443 if (l == 0) {
7b77ed8c 444 stdout_stream_scan(s, true);
91bf3b3e 445 goto terminate;
a45b9fca
LP
446 }
447
448 s->length += l;
449 r = stdout_stream_scan(s, false);
450 if (r < 0)
91bf3b3e 451 goto terminate;
a45b9fca
LP
452
453 return 1;
454
91bf3b3e 455terminate:
13790add 456 stdout_stream_destroy(s);
f9a810be 457 return 0;
a45b9fca
LP
458}
459
13790add
LP
460static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
461 _cleanup_(stdout_stream_freep) StdoutStream *stream = NULL;
462 int r;
463
a45b9fca 464 assert(s);
13790add 465 assert(fd >= 0);
a45b9fca 466
13790add
LP
467 stream = new0(StdoutStream, 1);
468 if (!stream)
469 return log_oom();
a45b9fca 470
13790add
LP
471 stream->fd = -1;
472 stream->priority = LOG_INFO;
a45b9fca 473
13790add
LP
474 r = getpeercred(fd, &stream->ucred);
475 if (r < 0)
476 return log_error_errno(r, "Failed to determine peer credentials: %m");
a45b9fca 477
13790add 478 if (mac_selinux_use()) {
2de56f70
ZJS
479 r = getpeersec(fd, &stream->label);
480 if (r < 0 && r != -EOPNOTSUPP)
481 (void) log_warning_errno(r, "Failed to determine peer security context: %m");
13790add 482 }
a45b9fca 483
13790add
LP
484 (void) shutdown(fd, SHUT_WR);
485
486 r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream);
487 if (r < 0)
488 return log_error_errno(r, "Failed to add stream to event loop: %m");
489
490 r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5);
491 if (r < 0)
492 return log_error_errno(r, "Failed to adjust stdout event source priority: %m");
493
494 stream->fd = fd;
495
496 stream->server = s;
497 LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
498 s->n_stdout_streams ++;
499
500 if (ret)
501 *ret = stream;
502
503 stream = NULL;
504
505 return 0;
a45b9fca
LP
506}
507
f9a810be 508static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) {
13790add 509 _cleanup_close_ int fd = -1;
f9a810be 510 Server *s = userdata;
13790add 511 int r;
a45b9fca
LP
512
513 assert(s);
514
f9a810be
LP
515 if (revents != EPOLLIN) {
516 log_error("Got invalid event from epoll for stdout server fd: %"PRIx32, revents);
517 return -EIO;
518 }
519
a45b9fca
LP
520 fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
521 if (fd < 0) {
522 if (errno == EAGAIN)
523 return 0;
524
56f64d95 525 log_error_errno(errno, "Failed to accept stdout connection: %m");
a45b9fca
LP
526 return -errno;
527 }
528
529 if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
530 log_warning("Too many stdout streams, refusing connection.");
a45b9fca
LP
531 return 0;
532 }
533
13790add
LP
534 r = stdout_stream_install(s, fd, NULL);
535 if (r < 0)
536 return r;
537
538 fd = -1;
539 return 0;
540}
541
542static int stdout_stream_load(StdoutStream *stream, const char *fname) {
543 _cleanup_free_ char
544 *priority = NULL,
545 *level_prefix = NULL,
546 *forward_to_syslog = NULL,
547 *forward_to_kmsg = NULL,
548 *forward_to_console = NULL;
549 int r;
550
551 assert(stream);
552 assert(fname);
553
554 if (!stream->state_file) {
555 stream->state_file = strappend("/run/systemd/journal/streams/", fname);
556 if (!stream->state_file)
557 return log_oom();
a45b9fca
LP
558 }
559
13790add
LP
560 r = parse_env_file(stream->state_file, NEWLINE,
561 "PRIORITY", &priority,
562 "LEVEL_PREFIX", &level_prefix,
563 "FORWARD_TO_SYSLOG", &forward_to_syslog,
564 "FORWARD_TO_KMSG", &forward_to_kmsg,
565 "FORWARD_TO_CONSOLE", &forward_to_console,
566 "IDENTIFIER", &stream->identifier,
567 "UNIT", &stream->unit_id,
568 NULL);
569 if (r < 0)
570 return log_error_errno(r, "Failed to read: %s", stream->state_file);
a45b9fca 571
13790add
LP
572 if (priority) {
573 int p;
574
575 p = log_level_from_string(priority);
576 if (p >= 0)
577 stream->priority = p;
a45b9fca
LP
578 }
579
13790add
LP
580 if (level_prefix) {
581 r = parse_boolean(level_prefix);
582 if (r >= 0)
583 stream->level_prefix = r;
d682b3a7 584 }
a45b9fca 585
13790add
LP
586 if (forward_to_syslog) {
587 r = parse_boolean(forward_to_syslog);
588 if (r >= 0)
589 stream->forward_to_syslog = r;
a45b9fca
LP
590 }
591
13790add
LP
592 if (forward_to_kmsg) {
593 r = parse_boolean(forward_to_kmsg);
594 if (r >= 0)
595 stream->forward_to_kmsg = r;
f9a810be
LP
596 }
597
13790add
LP
598 if (forward_to_console) {
599 r = parse_boolean(forward_to_console);
600 if (r >= 0)
601 stream->forward_to_console = r;
a45b9fca
LP
602 }
603
13790add
LP
604 return 0;
605}
606
607static int stdout_stream_restore(Server *s, const char *fname, int fd) {
608 StdoutStream *stream;
609 int r;
610
611 assert(s);
612 assert(fname);
613 assert(fd >= 0);
614
615 if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
616 log_warning("Too many stdout streams, refusing restoring of stream.");
617 return -ENOBUFS;
618 }
619
620 r = stdout_stream_install(s, fd, &stream);
621 if (r < 0)
622 return r;
623
624 stream->state = STDOUT_STREAM_RUNNING;
625 stream->fdstore = true;
626
627 /* Ignore all parsing errors */
628 (void) stdout_stream_load(stream, fname);
a45b9fca
LP
629
630 return 0;
13790add
LP
631}
632
15d91bff 633int server_restore_streams(Server *s, FDSet *fds) {
13790add
LP
634 _cleanup_closedir_ DIR *d = NULL;
635 struct dirent *de;
636 int r;
637
638 d = opendir("/run/systemd/journal/streams");
639 if (!d) {
640 if (errno == ENOENT)
641 return 0;
642
643 return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m");
644 }
645
646 FOREACH_DIRENT(de, d, goto fail) {
647 unsigned long st_dev, st_ino;
648 bool found = false;
649 Iterator i;
650 int fd;
651
652 if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2)
653 continue;
654
655 FDSET_FOREACH(fd, fds, i) {
656 struct stat st;
657
658 if (fstat(fd, &st) < 0)
659 return log_error_errno(errno, "Failed to stat %s: %m", de->d_name);
660
661 if (S_ISSOCK(st.st_mode) && st.st_dev == st_dev && st.st_ino == st_ino) {
662 found = true;
663 break;
664 }
665 }
666
667 if (!found) {
668 /* No file descriptor? Then let's delete the state file */
669 log_debug("Cannot restore stream file %s", de->d_name);
670 unlinkat(dirfd(d), de->d_name, 0);
671 continue;
672 }
673
674 fdset_remove(fds, fd);
675
676 r = stdout_stream_restore(s, de->d_name, fd);
677 if (r < 0)
678 safe_close(fd);
679 }
a45b9fca 680
7b77ed8c 681 return 0;
13790add
LP
682
683fail:
684 return log_error_errno(errno, "Failed to read streams directory: %m");
a45b9fca
LP
685}
686
15d91bff 687int server_open_stdout_socket(Server *s) {
a45b9fca 688 int r;
a45b9fca
LP
689
690 assert(s);
691
692 if (s->stdout_fd < 0) {
b92bea5d
ZJS
693 union sockaddr_union sa = {
694 .un.sun_family = AF_UNIX,
695 .un.sun_path = "/run/systemd/journal/stdout",
696 };
a45b9fca
LP
697
698 s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
4a62c710
MS
699 if (s->stdout_fd < 0)
700 return log_error_errno(errno, "socket() failed: %m");
a45b9fca 701
a45b9fca
LP
702 unlink(sa.un.sun_path);
703
704 r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
4a62c710
MS
705 if (r < 0)
706 return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
a45b9fca 707
4a61c3e5 708 (void) chmod(sa.un.sun_path, 0666);
a45b9fca 709
4a62c710
MS
710 if (listen(s->stdout_fd, SOMAXCONN) < 0)
711 return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path);
a45b9fca
LP
712 } else
713 fd_nonblock(s->stdout_fd, 1);
714
151b9b96 715 r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLIN, stdout_stream_new, s);
23bbb0de
MS
716 if (r < 0)
717 return log_error_errno(r, "Failed to add stdout server fd to event source: %m");
f9a810be
LP
718
719 r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+10);
23bbb0de
MS
720 if (r < 0)
721 return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
a45b9fca
LP
722
723 return 0;
724}