| File: | build-scan/../src/journal/journald-stream.c |
| Warning: | line 621, column 9 Value stored to 'fd' is never read |
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_A13 = ((s->allocated - 1)); const typeof((s->server->line_max )) __unique_prefix_B14 = ((s->server->line_max)); __unique_prefix_A13 < __unique_prefix_B14 ? __unique_prefix_A13 : __unique_prefix_B14 ; }); |
| 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; |
Value stored to 'fd' is never read | |
| 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 | } |