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) {
97 console_fd
= safe_close_above_stdio(console_fd
);
100 static int log_open_console(void) {
102 if (!always_reopen_console
) {
103 console_fd
= STDERR_FILENO
;
107 if (console_fd
< 3) {
108 console_fd
= open_terminal("/dev/console", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
112 console_fd
= fd_move_above_stdio(console_fd
);
118 static void log_close_kmsg(void) {
119 kmsg_fd
= safe_close(kmsg_fd
);
122 static int log_open_kmsg(void) {
127 kmsg_fd
= open("/dev/kmsg", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
131 kmsg_fd
= fd_move_above_stdio(kmsg_fd
);
135 static void log_close_syslog(void) {
136 syslog_fd
= safe_close(syslog_fd
);
139 static int create_log_socket(int type
) {
143 fd
= socket(AF_UNIX
, type
|SOCK_CLOEXEC
, 0);
147 fd
= fd_move_above_stdio(fd
);
148 (void) fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
150 /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
151 * in the unlikely case of a deadlock. */
152 if (getpid_cached() == 1)
153 timeval_store(&tv
, 10 * USEC_PER_MSEC
);
155 timeval_store(&tv
, 10 * USEC_PER_SEC
);
156 (void) setsockopt(fd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
161 static int log_open_syslog(void) {
163 static const union sockaddr_union sa
= {
164 .un
.sun_family
= AF_UNIX
,
165 .un
.sun_path
= "/dev/log",
173 syslog_fd
= create_log_socket(SOCK_DGRAM
);
179 if (connect(syslog_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
180 safe_close(syslog_fd
);
182 /* Some legacy syslog systems still use stream
183 * sockets. They really shouldn't. But what can we
185 syslog_fd
= create_log_socket(SOCK_STREAM
);
191 if (connect(syslog_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
196 syslog_is_stream
= true;
198 syslog_is_stream
= false;
207 static void log_close_journal(void) {
208 journal_fd
= safe_close(journal_fd
);
211 static int log_open_journal(void) {
213 static const union sockaddr_union sa
= {
214 .un
.sun_family
= AF_UNIX
,
215 .un
.sun_path
= "/run/systemd/journal/socket",
223 journal_fd
= create_log_socket(SOCK_DGRAM
);
224 if (journal_fd
< 0) {
229 if (connect(journal_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
244 /* Do not call from library code. */
246 /* If we don't use the console we close it here, to not get
247 * killed by SAK. If we don't use syslog we close it here so
248 * that we are not confused by somebody deleting the socket in
249 * the fs, and to make sure we don't use it if prohibit_ipc is
250 * set. If we don't use /dev/kmsg we still keep it open,
251 * because there is no reason to close it. */
253 if (log_target
== LOG_TARGET_NULL
) {
260 if (log_target
!= LOG_TARGET_AUTO
||
261 getpid_cached() == 1 ||
262 isatty(STDERR_FILENO
) <= 0) {
265 IN_SET(log_target
, LOG_TARGET_AUTO
,
266 LOG_TARGET_JOURNAL_OR_KMSG
,
267 LOG_TARGET_JOURNAL
)) {
268 r
= log_open_journal();
277 IN_SET(log_target
, LOG_TARGET_SYSLOG_OR_KMSG
,
278 LOG_TARGET_SYSLOG
)) {
279 r
= log_open_syslog();
287 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
288 LOG_TARGET_JOURNAL_OR_KMSG
,
289 LOG_TARGET_SYSLOG_OR_KMSG
,
304 return log_open_console();
307 void log_set_target(LogTarget target
) {
309 assert(target
< _LOG_TARGET_MAX
);
311 if (upgrade_syslog_to_journal
) {
312 if (target
== LOG_TARGET_SYSLOG
)
313 target
= LOG_TARGET_JOURNAL
;
314 else if (target
== LOG_TARGET_SYSLOG_OR_KMSG
)
315 target
= LOG_TARGET_JOURNAL_OR_KMSG
;
321 void log_close(void) {
322 /* Do not call from library code. */
330 void log_forget_fds(void) {
331 /* Do not call from library code. */
333 console_fd
= kmsg_fd
= syslog_fd
= journal_fd
= -1;
336 void log_set_max_level_realm(LogRealm realm
, int level
) {
337 assert((level
& LOG_PRIMASK
) == level
);
338 assert(realm
< ELEMENTSOF(log_max_level
));
340 log_max_level
[realm
] = level
;
343 void log_set_facility(int facility
) {
344 log_facility
= facility
;
347 static int write_to_console(
353 const char *buffer
) {
355 char location
[256], prefix
[1 + DECIMAL_STR_MAX(int) + 2];
356 struct iovec iovec
[6] = {};
363 if (log_target
== LOG_TARGET_CONSOLE_PREFIXED
) {
364 xsprintf(prefix
, "<%i>", level
);
365 iovec
[n
++] = IOVEC_MAKE_STRING(prefix
);
368 highlight
= LOG_PRI(level
) <= LOG_ERR
&& show_color
;
371 (void) snprintf(location
, sizeof location
, "(%s:%i) ", file
, line
);
372 iovec
[n
++] = IOVEC_MAKE_STRING(location
);
376 iovec
[n
++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED
);
377 iovec
[n
++] = IOVEC_MAKE_STRING(buffer
);
379 iovec
[n
++] = IOVEC_MAKE_STRING(ANSI_NORMAL
);
380 iovec
[n
++] = IOVEC_MAKE_STRING("\n");
382 if (writev(console_fd
, iovec
, n
) < 0) {
384 if (errno
== EIO
&& getpid_cached() == 1) {
386 /* If somebody tried to kick us from our
387 * console tty (via vhangup() or suchlike),
388 * try to reconnect */
396 if (writev(console_fd
, iovec
, n
) < 0)
405 static int write_to_syslog(
411 const char *buffer
) {
413 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
415 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
416 struct iovec iovec
[5] = {};
417 struct msghdr msghdr
= {
419 .msg_iovlen
= ELEMENTSOF(iovec
),
427 xsprintf(header_priority
, "<%i>", level
);
429 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
434 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
437 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid_cached());
439 iovec
[0] = IOVEC_MAKE_STRING(header_priority
);
440 iovec
[1] = IOVEC_MAKE_STRING(header_time
);
441 iovec
[2] = IOVEC_MAKE_STRING(program_invocation_short_name
);
442 iovec
[3] = IOVEC_MAKE_STRING(header_pid
);
443 iovec
[4] = IOVEC_MAKE_STRING(buffer
);
445 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
446 if (syslog_is_stream
)
452 n
= sendmsg(syslog_fd
, &msghdr
, MSG_NOSIGNAL
);
456 if (!syslog_is_stream
||
457 (size_t) n
>= IOVEC_TOTAL_SIZE(iovec
, ELEMENTSOF(iovec
)))
460 IOVEC_INCREMENT(iovec
, ELEMENTSOF(iovec
), n
);
466 static int write_to_kmsg(
472 const char *buffer
) {
474 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
475 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
476 struct iovec iovec
[5] = {};
481 xsprintf(header_priority
, "<%i>", level
);
482 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid_cached());
484 iovec
[0] = IOVEC_MAKE_STRING(header_priority
);
485 iovec
[1] = IOVEC_MAKE_STRING(program_invocation_short_name
);
486 iovec
[2] = IOVEC_MAKE_STRING(header_pid
);
487 iovec
[3] = IOVEC_MAKE_STRING(buffer
);
488 iovec
[4] = IOVEC_MAKE_STRING("\n");
490 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
496 static int log_do_header(
501 const char *file
, int line
, const char *func
,
502 const char *object_field
, const char *object
,
503 const char *extra_field
, const char *extra
) {
506 r
= snprintf(header
, size
,
508 "SYSLOG_FACILITY=%i\n"
509 "%s%.256s%s" /* CODE_FILE */
510 "%s%.*i%s" /* CODE_LINE */
511 "%s%.256s%s" /* CODE_FUNC */
512 "%s%.*i%s" /* ERRNO */
513 "%s%.256s%s" /* object */
514 "%s%.256s%s" /* extra */
515 "SYSLOG_IDENTIFIER=%.256s\n",
518 isempty(file
) ? "" : "CODE_FILE=",
519 isempty(file
) ? "" : file
,
520 isempty(file
) ? "" : "\n",
521 line
? "CODE_LINE=" : "",
522 line
? 1 : 0, line
, /* %.0d means no output too, special case for 0 */
524 isempty(func
) ? "" : "CODE_FUNC=",
525 isempty(func
) ? "" : func
,
526 isempty(func
) ? "" : "\n",
527 error
? "ERRNO=" : "",
528 error
? 1 : 0, error
,
530 isempty(object
) ? "" : object_field
,
531 isempty(object
) ? "" : object
,
532 isempty(object
) ? "" : "\n",
533 isempty(extra
) ? "" : extra_field
,
534 isempty(extra
) ? "" : extra
,
535 isempty(extra
) ? "" : "\n",
536 program_invocation_short_name
);
537 assert_raw((size_t) r
< size
);
542 static int write_to_journal(
548 const char *object_field
,
550 const char *extra_field
,
552 const char *buffer
) {
554 char header
[LINE_MAX
];
555 struct iovec iovec
[4] = {};
556 struct msghdr mh
= {};
561 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
);
563 iovec
[0] = IOVEC_MAKE_STRING(header
);
564 iovec
[1] = IOVEC_MAKE_STRING("MESSAGE=");
565 iovec
[2] = IOVEC_MAKE_STRING(buffer
);
566 iovec
[3] = IOVEC_MAKE_STRING("\n");
569 mh
.msg_iovlen
= ELEMENTSOF(iovec
);
571 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) < 0)
577 int log_dispatch_internal(
583 const char *object_field
,
585 const char *extra_field
,
594 if (log_target
== LOG_TARGET_NULL
)
597 /* Patch in LOG_DAEMON facility if necessary */
598 if ((level
& LOG_FACMASK
) == 0)
599 level
= log_facility
| LOG_PRI(level
);
601 if (open_when_needed
)
608 buffer
+= strspn(buffer
, NEWLINE
);
613 if ((e
= strpbrk(buffer
, NEWLINE
)))
616 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
617 LOG_TARGET_JOURNAL_OR_KMSG
,
618 LOG_TARGET_JOURNAL
)) {
620 k
= write_to_journal(level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
, buffer
);
621 if (k
< 0 && k
!= -EAGAIN
)
625 if (IN_SET(log_target
, LOG_TARGET_SYSLOG_OR_KMSG
,
626 LOG_TARGET_SYSLOG
)) {
628 k
= write_to_syslog(level
, error
, file
, line
, func
, buffer
);
629 if (k
< 0 && k
!= -EAGAIN
)
634 IN_SET(log_target
, LOG_TARGET_AUTO
,
635 LOG_TARGET_SYSLOG_OR_KMSG
,
636 LOG_TARGET_JOURNAL_OR_KMSG
,
642 k
= write_to_kmsg(level
, error
, file
, line
, func
, buffer
);
650 (void) write_to_console(level
, error
, file
, line
, func
, buffer
);
655 if (open_when_needed
)
661 int log_dump_internal(
669 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
672 /* This modifies the buffer... */
677 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
680 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
683 int log_internalv_realm(
692 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
693 char buffer
[LINE_MAX
];
699 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
702 /* Make sure that %m maps to the specified error */
706 (void) vsnprintf(buffer
, sizeof buffer
, format
, ap
);
708 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
711 int log_internal_realm(
717 const char *format
, ...) {
722 va_start(ap
, format
);
723 r
= log_internalv_realm(level
, error
, file
, line
, func
, format
, ap
);
730 static int log_object_internalv(
736 const char *object_field
,
738 const char *extra_field
,
749 if (_likely_(LOG_PRI(level
) > log_max_level
[LOG_REALM_SYSTEMD
]))
752 /* Make sure that %m maps to the specified error */
756 /* Prepend the object name before the message */
761 buffer
= newa(char, n
+ 2 + LINE_MAX
);
762 b
= stpcpy(stpcpy(buffer
, object
), ": ");
764 b
= buffer
= newa(char, LINE_MAX
);
766 (void) vsnprintf(b
, LINE_MAX
, format
, ap
);
768 return log_dispatch_internal(level
, error
, file
, line
, func
,
769 object_field
, object
, extra_field
, extra
, buffer
);
772 int log_object_internal(
778 const char *object_field
,
780 const char *extra_field
,
782 const char *format
, ...) {
787 va_start(ap
, format
);
788 r
= log_object_internalv(level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
, format
, ap
);
794 static void log_assert(
800 const char *format
) {
802 static char buffer
[LINE_MAX
];
803 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
805 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
808 DISABLE_WARNING_FORMAT_NONLITERAL
;
809 (void) snprintf(buffer
, sizeof buffer
, format
, text
, file
, line
, func
);
812 log_abort_msg
= buffer
;
814 log_dispatch_internal(level
, 0, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
817 noreturn
void log_assert_failed_realm(
824 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_CRIT
), text
, file
, line
, func
,
825 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
829 noreturn
void log_assert_failed_unreachable_realm(
836 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_CRIT
), text
, file
, line
, func
,
837 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
841 void log_assert_failed_return_realm(
848 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_DEBUG
), text
, file
, line
, func
,
849 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
852 int log_oom_internal(LogRealm realm
, const char *file
, int line
, const char *func
) {
853 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm
, LOG_ERR
),
854 ENOMEM
, file
, line
, func
, "Out of memory.");
857 int log_format_iovec(
861 bool newline_separator
,
866 static const char nl
= '\n';
868 while (format
&& *n
+ 1 < iovec_len
) {
873 /* We need to copy the va_list structure,
874 * since vasprintf() leaves it afterwards at
875 * an undefined location */
881 r
= vasprintf(&m
, format
, aq
);
886 /* Now, jump enough ahead, so that we point to
887 * the next format string */
888 VA_FORMAT_ADVANCE(format
, ap
);
890 iovec
[(*n
)++] = IOVEC_MAKE_STRING(m
);
892 if (newline_separator
) {
893 iovec
[*n
].iov_base
= (char*) &nl
;
894 iovec
[*n
].iov_len
= 1;
898 format
= va_arg(ap
, char *);
903 int log_struct_internal(
909 const char *format
, ...) {
911 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
920 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
923 if (log_target
== LOG_TARGET_NULL
)
926 if ((level
& LOG_FACMASK
) == 0)
927 level
= log_facility
| LOG_PRI(level
);
929 if (IN_SET(log_target
,
931 LOG_TARGET_JOURNAL_OR_KMSG
,
932 LOG_TARGET_JOURNAL
)) {
934 if (open_when_needed
)
937 if (journal_fd
>= 0) {
938 char header
[LINE_MAX
];
939 struct iovec iovec
[17] = {};
945 bool fallback
= false;
947 /* If the journal is available do structured logging */
948 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
);
949 iovec
[n
++] = IOVEC_MAKE_STRING(header
);
951 va_start(ap
, format
);
952 r
= log_format_iovec(iovec
, ELEMENTSOF(iovec
), &n
, true, error
, format
, ap
);
957 (void) sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
);
961 for (i
= 1; i
< n
; i
+= 2)
962 free(iovec
[i
].iov_base
);
965 if (open_when_needed
)
973 /* Fallback if journal logging is not available or didn't work. */
975 va_start(ap
, format
);
983 (void) vsnprintf(buf
, sizeof buf
, format
, aq
);
986 if (startswith(buf
, "MESSAGE=")) {
991 VA_FORMAT_ADVANCE(format
, ap
);
993 format
= va_arg(ap
, char *);
998 if (open_when_needed
)
1004 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buf
+ 8);
1007 int log_struct_iovec_internal(
1013 const struct iovec input_iovec
[],
1014 size_t n_input_iovec
) {
1016 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
1024 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
1027 if (log_target
== LOG_TARGET_NULL
)
1030 if ((level
& LOG_FACMASK
) == 0)
1031 level
= log_facility
| LOG_PRI(level
);
1033 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
1034 LOG_TARGET_JOURNAL_OR_KMSG
,
1035 LOG_TARGET_JOURNAL
) &&
1038 struct iovec iovec
[1 + n_input_iovec
*2];
1039 char header
[LINE_MAX
];
1040 struct msghdr mh
= {
1042 .msg_iovlen
= 1 + n_input_iovec
*2,
1045 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
);
1046 iovec
[0] = IOVEC_MAKE_STRING(header
);
1048 for (i
= 0; i
< n_input_iovec
; i
++) {
1049 iovec
[1+i
*2] = input_iovec
[i
];
1050 iovec
[1+i
*2+1] = IOVEC_MAKE_STRING("\n");
1053 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) >= 0)
1057 for (i
= 0; i
< n_input_iovec
; i
++) {
1058 if (input_iovec
[i
].iov_len
< STRLEN("MESSAGE="))
1061 if (memcmp(input_iovec
[i
].iov_base
, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
1065 if (_unlikely_(i
>= n_input_iovec
)) /* Couldn't find MESSAGE=? */
1068 m
= strndupa(input_iovec
[i
].iov_base
+ STRLEN("MESSAGE="),
1069 input_iovec
[i
].iov_len
- STRLEN("MESSAGE="));
1071 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, m
);
1074 int log_set_target_from_string(const char *e
) {
1077 t
= log_target_from_string(e
);
1085 int log_set_max_level_from_string_realm(LogRealm realm
, const char *e
) {
1088 t
= log_level_from_string(e
);
1092 log_set_max_level_realm(realm
, t
);
1096 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
1099 * The systemd.log_xyz= settings are parsed by all tools, and
1102 * However, "quiet" is only parsed by PID 1, and only turns of
1103 * status output to /dev/console, but does not alter the log
1107 if (streq(key
, "debug") && !value
)
1108 log_set_max_level(LOG_DEBUG
);
1110 else if (proc_cmdline_key_streq(key
, "systemd.log_target")) {
1112 if (proc_cmdline_value_missing(key
, value
))
1115 if (log_set_target_from_string(value
) < 0)
1116 log_warning("Failed to parse log target '%s'. Ignoring.", value
);
1118 } else if (proc_cmdline_key_streq(key
, "systemd.log_level")) {
1120 if (proc_cmdline_value_missing(key
, value
))
1123 if (log_set_max_level_from_string(value
) < 0)
1124 log_warning("Failed to parse log level '%s'. Ignoring.", value
);
1126 } else if (proc_cmdline_key_streq(key
, "systemd.log_color")) {
1128 if (log_show_color_from_string(value
?: "1") < 0)
1129 log_warning("Failed to parse log color setting '%s'. Ignoring.", value
);
1131 } else if (proc_cmdline_key_streq(key
, "systemd.log_location")) {
1133 if (log_show_location_from_string(value
?: "1") < 0)
1134 log_warning("Failed to parse log location setting '%s'. Ignoring.", value
);
1140 void log_parse_environment_realm(LogRealm realm
) {
1141 /* Do not call from library code. */
1145 if (get_ctty_devnr(0, NULL
) < 0)
1146 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1148 (void) proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_STRIP_RD_PREFIX
);
1150 e
= getenv("SYSTEMD_LOG_TARGET");
1151 if (e
&& log_set_target_from_string(e
) < 0)
1152 log_warning("Failed to parse log target '%s'. Ignoring.", e
);
1154 e
= getenv("SYSTEMD_LOG_LEVEL");
1155 if (e
&& log_set_max_level_from_string_realm(realm
, e
) < 0)
1156 log_warning("Failed to parse log level '%s'. Ignoring.", e
);
1158 e
= getenv("SYSTEMD_LOG_COLOR");
1159 if (e
&& log_show_color_from_string(e
) < 0)
1160 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1162 e
= getenv("SYSTEMD_LOG_LOCATION");
1163 if (e
&& log_show_location_from_string(e
) < 0)
1164 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1167 LogTarget
log_get_target(void) {
1171 int log_get_max_level_realm(LogRealm realm
) {
1172 return log_max_level
[realm
];
1175 void log_show_color(bool b
) {
1179 bool log_get_show_color(void) {
1183 void log_show_location(bool b
) {
1187 bool log_get_show_location(void) {
1188 return show_location
;
1191 int log_show_color_from_string(const char *e
) {
1194 t
= parse_boolean(e
);
1202 int log_show_location_from_string(const char *e
) {
1205 t
= parse_boolean(e
);
1209 log_show_location(t
);
1213 bool log_on_console(void) {
1214 if (IN_SET(log_target
, LOG_TARGET_CONSOLE
,
1215 LOG_TARGET_CONSOLE_PREFIXED
))
1218 return syslog_fd
< 0 && kmsg_fd
< 0 && journal_fd
< 0;
1221 static const char *const log_target_table
[_LOG_TARGET_MAX
] = {
1222 [LOG_TARGET_CONSOLE
] = "console",
1223 [LOG_TARGET_CONSOLE_PREFIXED
] = "console-prefixed",
1224 [LOG_TARGET_KMSG
] = "kmsg",
1225 [LOG_TARGET_JOURNAL
] = "journal",
1226 [LOG_TARGET_JOURNAL_OR_KMSG
] = "journal-or-kmsg",
1227 [LOG_TARGET_SYSLOG
] = "syslog",
1228 [LOG_TARGET_SYSLOG_OR_KMSG
] = "syslog-or-kmsg",
1229 [LOG_TARGET_AUTO
] = "auto",
1230 [LOG_TARGET_NULL
] = "null",
1233 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);
1235 void log_received_signal(int level
, const struct signalfd_siginfo
*si
) {
1238 if (pid_is_valid(si
->ssi_pid
)) {
1239 _cleanup_free_
char *p
= NULL
;
1241 (void) get_process_comm(si
->ssi_pid
, &p
);
1244 "Received SIG%s from PID %"PRIu32
" (%s).",
1245 signal_to_string(si
->ssi_signo
),
1246 si
->ssi_pid
, strna(p
));
1250 signal_to_string(si
->ssi_signo
));
1253 int log_syntax_internal(
1256 const char *config_file
,
1257 unsigned config_line
,
1262 const char *format
, ...) {
1265 char buffer
[LINE_MAX
];
1267 const char *unit_fmt
= NULL
;
1272 if (_likely_(LOG_PRI(level
) > log_max_level
[LOG_REALM_SYSTEMD
]))
1275 if (log_target
== LOG_TARGET_NULL
)
1281 va_start(ap
, format
);
1282 (void) vsnprintf(buffer
, sizeof buffer
, format
, ap
);
1286 unit_fmt
= getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1288 return log_struct_internal(
1289 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
1292 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
1293 "CONFIG_FILE=%s", config_file
,
1294 "CONFIG_LINE=%u", config_line
,
1295 LOG_MESSAGE("%s:%u: %s", config_file
, config_line
, buffer
),
1300 int log_syntax_invalid_utf8_internal(
1303 const char *config_file
,
1304 unsigned config_line
,
1308 const char *rvalue
) {
1310 _cleanup_free_
char *p
= NULL
;
1313 p
= utf8_escape_invalid(rvalue
);
1315 log_syntax_internal(unit
, level
, config_file
, config_line
, 0, file
, line
, func
,
1316 "String is not UTF-8 clean, ignoring assignment: %s", strna(p
));
1321 void log_set_upgrade_syslog_to_journal(bool b
) {
1322 upgrade_syslog_to_journal
= b
;
1324 /* Make the change effective immediately */
1326 if (log_target
== LOG_TARGET_SYSLOG
)
1327 log_target
= LOG_TARGET_JOURNAL
;
1328 else if (log_target
== LOG_TARGET_SYSLOG_OR_KMSG
)
1329 log_target
= LOG_TARGET_JOURNAL_OR_KMSG
;
1333 void log_set_always_reopen_console(bool b
) {
1334 always_reopen_console
= b
;
1337 void log_set_open_when_needed(bool b
) {
1338 open_when_needed
= b
;
1341 void log_set_prohibit_ipc(bool b
) {
1345 int log_emergency_level(void) {
1346 /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1347 * then the system of the whole system is obviously affected. */
1349 return getpid_cached() == 1 ? LOG_EMERG
: LOG_ERR
;