File: | build-scan/../src/journal/journald-stream.c |
Warning: | line 717, column 23 Access to field 'state' results in a dereference of an undefined pointer value (loaded from variable 'stream') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <stddef.h> | |||
4 | #include <unistd.h> | |||
5 | ||||
6 | #if HAVE_SELINUX1 | |||
7 | #include <selinux/selinux.h> | |||
8 | #endif | |||
9 | ||||
10 | #include "sd-daemon.h" | |||
11 | #include "sd-event.h" | |||
12 | ||||
13 | #include "alloc-util.h" | |||
14 | #include "dirent-util.h" | |||
15 | #include "escape.h" | |||
16 | #include "fd-util.h" | |||
17 | #include "fileio.h" | |||
18 | #include "io-util.h" | |||
19 | #include "journald-console.h" | |||
20 | #include "journald-context.h" | |||
21 | #include "journald-kmsg.h" | |||
22 | #include "journald-server.h" | |||
23 | #include "journald-stream.h" | |||
24 | #include "journald-syslog.h" | |||
25 | #include "journald-wall.h" | |||
26 | #include "mkdir.h" | |||
27 | #include "parse-util.h" | |||
28 | #include "process-util.h" | |||
29 | #include "selinux-util.h" | |||
30 | #include "socket-util.h" | |||
31 | #include "stdio-util.h" | |||
32 | #include "string-util.h" | |||
33 | #include "syslog-util.h" | |||
34 | #include "unit-name.h" | |||
35 | ||||
36 | #define STDOUT_STREAMS_MAX4096 4096 | |||
37 | ||||
38 | typedef enum StdoutStreamState { | |||
39 | STDOUT_STREAM_IDENTIFIER, | |||
40 | STDOUT_STREAM_UNIT_ID, | |||
41 | STDOUT_STREAM_PRIORITY, | |||
42 | STDOUT_STREAM_LEVEL_PREFIX, | |||
43 | STDOUT_STREAM_FORWARD_TO_SYSLOG, | |||
44 | STDOUT_STREAM_FORWARD_TO_KMSG, | |||
45 | STDOUT_STREAM_FORWARD_TO_CONSOLE, | |||
46 | STDOUT_STREAM_RUNNING | |||
47 | } StdoutStreamState; | |||
48 | ||||
49 | /* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length | |||
50 | * was reached, or the end of the stream was reached */ | |||
51 | ||||
52 | typedef enum LineBreak { | |||
53 | LINE_BREAK_NEWLINE, | |||
54 | LINE_BREAK_NUL, | |||
55 | LINE_BREAK_LINE_MAX, | |||
56 | LINE_BREAK_EOF, | |||
57 | } LineBreak; | |||
58 | ||||
59 | struct StdoutStream { | |||
60 | Server *server; | |||
61 | StdoutStreamState state; | |||
62 | ||||
63 | int fd; | |||
64 | ||||
65 | struct ucred ucred; | |||
66 | char *label; | |||
67 | char *identifier; | |||
68 | char *unit_id; | |||
69 | int priority; | |||
70 | bool_Bool level_prefix:1; | |||
71 | bool_Bool forward_to_syslog:1; | |||
72 | bool_Bool forward_to_kmsg:1; | |||
73 | bool_Bool forward_to_console:1; | |||
74 | ||||
75 | bool_Bool fdstore:1; | |||
76 | bool_Bool in_notify_queue:1; | |||
77 | ||||
78 | char *buffer; | |||
79 | size_t length; | |||
80 | size_t allocated; | |||
81 | ||||
82 | sd_event_source *event_source; | |||
83 | ||||
84 | char *state_file; | |||
85 | ||||
86 | ClientContext *context; | |||
87 | ||||
88 | LIST_FIELDS(StdoutStream, stdout_stream)StdoutStream *stdout_stream_next, *stdout_stream_prev; | |||
89 | LIST_FIELDS(StdoutStream, stdout_stream_notify_queue)StdoutStream *stdout_stream_notify_queue_next, *stdout_stream_notify_queue_prev; | |||
90 | ||||
91 | char id_field[STRLEN("_STREAM_ID=")(sizeof("""_STREAM_ID=""") - 1) + SD_ID128_STRING_MAX33]; | |||
92 | }; | |||
93 | ||||
94 | void stdout_stream_free(StdoutStream *s) { | |||
95 | if (!s) | |||
96 | return; | |||
97 | ||||
98 | if (s->server) { | |||
99 | ||||
100 | if (s->context) | |||
101 | client_context_release(s->server, s->context); | |||
102 | ||||
103 | assert(s->server->n_stdout_streams > 0)do { if ((__builtin_expect(!!(!(s->server->n_stdout_streams > 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->server->n_stdout_streams > 0" ), "../src/journal/journald-stream.c", 103, __PRETTY_FUNCTION__ ); } while (0); | |||
104 | s->server->n_stdout_streams--; | |||
105 | LIST_REMOVE(stdout_stream, s->server->stdout_streams, s)do { typeof(*(s->server->stdout_streams)) **_head = & (s->server->stdout_streams), *_item = (s); do { if ((__builtin_expect (!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/journal/journald-stream.c", 105, __PRETTY_FUNCTION__ ); } while (0); if (_item->stdout_stream_next) _item->stdout_stream_next ->stdout_stream_prev = _item->stdout_stream_prev; if (_item ->stdout_stream_prev) _item->stdout_stream_prev->stdout_stream_next = _item->stdout_stream_next; else { do { if ((__builtin_expect (!!(!(*_head == _item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("*_head == _item"), "../src/journal/journald-stream.c", 105 , __PRETTY_FUNCTION__); } while (0); *_head = _item->stdout_stream_next ; } _item->stdout_stream_next = _item->stdout_stream_prev = ((void*)0); } while (0); | |||
106 | ||||
107 | if (s->in_notify_queue) | |||
108 | LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s)do { typeof(*(s->server->stdout_streams_notify_queue)) * *_head = &(s->server->stdout_streams_notify_queue), *_item = (s); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_item"), "../src/journal/journald-stream.c" , 108, __PRETTY_FUNCTION__); } while (0); if (_item->stdout_stream_notify_queue_next ) _item->stdout_stream_notify_queue_next->stdout_stream_notify_queue_prev = _item->stdout_stream_notify_queue_prev; if (_item->stdout_stream_notify_queue_prev ) _item->stdout_stream_notify_queue_prev->stdout_stream_notify_queue_next = _item->stdout_stream_notify_queue_next; else { do { if ( (__builtin_expect(!!(!(*_head == _item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*_head == _item"), "../src/journal/journald-stream.c" , 108, __PRETTY_FUNCTION__); } while (0); *_head = _item-> stdout_stream_notify_queue_next; } _item->stdout_stream_notify_queue_next = _item->stdout_stream_notify_queue_prev = ((void*)0); } while (0); | |||
109 | } | |||
110 | ||||
111 | if (s->event_source) { | |||
112 | sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF); | |||
113 | s->event_source = sd_event_source_unref(s->event_source); | |||
114 | } | |||
115 | ||||
116 | safe_close(s->fd); | |||
117 | free(s->label); | |||
118 | free(s->identifier); | |||
119 | free(s->unit_id); | |||
120 | free(s->state_file); | |||
121 | free(s->buffer); | |||
122 | ||||
123 | free(s); | |||
124 | } | |||
125 | ||||
126 | DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free)static inline void stdout_stream_freep(StdoutStream* *p) { if (*p) stdout_stream_free(*p); }; | |||
127 | ||||
128 | void stdout_stream_destroy(StdoutStream *s) { | |||
129 | if (!s) | |||
130 | return; | |||
131 | ||||
132 | if (s->state_file) | |||
133 | (void) unlink(s->state_file); | |||
134 | ||||
135 | stdout_stream_free(s); | |||
136 | } | |||
137 | ||||
138 | static int stdout_stream_save(StdoutStream *s) { | |||
139 | _cleanup_free___attribute__((cleanup(freep))) char *temp_path = NULL((void*)0); | |||
140 | _cleanup_fclose___attribute__((cleanup(fclosep))) FILE *f = NULL((void*)0); | |||
141 | int r; | |||
142 | ||||
143 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 143, __PRETTY_FUNCTION__); } while (0); | |||
144 | ||||
145 | if (s->state != STDOUT_STREAM_RUNNING) | |||
146 | return 0; | |||
147 | ||||
148 | if (!s->state_file) { | |||
149 | struct stat st; | |||
150 | ||||
151 | r = fstat(s->fd, &st); | |||
152 | if (r < 0) | |||
153 | return log_warning_errno(errno, "Failed to stat connected stream: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 153, __func__, "Failed to stat connected stream: %m") : -abs(_e); }); | |||
154 | ||||
155 | /* We use device and inode numbers as identifier for the stream */ | |||
156 | if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0) | |||
157 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal/journald-stream.c" , 157, __func__); | |||
158 | } | |||
159 | ||||
160 | mkdir_p("/run/systemd/journal/streams", 0755); | |||
161 | ||||
162 | r = fopen_temporary(s->state_file, &f, &temp_path); | |||
163 | if (r < 0) | |||
164 | goto fail; | |||
165 | ||||
166 | fprintf(f, | |||
167 | "# This is private data. Do not parse\n" | |||
168 | "PRIORITY=%i\n" | |||
169 | "LEVEL_PREFIX=%i\n" | |||
170 | "FORWARD_TO_SYSLOG=%i\n" | |||
171 | "FORWARD_TO_KMSG=%i\n" | |||
172 | "FORWARD_TO_CONSOLE=%i\n" | |||
173 | "STREAM_ID=%s\n", | |||
174 | s->priority, | |||
175 | s->level_prefix, | |||
176 | s->forward_to_syslog, | |||
177 | s->forward_to_kmsg, | |||
178 | s->forward_to_console, | |||
179 | s->id_field + STRLEN("_STREAM_ID=")(sizeof("""_STREAM_ID=""") - 1)); | |||
180 | ||||
181 | if (!isempty(s->identifier)) { | |||
182 | _cleanup_free___attribute__((cleanup(freep))) char *escaped; | |||
183 | ||||
184 | escaped = cescape(s->identifier); | |||
185 | if (!escaped) { | |||
186 | r = -ENOMEM12; | |||
187 | goto fail; | |||
188 | } | |||
189 | ||||
190 | fprintf(f, "IDENTIFIER=%s\n", escaped); | |||
191 | } | |||
192 | ||||
193 | if (!isempty(s->unit_id)) { | |||
194 | _cleanup_free___attribute__((cleanup(freep))) char *escaped; | |||
195 | ||||
196 | escaped = cescape(s->unit_id); | |||
197 | if (!escaped) { | |||
198 | r = -ENOMEM12; | |||
199 | goto fail; | |||
200 | } | |||
201 | ||||
202 | fprintf(f, "UNIT=%s\n", escaped); | |||
203 | } | |||
204 | ||||
205 | r = fflush_and_check(f); | |||
206 | if (r < 0) | |||
207 | goto fail; | |||
208 | ||||
209 | if (rename(temp_path, s->state_file) < 0) { | |||
210 | r = -errno(*__errno_location ()); | |||
211 | goto fail; | |||
212 | } | |||
213 | ||||
214 | if (!s->fdstore && !s->in_notify_queue) { | |||
215 | LIST_PREPEND(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s)do { typeof(*(s->server->stdout_streams_notify_queue)) * *_head = &(s->server->stdout_streams_notify_queue), *_item = (s); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_item"), "../src/journal/journald-stream.c" , 215, __PRETTY_FUNCTION__); } while (0); if ((_item->stdout_stream_notify_queue_next = *_head)) _item->stdout_stream_notify_queue_next->stdout_stream_notify_queue_prev = _item; _item->stdout_stream_notify_queue_prev = ((void* )0); *_head = _item; } while (0); | |||
216 | s->in_notify_queue = true1; | |||
217 | ||||
218 | if (s->server->notify_event_source) { | |||
219 | r = sd_event_source_set_enabled(s->server->notify_event_source, SD_EVENT_ON); | |||
220 | if (r < 0) | |||
221 | log_warning_errno(r, "Failed to enable notify event source: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 221, __func__, "Failed to enable notify event source: %m" ) : -abs(_e); }); | |||
222 | } | |||
223 | } | |||
224 | ||||
225 | return 0; | |||
226 | ||||
227 | fail: | |||
228 | (void) unlink(s->state_file); | |||
229 | ||||
230 | if (temp_path) | |||
231 | (void) unlink(temp_path); | |||
232 | ||||
233 | return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 233, __func__, "Failed to save stream data %s: %m" , s->state_file) : -abs(_e); }); | |||
234 | } | |||
235 | ||||
236 | static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) { | |||
237 | struct iovec *iovec; | |||
238 | int priority; | |||
239 | char syslog_priority[] = "PRIORITY=\0"; | |||
240 | char syslog_facility[STRLEN("SYSLOG_FACILITY=")(sizeof("""SYSLOG_FACILITY=""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)]))) + 1]; | |||
241 | _cleanup_free___attribute__((cleanup(freep))) char *message = NULL((void*)0), *syslog_identifier = NULL((void*)0); | |||
242 | size_t n = 0, m; | |||
243 | int r; | |||
244 | ||||
245 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 245, __PRETTY_FUNCTION__); } while (0); | |||
246 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/journal/journald-stream.c" , 246, __PRETTY_FUNCTION__); } while (0); | |||
247 | ||||
248 | if (s->context) | |||
249 | (void) client_context_maybe_refresh(s->server, s->context, NULL((void*)0), NULL((void*)0), 0, NULL((void*)0), USEC_INFINITY((usec_t) -1)); | |||
250 | else if (pid_is_valid(s->ucred.pid)) { | |||
251 | r = client_context_acquire(s->server, s->ucred.pid, &s->ucred, s->label, strlen_ptr(s->label), s->unit_id, &s->context); | |||
252 | if (r < 0) | |||
253 | log_warning_errno(r, "Failed to acquire client context, ignoring: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 253, __func__, "Failed to acquire client context, ignoring: %m" ) : -abs(_e); }); | |||
254 | } | |||
255 | ||||
256 | priority = s->priority; | |||
257 | ||||
258 | if (s->level_prefix) | |||
259 | syslog_parse_priority(&p, &priority, false0); | |||
260 | ||||
261 | if (!client_context_test_priority(s->context, priority)) | |||
262 | return 0; | |||
263 | ||||
264 | if (isempty(p)) | |||
265 | return 0; | |||
266 | ||||
267 | if (s->forward_to_syslog || s->server->forward_to_syslog) | |||
268 | server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL((void*)0)); | |||
269 | ||||
270 | if (s->forward_to_kmsg || s->server->forward_to_kmsg) | |||
271 | server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred); | |||
272 | ||||
273 | if (s->forward_to_console || s->server->forward_to_console) | |||
274 | server_forward_console(s->server, priority, s->identifier, p, &s->ucred); | |||
275 | ||||
276 | if (s->server->forward_to_wall) | |||
277 | server_forward_wall(s->server, priority, s->identifier, p, &s->ucred); | |||
278 | ||||
279 | m = N_IOVEC_META_FIELDS22 + 7 + client_context_extra_fields_n_iovec(s->context); | |||
280 | iovec = newa(struct iovec, m)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (struct iovec), m))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("!size_multiply_overflow(sizeof(struct iovec), m)"), "../src/journal/journald-stream.c" , 280, __PRETTY_FUNCTION__); } while (0); (struct iovec*) __builtin_alloca (sizeof(struct iovec)*(m)); }); | |||
281 | ||||
282 | iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=stdout")(struct iovec) { .iov_base = ((char*) "_TRANSPORT=stdout"), . iov_len = (strlen("_TRANSPORT=stdout")) }; | |||
283 | iovec[n++] = IOVEC_MAKE_STRING(s->id_field)(struct iovec) { .iov_base = ((char*) s->id_field), .iov_len = (strlen(s->id_field)) }; | |||
284 | ||||
285 | syslog_priority[STRLEN("PRIORITY=")(sizeof("""PRIORITY=""") - 1)] = '0' + LOG_PRI(priority)((priority) & 0x07); | |||
286 | iovec[n++] = IOVEC_MAKE_STRING(syslog_priority)(struct iovec) { .iov_base = ((char*) syslog_priority), .iov_len = (strlen(syslog_priority)) }; | |||
287 | ||||
288 | if (priority & LOG_FACMASK0x03f8) { | |||
289 | xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority))do { if ((__builtin_expect(!!(!(((size_t) snprintf(syslog_facility , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(syslog_facility), typeof(&*(syslog_facility))), sizeof (syslog_facility)/sizeof((syslog_facility)[0]), ((void)0))), "SYSLOG_FACILITY=%i" , (((priority) & 0x03f8) >> 3)) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (syslog_facility), typeof(&*(syslog_facility))), sizeof(syslog_facility )/sizeof((syslog_facility)[0]), ((void)0))))))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("xsprintf: " "syslog_facility" "[] must be big enough" ), "../src/journal/journald-stream.c", 289, __PRETTY_FUNCTION__ ); } while (0); | |||
290 | iovec[n++] = IOVEC_MAKE_STRING(syslog_facility)(struct iovec) { .iov_base = ((char*) syslog_facility), .iov_len = (strlen(syslog_facility)) }; | |||
291 | } | |||
292 | ||||
293 | if (s->identifier) { | |||
294 | syslog_identifier = strappend("SYSLOG_IDENTIFIER=", s->identifier); | |||
295 | if (syslog_identifier) | |||
296 | iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier)(struct iovec) { .iov_base = ((char*) syslog_identifier), .iov_len = (strlen(syslog_identifier)) }; | |||
297 | } | |||
298 | ||||
299 | if (line_break != LINE_BREAK_NEWLINE) { | |||
300 | const char *c; | |||
301 | ||||
302 | /* If this log message was generated due to an uncommon line break then mention this in the log | |||
303 | * entry */ | |||
304 | ||||
305 | c = line_break == LINE_BREAK_NUL ? "_LINE_BREAK=nul" : | |||
306 | line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" : | |||
307 | "_LINE_BREAK=eof"; | |||
308 | iovec[n++] = IOVEC_MAKE_STRING(c)(struct iovec) { .iov_base = ((char*) c), .iov_len = (strlen( c)) }; | |||
309 | } | |||
310 | ||||
311 | message = strappend("MESSAGE=", p); | |||
312 | if (message) | |||
313 | iovec[n++] = IOVEC_MAKE_STRING(message)(struct iovec) { .iov_base = ((char*) message), .iov_len = (strlen (message)) }; | |||
314 | ||||
315 | server_dispatch_message(s->server, iovec, n, m, s->context, NULL((void*)0), priority, 0); | |||
316 | return 0; | |||
317 | } | |||
318 | ||||
319 | static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { | |||
320 | int r; | |||
321 | char *orig; | |||
322 | ||||
323 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 323, __PRETTY_FUNCTION__); } while (0); | |||
324 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/journal/journald-stream.c" , 324, __PRETTY_FUNCTION__); } while (0); | |||
325 | ||||
326 | orig = p; | |||
327 | p = strstrip(p); | |||
328 | ||||
329 | /* line breaks by NUL, line max length or EOF are not permissible during the negotiation part of the protocol */ | |||
330 | if (line_break != LINE_BREAK_NEWLINE && s->state != STDOUT_STREAM_RUNNING) { | |||
331 | log_warning("Control protocol line not properly terminated.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 331, __func__, "Control protocol line not properly terminated." ) : -abs(_e); }); | |||
332 | return -EINVAL22; | |||
333 | } | |||
334 | ||||
335 | switch (s->state) { | |||
336 | ||||
337 | case STDOUT_STREAM_IDENTIFIER: | |||
338 | if (!isempty(p)) { | |||
339 | s->identifier = strdup(p); | |||
340 | if (!s->identifier) | |||
341 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal/journald-stream.c" , 341, __func__); | |||
342 | } | |||
343 | ||||
344 | s->state = STDOUT_STREAM_UNIT_ID; | |||
345 | return 0; | |||
346 | ||||
347 | case STDOUT_STREAM_UNIT_ID: | |||
348 | if (s->ucred.uid == 0 && | |||
349 | unit_name_is_valid(p, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) { | |||
350 | ||||
351 | s->unit_id = strdup(p); | |||
352 | if (!s->unit_id) | |||
353 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal/journald-stream.c" , 353, __func__); | |||
354 | } | |||
355 | ||||
356 | s->state = STDOUT_STREAM_PRIORITY; | |||
357 | return 0; | |||
358 | ||||
359 | case STDOUT_STREAM_PRIORITY: | |||
360 | r = safe_atoi(p, &s->priority); | |||
361 | if (r < 0 || s->priority < 0 || s->priority > 999) { | |||
362 | log_warning("Failed to parse log priority line.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 362, __func__, "Failed to parse log priority line." ) : -abs(_e); }); | |||
363 | return -EINVAL22; | |||
364 | } | |||
365 | ||||
366 | s->state = STDOUT_STREAM_LEVEL_PREFIX; | |||
367 | return 0; | |||
368 | ||||
369 | case STDOUT_STREAM_LEVEL_PREFIX: | |||
370 | r = parse_boolean(p); | |||
371 | if (r < 0) { | |||
372 | log_warning("Failed to parse level prefix line.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 372, __func__, "Failed to parse level prefix line." ) : -abs(_e); }); | |||
373 | return -EINVAL22; | |||
374 | } | |||
375 | ||||
376 | s->level_prefix = r; | |||
377 | s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG; | |||
378 | return 0; | |||
379 | ||||
380 | case STDOUT_STREAM_FORWARD_TO_SYSLOG: | |||
381 | r = parse_boolean(p); | |||
382 | if (r < 0) { | |||
383 | log_warning("Failed to parse forward to syslog line.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 383, __func__, "Failed to parse forward to syslog line." ) : -abs(_e); }); | |||
384 | return -EINVAL22; | |||
385 | } | |||
386 | ||||
387 | s->forward_to_syslog = r; | |||
388 | s->state = STDOUT_STREAM_FORWARD_TO_KMSG; | |||
389 | return 0; | |||
390 | ||||
391 | case STDOUT_STREAM_FORWARD_TO_KMSG: | |||
392 | r = parse_boolean(p); | |||
393 | if (r < 0) { | |||
394 | log_warning("Failed to parse copy to kmsg line.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 394, __func__, "Failed to parse copy to kmsg line." ) : -abs(_e); }); | |||
395 | return -EINVAL22; | |||
396 | } | |||
397 | ||||
398 | s->forward_to_kmsg = r; | |||
399 | s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE; | |||
400 | return 0; | |||
401 | ||||
402 | case STDOUT_STREAM_FORWARD_TO_CONSOLE: | |||
403 | r = parse_boolean(p); | |||
404 | if (r < 0) { | |||
405 | log_warning("Failed to parse copy to console line.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 405, __func__, "Failed to parse copy to console line." ) : -abs(_e); }); | |||
406 | return -EINVAL22; | |||
407 | } | |||
408 | ||||
409 | s->forward_to_console = r; | |||
410 | s->state = STDOUT_STREAM_RUNNING; | |||
411 | ||||
412 | /* Try to save the stream, so that journald can be restarted and we can recover */ | |||
413 | (void) stdout_stream_save(s); | |||
414 | return 0; | |||
415 | ||||
416 | case STDOUT_STREAM_RUNNING: | |||
417 | return stdout_stream_log(s, orig, line_break); | |||
418 | } | |||
419 | ||||
420 | assert_not_reached("Unknown stream state")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown stream state"), "../src/journal/journald-stream.c", 420 , __PRETTY_FUNCTION__); } while (0); | |||
421 | } | |||
422 | ||||
423 | static int stdout_stream_scan(StdoutStream *s, bool_Bool force_flush) { | |||
424 | char *p; | |||
425 | size_t remaining; | |||
426 | int r; | |||
427 | ||||
428 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 428, __PRETTY_FUNCTION__); } while (0); | |||
429 | ||||
430 | p = s->buffer; | |||
431 | remaining = s->length; | |||
432 | ||||
433 | /* XXX: This function does nothing if (s->length == 0) */ | |||
434 | ||||
435 | for (;;) { | |||
436 | LineBreak line_break; | |||
437 | size_t skip; | |||
438 | char *end1, *end2; | |||
439 | ||||
440 | end1 = memchr(p, '\n', remaining); | |||
441 | end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : remaining); | |||
442 | ||||
443 | if (end2) { | |||
444 | /* We found a NUL terminator */ | |||
445 | skip = end2 - p + 1; | |||
446 | line_break = LINE_BREAK_NUL; | |||
447 | } else if (end1) { | |||
448 | /* We found a \n terminator */ | |||
449 | *end1 = 0; | |||
450 | skip = end1 - p + 1; | |||
451 | line_break = LINE_BREAK_NEWLINE; | |||
452 | } else if (remaining >= s->server->line_max) { | |||
453 | /* Force a line break after the maximum line length */ | |||
454 | *(p + s->server->line_max) = 0; | |||
455 | skip = remaining; | |||
456 | line_break = LINE_BREAK_LINE_MAX; | |||
457 | } else | |||
458 | break; | |||
459 | ||||
460 | r = stdout_stream_line(s, p, line_break); | |||
461 | if (r < 0) | |||
462 | return r; | |||
463 | ||||
464 | remaining -= skip; | |||
465 | p += skip; | |||
466 | } | |||
467 | ||||
468 | if (force_flush && remaining > 0) { | |||
469 | p[remaining] = 0; | |||
470 | r = stdout_stream_line(s, p, LINE_BREAK_EOF); | |||
471 | if (r < 0) | |||
472 | return r; | |||
473 | ||||
474 | p += remaining; | |||
475 | remaining = 0; | |||
476 | } | |||
477 | ||||
478 | if (p > s->buffer) { | |||
479 | memmove(s->buffer, p, remaining); | |||
480 | s->length = remaining; | |||
481 | } | |||
482 | ||||
483 | return 0; | |||
484 | } | |||
485 | ||||
486 | static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { | |||
487 | StdoutStream *s = userdata; | |||
488 | size_t limit; | |||
489 | ssize_t l; | |||
490 | int r; | |||
491 | ||||
492 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 492, __PRETTY_FUNCTION__); } while (0); | |||
493 | ||||
494 | if ((revents|EPOLLINEPOLLIN|EPOLLHUPEPOLLHUP) != (EPOLLINEPOLLIN|EPOLLHUPEPOLLHUP)) { | |||
495 | log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 495, __func__, "Got invalid event from epoll for stdout stream: %" "x", revents) : -abs(_e); }); | |||
496 | goto terminate; | |||
497 | } | |||
498 | ||||
499 | /* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */ | |||
500 | if (s->length + 1 >= s->allocated) { | |||
501 | if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)greedy_realloc((void**) &(s->buffer), &(s->allocated ), (s->length + 1 + 1024), sizeof((s->buffer)[0]))) { | |||
502 | log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal/journald-stream.c" , 502, __func__); | |||
503 | goto terminate; | |||
504 | } | |||
505 | } | |||
506 | ||||
507 | /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, | |||
508 | * always leave room for a terminating NUL we might need to add. */ | |||
509 | limit = MIN(s->allocated - 1, s->server->line_max)__extension__ ({ const typeof((s->allocated - 1)) __unique_prefix_A15 = ((s->allocated - 1)); const typeof((s->server->line_max )) __unique_prefix_B16 = ((s->server->line_max)); __unique_prefix_A15 < __unique_prefix_B16 ? __unique_prefix_A15 : __unique_prefix_B16 ; }); | |||
510 | ||||
511 | l = read(s->fd, s->buffer + s->length, limit - s->length); | |||
512 | if (l < 0) { | |||
513 | if (errno(*__errno_location ()) == EAGAIN11) | |||
514 | return 0; | |||
515 | ||||
516 | log_warning_errno(errno, "Failed to read from stream: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 516, __func__, "Failed to read from stream: %m") : -abs(_e); }); | |||
517 | goto terminate; | |||
518 | } | |||
519 | ||||
520 | if (l == 0) { | |||
521 | stdout_stream_scan(s, true1); | |||
522 | goto terminate; | |||
523 | } | |||
524 | ||||
525 | s->length += l; | |||
526 | r = stdout_stream_scan(s, false0); | |||
527 | if (r < 0) | |||
528 | goto terminate; | |||
529 | ||||
530 | return 1; | |||
531 | ||||
532 | terminate: | |||
533 | stdout_stream_destroy(s); | |||
534 | return 0; | |||
535 | } | |||
536 | ||||
537 | int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { | |||
538 | _cleanup_(stdout_stream_freep)__attribute__((cleanup(stdout_stream_freep))) StdoutStream *stream = NULL((void*)0); | |||
539 | sd_id128_t id; | |||
540 | int r; | |||
541 | ||||
542 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 542, __PRETTY_FUNCTION__); } while (0); | |||
543 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal/journald-stream.c" , 543, __PRETTY_FUNCTION__); } while (0); | |||
544 | ||||
545 | r = sd_id128_randomize(&id); | |||
546 | if (r < 0) | |||
547 | return log_error_errno(r, "Failed to generate stream ID: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 547, __func__, "Failed to generate stream ID: %m" ) : -abs(_e); }); | |||
548 | ||||
549 | stream = new0(StdoutStream, 1)((StdoutStream*) calloc((1), sizeof(StdoutStream))); | |||
550 | if (!stream) | |||
551 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal/journald-stream.c" , 551, __func__); | |||
552 | ||||
553 | stream->fd = -1; | |||
554 | stream->priority = LOG_INFO6; | |||
555 | ||||
556 | xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id))do { if ((__builtin_expect(!!(!(((size_t) snprintf(stream-> id_field, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(stream->id_field), typeof(&*(stream->id_field ))), sizeof(stream->id_field)/sizeof((stream->id_field) [0]), ((void)0))), "_STREAM_ID=" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" , (id).bytes[0], (id).bytes[1], (id).bytes[2], (id).bytes[3], (id).bytes[4], (id).bytes[5], (id).bytes[6], (id).bytes[7], ( id).bytes[8], (id).bytes[9], (id).bytes[10], (id).bytes[11], ( id).bytes[12], (id).bytes[13], (id).bytes[14], (id).bytes[15] ) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(stream->id_field), typeof(&*(stream->id_field ))), sizeof(stream->id_field)/sizeof((stream->id_field) [0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "stream->id_field" "[] must be big enough" ), "../src/journal/journald-stream.c", 556, __PRETTY_FUNCTION__ ); } while (0); | |||
557 | ||||
558 | r = getpeercred(fd, &stream->ucred); | |||
559 | if (r < 0) | |||
560 | return log_error_errno(r, "Failed to determine peer credentials: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 560, __func__, "Failed to determine peer credentials: %m" ) : -abs(_e); }); | |||
561 | ||||
562 | if (mac_selinux_use()) { | |||
563 | r = getpeersec(fd, &stream->label); | |||
564 | if (r < 0 && r != -EOPNOTSUPP95) | |||
565 | (void) log_warning_errno(r, "Failed to determine peer security context: %m")({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 565, __func__, "Failed to determine peer security context: %m" ) : -abs(_e); }); | |||
566 | } | |||
567 | ||||
568 | (void) shutdown(fd, SHUT_WRSHUT_WR); | |||
569 | ||||
570 | r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLINEPOLLIN, stdout_stream_process, stream); | |||
571 | if (r < 0) | |||
572 | return log_error_errno(r, "Failed to add stream to event loop: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 572, __func__, "Failed to add stream to event loop: %m" ) : -abs(_e); }); | |||
573 | ||||
574 | r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5); | |||
575 | if (r < 0) | |||
576 | return log_error_errno(r, "Failed to adjust stdout event source priority: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 576, __func__, "Failed to adjust stdout event source priority: %m" ) : -abs(_e); }); | |||
577 | ||||
578 | stream->fd = fd; | |||
579 | ||||
580 | stream->server = s; | |||
581 | LIST_PREPEND(stdout_stream, s->stdout_streams, stream)do { typeof(*(s->stdout_streams)) **_head = &(s->stdout_streams ), *_item = (stream); do { if ((__builtin_expect(!!(!(_item)) ,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/journal/journald-stream.c" , 581, __PRETTY_FUNCTION__); } while (0); if ((_item->stdout_stream_next = *_head)) _item->stdout_stream_next->stdout_stream_prev = _item; _item->stdout_stream_prev = ((void*)0); *_head = _item; } while (0); | |||
582 | s->n_stdout_streams++; | |||
583 | ||||
584 | if (ret) | |||
585 | *ret = stream; | |||
586 | ||||
587 | stream = NULL((void*)0); | |||
588 | ||||
589 | return 0; | |||
590 | } | |||
591 | ||||
592 | static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) { | |||
593 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | |||
594 | Server *s = userdata; | |||
595 | int r; | |||
596 | ||||
597 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 597, __PRETTY_FUNCTION__); } while (0); | |||
598 | ||||
599 | if (revents != EPOLLINEPOLLIN) { | |||
600 | log_error("Got invalid event from epoll for stdout server fd: %"PRIx32, revents)({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 600, __func__, "Got invalid event from epoll for stdout server fd: %" "x", revents) : -abs(_e); }); | |||
601 | return -EIO5; | |||
602 | } | |||
603 | ||||
604 | fd = accept4(s->stdout_fd, NULL((void*)0), NULL((void*)0), SOCK_NONBLOCKSOCK_NONBLOCK|SOCK_CLOEXECSOCK_CLOEXEC); | |||
605 | if (fd < 0) { | |||
606 | if (errno(*__errno_location ()) == EAGAIN11) | |||
607 | return 0; | |||
608 | ||||
609 | return log_error_errno(errno, "Failed to accept stdout connection: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 609, __func__, "Failed to accept stdout connection: %m") : -abs(_e ); }); | |||
610 | } | |||
611 | ||||
612 | if (s->n_stdout_streams >= STDOUT_STREAMS_MAX4096) { | |||
613 | log_warning("Too many stdout streams, refusing connection.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 613, __func__, "Too many stdout streams, refusing connection." ) : -abs(_e); }); | |||
614 | return 0; | |||
615 | } | |||
616 | ||||
617 | r = stdout_stream_install(s, fd, NULL((void*)0)); | |||
618 | if (r < 0) | |||
619 | return r; | |||
620 | ||||
621 | fd = -1; | |||
622 | return 0; | |||
623 | } | |||
624 | ||||
625 | static int stdout_stream_load(StdoutStream *stream, const char *fname) { | |||
626 | _cleanup_free___attribute__((cleanup(freep))) char | |||
627 | *priority = NULL((void*)0), | |||
628 | *level_prefix = NULL((void*)0), | |||
629 | *forward_to_syslog = NULL((void*)0), | |||
630 | *forward_to_kmsg = NULL((void*)0), | |||
631 | *forward_to_console = NULL((void*)0), | |||
632 | *stream_id = NULL((void*)0); | |||
633 | int r; | |||
634 | ||||
635 | assert(stream)do { if ((__builtin_expect(!!(!(stream)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("stream"), "../src/journal/journald-stream.c" , 635, __PRETTY_FUNCTION__); } while (0); | |||
636 | assert(fname)do { if ((__builtin_expect(!!(!(fname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fname"), "../src/journal/journald-stream.c" , 636, __PRETTY_FUNCTION__); } while (0); | |||
637 | ||||
638 | if (!stream->state_file) { | |||
639 | stream->state_file = strappend("/run/systemd/journal/streams/", fname); | |||
640 | if (!stream->state_file) | |||
641 | return log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/journal/journald-stream.c" , 641, __func__); | |||
642 | } | |||
643 | ||||
644 | r = parse_env_file(NULL((void*)0), stream->state_file, NEWLINE"\n\r", | |||
645 | "PRIORITY", &priority, | |||
646 | "LEVEL_PREFIX", &level_prefix, | |||
647 | "FORWARD_TO_SYSLOG", &forward_to_syslog, | |||
648 | "FORWARD_TO_KMSG", &forward_to_kmsg, | |||
649 | "FORWARD_TO_CONSOLE", &forward_to_console, | |||
650 | "IDENTIFIER", &stream->identifier, | |||
651 | "UNIT", &stream->unit_id, | |||
652 | "STREAM_ID", &stream_id, | |||
653 | NULL((void*)0)); | |||
654 | if (r < 0) | |||
655 | return log_error_errno(r, "Failed to read: %s", stream->state_file)({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 655, __func__, "Failed to read: %s" , stream->state_file) : -abs(_e); }); | |||
656 | ||||
657 | if (priority) { | |||
658 | int p; | |||
659 | ||||
660 | p = log_level_from_string(priority); | |||
661 | if (p >= 0) | |||
662 | stream->priority = p; | |||
663 | } | |||
664 | ||||
665 | if (level_prefix) { | |||
666 | r = parse_boolean(level_prefix); | |||
667 | if (r >= 0) | |||
668 | stream->level_prefix = r; | |||
669 | } | |||
670 | ||||
671 | if (forward_to_syslog) { | |||
672 | r = parse_boolean(forward_to_syslog); | |||
673 | if (r >= 0) | |||
674 | stream->forward_to_syslog = r; | |||
675 | } | |||
676 | ||||
677 | if (forward_to_kmsg) { | |||
678 | r = parse_boolean(forward_to_kmsg); | |||
679 | if (r >= 0) | |||
680 | stream->forward_to_kmsg = r; | |||
681 | } | |||
682 | ||||
683 | if (forward_to_console) { | |||
684 | r = parse_boolean(forward_to_console); | |||
685 | if (r >= 0) | |||
686 | stream->forward_to_console = r; | |||
687 | } | |||
688 | ||||
689 | if (stream_id) { | |||
690 | sd_id128_t id; | |||
691 | ||||
692 | r = sd_id128_from_string(stream_id, &id); | |||
693 | if (r >= 0) | |||
694 | xsprintf(stream->id_field, "_STREAM_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id))do { if ((__builtin_expect(!!(!(((size_t) snprintf(stream-> id_field, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(stream->id_field), typeof(&*(stream->id_field ))), sizeof(stream->id_field)/sizeof((stream->id_field) [0]), ((void)0))), "_STREAM_ID=" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" , (id).bytes[0], (id).bytes[1], (id).bytes[2], (id).bytes[3], (id).bytes[4], (id).bytes[5], (id).bytes[6], (id).bytes[7], ( id).bytes[8], (id).bytes[9], (id).bytes[10], (id).bytes[11], ( id).bytes[12], (id).bytes[13], (id).bytes[14], (id).bytes[15] ) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(stream->id_field), typeof(&*(stream->id_field ))), sizeof(stream->id_field)/sizeof((stream->id_field) [0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "stream->id_field" "[] must be big enough" ), "../src/journal/journald-stream.c", 694, __PRETTY_FUNCTION__ ); } while (0); | |||
695 | } | |||
696 | ||||
697 | return 0; | |||
698 | } | |||
699 | ||||
700 | static int stdout_stream_restore(Server *s, const char *fname, int fd) { | |||
701 | StdoutStream *stream; | |||
702 | int r; | |||
703 | ||||
704 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 704, __PRETTY_FUNCTION__); } while (0); | |||
705 | assert(fname)do { if ((__builtin_expect(!!(!(fname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fname"), "../src/journal/journald-stream.c" , 705, __PRETTY_FUNCTION__); } while (0); | |||
706 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/journal/journald-stream.c" , 706, __PRETTY_FUNCTION__); } while (0); | |||
707 | ||||
708 | if (s->n_stdout_streams >= STDOUT_STREAMS_MAX4096) { | |||
709 | log_warning("Too many stdout streams, refusing restoring of stream.")({ int _level = (((4))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 709, __func__, "Too many stdout streams, refusing restoring of stream." ) : -abs(_e); }); | |||
710 | return -ENOBUFS105; | |||
711 | } | |||
712 | ||||
713 | r = stdout_stream_install(s, fd, &stream); | |||
714 | if (r < 0) | |||
715 | return r; | |||
716 | ||||
717 | stream->state = STDOUT_STREAM_RUNNING; | |||
| ||||
718 | stream->fdstore = true1; | |||
719 | ||||
720 | /* Ignore all parsing errors */ | |||
721 | (void) stdout_stream_load(stream, fname); | |||
722 | ||||
723 | return 0; | |||
724 | } | |||
725 | ||||
726 | int server_restore_streams(Server *s, FDSet *fds) { | |||
727 | _cleanup_closedir___attribute__((cleanup(closedirp))) DIR *d = NULL((void*)0); | |||
728 | struct dirent *de; | |||
729 | int r; | |||
730 | ||||
731 | d = opendir("/run/systemd/journal/streams"); | |||
732 | if (!d) { | |||
| ||||
733 | if (errno(*__errno_location ()) == ENOENT2) | |||
734 | return 0; | |||
735 | ||||
736 | return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 736, __func__, "Failed to enumerate /run/systemd/journal/streams: %m" ) : -abs(_e); }); | |||
737 | } | |||
738 | ||||
739 | FOREACH_DIRENT(de, d, goto fail)for ((*__errno_location ()) = 0, de = readdir(d);; (*__errno_location ()) = 0, de = readdir(d)) if (!de) { if ((*__errno_location ( )) > 0) { goto fail; } break; } else if (hidden_or_backup_file ((de)->d_name)) continue; else { | |||
740 | unsigned long st_dev, st_ino; | |||
741 | bool_Bool found = false0; | |||
742 | Iterator i; | |||
743 | int fd; | |||
744 | ||||
745 | if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2) | |||
746 | continue; | |||
747 | ||||
748 | FDSET_FOREACH(fd, fds, i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }), (fd) = fdset_iterate((fds), &(i )); (fd) >= 0; (fd) = fdset_iterate((fds), &(i))) { | |||
749 | struct stat st; | |||
750 | ||||
751 | if (fstat(fd, &st) < 0) | |||
752 | return log_error_errno(errno, "Failed to stat %s: %m", de->d_name)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 752, __func__, "Failed to stat %s: %m", de->d_name) : -abs(_e) ; }); | |||
753 | ||||
754 | if (S_ISSOCK(st.st_mode)((((st.st_mode)) & 0170000) == (0140000)) && st.st_dev == st_dev && st.st_ino == st_ino) { | |||
755 | found = true1; | |||
756 | break; | |||
757 | } | |||
758 | } | |||
759 | ||||
760 | if (!found
| |||
761 | /* No file descriptor? Then let's delete the state file */ | |||
762 | log_debug("Cannot restore stream file %s", de->d_name)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 762, __func__, "Cannot restore stream file %s" , de->d_name) : -abs(_e); }); | |||
763 | if (unlinkat(dirfd(d), de->d_name, 0) < 0) | |||
764 | log_warning_errno(errno, "Failed to remove /run/systemd/journal/streams/%s: %m",({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 765, __func__, "Failed to remove /run/systemd/journal/streams/%s: %m" , de->d_name) : -abs(_e); }) | |||
765 | de->d_name)({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 765, __func__, "Failed to remove /run/systemd/journal/streams/%s: %m" , de->d_name) : -abs(_e); }); | |||
766 | continue; | |||
767 | } | |||
768 | ||||
769 | fdset_remove(fds, fd); | |||
770 | ||||
771 | r = stdout_stream_restore(s, de->d_name, fd); | |||
772 | if (r < 0) | |||
773 | safe_close(fd); | |||
774 | } | |||
775 | ||||
776 | return 0; | |||
777 | ||||
778 | fail: | |||
779 | return log_error_errno(errno, "Failed to read streams directory: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 779, __func__, "Failed to read streams directory: %m") : -abs(_e) ; }); | |||
780 | } | |||
781 | ||||
782 | int server_open_stdout_socket(Server *s) { | |||
783 | static const union sockaddr_union sa = { | |||
784 | .un.sun_family = AF_UNIX1, | |||
785 | .un.sun_path = "/run/systemd/journal/stdout", | |||
786 | }; | |||
787 | int r; | |||
788 | ||||
789 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 789, __PRETTY_FUNCTION__); } while (0); | |||
790 | ||||
791 | if (s->stdout_fd < 0) { | |||
792 | s->stdout_fd = socket(AF_UNIX1, SOCK_STREAMSOCK_STREAM|SOCK_CLOEXECSOCK_CLOEXEC|SOCK_NONBLOCKSOCK_NONBLOCK, 0); | |||
793 | if (s->stdout_fd < 0) | |||
794 | return log_error_errno(errno, "socket() failed: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 794, __func__, "socket() failed: %m") : -abs(_e); }); | |||
795 | ||||
796 | (void) unlink(sa.un.sun_path); | |||
797 | ||||
798 | r = bind(s->stdout_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect (!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm( LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/journal/journald-stream.c" , 798, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof( struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen (_sa->sun_path, sizeof(_sa->sun_path))); })); | |||
799 | if (r < 0) | |||
800 | return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 800, __func__, "bind(%s) failed: %m", sa.un.sun_path) : -abs(_e); }); | |||
801 | ||||
802 | (void) chmod(sa.un.sun_path, 0666); | |||
803 | ||||
804 | if (listen(s->stdout_fd, SOMAXCONN4096) < 0) | |||
805 | return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 805, __func__, "listen(%s) failed: %m", sa.un.sun_path) : -abs(_e ); }); | |||
806 | } else | |||
807 | fd_nonblock(s->stdout_fd, 1); | |||
808 | ||||
809 | r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLINEPOLLIN, stdout_stream_new, s); | |||
810 | if (r < 0) | |||
811 | return log_error_errno(r, "Failed to add stdout server fd to event source: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 811, __func__, "Failed to add stdout server fd to event source: %m" ) : -abs(_e); }); | |||
812 | ||||
813 | r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5); | |||
814 | if (r < 0) | |||
815 | return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 815, __func__, "Failed to adjust priority of stdout server event source: %m" ) : -abs(_e); }); | |||
816 | ||||
817 | return 0; | |||
818 | } | |||
819 | ||||
820 | void stdout_stream_send_notify(StdoutStream *s) { | |||
821 | struct iovec iovec = { | |||
822 | .iov_base = (char*) "FDSTORE=1", | |||
823 | .iov_len = STRLEN("FDSTORE=1")(sizeof("""FDSTORE=1""") - 1), | |||
824 | }; | |||
825 | struct msghdr msghdr = { | |||
826 | .msg_iov = &iovec, | |||
827 | .msg_iovlen = 1, | |||
828 | }; | |||
829 | struct cmsghdr *cmsg; | |||
830 | ssize_t l; | |||
831 | ||||
832 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-stream.c" , 832, __PRETTY_FUNCTION__); } while (0); | |||
833 | assert(!s->fdstore)do { if ((__builtin_expect(!!(!(!s->fdstore)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("!s->fdstore"), "../src/journal/journald-stream.c" , 833, __PRETTY_FUNCTION__); } while (0); | |||
834 | assert(s->in_notify_queue)do { if ((__builtin_expect(!!(!(s->in_notify_queue)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->in_notify_queue"), "../src/journal/journald-stream.c" , 834, __PRETTY_FUNCTION__); } while (0); | |||
835 | assert(s->server)do { if ((__builtin_expect(!!(!(s->server)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->server"), "../src/journal/journald-stream.c" , 835, __PRETTY_FUNCTION__); } while (0); | |||
836 | assert(s->server->notify_fd >= 0)do { if ((__builtin_expect(!!(!(s->server->notify_fd >= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->server->notify_fd >= 0" ), "../src/journal/journald-stream.c", 836, __PRETTY_FUNCTION__ ); } while (0); | |||
837 | ||||
838 | /* Store the connection fd in PID 1, so that we get it passed | |||
839 | * in again on next start */ | |||
840 | ||||
841 | msghdr.msg_controllen = CMSG_SPACE(sizeof(int))((((sizeof(int)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t ) - 1) & (size_t) ~(sizeof (size_t) - 1))); | |||
842 | msghdr.msg_control = alloca0(msghdr.msg_controllen)({ char *_new_; size_t _len_ = msghdr.msg_controllen; _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_); } ); | |||
843 | ||||
844 | cmsg = CMSG_FIRSTHDR(&msghdr)((size_t) (&msghdr)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msghdr)->msg_control : (struct cmsghdr *) 0); | |||
845 | cmsg->cmsg_level = SOL_SOCKET1; | |||
846 | cmsg->cmsg_type = SCM_RIGHTSSCM_RIGHTS; | |||
847 | cmsg->cmsg_len = CMSG_LEN(sizeof(int))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (sizeof(int))); | |||
848 | ||||
849 | memcpy(CMSG_DATA(cmsg)((cmsg)->__cmsg_data), &s->fd, sizeof(int)); | |||
850 | ||||
851 | l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAITMSG_DONTWAIT|MSG_NOSIGNALMSG_NOSIGNAL); | |||
852 | if (l < 0) { | |||
853 | if (errno(*__errno_location ()) == EAGAIN11) | |||
854 | return; | |||
855 | ||||
856 | log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-stream.c", 856, __func__, "Failed to send stream file descriptor to service manager: %m" ) : -abs(_e); }); | |||
857 | } else { | |||
858 | log_debug("Successfully sent stream file descriptor to service manager.")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-stream.c", 858, __func__, "Successfully sent stream file descriptor to service manager." ) : -abs(_e); }); | |||
859 | s->fdstore = 1; | |||
860 | } | |||
861 | ||||
862 | LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s)do { typeof(*(s->server->stdout_streams_notify_queue)) * *_head = &(s->server->stdout_streams_notify_queue), *_item = (s); do { if ((__builtin_expect(!!(!(_item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_item"), "../src/journal/journald-stream.c" , 862, __PRETTY_FUNCTION__); } while (0); if (_item->stdout_stream_notify_queue_next ) _item->stdout_stream_notify_queue_next->stdout_stream_notify_queue_prev = _item->stdout_stream_notify_queue_prev; if (_item->stdout_stream_notify_queue_prev ) _item->stdout_stream_notify_queue_prev->stdout_stream_notify_queue_next = _item->stdout_stream_notify_queue_next; else { do { if ( (__builtin_expect(!!(!(*_head == _item)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*_head == _item"), "../src/journal/journald-stream.c" , 862, __PRETTY_FUNCTION__); } while (0); *_head = _item-> stdout_stream_notify_queue_next; } _item->stdout_stream_notify_queue_next = _item->stdout_stream_notify_queue_prev = ((void*)0); } while (0); | |||
863 | s->in_notify_queue = false0; | |||
864 | ||||
865 | } |