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