]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/log.c
Merge pull request #8441 from keszybz/oss-fuzz-fixes
[thirdparty/systemd.git] / src / basic / log.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7334b09
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
a7334b09 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
c9b97d2a 21#include <errno.h>
16801e90 22#include <fcntl.h>
11c3a366
TA
23#include <inttypes.h>
24#include <limits.h>
07630cea
LP
25#include <stdarg.h>
26#include <stddef.h>
27#include <stdio.h>
11c3a366
TA
28#include <string.h>
29#include <sys/signalfd.h>
16801e90 30#include <sys/socket.h>
11c3a366
TA
31#include <sys/time.h>
32#include <sys/uio.h>
16801e90 33#include <sys/un.h>
11c3a366 34#include <time.h>
07630cea 35#include <unistd.h>
5899f3b7 36
158350e8 37#include "sd-messages.h"
07630cea 38
b5efdb8a 39#include "alloc-util.h"
3ffd4af2 40#include "fd-util.h"
f97b34a6 41#include "format-util.h"
afc5dbf3 42#include "io-util.h"
3ffd4af2 43#include "log.h"
07630cea
LP
44#include "macro.h"
45#include "missing.h"
4e731273
LP
46#include "parse-util.h"
47#include "proc-cmdline.h"
0b452006 48#include "process-util.h"
24882e06 49#include "signal-util.h"
07630cea 50#include "socket-util.h"
15a5e950 51#include "stdio-util.h"
8b43440b 52#include "string-table.h"
07630cea 53#include "string-util.h"
7ccbd1ae 54#include "syslog-util.h"
07630cea 55#include "terminal-util.h"
93cc7779 56#include "time-util.h"
d04ce5a9 57#include "utf8.h"
07630cea 58#include "util.h"
5899f3b7 59
bb99a35a
LP
60#define SNDBUF_SIZE (8*1024*1024)
61
16801e90 62static LogTarget log_target = LOG_TARGET_CONSOLE;
ff524019
ZJS
63static int log_max_level[] = {LOG_INFO, LOG_INFO};
64assert_cc(ELEMENTSOF(log_max_level) == _LOG_REALM_MAX);
3eff4208 65static int log_facility = LOG_DAEMON;
16801e90 66
843d2643 67static int console_fd = STDERR_FILENO;
16801e90
LP
68static int syslog_fd = -1;
69static int kmsg_fd = -1;
5ba081b0 70static int journal_fd = -1;
16801e90 71
c31e1495
LP
72static bool syslog_is_stream = false;
73
bbe63281
LP
74static bool show_color = false;
75static bool show_location = false;
76
c1dc6153 77static bool upgrade_syslog_to_journal = false;
48a601fe 78static bool always_reopen_console = false;
16e4fd87 79static bool open_when_needed = false;
adf47c91 80static bool prohibit_ipc = false;
c1dc6153 81
35b8ca3a 82/* Akin to glibc's __abort_msg; which is private and we hence cannot
185986c6
LP
83 * use here. */
84static char *log_abort_msg = NULL;
85
780747da
ZJS
86/* An assert to use in logging functions that does not call recursively
87 * into our logging functions (since that might lead to a loop). */
88#define assert_raw(expr) \
89 do { \
90 if (_unlikely_(!(expr))) { \
91 fputs(#expr "\n", stderr); \
92 abort(); \
93 } \
94 } while (false)
95
cc2b9e6b 96static void log_close_console(void) {
e7685a77 97 console_fd = safe_close_above_stdio(console_fd);
16801e90
LP
98}
99
843d2643 100static int log_open_console(void) {
16801e90 101
cc2b9e6b
AJ
102 if (!always_reopen_console) {
103 console_fd = STDERR_FILENO;
16801e90 104 return 0;
cc2b9e6b 105 }
843d2643 106
cc2b9e6b 107 if (console_fd < 3) {
5ba081b0 108 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
cd15c418 109 if (console_fd < 0)
843d2643 110 return console_fd;
7fe2903c
LP
111
112 console_fd = fd_move_above_stdio(console_fd);
cc2b9e6b 113 }
843d2643
LP
114
115 return 0;
116}
117
cc2b9e6b 118static void log_close_kmsg(void) {
03e334a1 119 kmsg_fd = safe_close(kmsg_fd);
843d2643
LP
120}
121
122static int log_open_kmsg(void) {
16801e90
LP
123
124 if (kmsg_fd >= 0)
125 return 0;
126
674f8283 127 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
cd15c418 128 if (kmsg_fd < 0)
16801e90 129 return -errno;
0dae83f9 130
7fe2903c 131 kmsg_fd = fd_move_above_stdio(kmsg_fd);
16801e90
LP
132 return 0;
133}
134
cc2b9e6b 135static void log_close_syslog(void) {
03e334a1 136 syslog_fd = safe_close(syslog_fd);
16801e90
LP
137}
138
c31e1495 139static int create_log_socket(int type) {
8b18fdc1 140 struct timeval tv;
95066a90 141 int fd;
c31e1495 142
8b18fdc1 143 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
5ba081b0 144 if (fd < 0)
c31e1495
LP
145 return -errno;
146
7fe2903c 147 fd = fd_move_above_stdio(fd);
0474ef7b 148 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
bb99a35a 149
7fe2903c
LP
150 /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
151 * in the unlikely case of a deadlock. */
df0ff127 152 if (getpid_cached() == 1)
4d89874a
ZJS
153 timeval_store(&tv, 10 * USEC_PER_MSEC);
154 else
155 timeval_store(&tv, 10 * USEC_PER_SEC);
086891e5 156 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
8b18fdc1 157
c31e1495
LP
158 return fd;
159}
160
843d2643 161static int log_open_syslog(void) {
95066a90
LP
162
163 static const union sockaddr_union sa = {
b92bea5d
ZJS
164 .un.sun_family = AF_UNIX,
165 .un.sun_path = "/dev/log",
166 };
16801e90 167
95066a90
LP
168 int r;
169
16801e90
LP
170 if (syslog_fd >= 0)
171 return 0;
172
5ba081b0
LP
173 syslog_fd = create_log_socket(SOCK_DGRAM);
174 if (syslog_fd < 0) {
175 r = syslog_fd;
843d2643 176 goto fail;
16801e90
LP
177 }
178
fc2fffe7 179 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
03e334a1 180 safe_close(syslog_fd);
c31e1495
LP
181
182 /* Some legacy syslog systems still use stream
183 * sockets. They really shouldn't. But what can we
184 * do... */
5ba081b0
LP
185 syslog_fd = create_log_socket(SOCK_STREAM);
186 if (syslog_fd < 0) {
187 r = syslog_fd;
c31e1495
LP
188 goto fail;
189 }
190
fc2fffe7 191 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
c31e1495
LP
192 r = -errno;
193 goto fail;
194 }
195
196 syslog_is_stream = true;
197 } else
198 syslog_is_stream = false;
199
16801e90 200 return 0;
843d2643
LP
201
202fail:
203 log_close_syslog();
843d2643
LP
204 return r;
205}
206
cc2b9e6b 207static void log_close_journal(void) {
03e334a1 208 journal_fd = safe_close(journal_fd);
5ba081b0
LP
209}
210
211static int log_open_journal(void) {
95066a90
LP
212
213 static const union sockaddr_union sa = {
b92bea5d
ZJS
214 .un.sun_family = AF_UNIX,
215 .un.sun_path = "/run/systemd/journal/socket",
216 };
95066a90 217
5ba081b0
LP
218 int r;
219
220 if (journal_fd >= 0)
221 return 0;
222
223 journal_fd = create_log_socket(SOCK_DGRAM);
224 if (journal_fd < 0) {
225 r = journal_fd;
226 goto fail;
227 }
228
fc2fffe7 229 if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
5ba081b0
LP
230 r = -errno;
231 goto fail;
232 }
233
5ba081b0
LP
234 return 0;
235
236fail:
237 log_close_journal();
5ba081b0
LP
238 return r;
239}
240
843d2643
LP
241int log_open(void) {
242 int r;
243
e3e42fc2
ZJS
244 /* Do not call from library code. */
245
843d2643
LP
246 /* If we don't use the console we close it here, to not get
247 * killed by SAK. If we don't use syslog we close it here so
248 * that we are not confused by somebody deleting the socket in
cc2b9e6b
AJ
249 * the fs, and to make sure we don't use it if prohibit_ipc is
250 * set. If we don't use /dev/kmsg we still keep it open,
843d2643
LP
251 * because there is no reason to close it. */
252
9fae33d2 253 if (log_target == LOG_TARGET_NULL) {
5ba081b0 254 log_close_journal();
9fae33d2
LP
255 log_close_syslog();
256 log_close_console();
257 return 0;
258 }
259
6c347d50 260 if (log_target != LOG_TARGET_AUTO ||
df0ff127 261 getpid_cached() == 1 ||
f41c094c 262 isatty(STDERR_FILENO) <= 0) {
bb7df0da 263
adf47c91
LP
264 if (!prohibit_ipc &&
265 IN_SET(log_target, LOG_TARGET_AUTO,
5b5688af
ZJS
266 LOG_TARGET_JOURNAL_OR_KMSG,
267 LOG_TARGET_JOURNAL)) {
5ba081b0
LP
268 r = log_open_journal();
269 if (r >= 0) {
270 log_close_syslog();
bb7df0da
LP
271 log_close_console();
272 return r;
273 }
5ba081b0
LP
274 }
275
adf47c91
LP
276 if (!prohibit_ipc &&
277 IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
5b5688af 278 LOG_TARGET_SYSLOG)) {
5ba081b0
LP
279 r = log_open_syslog();
280 if (r >= 0) {
281 log_close_journal();
282 log_close_console();
283 return r;
284 }
285 }
286
5b5688af 287 if (IN_SET(log_target, LOG_TARGET_AUTO,
5b5688af
ZJS
288 LOG_TARGET_JOURNAL_OR_KMSG,
289 LOG_TARGET_SYSLOG_OR_KMSG,
290 LOG_TARGET_KMSG)) {
5ba081b0
LP
291 r = log_open_kmsg();
292 if (r >= 0) {
293 log_close_journal();
bb7df0da
LP
294 log_close_syslog();
295 log_close_console();
296 return r;
297 }
5ba081b0 298 }
bb7df0da 299 }
843d2643 300
5ba081b0 301 log_close_journal();
843d2643 302 log_close_syslog();
dcdf86bb 303
843d2643 304 return log_open_console();
16801e90
LP
305}
306
307void log_set_target(LogTarget target) {
308 assert(target >= 0);
309 assert(target < _LOG_TARGET_MAX);
310
c1dc6153
LP
311 if (upgrade_syslog_to_journal) {
312 if (target == LOG_TARGET_SYSLOG)
313 target = LOG_TARGET_JOURNAL;
314 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
315 target = LOG_TARGET_JOURNAL_OR_KMSG;
316 }
317
16801e90
LP
318 log_target = target;
319}
320
871e5809 321void log_close(void) {
e3e42fc2
ZJS
322 /* Do not call from library code. */
323
5ba081b0 324 log_close_journal();
871e5809 325 log_close_syslog();
5ba081b0
LP
326 log_close_kmsg();
327 log_close_console();
871e5809
LP
328}
329
4d8a7798 330void log_forget_fds(void) {
e3e42fc2
ZJS
331 /* Do not call from library code. */
332
5ba081b0 333 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
4d8a7798
MS
334}
335
ff524019 336void log_set_max_level_realm(LogRealm realm, int level) {
16801e90 337 assert((level & LOG_PRIMASK) == level);
ff524019 338 assert(realm < ELEMENTSOF(log_max_level));
16801e90 339
ff524019 340 log_max_level[realm] = level;
16801e90
LP
341}
342
3eff4208
LP
343void log_set_facility(int facility) {
344 log_facility = facility;
345}
346
843d2643 347static int write_to_console(
20c03b7b 348 int level,
086891e5 349 int error,
95066a90 350 const char *file,
20c03b7b
LP
351 int line,
352 const char *func,
353 const char *buffer) {
5899f3b7 354
79c95440 355 char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
aca83a53 356 struct iovec iovec[6] = {};
843d2643
LP
357 unsigned n = 0;
358 bool highlight;
5899f3b7 359
843d2643
LP
360 if (console_fd < 0)
361 return 0;
362
aca83a53 363 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
0474ef7b 364 xsprintf(prefix, "<%i>", level);
e6a7ec4b 365 iovec[n++] = IOVEC_MAKE_STRING(prefix);
aca83a53
LP
366 }
367
bbe63281 368 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
843d2643 369
674f8283 370 if (show_location) {
4ad2b562 371 (void) snprintf(location, sizeof location, "(%s:%i) ", file, line);
e6a7ec4b 372 iovec[n++] = IOVEC_MAKE_STRING(location);
674f8283
LP
373 }
374
843d2643 375 if (highlight)
e6a7ec4b
LP
376 iovec[n++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED);
377 iovec[n++] = IOVEC_MAKE_STRING(buffer);
843d2643 378 if (highlight)
e6a7ec4b
LP
379 iovec[n++] = IOVEC_MAKE_STRING(ANSI_NORMAL);
380 iovec[n++] = IOVEC_MAKE_STRING("\n");
843d2643 381
0e6eaa2d
LP
382 if (writev(console_fd, iovec, n) < 0) {
383
df0ff127 384 if (errno == EIO && getpid_cached() == 1) {
0e6eaa2d
LP
385
386 /* If somebody tried to kick us from our
387 * console tty (via vhangup() or suchlike),
388 * try to reconnect */
389
390 log_close_console();
391 log_open_console();
392
393 if (console_fd < 0)
394 return 0;
395
396 if (writev(console_fd, iovec, n) < 0)
397 return -errno;
398 } else
399 return -errno;
400 }
5899f3b7 401
843d2643 402 return 1;
16801e90 403}
5899f3b7 404
16801e90 405static int write_to_syslog(
086891e5
LP
406 int level,
407 int error,
95066a90 408 const char *file,
086891e5
LP
409 int line,
410 const char *func,
086891e5 411 const char *buffer) {
16801e90 412
5ffa8c81
ZJS
413 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
414 header_time[64],
415 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
b92bea5d
ZJS
416 struct iovec iovec[5] = {};
417 struct msghdr msghdr = {
418 .msg_iov = iovec,
419 .msg_iovlen = ELEMENTSOF(iovec),
420 };
16801e90
LP
421 time_t t;
422 struct tm *tm;
423
424 if (syslog_fd < 0)
843d2643 425 return 0;
16801e90 426
5ffa8c81 427 xsprintf(header_priority, "<%i>", level);
16801e90
LP
428
429 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
fdf9f9bb
ZJS
430 tm = localtime(&t);
431 if (!tm)
16801e90
LP
432 return -EINVAL;
433
434 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
435 return -EINVAL;
436
df0ff127 437 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
16801e90 438
e6a7ec4b
LP
439 iovec[0] = IOVEC_MAKE_STRING(header_priority);
440 iovec[1] = IOVEC_MAKE_STRING(header_time);
441 iovec[2] = IOVEC_MAKE_STRING(program_invocation_short_name);
442 iovec[3] = IOVEC_MAKE_STRING(header_pid);
443 iovec[4] = IOVEC_MAKE_STRING(buffer);
16801e90 444
c899f8c6 445 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
c31e1495
LP
446 if (syslog_is_stream)
447 iovec[4].iov_len++;
448
c31e1495
LP
449 for (;;) {
450 ssize_t n;
451
8f7f7a1b
MS
452 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
453 if (n < 0)
c31e1495
LP
454 return -errno;
455
456 if (!syslog_is_stream ||
457 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
458 break;
459
460 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
461 }
16801e90 462
843d2643 463 return 1;
16801e90
LP
464}
465
466static int write_to_kmsg(
086891e5
LP
467 int level,
468 int error,
bcf5c276 469 const char *file,
086891e5
LP
470 int line,
471 const char *func,
086891e5 472 const char *buffer) {
16801e90 473
5ffa8c81
ZJS
474 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
475 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
b92bea5d 476 struct iovec iovec[5] = {};
16801e90
LP
477
478 if (kmsg_fd < 0)
843d2643 479 return 0;
16801e90 480
5ffa8c81 481 xsprintf(header_priority, "<%i>", level);
df0ff127 482 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
16801e90 483
e6a7ec4b
LP
484 iovec[0] = IOVEC_MAKE_STRING(header_priority);
485 iovec[1] = IOVEC_MAKE_STRING(program_invocation_short_name);
486 iovec[2] = IOVEC_MAKE_STRING(header_pid);
487 iovec[3] = IOVEC_MAKE_STRING(buffer);
488 iovec[4] = IOVEC_MAKE_STRING("\n");
16801e90
LP
489
490 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
491 return -errno;
492
843d2643 493 return 1;
16801e90
LP
494}
495
086891e5
LP
496static int log_do_header(
497 char *header,
498 size_t size,
499 int level,
500 int error,
501 const char *file, int line, const char *func,
4b58153d
LP
502 const char *object_field, const char *object,
503 const char *extra_field, const char *extra) {
f8e6f4aa 504 int r;
086891e5 505
f8e6f4aa
ZJS
506 r = snprintf(header, size,
507 "PRIORITY=%i\n"
508 "SYSLOG_FACILITY=%i\n"
509 "%s%.256s%s" /* CODE_FILE */
510 "%s%.*i%s" /* CODE_LINE */
511 "%s%.256s%s" /* CODE_FUNC */
512 "%s%.*i%s" /* ERRNO */
513 "%s%.256s%s" /* object */
514 "%s%.256s%s" /* extra */
515 "SYSLOG_IDENTIFIER=%.256s\n",
516 LOG_PRI(level),
517 LOG_FAC(level),
518 isempty(file) ? "" : "CODE_FILE=",
519 isempty(file) ? "" : file,
520 isempty(file) ? "" : "\n",
521 line ? "CODE_LINE=" : "",
522 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
523 line ? "\n" : "",
524 isempty(func) ? "" : "CODE_FUNC=",
525 isempty(func) ? "" : func,
526 isempty(func) ? "" : "\n",
527 error ? "ERRNO=" : "",
528 error ? 1 : 0, error,
529 error ? "\n" : "",
530 isempty(object) ? "" : object_field,
531 isempty(object) ? "" : object,
532 isempty(object) ? "" : "\n",
533 isempty(extra) ? "" : extra_field,
534 isempty(extra) ? "" : extra,
535 isempty(extra) ? "" : "\n",
536 program_invocation_short_name);
780747da 537 assert_raw((size_t) r < size);
086891e5 538
41a79f10
ZJS
539 return 0;
540}
5ba081b0 541
41a79f10 542static int write_to_journal(
086891e5
LP
543 int level,
544 int error,
bcf5c276 545 const char *file,
086891e5
LP
546 int line,
547 const char *func,
548 const char *object_field,
549 const char *object,
4b58153d
LP
550 const char *extra_field,
551 const char *extra,
086891e5 552 const char *buffer) {
41a79f10
ZJS
553
554 char header[LINE_MAX];
b92bea5d
ZJS
555 struct iovec iovec[4] = {};
556 struct msghdr mh = {};
41a79f10
ZJS
557
558 if (journal_fd < 0)
559 return 0;
560
4b58153d 561 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
5ba081b0 562
e6a7ec4b
LP
563 iovec[0] = IOVEC_MAKE_STRING(header);
564 iovec[1] = IOVEC_MAKE_STRING("MESSAGE=");
565 iovec[2] = IOVEC_MAKE_STRING(buffer);
566 iovec[3] = IOVEC_MAKE_STRING("\n");
5ba081b0 567
5ba081b0
LP
568 mh.msg_iov = iovec;
569 mh.msg_iovlen = ELEMENTSOF(iovec);
570
571 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
572 return -errno;
573
574 return 1;
575}
576
93484b47 577int log_dispatch_internal(
086891e5
LP
578 int level,
579 int error,
95066a90 580 const char *file,
086891e5
LP
581 int line,
582 const char *func,
583 const char *object_field,
584 const char *object,
4b58153d 585 const char *extra_field,
4dd09c6a 586 const char *extra,
086891e5 587 char *buffer) {
843d2643 588
780747da 589 assert_raw(buffer);
843d2643 590
0474ef7b
LP
591 if (error < 0)
592 error = -error;
593
9fae33d2 594 if (log_target == LOG_TARGET_NULL)
bf371116 595 return -error;
9fae33d2 596
29db5834 597 /* Patch in LOG_DAEMON facility if necessary */
7d76f312 598 if ((level & LOG_FACMASK) == 0)
3eff4208 599 level = log_facility | LOG_PRI(level);
29db5834 600
16e4fd87
LP
601 if (open_when_needed)
602 log_open();
603
9726b29e
LP
604 do {
605 char *e;
9499b235 606 int k = 0;
843d2643 607
9726b29e 608 buffer += strspn(buffer, NEWLINE);
843d2643 609
9726b29e
LP
610 if (buffer[0] == 0)
611 break;
843d2643 612
9726b29e
LP
613 if ((e = strpbrk(buffer, NEWLINE)))
614 *(e++) = 0;
843d2643 615
5b5688af
ZJS
616 if (IN_SET(log_target, LOG_TARGET_AUTO,
617 LOG_TARGET_JOURNAL_OR_KMSG,
618 LOG_TARGET_JOURNAL)) {
5ba081b0 619
4b58153d 620 k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
e38b8a40
LP
621 if (k < 0 && k != -EAGAIN)
622 log_close_journal();
5ba081b0
LP
623 }
624
5b5688af
ZJS
625 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
626 LOG_TARGET_SYSLOG)) {
9726b29e 627
4b58153d 628 k = write_to_syslog(level, error, file, line, func, buffer);
e38b8a40
LP
629 if (k < 0 && k != -EAGAIN)
630 log_close_syslog();
9726b29e
LP
631 }
632
9499b235 633 if (k <= 0 &&
5b5688af 634 IN_SET(log_target, LOG_TARGET_AUTO,
5b5688af
ZJS
635 LOG_TARGET_SYSLOG_OR_KMSG,
636 LOG_TARGET_JOURNAL_OR_KMSG,
637 LOG_TARGET_KMSG)) {
9726b29e 638
e38b8a40
LP
639 if (k < 0)
640 log_open_kmsg();
641
4b58153d 642 k = write_to_kmsg(level, error, file, line, func, buffer);
4e7bc3f3
LP
643 if (k < 0) {
644 log_close_kmsg();
9726b29e 645 log_open_console();
bf371116 646 }
9726b29e
LP
647 }
648
bf371116 649 if (k <= 0)
4b58153d 650 (void) write_to_console(level, error, file, line, func, buffer);
9726b29e
LP
651
652 buffer = e;
653 } while (buffer);
654
16e4fd87
LP
655 if (open_when_needed)
656 log_close();
657
bf371116 658 return -error;
843d2643
LP
659}
660
2149e37c 661int log_dump_internal(
ff524019
ZJS
662 int level,
663 int error,
664 const char *file,
665 int line,
666 const char *func,
667 char *buffer) {
2149e37c 668
ff524019 669 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
5c0aa72a 670 PROTECT_ERRNO;
2149e37c
LP
671
672 /* This modifies the buffer... */
673
bf371116
LP
674 if (error < 0)
675 error = -error;
676
ff524019 677 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
bf371116 678 return -error;
2149e37c 679
93484b47 680 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
2149e37c
LP
681}
682
ff524019 683int log_internalv_realm(
086891e5
LP
684 int level,
685 int error,
bcf5c276 686 const char *file,
086891e5
LP
687 int line,
688 const char *func,
689 const char *format,
690 va_list ap) {
16801e90 691
ff524019 692 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
addab137 693 char buffer[LINE_MAX];
ff524019 694 PROTECT_ERRNO;
16801e90 695
bf371116
LP
696 if (error < 0)
697 error = -error;
698
ff524019 699 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
bf371116 700 return -error;
16801e90 701
086891e5
LP
702 /* Make sure that %m maps to the specified error */
703 if (error != 0)
bf371116 704 errno = error;
086891e5 705
4ad2b562 706 (void) vsnprintf(buffer, sizeof buffer, format, ap);
843d2643 707
93484b47 708 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
185986c6 709}
16801e90 710
ff524019 711int log_internal_realm(
086891e5
LP
712 int level,
713 int error,
bcf5c276 714 const char *file,
086891e5
LP
715 int line,
716 const char *func,
717 const char *format, ...) {
17a94911 718
17a94911 719 va_list ap;
bf371116 720 int r;
17a94911
LP
721
722 va_start(ap, format);
ff524019 723 r = log_internalv_realm(level, error, file, line, func, format, ap);
17a94911
LP
724 va_end(ap);
725
726 return r;
727}
728
a3bf7137
ZJS
729_printf_(10,0)
730static int log_object_internalv(
086891e5
LP
731 int level,
732 int error,
bcf5c276 733 const char *file,
086891e5
LP
734 int line,
735 const char *func,
736 const char *object_field,
737 const char *object,
4b58153d
LP
738 const char *extra_field,
739 const char *extra,
086891e5
LP
740 const char *format,
741 va_list ap) {
fdf9f9bb 742
5c0aa72a 743 PROTECT_ERRNO;
f2341e0a 744 char *buffer, *b;
fdf9f9bb 745
bf371116
LP
746 if (error < 0)
747 error = -error;
748
ff524019 749 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
bf371116 750 return -error;
fdf9f9bb 751
086891e5
LP
752 /* Make sure that %m maps to the specified error */
753 if (error != 0)
bf371116 754 errno = error;
086891e5 755
f2341e0a
LP
756 /* Prepend the object name before the message */
757 if (object) {
758 size_t n;
759
760 n = strlen(object);
1741b25c 761 buffer = newa(char, n + 2 + LINE_MAX);
f2341e0a 762 b = stpcpy(stpcpy(buffer, object), ": ");
1741b25c
EV
763 } else
764 b = buffer = newa(char, LINE_MAX);
f2341e0a 765
4ad2b562 766 (void) vsnprintf(b, LINE_MAX, format, ap);
fdf9f9bb 767
93484b47
ZJS
768 return log_dispatch_internal(level, error, file, line, func,
769 object_field, object, extra_field, extra, buffer);
fdf9f9bb
ZJS
770}
771
79008bdd 772int log_object_internal(
086891e5
LP
773 int level,
774 int error,
bcf5c276 775 const char *file,
086891e5
LP
776 int line,
777 const char *func,
778 const char *object_field,
779 const char *object,
4b58153d
LP
780 const char *extra_field,
781 const char *extra,
086891e5 782 const char *format, ...) {
fdf9f9bb 783
fdf9f9bb 784 va_list ap;
bf371116 785 int r;
fdf9f9bb
ZJS
786
787 va_start(ap, format);
4b58153d 788 r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
fdf9f9bb
ZJS
789 va_end(ap);
790
791 return r;
792}
793
086891e5
LP
794static void log_assert(
795 int level,
796 const char *text,
797 const char *file,
798 int line,
799 const char *func,
800 const char *format) {
801
addab137 802 static char buffer[LINE_MAX];
ff524019 803 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
185986c6 804
ff524019 805 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
50f72bca
ZJS
806 return;
807
bcfce235 808 DISABLE_WARNING_FORMAT_NONLITERAL;
4ad2b562 809 (void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
bcfce235 810 REENABLE_WARNING;
185986c6 811
185986c6
LP
812 log_abort_msg = buffer;
813
93484b47 814 log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
5899f3b7 815}
34f0e866 816
ff524019
ZJS
817noreturn void log_assert_failed_realm(
818 LogRealm realm,
819 const char *text,
820 const char *file,
821 int line,
822 const char *func) {
ea89a119 823 log_open();
ff524019
ZJS
824 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
825 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
80514f9c 826 abort();
b7f33638
MS
827}
828
ff524019
ZJS
829noreturn void log_assert_failed_unreachable_realm(
830 LogRealm realm,
831 const char *text,
832 const char *file,
833 int line,
834 const char *func) {
ea89a119 835 log_open();
ff524019
ZJS
836 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
837 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
80514f9c
LP
838 abort();
839}
840
ff524019
ZJS
841void log_assert_failed_return_realm(
842 LogRealm realm,
843 const char *text,
844 const char *file,
845 int line,
846 const char *func) {
e5ca092c 847 PROTECT_ERRNO;
ff524019
ZJS
848 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
849 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
b7f33638
MS
850}
851
ff524019 852int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
7558e10c
LP
853 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
854 ENOMEM, file, line, func, "Out of memory.");
6dc1e7e0
MS
855}
856
8a03c9ef
ZJS
857int log_format_iovec(
858 struct iovec *iovec,
d3070fbd
LP
859 size_t iovec_len,
860 size_t *n,
8a03c9ef
ZJS
861 bool newline_separator,
862 int error,
863 const char *format,
864 va_list ap) {
865
866 static const char nl = '\n';
867
868 while (format && *n + 1 < iovec_len) {
869 va_list aq;
870 char *m;
871 int r;
872
873 /* We need to copy the va_list structure,
874 * since vasprintf() leaves it afterwards at
875 * an undefined location */
876
877 if (error != 0)
878 errno = error;
879
880 va_copy(aq, ap);
881 r = vasprintf(&m, format, aq);
882 va_end(aq);
883 if (r < 0)
884 return -EINVAL;
885
886 /* Now, jump enough ahead, so that we point to
887 * the next format string */
888 VA_FORMAT_ADVANCE(format, ap);
889
e6a7ec4b 890 iovec[(*n)++] = IOVEC_MAKE_STRING(m);
8a03c9ef
ZJS
891
892 if (newline_separator) {
893 iovec[*n].iov_base = (char*) &nl;
894 iovec[*n].iov_len = 1;
895 (*n)++;
896 }
897
898 format = va_arg(ap, char *);
899 }
900 return 0;
901}
902
877d54e9
LP
903int log_struct_internal(
904 int level,
086891e5 905 int error,
877d54e9
LP
906 const char *file,
907 int line,
908 const char *func,
909 const char *format, ...) {
910
e6a7ec4b 911 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
bf371116
LP
912 char buf[LINE_MAX];
913 bool found = false;
5c0aa72a 914 PROTECT_ERRNO;
877d54e9 915 va_list ap;
bf371116
LP
916
917 if (error < 0)
918 error = -error;
877d54e9 919
ff524019 920 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
bf371116 921 return -error;
877d54e9
LP
922
923 if (log_target == LOG_TARGET_NULL)
bf371116 924 return -error;
877d54e9
LP
925
926 if ((level & LOG_FACMASK) == 0)
927 level = log_facility | LOG_PRI(level);
928
16e4fd87
LP
929 if (IN_SET(log_target,
930 LOG_TARGET_AUTO,
931 LOG_TARGET_JOURNAL_OR_KMSG,
932 LOG_TARGET_JOURNAL)) {
933
934 if (open_when_needed)
935 log_open_journal();
936
937 if (journal_fd >= 0) {
938 char header[LINE_MAX];
939 struct iovec iovec[17] = {};
d3070fbd 940 size_t n = 0, i;
16e4fd87
LP
941 int r;
942 struct msghdr mh = {
943 .msg_iov = iovec,
944 };
945 bool fallback = false;
946
947 /* If the journal is available do structured logging */
948 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
949 iovec[n++] = IOVEC_MAKE_STRING(header);
950
951 va_start(ap, format);
952 r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
953 if (r < 0)
954 fallback = true;
955 else {
956 mh.msg_iovlen = n;
957 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
958 }
877d54e9 959
16e4fd87
LP
960 va_end(ap);
961 for (i = 1; i < n; i += 2)
962 free(iovec[i].iov_base);
877d54e9 963
16e4fd87
LP
964 if (!fallback) {
965 if (open_when_needed)
966 log_close();
877d54e9 967
16e4fd87
LP
968 return -error;
969 }
970 }
bf371116 971 }
877d54e9 972
bf371116 973 /* Fallback if journal logging is not available or didn't work. */
6357ac66 974
bf371116
LP
975 va_start(ap, format);
976 while (format) {
977 va_list aq;
877d54e9 978
bf371116
LP
979 if (error != 0)
980 errno = error;
877d54e9 981
bf371116 982 va_copy(aq, ap);
4ad2b562 983 (void) vsnprintf(buf, sizeof buf, format, aq);
bf371116 984 va_end(aq);
963ddb91 985
bf371116
LP
986 if (startswith(buf, "MESSAGE=")) {
987 found = true;
988 break;
877d54e9 989 }
877d54e9 990
bf371116
LP
991 VA_FORMAT_ADVANCE(format, ap);
992
993 format = va_arg(ap, char *);
877d54e9 994 }
bf371116 995 va_end(ap);
877d54e9 996
16e4fd87
LP
997 if (!found) {
998 if (open_when_needed)
999 log_close();
1000
bf371116 1001 return -error;
16e4fd87 1002 }
bf371116 1003
93484b47 1004 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
877d54e9
LP
1005}
1006
915b1d01
LP
1007int log_struct_iovec_internal(
1008 int level,
1009 int error,
1010 const char *file,
1011 int line,
1012 const char *func,
1013 const struct iovec input_iovec[],
1014 size_t n_input_iovec) {
1015
1016 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
1017 PROTECT_ERRNO;
1018 size_t i;
1019 char *m;
1020
1021 if (error < 0)
1022 error = -error;
1023
1024 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
1025 return -error;
1026
1027 if (log_target == LOG_TARGET_NULL)
1028 return -error;
1029
1030 if ((level & LOG_FACMASK) == 0)
1031 level = log_facility | LOG_PRI(level);
1032
1033 if (IN_SET(log_target, LOG_TARGET_AUTO,
1034 LOG_TARGET_JOURNAL_OR_KMSG,
1035 LOG_TARGET_JOURNAL) &&
1036 journal_fd >= 0) {
1037
1038 struct iovec iovec[1 + n_input_iovec*2];
1039 char header[LINE_MAX];
1040 struct msghdr mh = {
1041 .msg_iov = iovec,
1042 .msg_iovlen = 1 + n_input_iovec*2,
1043 };
1044
1045 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
1046 iovec[0] = IOVEC_MAKE_STRING(header);
1047
1048 for (i = 0; i < n_input_iovec; i++) {
1049 iovec[1+i*2] = input_iovec[i];
1050 iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
1051 }
1052
1053 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0)
40056777 1054 return -error;
915b1d01
LP
1055 }
1056
1057 for (i = 0; i < n_input_iovec; i++) {
fbd0b64f 1058 if (input_iovec[i].iov_len < STRLEN("MESSAGE="))
915b1d01
LP
1059 continue;
1060
fbd0b64f 1061 if (memcmp(input_iovec[i].iov_base, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
915b1d01
LP
1062 break;
1063 }
1064
1065 if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
1066 return -error;
1067
fbd0b64f
LP
1068 m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
1069 input_iovec[i].iov_len - STRLEN("MESSAGE="));
915b1d01
LP
1070
1071 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
1072}
1073
34f0e866
LP
1074int log_set_target_from_string(const char *e) {
1075 LogTarget t;
1076
5ba081b0
LP
1077 t = log_target_from_string(e);
1078 if (t < 0)
34f0e866
LP
1079 return -EINVAL;
1080
1081 log_set_target(t);
1082 return 0;
1083}
1084
ff524019 1085int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
34f0e866
LP
1086 int t;
1087
5ba081b0
LP
1088 t = log_level_from_string(e);
1089 if (t < 0)
737af734 1090 return -EINVAL;
34f0e866 1091
ff524019 1092 log_set_max_level_realm(realm, t);
34f0e866
LP
1093 return 0;
1094}
1095
96287a49 1096static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
1de1c9c3
LP
1097
1098 /*
1099 * The systemd.log_xyz= settings are parsed by all tools, and
1100 * so is "debug".
1101 *
5e07a79e
LP
1102 * However, "quiet" is only parsed by PID 1, and only turns of
1103 * status output to /dev/console, but does not alter the log
1104 * level.
1de1c9c3
LP
1105 */
1106
1107 if (streq(key, "debug") && !value)
1108 log_set_max_level(LOG_DEBUG);
1109
1d84ad94
LP
1110 else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1111
1112 if (proc_cmdline_value_missing(key, value))
1113 return 0;
1de1c9c3
LP
1114
1115 if (log_set_target_from_string(value) < 0)
1116 log_warning("Failed to parse log target '%s'. Ignoring.", value);
1117
1d84ad94
LP
1118 } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1119
1120 if (proc_cmdline_value_missing(key, value))
1121 return 0;
1de1c9c3
LP
1122
1123 if (log_set_max_level_from_string(value) < 0)
1124 log_warning("Failed to parse log level '%s'. Ignoring.", value);
1125
1d84ad94 1126 } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
1de1c9c3 1127
1d84ad94 1128 if (log_show_color_from_string(value ?: "1") < 0)
1de1c9c3
LP
1129 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1130
1d84ad94 1131 } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
1de1c9c3 1132
1d84ad94 1133 if (log_show_location_from_string(value ?: "1") < 0)
1de1c9c3
LP
1134 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1135 }
1136
1137 return 0;
1138}
1139
ff524019 1140void log_parse_environment_realm(LogRealm realm) {
e3e42fc2
ZJS
1141 /* Do not call from library code. */
1142
34f0e866 1143 const char *e;
b8d0ffc2 1144
ee46e555 1145 if (get_ctty_devnr(0, NULL) < 0)
1d84ad94
LP
1146 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1147 user stuff. */
1148 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
34f0e866 1149
a99e002c 1150 e = getenv("SYSTEMD_LOG_TARGET");
88fae6e0 1151 if (e && log_set_target_from_string(e) < 0)
f0ea29ea 1152 log_warning("Failed to parse log target '%s'. Ignoring.", e);
34f0e866 1153
a99e002c 1154 e = getenv("SYSTEMD_LOG_LEVEL");
ff524019 1155 if (e && log_set_max_level_from_string_realm(realm, e) < 0)
f0ea29ea 1156 log_warning("Failed to parse log level '%s'. Ignoring.", e);
bbe63281 1157
a99e002c 1158 e = getenv("SYSTEMD_LOG_COLOR");
88fae6e0 1159 if (e && log_show_color_from_string(e) < 0)
f0ea29ea 1160 log_warning("Failed to parse bool '%s'. Ignoring.", e);
bbe63281 1161
a99e002c 1162 e = getenv("SYSTEMD_LOG_LOCATION");
88fae6e0 1163 if (e && log_show_location_from_string(e) < 0)
f0ea29ea 1164 log_warning("Failed to parse bool '%s'. Ignoring.", e);
34f0e866
LP
1165}
1166
1adf1049
LP
1167LogTarget log_get_target(void) {
1168 return log_target;
1169}
1170
ff524019
ZJS
1171int log_get_max_level_realm(LogRealm realm) {
1172 return log_max_level[realm];
1adf1049
LP
1173}
1174
bbe63281
LP
1175void log_show_color(bool b) {
1176 show_color = b;
1177}
1178
b1e90ec5
ZJS
1179bool log_get_show_color(void) {
1180 return show_color;
1181}
1182
bbe63281
LP
1183void log_show_location(bool b) {
1184 show_location = b;
1185}
1186
b1e90ec5
ZJS
1187bool log_get_show_location(void) {
1188 return show_location;
1189}
1190
bbe63281
LP
1191int log_show_color_from_string(const char *e) {
1192 int t;
1193
5ba081b0
LP
1194 t = parse_boolean(e);
1195 if (t < 0)
1196 return t;
bbe63281
LP
1197
1198 log_show_color(t);
1199 return 0;
1200}
1201
1202int log_show_location_from_string(const char *e) {
1203 int t;
1204
5ba081b0
LP
1205 t = parse_boolean(e);
1206 if (t < 0)
1207 return t;
bbe63281
LP
1208
1209 log_show_location(t);
1210 return 0;
1211}
1212
81270860 1213bool log_on_console(void) {
5b5688af
ZJS
1214 if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1215 LOG_TARGET_CONSOLE_PREFIXED))
81270860
LP
1216 return true;
1217
1218 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1219}
1220
2c5859af 1221static const char *const log_target_table[_LOG_TARGET_MAX] = {
34f0e866 1222 [LOG_TARGET_CONSOLE] = "console",
aca83a53 1223 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
34f0e866 1224 [LOG_TARGET_KMSG] = "kmsg",
5ba081b0
LP
1225 [LOG_TARGET_JOURNAL] = "journal",
1226 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1227 [LOG_TARGET_SYSLOG] = "syslog",
843d2643 1228 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
5ba081b0 1229 [LOG_TARGET_AUTO] = "auto",
6c347d50 1230 [LOG_TARGET_NULL] = "null",
34f0e866
LP
1231};
1232
1233DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
4daf54a8
ZJS
1234
1235void log_received_signal(int level, const struct signalfd_siginfo *si) {
a6ab2365
LP
1236 assert(si);
1237
1238 if (pid_is_valid(si->ssi_pid)) {
4daf54a8
ZJS
1239 _cleanup_free_ char *p = NULL;
1240
a6ab2365 1241 (void) get_process_comm(si->ssi_pid, &p);
4daf54a8
ZJS
1242
1243 log_full(level,
1fa2f38f 1244 "Received SIG%s from PID %"PRIu32" (%s).",
4daf54a8
ZJS
1245 signal_to_string(si->ssi_signo),
1246 si->ssi_pid, strna(p));
1247 } else
1248 log_full(level,
1249 "Received SIG%s.",
1250 signal_to_string(si->ssi_signo));
4daf54a8 1251}
c1dc6153 1252
158350e8
LP
1253int log_syntax_internal(
1254 const char *unit,
1255 int level,
1256 const char *config_file,
1257 unsigned config_line,
1258 int error,
1259 const char *file,
1260 int line,
1261 const char *func,
1262 const char *format, ...) {
1263
1264 PROTECT_ERRNO;
1265 char buffer[LINE_MAX];
158350e8 1266 va_list ap;
c2dec702 1267 const char *unit_fmt = NULL;
158350e8
LP
1268
1269 if (error < 0)
1270 error = -error;
1271
ff524019 1272 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
158350e8
LP
1273 return -error;
1274
1275 if (log_target == LOG_TARGET_NULL)
1276 return -error;
1277
1278 if (error != 0)
1279 errno = error;
1280
1281 va_start(ap, format);
4ad2b562 1282 (void) vsnprintf(buffer, sizeof buffer, format, ap);
158350e8
LP
1283 va_end(ap);
1284
1285 if (unit)
df0ff127 1286 unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
c2dec702
ZJS
1287
1288 return log_struct_internal(
ff524019
ZJS
1289 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
1290 error,
c2dec702 1291 file, line, func,
2b044526 1292 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
c2dec702
ZJS
1293 "CONFIG_FILE=%s", config_file,
1294 "CONFIG_LINE=%u", config_line,
e697dfef 1295 LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
c2dec702
ZJS
1296 unit_fmt, unit,
1297 NULL);
158350e8 1298}
48a601fe 1299
d04ce5a9
LP
1300int log_syntax_invalid_utf8_internal(
1301 const char *unit,
1302 int level,
1303 const char *config_file,
1304 unsigned config_line,
1305 const char *file,
1306 int line,
1307 const char *func,
1308 const char *rvalue) {
1309
1310 _cleanup_free_ char *p = NULL;
1311
1312 if (rvalue)
1313 p = utf8_escape_invalid(rvalue);
1314
1315 log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
1316 "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
1317
1318 return -EINVAL;
1319}
1320
16e4fd87
LP
1321void log_set_upgrade_syslog_to_journal(bool b) {
1322 upgrade_syslog_to_journal = b;
6fdb8de4
LP
1323
1324 /* Make the change effective immediately */
1325 if (b) {
1326 if (log_target == LOG_TARGET_SYSLOG)
1327 log_target = LOG_TARGET_JOURNAL;
1328 else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
1329 log_target = LOG_TARGET_JOURNAL_OR_KMSG;
1330 }
16e4fd87
LP
1331}
1332
48a601fe
LP
1333void log_set_always_reopen_console(bool b) {
1334 always_reopen_console = b;
1335}
16e4fd87
LP
1336
1337void log_set_open_when_needed(bool b) {
1338 open_when_needed = b;
1339}
dccca82b 1340
adf47c91
LP
1341void log_set_prohibit_ipc(bool b) {
1342 prohibit_ipc = b;
1343}
1344
dccca82b
LP
1345int log_emergency_level(void) {
1346 /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1347 * then the system of the whole system is obviously affected. */
1348
1349 return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;
1350}