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