1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include <sys/signalfd.h>
30 #include <sys/socket.h>
37 #include "sd-messages.h"
39 #include "alloc-util.h"
41 #include "format-util.h"
46 #include "parse-util.h"
47 #include "proc-cmdline.h"
48 #include "process-util.h"
49 #include "signal-util.h"
50 #include "socket-util.h"
51 #include "stdio-util.h"
52 #include "string-table.h"
53 #include "string-util.h"
54 #include "syslog-util.h"
55 #include "terminal-util.h"
56 #include "time-util.h"
60 #define SNDBUF_SIZE (8*1024*1024)
62 static LogTarget log_target
= LOG_TARGET_CONSOLE
;
63 static int log_max_level
[] = {LOG_INFO
, LOG_INFO
};
64 assert_cc(ELEMENTSOF(log_max_level
) == _LOG_REALM_MAX
);
65 static int log_facility
= LOG_DAEMON
;
67 static int console_fd
= STDERR_FILENO
;
68 static int syslog_fd
= -1;
69 static int kmsg_fd
= -1;
70 static int journal_fd
= -1;
72 static bool syslog_is_stream
= false;
74 static bool show_color
= false;
75 static bool show_location
= false;
77 static bool upgrade_syslog_to_journal
= false;
78 static bool always_reopen_console
= false;
79 static bool open_when_needed
= false;
80 static bool prohibit_ipc
= false;
82 /* Akin to glibc's __abort_msg; which is private and we hence cannot
84 static char *log_abort_msg
= NULL
;
86 /* An assert to use in logging functions that does not call recursively
87 * into our logging functions (since that might lead to a loop). */
88 #define assert_raw(expr) \
90 if (_unlikely_(!(expr))) { \
91 fputs(#expr "\n", stderr); \
96 static void log_close_console(void) {
102 safe_close(console_fd
);
107 static int log_open_console(void) {
109 if (!always_reopen_console
) {
110 console_fd
= STDERR_FILENO
;
114 if (console_fd
< 3) {
115 console_fd
= open_terminal("/dev/console", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
119 console_fd
= fd_move_above_stdio(console_fd
);
125 static void log_close_kmsg(void) {
126 kmsg_fd
= safe_close(kmsg_fd
);
129 static int log_open_kmsg(void) {
134 kmsg_fd
= open("/dev/kmsg", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
138 kmsg_fd
= fd_move_above_stdio(kmsg_fd
);
142 static void log_close_syslog(void) {
143 syslog_fd
= safe_close(syslog_fd
);
146 static int create_log_socket(int type
) {
150 fd
= socket(AF_UNIX
, type
|SOCK_CLOEXEC
, 0);
154 fd
= fd_move_above_stdio(fd
);
155 (void) fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
157 /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
158 * in the unlikely case of a deadlock. */
159 if (getpid_cached() == 1)
160 timeval_store(&tv
, 10 * USEC_PER_MSEC
);
162 timeval_store(&tv
, 10 * USEC_PER_SEC
);
163 (void) setsockopt(fd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
168 static int log_open_syslog(void) {
170 static const union sockaddr_union sa
= {
171 .un
.sun_family
= AF_UNIX
,
172 .un
.sun_path
= "/dev/log",
180 syslog_fd
= create_log_socket(SOCK_DGRAM
);
186 if (connect(syslog_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
187 safe_close(syslog_fd
);
189 /* Some legacy syslog systems still use stream
190 * sockets. They really shouldn't. But what can we
192 syslog_fd
= create_log_socket(SOCK_STREAM
);
198 if (connect(syslog_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
203 syslog_is_stream
= true;
205 syslog_is_stream
= false;
214 static void log_close_journal(void) {
215 journal_fd
= safe_close(journal_fd
);
218 static int log_open_journal(void) {
220 static const union sockaddr_union sa
= {
221 .un
.sun_family
= AF_UNIX
,
222 .un
.sun_path
= "/run/systemd/journal/socket",
230 journal_fd
= create_log_socket(SOCK_DGRAM
);
231 if (journal_fd
< 0) {
236 if (connect(journal_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
251 /* Do not call from library code. */
253 /* If we don't use the console we close it here, to not get
254 * killed by SAK. If we don't use syslog we close it here so
255 * that we are not confused by somebody deleting the socket in
256 * the fs, and to make sure we don't use it if prohibit_ipc is
257 * set. If we don't use /dev/kmsg we still keep it open,
258 * because there is no reason to close it. */
260 if (log_target
== LOG_TARGET_NULL
) {
267 if (log_target
!= LOG_TARGET_AUTO
||
268 getpid_cached() == 1 ||
269 isatty(STDERR_FILENO
) <= 0) {
272 IN_SET(log_target
, LOG_TARGET_AUTO
,
273 LOG_TARGET_JOURNAL_OR_KMSG
,
274 LOG_TARGET_JOURNAL
)) {
275 r
= log_open_journal();
284 IN_SET(log_target
, LOG_TARGET_SYSLOG_OR_KMSG
,
285 LOG_TARGET_SYSLOG
)) {
286 r
= log_open_syslog();
294 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
295 LOG_TARGET_JOURNAL_OR_KMSG
,
296 LOG_TARGET_SYSLOG_OR_KMSG
,
311 return log_open_console();
314 void log_set_target(LogTarget target
) {
316 assert(target
< _LOG_TARGET_MAX
);
318 if (upgrade_syslog_to_journal
) {
319 if (target
== LOG_TARGET_SYSLOG
)
320 target
= LOG_TARGET_JOURNAL
;
321 else if (target
== LOG_TARGET_SYSLOG_OR_KMSG
)
322 target
= LOG_TARGET_JOURNAL_OR_KMSG
;
328 void log_close(void) {
329 /* Do not call from library code. */
337 void log_forget_fds(void) {
338 /* Do not call from library code. */
340 console_fd
= kmsg_fd
= syslog_fd
= journal_fd
= -1;
343 void log_set_max_level_realm(LogRealm realm
, int level
) {
344 assert((level
& LOG_PRIMASK
) == level
);
345 assert(realm
< ELEMENTSOF(log_max_level
));
347 log_max_level
[realm
] = level
;
350 void log_set_facility(int facility
) {
351 log_facility
= facility
;
354 static int write_to_console(
360 const char *buffer
) {
362 char location
[256], prefix
[1 + DECIMAL_STR_MAX(int) + 2];
363 struct iovec iovec
[6] = {};
370 if (log_target
== LOG_TARGET_CONSOLE_PREFIXED
) {
371 xsprintf(prefix
, "<%i>", level
);
372 iovec
[n
++] = IOVEC_MAKE_STRING(prefix
);
375 highlight
= LOG_PRI(level
) <= LOG_ERR
&& show_color
;
378 (void) snprintf(location
, sizeof location
, "(%s:%i) ", file
, line
);
379 iovec
[n
++] = IOVEC_MAKE_STRING(location
);
383 iovec
[n
++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED
);
384 iovec
[n
++] = IOVEC_MAKE_STRING(buffer
);
386 iovec
[n
++] = IOVEC_MAKE_STRING(ANSI_NORMAL
);
387 iovec
[n
++] = IOVEC_MAKE_STRING("\n");
389 if (writev(console_fd
, iovec
, n
) < 0) {
391 if (errno
== EIO
&& getpid_cached() == 1) {
393 /* If somebody tried to kick us from our
394 * console tty (via vhangup() or suchlike),
395 * try to reconnect */
403 if (writev(console_fd
, iovec
, n
) < 0)
412 static int write_to_syslog(
418 const char *buffer
) {
420 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
422 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
423 struct iovec iovec
[5] = {};
424 struct msghdr msghdr
= {
426 .msg_iovlen
= ELEMENTSOF(iovec
),
434 xsprintf(header_priority
, "<%i>", level
);
436 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
441 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
444 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid_cached());
446 iovec
[0] = IOVEC_MAKE_STRING(header_priority
);
447 iovec
[1] = IOVEC_MAKE_STRING(header_time
);
448 iovec
[2] = IOVEC_MAKE_STRING(program_invocation_short_name
);
449 iovec
[3] = IOVEC_MAKE_STRING(header_pid
);
450 iovec
[4] = IOVEC_MAKE_STRING(buffer
);
452 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
453 if (syslog_is_stream
)
459 n
= sendmsg(syslog_fd
, &msghdr
, MSG_NOSIGNAL
);
463 if (!syslog_is_stream
||
464 (size_t) n
>= IOVEC_TOTAL_SIZE(iovec
, ELEMENTSOF(iovec
)))
467 IOVEC_INCREMENT(iovec
, ELEMENTSOF(iovec
), n
);
473 static int write_to_kmsg(
479 const char *buffer
) {
481 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
482 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
483 struct iovec iovec
[5] = {};
488 xsprintf(header_priority
, "<%i>", level
);
489 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid_cached());
491 iovec
[0] = IOVEC_MAKE_STRING(header_priority
);
492 iovec
[1] = IOVEC_MAKE_STRING(program_invocation_short_name
);
493 iovec
[2] = IOVEC_MAKE_STRING(header_pid
);
494 iovec
[3] = IOVEC_MAKE_STRING(buffer
);
495 iovec
[4] = IOVEC_MAKE_STRING("\n");
497 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
503 static int log_do_header(
508 const char *file
, int line
, const char *func
,
509 const char *object_field
, const char *object
,
510 const char *extra_field
, const char *extra
) {
513 r
= snprintf(header
, size
,
515 "SYSLOG_FACILITY=%i\n"
516 "%s%.256s%s" /* CODE_FILE */
517 "%s%.*i%s" /* CODE_LINE */
518 "%s%.256s%s" /* CODE_FUNC */
519 "%s%.*i%s" /* ERRNO */
520 "%s%.256s%s" /* object */
521 "%s%.256s%s" /* extra */
522 "SYSLOG_IDENTIFIER=%.256s\n",
525 isempty(file
) ? "" : "CODE_FILE=",
526 isempty(file
) ? "" : file
,
527 isempty(file
) ? "" : "\n",
528 line
? "CODE_LINE=" : "",
529 line
? 1 : 0, line
, /* %.0d means no output too, special case for 0 */
531 isempty(func
) ? "" : "CODE_FUNC=",
532 isempty(func
) ? "" : func
,
533 isempty(func
) ? "" : "\n",
534 error
? "ERRNO=" : "",
535 error
? 1 : 0, error
,
537 isempty(object
) ? "" : object_field
,
538 isempty(object
) ? "" : object
,
539 isempty(object
) ? "" : "\n",
540 isempty(extra
) ? "" : extra_field
,
541 isempty(extra
) ? "" : extra
,
542 isempty(extra
) ? "" : "\n",
543 program_invocation_short_name
);
544 assert_raw((size_t) r
< size
);
549 static int write_to_journal(
555 const char *object_field
,
557 const char *extra_field
,
559 const char *buffer
) {
561 char header
[LINE_MAX
];
562 struct iovec iovec
[4] = {};
563 struct msghdr mh
= {};
568 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
);
570 iovec
[0] = IOVEC_MAKE_STRING(header
);
571 iovec
[1] = IOVEC_MAKE_STRING("MESSAGE=");
572 iovec
[2] = IOVEC_MAKE_STRING(buffer
);
573 iovec
[3] = IOVEC_MAKE_STRING("\n");
576 mh
.msg_iovlen
= ELEMENTSOF(iovec
);
578 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) < 0)
584 int log_dispatch_internal(
590 const char *object_field
,
592 const char *extra_field
,
601 if (log_target
== LOG_TARGET_NULL
)
604 /* Patch in LOG_DAEMON facility if necessary */
605 if ((level
& LOG_FACMASK
) == 0)
606 level
= log_facility
| LOG_PRI(level
);
608 if (open_when_needed
)
615 buffer
+= strspn(buffer
, NEWLINE
);
620 if ((e
= strpbrk(buffer
, NEWLINE
)))
623 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
624 LOG_TARGET_JOURNAL_OR_KMSG
,
625 LOG_TARGET_JOURNAL
)) {
627 k
= write_to_journal(level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
, buffer
);
628 if (k
< 0 && k
!= -EAGAIN
)
632 if (IN_SET(log_target
, LOG_TARGET_SYSLOG_OR_KMSG
,
633 LOG_TARGET_SYSLOG
)) {
635 k
= write_to_syslog(level
, error
, file
, line
, func
, buffer
);
636 if (k
< 0 && k
!= -EAGAIN
)
641 IN_SET(log_target
, LOG_TARGET_AUTO
,
642 LOG_TARGET_SYSLOG_OR_KMSG
,
643 LOG_TARGET_JOURNAL_OR_KMSG
,
649 k
= write_to_kmsg(level
, error
, file
, line
, func
, buffer
);
657 (void) write_to_console(level
, error
, file
, line
, func
, buffer
);
662 if (open_when_needed
)
668 int log_dump_internal(
676 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
679 /* This modifies the buffer... */
684 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
687 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
690 int log_internalv_realm(
699 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
700 char buffer
[LINE_MAX
];
706 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
709 /* Make sure that %m maps to the specified error */
713 (void) vsnprintf(buffer
, sizeof buffer
, format
, ap
);
715 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
718 int log_internal_realm(
724 const char *format
, ...) {
729 va_start(ap
, format
);
730 r
= log_internalv_realm(level
, error
, file
, line
, func
, format
, ap
);
737 static int log_object_internalv(
743 const char *object_field
,
745 const char *extra_field
,
756 if (_likely_(LOG_PRI(level
) > log_max_level
[LOG_REALM_SYSTEMD
]))
759 /* Make sure that %m maps to the specified error */
763 /* Prepend the object name before the message */
768 buffer
= newa(char, n
+ 2 + LINE_MAX
);
769 b
= stpcpy(stpcpy(buffer
, object
), ": ");
771 b
= buffer
= newa(char, LINE_MAX
);
773 (void) vsnprintf(b
, LINE_MAX
, format
, ap
);
775 return log_dispatch_internal(level
, error
, file
, line
, func
,
776 object_field
, object
, extra_field
, extra
, buffer
);
779 int log_object_internal(
785 const char *object_field
,
787 const char *extra_field
,
789 const char *format
, ...) {
794 va_start(ap
, format
);
795 r
= log_object_internalv(level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
, format
, ap
);
801 static void log_assert(
807 const char *format
) {
809 static char buffer
[LINE_MAX
];
810 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
812 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
815 DISABLE_WARNING_FORMAT_NONLITERAL
;
816 (void) snprintf(buffer
, sizeof buffer
, format
, text
, file
, line
, func
);
819 log_abort_msg
= buffer
;
821 log_dispatch_internal(level
, 0, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
824 noreturn
void log_assert_failed_realm(
831 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_CRIT
), text
, file
, line
, func
,
832 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
836 noreturn
void log_assert_failed_unreachable_realm(
843 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_CRIT
), text
, file
, line
, func
,
844 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
848 void log_assert_failed_return_realm(
855 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_DEBUG
), text
, file
, line
, func
,
856 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
859 int log_oom_internal(LogRealm realm
, const char *file
, int line
, const char *func
) {
860 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm
, LOG_ERR
),
861 ENOMEM
, file
, line
, func
, "Out of memory.");
864 int log_format_iovec(
868 bool newline_separator
,
873 static const char nl
= '\n';
875 while (format
&& *n
+ 1 < iovec_len
) {
880 /* We need to copy the va_list structure,
881 * since vasprintf() leaves it afterwards at
882 * an undefined location */
888 r
= vasprintf(&m
, format
, aq
);
893 /* Now, jump enough ahead, so that we point to
894 * the next format string */
895 VA_FORMAT_ADVANCE(format
, ap
);
897 iovec
[(*n
)++] = IOVEC_MAKE_STRING(m
);
899 if (newline_separator
) {
900 iovec
[*n
].iov_base
= (char*) &nl
;
901 iovec
[*n
].iov_len
= 1;
905 format
= va_arg(ap
, char *);
910 int log_struct_internal(
916 const char *format
, ...) {
918 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
927 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
930 if (log_target
== LOG_TARGET_NULL
)
933 if ((level
& LOG_FACMASK
) == 0)
934 level
= log_facility
| LOG_PRI(level
);
936 if (IN_SET(log_target
,
938 LOG_TARGET_JOURNAL_OR_KMSG
,
939 LOG_TARGET_JOURNAL
)) {
941 if (open_when_needed
)
944 if (journal_fd
>= 0) {
945 char header
[LINE_MAX
];
946 struct iovec iovec
[17] = {};
952 bool fallback
= false;
954 /* If the journal is available do structured logging */
955 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
);
956 iovec
[n
++] = IOVEC_MAKE_STRING(header
);
958 va_start(ap
, format
);
959 r
= log_format_iovec(iovec
, ELEMENTSOF(iovec
), &n
, true, error
, format
, ap
);
964 (void) sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
);
968 for (i
= 1; i
< n
; i
+= 2)
969 free(iovec
[i
].iov_base
);
972 if (open_when_needed
)
980 /* Fallback if journal logging is not available or didn't work. */
982 va_start(ap
, format
);
990 (void) vsnprintf(buf
, sizeof buf
, format
, aq
);
993 if (startswith(buf
, "MESSAGE=")) {
998 VA_FORMAT_ADVANCE(format
, ap
);
1000 format
= va_arg(ap
, char *);
1005 if (open_when_needed
)
1011 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buf
+ 8);
1014 int log_struct_iovec_internal(
1020 const struct iovec input_iovec
[],
1021 size_t n_input_iovec
) {
1023 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
1031 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
1034 if (log_target
== LOG_TARGET_NULL
)
1037 if ((level
& LOG_FACMASK
) == 0)
1038 level
= log_facility
| LOG_PRI(level
);
1040 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
1041 LOG_TARGET_JOURNAL_OR_KMSG
,
1042 LOG_TARGET_JOURNAL
) &&
1045 struct iovec iovec
[1 + n_input_iovec
*2];
1046 char header
[LINE_MAX
];
1047 struct msghdr mh
= {
1049 .msg_iovlen
= 1 + n_input_iovec
*2,
1052 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
);
1053 iovec
[0] = IOVEC_MAKE_STRING(header
);
1055 for (i
= 0; i
< n_input_iovec
; i
++) {
1056 iovec
[1+i
*2] = input_iovec
[i
];
1057 iovec
[1+i
*2+1] = IOVEC_MAKE_STRING("\n");
1060 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) >= 0)
1064 for (i
= 0; i
< n_input_iovec
; i
++) {
1065 if (input_iovec
[i
].iov_len
< STRLEN("MESSAGE="))
1068 if (memcmp(input_iovec
[i
].iov_base
, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
1072 if (_unlikely_(i
>= n_input_iovec
)) /* Couldn't find MESSAGE=? */
1075 m
= strndupa(input_iovec
[i
].iov_base
+ STRLEN("MESSAGE="),
1076 input_iovec
[i
].iov_len
- STRLEN("MESSAGE="));
1078 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, m
);
1081 int log_set_target_from_string(const char *e
) {
1084 t
= log_target_from_string(e
);
1092 int log_set_max_level_from_string_realm(LogRealm realm
, const char *e
) {
1095 t
= log_level_from_string(e
);
1099 log_set_max_level_realm(realm
, t
);
1103 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
1106 * The systemd.log_xyz= settings are parsed by all tools, and
1109 * However, "quiet" is only parsed by PID 1, and only turns of
1110 * status output to /dev/console, but does not alter the log
1114 if (streq(key
, "debug") && !value
)
1115 log_set_max_level(LOG_DEBUG
);
1117 else if (proc_cmdline_key_streq(key
, "systemd.log_target")) {
1119 if (proc_cmdline_value_missing(key
, value
))
1122 if (log_set_target_from_string(value
) < 0)
1123 log_warning("Failed to parse log target '%s'. Ignoring.", value
);
1125 } else if (proc_cmdline_key_streq(key
, "systemd.log_level")) {
1127 if (proc_cmdline_value_missing(key
, value
))
1130 if (log_set_max_level_from_string(value
) < 0)
1131 log_warning("Failed to parse log level '%s'. Ignoring.", value
);
1133 } else if (proc_cmdline_key_streq(key
, "systemd.log_color")) {
1135 if (log_show_color_from_string(value
?: "1") < 0)
1136 log_warning("Failed to parse log color setting '%s'. Ignoring.", value
);
1138 } else if (proc_cmdline_key_streq(key
, "systemd.log_location")) {
1140 if (log_show_location_from_string(value
?: "1") < 0)
1141 log_warning("Failed to parse log location setting '%s'. Ignoring.", value
);
1147 void log_parse_environment_realm(LogRealm realm
) {
1148 /* Do not call from library code. */
1152 if (get_ctty_devnr(0, NULL
) < 0)
1153 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1155 (void) proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_STRIP_RD_PREFIX
);
1157 e
= getenv("SYSTEMD_LOG_TARGET");
1158 if (e
&& log_set_target_from_string(e
) < 0)
1159 log_warning("Failed to parse log target '%s'. Ignoring.", e
);
1161 e
= getenv("SYSTEMD_LOG_LEVEL");
1162 if (e
&& log_set_max_level_from_string_realm(realm
, e
) < 0)
1163 log_warning("Failed to parse log level '%s'. Ignoring.", e
);
1165 e
= getenv("SYSTEMD_LOG_COLOR");
1166 if (e
&& log_show_color_from_string(e
) < 0)
1167 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1169 e
= getenv("SYSTEMD_LOG_LOCATION");
1170 if (e
&& log_show_location_from_string(e
) < 0)
1171 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1174 LogTarget
log_get_target(void) {
1178 int log_get_max_level_realm(LogRealm realm
) {
1179 return log_max_level
[realm
];
1182 void log_show_color(bool b
) {
1186 bool log_get_show_color(void) {
1190 void log_show_location(bool b
) {
1194 bool log_get_show_location(void) {
1195 return show_location
;
1198 int log_show_color_from_string(const char *e
) {
1201 t
= parse_boolean(e
);
1209 int log_show_location_from_string(const char *e
) {
1212 t
= parse_boolean(e
);
1216 log_show_location(t
);
1220 bool log_on_console(void) {
1221 if (IN_SET(log_target
, LOG_TARGET_CONSOLE
,
1222 LOG_TARGET_CONSOLE_PREFIXED
))
1225 return syslog_fd
< 0 && kmsg_fd
< 0 && journal_fd
< 0;
1228 static const char *const log_target_table
[_LOG_TARGET_MAX
] = {
1229 [LOG_TARGET_CONSOLE
] = "console",
1230 [LOG_TARGET_CONSOLE_PREFIXED
] = "console-prefixed",
1231 [LOG_TARGET_KMSG
] = "kmsg",
1232 [LOG_TARGET_JOURNAL
] = "journal",
1233 [LOG_TARGET_JOURNAL_OR_KMSG
] = "journal-or-kmsg",
1234 [LOG_TARGET_SYSLOG
] = "syslog",
1235 [LOG_TARGET_SYSLOG_OR_KMSG
] = "syslog-or-kmsg",
1236 [LOG_TARGET_AUTO
] = "auto",
1237 [LOG_TARGET_NULL
] = "null",
1240 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);
1242 void log_received_signal(int level
, const struct signalfd_siginfo
*si
) {
1245 if (pid_is_valid(si
->ssi_pid
)) {
1246 _cleanup_free_
char *p
= NULL
;
1248 (void) get_process_comm(si
->ssi_pid
, &p
);
1251 "Received SIG%s from PID %"PRIu32
" (%s).",
1252 signal_to_string(si
->ssi_signo
),
1253 si
->ssi_pid
, strna(p
));
1257 signal_to_string(si
->ssi_signo
));
1260 int log_syntax_internal(
1263 const char *config_file
,
1264 unsigned config_line
,
1269 const char *format
, ...) {
1272 char buffer
[LINE_MAX
];
1274 const char *unit_fmt
= NULL
;
1279 if (_likely_(LOG_PRI(level
) > log_max_level
[LOG_REALM_SYSTEMD
]))
1282 if (log_target
== LOG_TARGET_NULL
)
1288 va_start(ap
, format
);
1289 (void) vsnprintf(buffer
, sizeof buffer
, format
, ap
);
1293 unit_fmt
= getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1295 return log_struct_internal(
1296 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
1299 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
1300 "CONFIG_FILE=%s", config_file
,
1301 "CONFIG_LINE=%u", config_line
,
1302 LOG_MESSAGE("%s:%u: %s", config_file
, config_line
, buffer
),
1307 int log_syntax_invalid_utf8_internal(
1310 const char *config_file
,
1311 unsigned config_line
,
1315 const char *rvalue
) {
1317 _cleanup_free_
char *p
= NULL
;
1320 p
= utf8_escape_invalid(rvalue
);
1322 log_syntax_internal(unit
, level
, config_file
, config_line
, 0, file
, line
, func
,
1323 "String is not UTF-8 clean, ignoring assignment: %s", strna(p
));
1328 void log_set_upgrade_syslog_to_journal(bool b
) {
1329 upgrade_syslog_to_journal
= b
;
1331 /* Make the change effective immediately */
1333 if (log_target
== LOG_TARGET_SYSLOG
)
1334 log_target
= LOG_TARGET_JOURNAL
;
1335 else if (log_target
== LOG_TARGET_SYSLOG_OR_KMSG
)
1336 log_target
= LOG_TARGET_JOURNAL_OR_KMSG
;
1340 void log_set_always_reopen_console(bool b
) {
1341 always_reopen_console
= b
;
1344 void log_set_open_when_needed(bool b
) {
1345 open_when_needed
= b
;
1348 void log_set_prohibit_ipc(bool b
) {
1352 int log_emergency_level(void) {
1353 /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1354 * then the system of the whole system is obviously affected. */
1356 return getpid_cached() == 1 ? LOG_EMERG
: LOG_ERR
;