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