]> git.proxmox.com Git - systemd.git/blame - src/basic/log.c
New upstream version 249~rc1
[systemd.git] / src / basic / log.c
CommitLineData
a032b68d 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
663996b3 2
663996b3 3#include <errno.h>
663996b3 4#include <fcntl.h>
4c89c718
MP
5#include <inttypes.h>
6#include <limits.h>
db2df898
MP
7#include <stdarg.h>
8#include <stddef.h>
4c89c718 9#include <sys/signalfd.h>
a10f5d05 10#include <sys/stat.h>
4c89c718
MP
11#include <sys/time.h>
12#include <sys/uio.h>
663996b3 13#include <sys/un.h>
db2df898 14#include <unistd.h>
663996b3 15
e3bff60a 16#include "sd-messages.h"
db2df898
MP
17
18#include "alloc-util.h"
bb4f798a 19#include "errno-util.h"
db2df898 20#include "fd-util.h"
2897b343 21#include "format-util.h"
db2df898 22#include "io-util.h"
663996b3 23#include "log.h"
663996b3 24#include "macro.h"
a032b68d 25#include "missing_syscall.h"
db2df898
MP
26#include "parse-util.h"
27#include "proc-cmdline.h"
e3bff60a 28#include "process-util.h"
e1f67bc7 29#include "ratelimit.h"
86f210e9 30#include "signal-util.h"
db2df898
MP
31#include "socket-util.h"
32#include "stdio-util.h"
33#include "string-table.h"
34#include "string-util.h"
35#include "syslog-util.h"
36#include "terminal-util.h"
4c89c718 37#include "time-util.h"
1d42b86d 38#include "utf8.h"
663996b3
MS
39
40#define SNDBUF_SIZE (8*1024*1024)
41
42static LogTarget log_target = LOG_TARGET_CONSOLE;
3a6ce677 43static int log_max_level = LOG_INFO;
663996b3
MS
44static int log_facility = LOG_DAEMON;
45
46static int console_fd = STDERR_FILENO;
47static int syslog_fd = -1;
48static int kmsg_fd = -1;
49static int journal_fd = -1;
50
51static bool syslog_is_stream = false;
52
3a6ce677 53static int show_color = -1; /* tristate */
663996b3 54static bool show_location = false;
a10f5d05 55static bool show_time = false;
a032b68d 56static bool show_tid = false;
663996b3 57
5eef597e 58static bool upgrade_syslog_to_journal = false;
2897b343 59static bool always_reopen_console = false;
f5e65279 60static bool open_when_needed = false;
1d42b86d 61static bool prohibit_ipc = false;
5eef597e 62
663996b3
MS
63/* Akin to glibc's __abort_msg; which is private and we hence cannot
64 * use here. */
65static char *log_abort_msg = NULL;
66
98393f85
MB
67/* An assert to use in logging functions that does not call recursively
68 * into our logging functions (since that might lead to a loop). */
69#define assert_raw(expr) \
70 do { \
71 if (_unlikely_(!(expr))) { \
72 fputs(#expr "\n", stderr); \
73 abort(); \
74 } \
75 } while (false)
663996b3 76
98393f85
MB
77static void log_close_console(void) {
78 console_fd = safe_close_above_stdio(console_fd);
663996b3
MS
79}
80
81static int log_open_console(void) {
82
1d42b86d
MB
83 if (!always_reopen_console) {
84 console_fd = STDERR_FILENO;
663996b3 85 return 0;
1d42b86d 86 }
663996b3 87
1d42b86d 88 if (console_fd < 3) {
c5fca32e 89 int fd;
98393f85 90
c5fca32e
MB
91 fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
92 if (fd < 0)
93 return fd;
94
95 console_fd = fd_move_above_stdio(fd);
1d42b86d 96 }
663996b3
MS
97
98 return 0;
99}
100
1d42b86d 101static void log_close_kmsg(void) {
60f067b4 102 kmsg_fd = safe_close(kmsg_fd);
663996b3
MS
103}
104
105static int log_open_kmsg(void) {
106
107 if (kmsg_fd >= 0)
108 return 0;
109
110 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
111 if (kmsg_fd < 0)
112 return -errno;
113
98393f85 114 kmsg_fd = fd_move_above_stdio(kmsg_fd);
663996b3
MS
115 return 0;
116}
117
1d42b86d 118static void log_close_syslog(void) {
60f067b4 119 syslog_fd = safe_close(syslog_fd);
663996b3
MS
120}
121
122static int create_log_socket(int type) {
14228c0d 123 struct timeval tv;
f47781d8 124 int fd;
663996b3 125
14228c0d 126 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
663996b3
MS
127 if (fd < 0)
128 return -errno;
129
98393f85 130 fd = fd_move_above_stdio(fd);
8a584da2 131 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
663996b3 132
98393f85
MB
133 /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
134 * in the unlikely case of a deadlock. */
f5e65279 135 if (getpid_cached() == 1)
60f067b4
JS
136 timeval_store(&tv, 10 * USEC_PER_MSEC);
137 else
138 timeval_store(&tv, 10 * USEC_PER_SEC);
f47781d8 139 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
14228c0d 140
663996b3
MS
141 return fd;
142}
143
144static int log_open_syslog(void) {
f47781d8
MP
145
146 static const union sockaddr_union sa = {
663996b3
MS
147 .un.sun_family = AF_UNIX,
148 .un.sun_path = "/dev/log",
149 };
150
f47781d8
MP
151 int r;
152
663996b3
MS
153 if (syslog_fd >= 0)
154 return 0;
155
156 syslog_fd = create_log_socket(SOCK_DGRAM);
157 if (syslog_fd < 0) {
158 r = syslog_fd;
159 goto fail;
160 }
161
aa27b158 162 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
60f067b4 163 safe_close(syslog_fd);
663996b3
MS
164
165 /* Some legacy syslog systems still use stream
166 * sockets. They really shouldn't. But what can we
167 * do... */
168 syslog_fd = create_log_socket(SOCK_STREAM);
169 if (syslog_fd < 0) {
170 r = syslog_fd;
171 goto fail;
172 }
173
aa27b158 174 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
663996b3
MS
175 r = -errno;
176 goto fail;
177 }
178
179 syslog_is_stream = true;
180 } else
181 syslog_is_stream = false;
182
183 return 0;
184
185fail:
186 log_close_syslog();
187 return r;
188}
189
1d42b86d 190static void log_close_journal(void) {
60f067b4 191 journal_fd = safe_close(journal_fd);
663996b3
MS
192}
193
194static int log_open_journal(void) {
f47781d8
MP
195
196 static const union sockaddr_union sa = {
663996b3
MS
197 .un.sun_family = AF_UNIX,
198 .un.sun_path = "/run/systemd/journal/socket",
199 };
f47781d8 200
663996b3
MS
201 int r;
202
203 if (journal_fd >= 0)
204 return 0;
205
206 journal_fd = create_log_socket(SOCK_DGRAM);
207 if (journal_fd < 0) {
208 r = journal_fd;
209 goto fail;
210 }
211
aa27b158 212 if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
663996b3
MS
213 r = -errno;
214 goto fail;
215 }
216
217 return 0;
218
219fail:
220 log_close_journal();
221 return r;
222}
223
a10f5d05
MB
224static bool stderr_is_journal(void) {
225 _cleanup_free_ char *w = NULL;
226 const char *e;
227 uint64_t dev, ino;
228 struct stat st;
229
230 e = getenv("JOURNAL_STREAM");
231 if (!e)
232 return false;
233
234 if (extract_first_word(&e, &w, ":", EXTRACT_DONT_COALESCE_SEPARATORS) <= 0)
235 return false;
236 if (!e)
237 return false;
238
239 if (safe_atou64(w, &dev) < 0)
240 return false;
241 if (safe_atou64(e, &ino) < 0)
242 return false;
243
244 if (fstat(STDERR_FILENO, &st) < 0)
245 return false;
246
247 return st.st_dev == dev && st.st_ino == ino;
248}
249
663996b3
MS
250int log_open(void) {
251 int r;
252
81c58355
MB
253 /* Do not call from library code. */
254
3a6ce677
BR
255 /* This function is often called in preparation for logging. Let's make sure we don't clobber errno,
256 * so that a call to a logging function immediately following a log_open() call can still easily
257 * reference an error that happened immediately before the log_open() call. */
258 PROTECT_ERRNO;
259
260 /* If we don't use the console, we close it here to not get killed by SAK. If we don't use syslog, we
261 * close it here too, so that we are not confused by somebody deleting the socket in the fs, and to
262 * make sure we don't use it if prohibit_ipc is set. If we don't use /dev/kmsg we still keep it open,
663996b3
MS
263 * because there is no reason to close it. */
264
265 if (log_target == LOG_TARGET_NULL) {
266 log_close_journal();
267 log_close_syslog();
268 log_close_console();
269 return 0;
270 }
271
a032b68d
MB
272 if (getpid_cached() == 1 ||
273 stderr_is_journal() ||
274 IN_SET(log_target,
275 LOG_TARGET_KMSG,
276 LOG_TARGET_JOURNAL,
277 LOG_TARGET_JOURNAL_OR_KMSG,
278 LOG_TARGET_SYSLOG,
279 LOG_TARGET_SYSLOG_OR_KMSG)) {
280
281 if (!prohibit_ipc) {
282 if (IN_SET(log_target,
283 LOG_TARGET_AUTO,
284 LOG_TARGET_JOURNAL_OR_KMSG,
285 LOG_TARGET_JOURNAL)) {
286
287 r = log_open_journal();
288 if (r >= 0) {
289 log_close_syslog();
290 log_close_console();
291 return r;
292 }
663996b3 293 }
663996b3 294
a032b68d
MB
295 if (IN_SET(log_target,
296 LOG_TARGET_SYSLOG_OR_KMSG,
297 LOG_TARGET_SYSLOG)) {
298
299 r = log_open_syslog();
300 if (r >= 0) {
301 log_close_journal();
302 log_close_console();
303 return r;
304 }
663996b3
MS
305 }
306 }
307
2897b343 308 if (IN_SET(log_target, LOG_TARGET_AUTO,
2897b343
MP
309 LOG_TARGET_JOURNAL_OR_KMSG,
310 LOG_TARGET_SYSLOG_OR_KMSG,
311 LOG_TARGET_KMSG)) {
663996b3
MS
312 r = log_open_kmsg();
313 if (r >= 0) {
314 log_close_journal();
315 log_close_syslog();
316 log_close_console();
317 return r;
318 }
319 }
320 }
321
322 log_close_journal();
323 log_close_syslog();
324
663996b3
MS
325 return log_open_console();
326}
327
328void log_set_target(LogTarget target) {
329 assert(target >= 0);
330 assert(target < _LOG_TARGET_MAX);
331
5eef597e
MP
332 if (upgrade_syslog_to_journal) {
333 if (target == LOG_TARGET_SYSLOG)
334 target = LOG_TARGET_JOURNAL;
335 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
336 target = LOG_TARGET_JOURNAL_OR_KMSG;
337 }
338
663996b3
MS
339 log_target = target;
340}
341
342void log_close(void) {
81c58355
MB
343 /* Do not call from library code. */
344
663996b3
MS
345 log_close_journal();
346 log_close_syslog();
347 log_close_kmsg();
348 log_close_console();
349}
350
351void log_forget_fds(void) {
81c58355
MB
352 /* Do not call from library code. */
353
663996b3
MS
354 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
355}
356
3a6ce677 357void log_set_max_level(int level) {
663996b3
MS
358 assert((level & LOG_PRIMASK) == level);
359
3a6ce677 360 log_max_level = level;
663996b3
MS
361}
362
363void log_set_facility(int facility) {
364 log_facility = facility;
365}
366
367static int write_to_console(
368 int level,
f47781d8
MP
369 int error,
370 const char *file,
663996b3
MS
371 int line,
372 const char *func,
663996b3
MS
373 const char *buffer) {
374
a10f5d05
MB
375 char location[256],
376 header_time[FORMAT_TIMESTAMP_MAX],
a032b68d
MB
377 prefix[1 + DECIMAL_STR_MAX(int) + 2],
378 tid_string[3 + DECIMAL_STR_MAX(pid_t) + 1];
379 struct iovec iovec[9];
f2dec872 380 const char *on = NULL, *off = NULL;
b012e921 381 size_t n = 0;
663996b3
MS
382
383 if (console_fd < 0)
384 return 0;
385
e735f4d4 386 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
8a584da2 387 xsprintf(prefix, "<%i>", level);
f5e65279 388 iovec[n++] = IOVEC_MAKE_STRING(prefix);
e735f4d4
MP
389 }
390
3a6ce677
BR
391 if (show_time &&
392 format_timestamp(header_time, sizeof(header_time), now(CLOCK_REALTIME))) {
393 iovec[n++] = IOVEC_MAKE_STRING(header_time);
394 iovec[n++] = IOVEC_MAKE_STRING(" ");
a10f5d05
MB
395 }
396
a032b68d
MB
397 if (show_tid) {
398 xsprintf(tid_string, "(" PID_FMT ") ", gettid());
399 iovec[n++] = IOVEC_MAKE_STRING(tid_string);
400 }
401
3a6ce677 402 if (log_get_show_color())
f2dec872 403 get_log_colors(LOG_PRI(level), &on, &off, NULL);
663996b3
MS
404
405 if (show_location) {
f2dec872 406 const char *lon = "", *loff = "";
3a6ce677
BR
407 if (log_get_show_color()) {
408 lon = ansi_highlight_yellow4();
409 loff = ansi_normal();
f2dec872
BR
410 }
411
412 (void) snprintf(location, sizeof location, "%s%s:%i%s: ", lon, file, line, loff);
f5e65279 413 iovec[n++] = IOVEC_MAKE_STRING(location);
663996b3
MS
414 }
415
f2dec872
BR
416 if (on)
417 iovec[n++] = IOVEC_MAKE_STRING(on);
f5e65279 418 iovec[n++] = IOVEC_MAKE_STRING(buffer);
f2dec872
BR
419 if (off)
420 iovec[n++] = IOVEC_MAKE_STRING(off);
f5e65279 421 iovec[n++] = IOVEC_MAKE_STRING("\n");
663996b3 422
60f067b4
JS
423 if (writev(console_fd, iovec, n) < 0) {
424
f5e65279 425 if (errno == EIO && getpid_cached() == 1) {
60f067b4 426
c5fca32e
MB
427 /* If somebody tried to kick us from our console tty (via vhangup() or suchlike), try
428 * to reconnect. */
60f067b4
JS
429
430 log_close_console();
c5fca32e 431 (void) log_open_console();
60f067b4
JS
432 if (console_fd < 0)
433 return 0;
434
435 if (writev(console_fd, iovec, n) < 0)
436 return -errno;
437 } else
438 return -errno;
439 }
663996b3
MS
440
441 return 1;
442}
443
444static int write_to_syslog(
f47781d8
MP
445 int level,
446 int error,
447 const char *file,
448 int line,
449 const char *func,
f47781d8 450 const char *buffer) {
663996b3 451
e735f4d4
MP
452 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
453 header_time[64],
454 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
663996b3 455 time_t t;
6e866b33 456 struct tm tm;
663996b3
MS
457
458 if (syslog_fd < 0)
459 return 0;
460
e735f4d4 461 xsprintf(header_priority, "<%i>", level);
663996b3
MS
462
463 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
6e866b33 464 if (!localtime_r(&t, &tm))
663996b3
MS
465 return -EINVAL;
466
6e866b33 467 if (strftime(header_time, sizeof(header_time), "%h %e %T ", &tm) <= 0)
663996b3
MS
468 return -EINVAL;
469
f5e65279 470 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
663996b3 471
8b3d4ff0
MB
472 struct iovec iovec[] = {
473 IOVEC_MAKE_STRING(header_priority),
474 IOVEC_MAKE_STRING(header_time),
475 IOVEC_MAKE_STRING(program_invocation_short_name),
476 IOVEC_MAKE_STRING(header_pid),
477 IOVEC_MAKE_STRING(buffer),
478 };
479 struct msghdr msghdr = {
480 .msg_iov = iovec,
481 .msg_iovlen = ELEMENTSOF(iovec),
482 };
663996b3
MS
483
484 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
485 if (syslog_is_stream)
8b3d4ff0 486 iovec[ELEMENTSOF(iovec) - 1].iov_len++;
663996b3
MS
487
488 for (;;) {
489 ssize_t n;
490
491 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
492 if (n < 0)
493 return -errno;
494
8b3d4ff0 495 if (!syslog_is_stream)
663996b3
MS
496 break;
497
8b3d4ff0
MB
498 if (IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n))
499 break;
663996b3
MS
500 }
501
502 return 1;
503}
504
505static int write_to_kmsg(
f47781d8
MP
506 int level,
507 int error,
db2df898 508 const char *file,
f47781d8
MP
509 int line,
510 const char *func,
f47781d8 511 const char *buffer) {
663996b3 512
e1f67bc7
MB
513 /* Set a ratelimit on the amount of messages logged to /dev/kmsg. This is mostly supposed to be a
514 * safety catch for the case where start indiscriminately logging in a loop. It will not catch cases
515 * where we log excessively, but not in a tight loop.
516 *
517 * Note that this ratelimit is per-emitter, so we might still overwhelm /dev/kmsg with multiple
518 * loggers.
519 */
520 static thread_local RateLimit ratelimit = { 5 * USEC_PER_SEC, 200 };
521
e735f4d4
MP
522 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
523 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
663996b3
MS
524
525 if (kmsg_fd < 0)
526 return 0;
527
e1f67bc7
MB
528 if (!ratelimit_below(&ratelimit))
529 return 0;
530
e735f4d4 531 xsprintf(header_priority, "<%i>", level);
f5e65279 532 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
663996b3 533
8b3d4ff0
MB
534 const struct iovec iovec[] = {
535 IOVEC_MAKE_STRING(header_priority),
536 IOVEC_MAKE_STRING(program_invocation_short_name),
537 IOVEC_MAKE_STRING(header_pid),
538 IOVEC_MAKE_STRING(buffer),
539 IOVEC_MAKE_STRING("\n"),
540 };
663996b3
MS
541
542 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
543 return -errno;
544
545 return 1;
546}
547
f47781d8
MP
548static int log_do_header(
549 char *header,
550 size_t size,
551 int level,
552 int error,
553 const char *file, int line, const char *func,
8a584da2
MP
554 const char *object_field, const char *object,
555 const char *extra_field, const char *extra) {
98393f85 556 int r;
f47781d8 557
6e866b33
MB
558 error = IS_SYNTHETIC_ERRNO(error) ? 0 : ERRNO_VALUE(error);
559
98393f85
MB
560 r = snprintf(header, size,
561 "PRIORITY=%i\n"
562 "SYSLOG_FACILITY=%i\n"
a032b68d 563 "TID=" PID_FMT "\n"
98393f85
MB
564 "%s%.256s%s" /* CODE_FILE */
565 "%s%.*i%s" /* CODE_LINE */
566 "%s%.256s%s" /* CODE_FUNC */
567 "%s%.*i%s" /* ERRNO */
568 "%s%.256s%s" /* object */
569 "%s%.256s%s" /* extra */
570 "SYSLOG_IDENTIFIER=%.256s\n",
571 LOG_PRI(level),
572 LOG_FAC(level),
a032b68d 573 gettid(),
98393f85
MB
574 isempty(file) ? "" : "CODE_FILE=",
575 isempty(file) ? "" : file,
576 isempty(file) ? "" : "\n",
577 line ? "CODE_LINE=" : "",
578 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
579 line ? "\n" : "",
580 isempty(func) ? "" : "CODE_FUNC=",
581 isempty(func) ? "" : func,
582 isempty(func) ? "" : "\n",
583 error ? "ERRNO=" : "",
584 error ? 1 : 0, error,
585 error ? "\n" : "",
586 isempty(object) ? "" : object_field,
587 isempty(object) ? "" : object,
588 isempty(object) ? "" : "\n",
589 isempty(extra) ? "" : extra_field,
590 isempty(extra) ? "" : extra,
591 isempty(extra) ? "" : "\n",
592 program_invocation_short_name);
593 assert_raw((size_t) r < size);
f47781d8 594
663996b3
MS
595 return 0;
596}
597
598static int write_to_journal(
f47781d8
MP
599 int level,
600 int error,
db2df898 601 const char *file,
f47781d8
MP
602 int line,
603 const char *func,
604 const char *object_field,
605 const char *object,
8a584da2
MP
606 const char *extra_field,
607 const char *extra,
f47781d8 608 const char *buffer) {
663996b3
MS
609
610 char header[LINE_MAX];
611 struct iovec iovec[4] = {};
612 struct msghdr mh = {};
613
614 if (journal_fd < 0)
615 return 0;
616
8a584da2 617 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
663996b3 618
f5e65279
MB
619 iovec[0] = IOVEC_MAKE_STRING(header);
620 iovec[1] = IOVEC_MAKE_STRING("MESSAGE=");
621 iovec[2] = IOVEC_MAKE_STRING(buffer);
622 iovec[3] = IOVEC_MAKE_STRING("\n");
663996b3
MS
623
624 mh.msg_iov = iovec;
625 mh.msg_iovlen = ELEMENTSOF(iovec);
626
627 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
628 return -errno;
629
630 return 1;
631}
632
81c58355 633int log_dispatch_internal(
f47781d8
MP
634 int level,
635 int error,
636 const char *file,
637 int line,
638 const char *func,
639 const char *object_field,
640 const char *object,
8a584da2 641 const char *extra_field,
98393f85 642 const char *extra,
f47781d8 643 char *buffer) {
663996b3 644
98393f85 645 assert_raw(buffer);
663996b3
MS
646
647 if (log_target == LOG_TARGET_NULL)
6e866b33 648 return -ERRNO_VALUE(error);
663996b3
MS
649
650 /* Patch in LOG_DAEMON facility if necessary */
651 if ((level & LOG_FACMASK) == 0)
6e866b33 652 level |= log_facility;
663996b3 653
f5e65279 654 if (open_when_needed)
c5fca32e 655 (void) log_open();
f5e65279 656
663996b3
MS
657 do {
658 char *e;
659 int k = 0;
660
661 buffer += strspn(buffer, NEWLINE);
662
663 if (buffer[0] == 0)
664 break;
665
666 if ((e = strpbrk(buffer, NEWLINE)))
667 *(e++) = 0;
668
2897b343
MP
669 if (IN_SET(log_target, LOG_TARGET_AUTO,
670 LOG_TARGET_JOURNAL_OR_KMSG,
671 LOG_TARGET_JOURNAL)) {
663996b3 672
8a584da2 673 k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
98393f85
MB
674 if (k < 0 && k != -EAGAIN)
675 log_close_journal();
663996b3
MS
676 }
677
2897b343
MP
678 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
679 LOG_TARGET_SYSLOG)) {
663996b3 680
8a584da2 681 k = write_to_syslog(level, error, file, line, func, buffer);
98393f85
MB
682 if (k < 0 && k != -EAGAIN)
683 log_close_syslog();
663996b3
MS
684 }
685
686 if (k <= 0 &&
2897b343 687 IN_SET(log_target, LOG_TARGET_AUTO,
2897b343
MP
688 LOG_TARGET_SYSLOG_OR_KMSG,
689 LOG_TARGET_JOURNAL_OR_KMSG,
690 LOG_TARGET_KMSG)) {
663996b3 691
98393f85
MB
692 if (k < 0)
693 log_open_kmsg();
694
8a584da2 695 k = write_to_kmsg(level, error, file, line, func, buffer);
663996b3
MS
696 if (k < 0) {
697 log_close_kmsg();
c5fca32e 698 (void) log_open_console();
f47781d8 699 }
663996b3
MS
700 }
701
f47781d8 702 if (k <= 0)
8a584da2 703 (void) write_to_console(level, error, file, line, func, buffer);
663996b3
MS
704
705 buffer = e;
706 } while (buffer);
707
f5e65279
MB
708 if (open_when_needed)
709 log_close();
710
6e866b33 711 return -ERRNO_VALUE(error);
663996b3
MS
712}
713
714int log_dump_internal(
81c58355
MB
715 int level,
716 int error,
717 const char *file,
718 int line,
719 const char *func,
720 char *buffer) {
663996b3
MS
721
722 PROTECT_ERRNO;
723
724 /* This modifies the buffer... */
725
3a6ce677 726 if (_likely_(LOG_PRI(level) > log_max_level))
6e866b33 727 return -ERRNO_VALUE(error);
663996b3 728
81c58355 729 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
663996b3
MS
730}
731
3a6ce677 732int log_internalv(
f47781d8
MP
733 int level,
734 int error,
db2df898 735 const char *file,
f47781d8
MP
736 int line,
737 const char *func,
738 const char *format,
739 va_list ap) {
663996b3 740
663996b3 741 char buffer[LINE_MAX];
81c58355 742 PROTECT_ERRNO;
663996b3 743
3a6ce677 744 if (_likely_(LOG_PRI(level) > log_max_level))
6e866b33 745 return -ERRNO_VALUE(error);
f47781d8 746
b012e921 747 /* Make sure that %m maps to the specified error (or "Success"). */
6e866b33 748 errno = ERRNO_VALUE(error);
663996b3 749
98393f85 750 (void) vsnprintf(buffer, sizeof buffer, format, ap);
663996b3 751
81c58355 752 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
663996b3
MS
753}
754
3a6ce677 755int log_internal(
f47781d8
MP
756 int level,
757 int error,
db2df898 758 const char *file,
f47781d8
MP
759 int line,
760 const char *func,
761 const char *format, ...) {
663996b3 762
663996b3 763 va_list ap;
f47781d8 764 int r;
663996b3
MS
765
766 va_start(ap, format);
3a6ce677 767 r = log_internalv(level, error, file, line, func, format, ap);
663996b3
MS
768 va_end(ap);
769
770 return r;
771}
772
bb4f798a 773int log_object_internalv(
f47781d8
MP
774 int level,
775 int error,
db2df898 776 const char *file,
f47781d8
MP
777 int line,
778 const char *func,
779 const char *object_field,
780 const char *object,
8a584da2
MP
781 const char *extra_field,
782 const char *extra,
f47781d8
MP
783 const char *format,
784 va_list ap) {
663996b3
MS
785
786 PROTECT_ERRNO;
e3bff60a 787 char *buffer, *b;
663996b3 788
3a6ce677 789 if (_likely_(LOG_PRI(level) > log_max_level))
6e866b33 790 return -ERRNO_VALUE(error);
f47781d8 791
b012e921 792 /* Make sure that %m maps to the specified error (or "Success"). */
6e866b33 793 errno = ERRNO_VALUE(error);
663996b3 794
e3bff60a
MP
795 /* Prepend the object name before the message */
796 if (object) {
797 size_t n;
798
799 n = strlen(object);
81c58355 800 buffer = newa(char, n + 2 + LINE_MAX);
e3bff60a 801 b = stpcpy(stpcpy(buffer, object), ": ");
81c58355
MB
802 } else
803 b = buffer = newa(char, LINE_MAX);
e3bff60a 804
98393f85 805 (void) vsnprintf(b, LINE_MAX, format, ap);
663996b3 806
81c58355
MB
807 return log_dispatch_internal(level, error, file, line, func,
808 object_field, object, extra_field, extra, buffer);
663996b3
MS
809}
810
f47781d8
MP
811int log_object_internal(
812 int level,
813 int error,
db2df898 814 const char *file,
f47781d8
MP
815 int line,
816 const char *func,
817 const char *object_field,
818 const char *object,
8a584da2
MP
819 const char *extra_field,
820 const char *extra,
f47781d8 821 const char *format, ...) {
663996b3 822
663996b3 823 va_list ap;
f47781d8 824 int r;
663996b3
MS
825
826 va_start(ap, format);
8a584da2 827 r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
663996b3
MS
828 va_end(ap);
829
830 return r;
831}
832
f47781d8
MP
833static void log_assert(
834 int level,
835 const char *text,
836 const char *file,
837 int line,
838 const char *func,
839 const char *format) {
840
663996b3
MS
841 static char buffer[LINE_MAX];
842
3a6ce677 843 if (_likely_(LOG_PRI(level) > log_max_level))
60f067b4
JS
844 return;
845
846 DISABLE_WARNING_FORMAT_NONLITERAL;
98393f85 847 (void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
60f067b4 848 REENABLE_WARNING;
663996b3 849
663996b3
MS
850 log_abort_msg = buffer;
851
81c58355 852 log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
60f067b4
JS
853}
854
3a6ce677 855_noreturn_ void log_assert_failed(
81c58355
MB
856 const char *text,
857 const char *file,
858 int line,
859 const char *func) {
3a6ce677 860 log_assert(LOG_CRIT, text, file, line, func,
81c58355 861 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
663996b3
MS
862 abort();
863}
663996b3 864
3a6ce677 865_noreturn_ void log_assert_failed_unreachable(
81c58355
MB
866 const char *text,
867 const char *file,
868 int line,
869 const char *func) {
3a6ce677 870 log_assert(LOG_CRIT, text, file, line, func,
81c58355 871 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
60f067b4 872 abort();
663996b3
MS
873}
874
3a6ce677 875void log_assert_failed_return(
81c58355
MB
876 const char *text,
877 const char *file,
878 int line,
879 const char *func) {
60f067b4 880 PROTECT_ERRNO;
3a6ce677 881 log_assert(LOG_DEBUG, text, file, line, func,
81c58355 882 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
663996b3
MS
883}
884
3a6ce677
BR
885int log_oom_internal(int level, const char *file, int line, const char *func) {
886 return log_internal(level, ENOMEM, file, line, func, "Out of memory.");
663996b3
MS
887}
888
4c89c718
MP
889int log_format_iovec(
890 struct iovec *iovec,
52ad194e
MB
891 size_t iovec_len,
892 size_t *n,
4c89c718
MP
893 bool newline_separator,
894 int error,
895 const char *format,
896 va_list ap) {
897
898 static const char nl = '\n';
899
900 while (format && *n + 1 < iovec_len) {
901 va_list aq;
902 char *m;
903 int r;
904
905 /* We need to copy the va_list structure,
906 * since vasprintf() leaves it afterwards at
907 * an undefined location */
908
6e866b33 909 errno = ERRNO_VALUE(error);
4c89c718
MP
910
911 va_copy(aq, ap);
912 r = vasprintf(&m, format, aq);
913 va_end(aq);
914 if (r < 0)
915 return -EINVAL;
916
917 /* Now, jump enough ahead, so that we point to
918 * the next format string */
919 VA_FORMAT_ADVANCE(format, ap);
920
f5e65279 921 iovec[(*n)++] = IOVEC_MAKE_STRING(m);
4c89c718
MP
922
923 if (newline_separator) {
6e866b33 924 iovec[*n] = IOVEC_MAKE((char *)&nl, 1);
4c89c718
MP
925 (*n)++;
926 }
927
928 format = va_arg(ap, char *);
929 }
930 return 0;
931}
932
663996b3
MS
933int log_struct_internal(
934 int level,
f47781d8 935 int error,
663996b3
MS
936 const char *file,
937 int line,
938 const char *func,
939 const char *format, ...) {
940
f47781d8
MP
941 char buf[LINE_MAX];
942 bool found = false;
663996b3
MS
943 PROTECT_ERRNO;
944 va_list ap;
f47781d8 945
3a6ce677 946 if (_likely_(LOG_PRI(level) > log_max_level) ||
6e866b33
MB
947 log_target == LOG_TARGET_NULL)
948 return -ERRNO_VALUE(error);
663996b3
MS
949
950 if ((level & LOG_FACMASK) == 0)
6e866b33 951 level |= log_facility;
663996b3 952
f5e65279
MB
953 if (IN_SET(log_target,
954 LOG_TARGET_AUTO,
955 LOG_TARGET_JOURNAL_OR_KMSG,
956 LOG_TARGET_JOURNAL)) {
957
958 if (open_when_needed)
959 log_open_journal();
960
961 if (journal_fd >= 0) {
962 char header[LINE_MAX];
963 struct iovec iovec[17] = {};
8b3d4ff0 964 size_t n = 0;
f5e65279
MB
965 int r;
966 struct msghdr mh = {
967 .msg_iov = iovec,
968 };
969 bool fallback = false;
970
6e866b33
MB
971 /* If the journal is available do structured logging.
972 * Do not report the errno if it is synthetic. */
f5e65279
MB
973 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
974 iovec[n++] = IOVEC_MAKE_STRING(header);
975
976 va_start(ap, format);
977 r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
978 if (r < 0)
979 fallback = true;
980 else {
981 mh.msg_iovlen = n;
982 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
983 }
663996b3 984
f5e65279 985 va_end(ap);
8b3d4ff0 986 for (size_t i = 1; i < n; i += 2)
f5e65279 987 free(iovec[i].iov_base);
663996b3 988
f5e65279
MB
989 if (!fallback) {
990 if (open_when_needed)
991 log_close();
663996b3 992
6e866b33 993 return -ERRNO_VALUE(error);
f5e65279
MB
994 }
995 }
f47781d8 996 }
663996b3 997
f47781d8 998 /* Fallback if journal logging is not available or didn't work. */
663996b3 999
f47781d8
MP
1000 va_start(ap, format);
1001 while (format) {
1002 va_list aq;
663996b3 1003
6e866b33 1004 errno = ERRNO_VALUE(error);
663996b3 1005
f47781d8 1006 va_copy(aq, ap);
98393f85 1007 (void) vsnprintf(buf, sizeof buf, format, aq);
f47781d8 1008 va_end(aq);
663996b3 1009
f47781d8
MP
1010 if (startswith(buf, "MESSAGE=")) {
1011 found = true;
1012 break;
663996b3 1013 }
663996b3 1014
f47781d8
MP
1015 VA_FORMAT_ADVANCE(format, ap);
1016
1017 format = va_arg(ap, char *);
663996b3 1018 }
f47781d8 1019 va_end(ap);
663996b3 1020
f5e65279
MB
1021 if (!found) {
1022 if (open_when_needed)
1023 log_close();
1024
6e866b33 1025 return -ERRNO_VALUE(error);
f5e65279 1026 }
f47781d8 1027
81c58355 1028 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
663996b3
MS
1029}
1030
f5e65279
MB
1031int log_struct_iovec_internal(
1032 int level,
1033 int error,
1034 const char *file,
1035 int line,
1036 const char *func,
1037 const struct iovec input_iovec[],
1038 size_t n_input_iovec) {
1039
f5e65279
MB
1040 PROTECT_ERRNO;
1041 size_t i;
1042 char *m;
1043
3a6ce677 1044 if (_likely_(LOG_PRI(level) > log_max_level) ||
6e866b33
MB
1045 log_target == LOG_TARGET_NULL)
1046 return -ERRNO_VALUE(error);
f5e65279
MB
1047
1048 if ((level & LOG_FACMASK) == 0)
6e866b33 1049 level |= log_facility;
f5e65279
MB
1050
1051 if (IN_SET(log_target, LOG_TARGET_AUTO,
1052 LOG_TARGET_JOURNAL_OR_KMSG,
1053 LOG_TARGET_JOURNAL) &&
1054 journal_fd >= 0) {
1055
1056 struct iovec iovec[1 + n_input_iovec*2];
1057 char header[LINE_MAX];
1058 struct msghdr mh = {
1059 .msg_iov = iovec,
1060 .msg_iovlen = 1 + n_input_iovec*2,
1061 };
1062
1063 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
1064 iovec[0] = IOVEC_MAKE_STRING(header);
1065
1066 for (i = 0; i < n_input_iovec; i++) {
1067 iovec[1+i*2] = input_iovec[i];
1068 iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
1069 }
1070
1071 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0)
6e866b33 1072 return -ERRNO_VALUE(error);
f5e65279
MB
1073 }
1074
b012e921
MB
1075 for (i = 0; i < n_input_iovec; i++)
1076 if (memory_startswith(input_iovec[i].iov_base, input_iovec[i].iov_len, "MESSAGE="))
f5e65279 1077 break;
f5e65279
MB
1078
1079 if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
6e866b33 1080 return -ERRNO_VALUE(error);
f5e65279 1081
52ad194e
MB
1082 m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
1083 input_iovec[i].iov_len - STRLEN("MESSAGE="));
f5e65279
MB
1084
1085 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
1086}
1087
663996b3
MS
1088int log_set_target_from_string(const char *e) {
1089 LogTarget t;
1090
1091 t = log_target_from_string(e);
1092 if (t < 0)
3a6ce677 1093 return t;
663996b3
MS
1094
1095 log_set_target(t);
1096 return 0;
1097}
1098
3a6ce677 1099int log_set_max_level_from_string(const char *e) {
663996b3
MS
1100 int t;
1101
1102 t = log_level_from_string(e);
1103 if (t < 0)
3a6ce677 1104 return t;
663996b3 1105
3a6ce677 1106 log_set_max_level(t);
663996b3
MS
1107 return 0;
1108}
1109
8a584da2 1110static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
60f067b4 1111
5eef597e
MP
1112 /*
1113 * The systemd.log_xyz= settings are parsed by all tools, and
1114 * so is "debug".
1115 *
e735f4d4
MP
1116 * However, "quiet" is only parsed by PID 1, and only turns of
1117 * status output to /dev/console, but does not alter the log
1118 * level.
5eef597e 1119 */
60f067b4 1120
5eef597e
MP
1121 if (streq(key, "debug") && !value)
1122 log_set_max_level(LOG_DEBUG);
1123
2897b343
MP
1124 else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1125
1126 if (proc_cmdline_value_missing(key, value))
1127 return 0;
5eef597e
MP
1128
1129 if (log_set_target_from_string(value) < 0)
1130 log_warning("Failed to parse log target '%s'. Ignoring.", value);
1131
2897b343
MP
1132 } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1133
1134 if (proc_cmdline_value_missing(key, value))
1135 return 0;
5eef597e
MP
1136
1137 if (log_set_max_level_from_string(value) < 0)
1138 log_warning("Failed to parse log level '%s'. Ignoring.", value);
1139
2897b343 1140 } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
5eef597e 1141
2897b343 1142 if (log_show_color_from_string(value ?: "1") < 0)
5eef597e
MP
1143 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1144
2897b343 1145 } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
5eef597e 1146
2897b343 1147 if (log_show_location_from_string(value ?: "1") < 0)
5eef597e 1148 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
a10f5d05 1149
a032b68d
MB
1150 } else if (proc_cmdline_key_streq(key, "systemd.log_tid")) {
1151
1152 if (log_show_tid_from_string(value ?: "1") < 0)
1153 log_warning("Failed to parse log tid setting '%s'. Ignoring.", value);
1154
a10f5d05
MB
1155 } else if (proc_cmdline_key_streq(key, "systemd.log_time")) {
1156
1157 if (log_show_time_from_string(value ?: "1") < 0)
1158 log_warning("Failed to parse log time setting '%s'. Ignoring.", value);
1159
60f067b4 1160 }
663996b3 1161
5eef597e
MP
1162 return 0;
1163}
1164
3a6ce677
BR
1165static bool should_parse_proc_cmdline(void) {
1166 const char *e;
1167 pid_t p;
1168
1169 /* PID1 always reads the kernel command line. */
1170 if (getpid_cached() == 1)
1171 return true;
1172
1173 /* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
1174 * or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
1175 e = getenv("SYSTEMD_EXEC_PID");
1176 if (!e)
1177 return false;
5eef597e 1178
3a6ce677
BR
1179 if (streq(e, "*"))
1180 /* For testing. */
1181 return true;
1182
1183 if (parse_pid(e, &p) < 0) {
1184 /* We know that systemd sets the variable correctly. Something else must have set it. */
1185 log_debug("Failed to parse \"$SYSTEMD_EXEC_PID=%s\". Ignoring.", e);
1186 return false;
1187 }
1188
1189 return getpid_cached() == p;
a10f5d05
MB
1190}
1191
3a6ce677
BR
1192void log_parse_environment(void) {
1193 const char *e;
1194
a10f5d05
MB
1195 /* Do not call from library code. */
1196
3a6ce677
BR
1197 if (should_parse_proc_cmdline())
1198 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
a10f5d05 1199
81c58355 1200 e = getenv("SYSTEMD_LOG_TARGET");
663996b3 1201 if (e && log_set_target_from_string(e) < 0)
5eef597e 1202 log_warning("Failed to parse log target '%s'. Ignoring.", e);
663996b3 1203
81c58355 1204 e = getenv("SYSTEMD_LOG_LEVEL");
3a6ce677 1205 if (e && log_set_max_level_from_string(e) < 0)
5eef597e 1206 log_warning("Failed to parse log level '%s'. Ignoring.", e);
663996b3 1207
81c58355 1208 e = getenv("SYSTEMD_LOG_COLOR");
663996b3 1209 if (e && log_show_color_from_string(e) < 0)
f2dec872 1210 log_warning("Failed to parse log color '%s'. Ignoring.", e);
663996b3 1211
81c58355 1212 e = getenv("SYSTEMD_LOG_LOCATION");
663996b3 1213 if (e && log_show_location_from_string(e) < 0)
f2dec872 1214 log_warning("Failed to parse log location '%s'. Ignoring.", e);
a10f5d05
MB
1215
1216 e = getenv("SYSTEMD_LOG_TIME");
1217 if (e && log_show_time_from_string(e) < 0)
1218 log_warning("Failed to parse log time '%s'. Ignoring.", e);
a032b68d
MB
1219
1220 e = getenv("SYSTEMD_LOG_TID");
1221 if (e && log_show_tid_from_string(e) < 0)
1222 log_warning("Failed to parse log tid '%s'. Ignoring.", e);
663996b3
MS
1223}
1224
1225LogTarget log_get_target(void) {
1226 return log_target;
1227}
1228
3a6ce677
BR
1229int log_get_max_level(void) {
1230 return log_max_level;
663996b3
MS
1231}
1232
1233void log_show_color(bool b) {
1234 show_color = b;
1235}
1236
60f067b4 1237bool log_get_show_color(void) {
3a6ce677 1238 return show_color > 0; /* Defaults to false. */
60f067b4
JS
1239}
1240
663996b3
MS
1241void log_show_location(bool b) {
1242 show_location = b;
1243}
1244
60f067b4
JS
1245bool log_get_show_location(void) {
1246 return show_location;
1247}
1248
a10f5d05
MB
1249void log_show_time(bool b) {
1250 show_time = b;
1251}
1252
1253bool log_get_show_time(void) {
1254 return show_time;
1255}
1256
a032b68d
MB
1257void log_show_tid(bool b) {
1258 show_tid = b;
1259}
1260
1261bool log_get_show_tid(void) {
1262 return show_tid;
1263}
1264
663996b3
MS
1265int log_show_color_from_string(const char *e) {
1266 int t;
1267
1268 t = parse_boolean(e);
1269 if (t < 0)
1270 return t;
1271
1272 log_show_color(t);
1273 return 0;
1274}
1275
1276int log_show_location_from_string(const char *e) {
1277 int t;
1278
1279 t = parse_boolean(e);
1280 if (t < 0)
1281 return t;
1282
1283 log_show_location(t);
1284 return 0;
1285}
1286
a10f5d05
MB
1287int log_show_time_from_string(const char *e) {
1288 int t;
1289
1290 t = parse_boolean(e);
1291 if (t < 0)
1292 return t;
1293
1294 log_show_time(t);
1295 return 0;
1296}
1297
a032b68d
MB
1298int log_show_tid_from_string(const char *e) {
1299 int t;
1300
1301 t = parse_boolean(e);
1302 if (t < 0)
1303 return t;
1304
1305 log_show_tid(t);
1306 return 0;
1307}
1308
663996b3 1309bool log_on_console(void) {
2897b343
MP
1310 if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1311 LOG_TARGET_CONSOLE_PREFIXED))
663996b3
MS
1312 return true;
1313
1314 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1315}
1316
60f067b4 1317static const char *const log_target_table[_LOG_TARGET_MAX] = {
3a6ce677 1318 [LOG_TARGET_CONSOLE] = "console",
e735f4d4 1319 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
3a6ce677
BR
1320 [LOG_TARGET_KMSG] = "kmsg",
1321 [LOG_TARGET_JOURNAL] = "journal",
1322 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1323 [LOG_TARGET_SYSLOG] = "syslog",
1324 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1325 [LOG_TARGET_AUTO] = "auto",
1326 [LOG_TARGET_NULL] = "null",
663996b3
MS
1327};
1328
1329DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
60f067b4
JS
1330
1331void log_received_signal(int level, const struct signalfd_siginfo *si) {
1d42b86d
MB
1332 assert(si);
1333
1334 if (pid_is_valid(si->ssi_pid)) {
60f067b4
JS
1335 _cleanup_free_ char *p = NULL;
1336
1d42b86d 1337 (void) get_process_comm(si->ssi_pid, &p);
60f067b4
JS
1338
1339 log_full(level,
e735f4d4 1340 "Received SIG%s from PID %"PRIu32" (%s).",
60f067b4
JS
1341 signal_to_string(si->ssi_signo),
1342 si->ssi_pid, strna(p));
1343 } else
1344 log_full(level,
1345 "Received SIG%s.",
1346 signal_to_string(si->ssi_signo));
60f067b4 1347}
5eef597e 1348
e3bff60a
MP
1349int log_syntax_internal(
1350 const char *unit,
1351 int level,
1352 const char *config_file,
1353 unsigned config_line,
1354 int error,
1355 const char *file,
1356 int line,
1357 const char *func,
1358 const char *format, ...) {
1359
1360 PROTECT_ERRNO;
1361 char buffer[LINE_MAX];
e3bff60a 1362 va_list ap;
2897b343 1363 const char *unit_fmt = NULL;
e3bff60a 1364
3a6ce677 1365 if (_likely_(LOG_PRI(level) > log_max_level) ||
6e866b33
MB
1366 log_target == LOG_TARGET_NULL)
1367 return -ERRNO_VALUE(error);
e3bff60a 1368
bb4f798a 1369 errno = ERRNO_VALUE(error);
e3bff60a
MP
1370
1371 va_start(ap, format);
98393f85 1372 (void) vsnprintf(buffer, sizeof buffer, format, ap);
e3bff60a
MP
1373 va_end(ap);
1374
1375 if (unit)
f5e65279 1376 unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
2897b343 1377
f2dec872
BR
1378 if (config_file) {
1379 if (config_line > 0)
1380 return log_struct_internal(
3a6ce677 1381 level,
f2dec872
BR
1382 error,
1383 file, line, func,
1384 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1385 "CONFIG_FILE=%s", config_file,
1386 "CONFIG_LINE=%u", config_line,
1387 LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
1388 unit_fmt, unit,
1389 NULL);
1390 else
1391 return log_struct_internal(
3a6ce677 1392 level,
f2dec872
BR
1393 error,
1394 file, line, func,
1395 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1396 "CONFIG_FILE=%s", config_file,
1397 LOG_MESSAGE("%s: %s", config_file, buffer),
1398 unit_fmt, unit,
1399 NULL);
1400 } else if (unit)
bb4f798a 1401 return log_struct_internal(
3a6ce677 1402 level,
bb4f798a
MB
1403 error,
1404 file, line, func,
1405 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1406 LOG_MESSAGE("%s: %s", unit, buffer),
1407 unit_fmt, unit,
1408 NULL);
1409 else
1410 return log_struct_internal(
3a6ce677 1411 level,
bb4f798a
MB
1412 error,
1413 file, line, func,
1414 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1415 LOG_MESSAGE("%s", buffer),
1416 NULL);
2897b343 1417}
e3bff60a 1418
1d42b86d
MB
1419int log_syntax_invalid_utf8_internal(
1420 const char *unit,
1421 int level,
1422 const char *config_file,
1423 unsigned config_line,
1424 const char *file,
1425 int line,
1426 const char *func,
1427 const char *rvalue) {
1428
1429 _cleanup_free_ char *p = NULL;
1430
1431 if (rvalue)
1432 p = utf8_escape_invalid(rvalue);
1433
8b3d4ff0
MB
1434 return log_syntax_internal(unit, level, config_file, config_line,
1435 SYNTHETIC_ERRNO(EINVAL), file, line, func,
1436 "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
1d42b86d
MB
1437}
1438
f5e65279
MB
1439void log_set_upgrade_syslog_to_journal(bool b) {
1440 upgrade_syslog_to_journal = b;
1d42b86d
MB
1441
1442 /* Make the change effective immediately */
1443 if (b) {
1444 if (log_target == LOG_TARGET_SYSLOG)
1445 log_target = LOG_TARGET_JOURNAL;
1446 else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
1447 log_target = LOG_TARGET_JOURNAL_OR_KMSG;
1448 }
f5e65279
MB
1449}
1450
2897b343
MP
1451void log_set_always_reopen_console(bool b) {
1452 always_reopen_console = b;
e3bff60a 1453}
f5e65279
MB
1454
1455void log_set_open_when_needed(bool b) {
1456 open_when_needed = b;
1457}
1d42b86d
MB
1458
1459void log_set_prohibit_ipc(bool b) {
1460 prohibit_ipc = b;
1461}
1462
1463int log_emergency_level(void) {
1464 /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1465 * then the system of the whole system is obviously affected. */
1466
1467 return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;
1468}
b012e921
MB
1469
1470int log_dup_console(void) {
1471 int copy;
1472
1473 /* Duplicate the fd we use for fd logging if it's < 3 and use the copy from now on. This call is useful
1474 * whenever we want to continue logging through the original fd, but want to rearrange stderr. */
1475
1476 if (console_fd >= 3)
1477 return 0;
1478
1479 copy = fcntl(console_fd, F_DUPFD_CLOEXEC, 3);
1480 if (copy < 0)
1481 return -errno;
1482
1483 console_fd = copy;
1484 return 0;
1485}
6e866b33 1486
3a6ce677 1487void log_setup(void) {
6e866b33
MB
1488 log_set_target(LOG_TARGET_AUTO);
1489 log_parse_environment();
c5fca32e 1490 (void) log_open();
3a6ce677
BR
1491 if (log_on_console() && show_color < 0)
1492 log_show_color(true);
a10f5d05 1493}