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