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