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