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"
59 #define SNDBUF_SIZE (8*1024*1024)
61 static LogTarget log_target
= LOG_TARGET_CONSOLE
;
62 static int log_max_level
[] = {LOG_INFO
, LOG_INFO
};
63 assert_cc(ELEMENTSOF(log_max_level
) == _LOG_REALM_MAX
);
64 static int log_facility
= LOG_DAEMON
;
66 static int console_fd
= STDERR_FILENO
;
67 static int syslog_fd
= -1;
68 static int kmsg_fd
= -1;
69 static int journal_fd
= -1;
71 static bool syslog_is_stream
= false;
73 static bool show_color
= false;
74 static bool show_location
= false;
76 static bool upgrade_syslog_to_journal
= false;
77 static bool always_reopen_console
= false;
78 static bool open_when_needed
= false;
80 /* Akin to glibc's __abort_msg; which is private and we hence cannot
82 static char *log_abort_msg
= NULL
;
84 void log_close_console(void) {
89 if (getpid_cached() == 1) {
91 safe_close(console_fd
);
97 static int log_open_console(void) {
102 if (always_reopen_console
) {
103 console_fd
= open_terminal("/dev/console", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
107 console_fd
= STDERR_FILENO
;
112 void log_close_kmsg(void) {
113 kmsg_fd
= safe_close(kmsg_fd
);
116 static int log_open_kmsg(void) {
121 kmsg_fd
= open("/dev/kmsg", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
128 void log_close_syslog(void) {
129 syslog_fd
= safe_close(syslog_fd
);
132 static int create_log_socket(int type
) {
136 fd
= socket(AF_UNIX
, type
|SOCK_CLOEXEC
, 0);
140 (void) fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
142 /* We need a blocking fd here since we'd otherwise lose
143 messages way too early. However, let's not hang forever in the
144 unlikely case of a deadlock. */
145 if (getpid_cached() == 1)
146 timeval_store(&tv
, 10 * USEC_PER_MSEC
);
148 timeval_store(&tv
, 10 * USEC_PER_SEC
);
149 (void) setsockopt(fd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
154 static int log_open_syslog(void) {
156 static const union sockaddr_union sa
= {
157 .un
.sun_family
= AF_UNIX
,
158 .un
.sun_path
= "/dev/log",
166 syslog_fd
= create_log_socket(SOCK_DGRAM
);
172 if (connect(syslog_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
173 safe_close(syslog_fd
);
175 /* Some legacy syslog systems still use stream
176 * sockets. They really shouldn't. But what can we
178 syslog_fd
= create_log_socket(SOCK_STREAM
);
184 if (connect(syslog_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
189 syslog_is_stream
= true;
191 syslog_is_stream
= false;
200 void log_close_journal(void) {
201 journal_fd
= safe_close(journal_fd
);
204 static int log_open_journal(void) {
206 static const union sockaddr_union sa
= {
207 .un
.sun_family
= AF_UNIX
,
208 .un
.sun_path
= "/run/systemd/journal/socket",
216 journal_fd
= create_log_socket(SOCK_DGRAM
);
217 if (journal_fd
< 0) {
222 if (connect(journal_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
237 /* Do not call from library code. */
239 /* If we don't use the console we close it here, to not get
240 * killed by SAK. If we don't use syslog we close it here so
241 * that we are not confused by somebody deleting the socket in
242 * the fs. If we don't use /dev/kmsg we still keep it open,
243 * because there is no reason to close it. */
245 if (log_target
== LOG_TARGET_NULL
) {
252 if (!IN_SET(log_target
, LOG_TARGET_AUTO
, LOG_TARGET_SAFE
) ||
253 getpid_cached() == 1 ||
254 isatty(STDERR_FILENO
) <= 0) {
256 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
257 LOG_TARGET_JOURNAL_OR_KMSG
,
258 LOG_TARGET_JOURNAL
)) {
259 r
= log_open_journal();
267 if (IN_SET(log_target
, LOG_TARGET_SYSLOG_OR_KMSG
,
268 LOG_TARGET_SYSLOG
)) {
269 r
= log_open_syslog();
277 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
279 LOG_TARGET_JOURNAL_OR_KMSG
,
280 LOG_TARGET_SYSLOG_OR_KMSG
,
295 return log_open_console();
298 void log_set_target(LogTarget target
) {
300 assert(target
< _LOG_TARGET_MAX
);
302 if (upgrade_syslog_to_journal
) {
303 if (target
== LOG_TARGET_SYSLOG
)
304 target
= LOG_TARGET_JOURNAL
;
305 else if (target
== LOG_TARGET_SYSLOG_OR_KMSG
)
306 target
= LOG_TARGET_JOURNAL_OR_KMSG
;
312 void log_close(void) {
313 /* Do not call from library code. */
321 void log_forget_fds(void) {
322 /* Do not call from library code. */
324 console_fd
= kmsg_fd
= syslog_fd
= journal_fd
= -1;
327 void log_set_max_level_realm(LogRealm realm
, int level
) {
328 assert((level
& LOG_PRIMASK
) == level
);
329 assert(realm
< ELEMENTSOF(log_max_level
));
331 log_max_level
[realm
] = level
;
334 void log_set_facility(int facility
) {
335 log_facility
= facility
;
338 static int write_to_console(
344 const char *buffer
) {
346 char location
[256], prefix
[1 + DECIMAL_STR_MAX(int) + 2];
347 struct iovec iovec
[6] = {};
354 if (log_target
== LOG_TARGET_CONSOLE_PREFIXED
) {
355 xsprintf(prefix
, "<%i>", level
);
356 iovec
[n
++] = IOVEC_MAKE_STRING(prefix
);
359 highlight
= LOG_PRI(level
) <= LOG_ERR
&& show_color
;
362 xsprintf(location
, "(%s:%i) ", file
, line
);
363 iovec
[n
++] = IOVEC_MAKE_STRING(location
);
367 iovec
[n
++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED
);
368 iovec
[n
++] = IOVEC_MAKE_STRING(buffer
);
370 iovec
[n
++] = IOVEC_MAKE_STRING(ANSI_NORMAL
);
371 iovec
[n
++] = IOVEC_MAKE_STRING("\n");
373 if (writev(console_fd
, iovec
, n
) < 0) {
375 if (errno
== EIO
&& getpid_cached() == 1) {
377 /* If somebody tried to kick us from our
378 * console tty (via vhangup() or suchlike),
379 * try to reconnect */
387 if (writev(console_fd
, iovec
, n
) < 0)
396 static int write_to_syslog(
402 const char *buffer
) {
404 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
406 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
407 struct iovec iovec
[5] = {};
408 struct msghdr msghdr
= {
410 .msg_iovlen
= ELEMENTSOF(iovec
),
418 xsprintf(header_priority
, "<%i>", level
);
420 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
425 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
428 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid_cached());
430 iovec
[0] = IOVEC_MAKE_STRING(header_priority
);
431 iovec
[1] = IOVEC_MAKE_STRING(header_time
);
432 iovec
[2] = IOVEC_MAKE_STRING(program_invocation_short_name
);
433 iovec
[3] = IOVEC_MAKE_STRING(header_pid
);
434 iovec
[4] = IOVEC_MAKE_STRING(buffer
);
436 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
437 if (syslog_is_stream
)
443 n
= sendmsg(syslog_fd
, &msghdr
, MSG_NOSIGNAL
);
447 if (!syslog_is_stream
||
448 (size_t) n
>= IOVEC_TOTAL_SIZE(iovec
, ELEMENTSOF(iovec
)))
451 IOVEC_INCREMENT(iovec
, ELEMENTSOF(iovec
), n
);
457 static int write_to_kmsg(
463 const char *buffer
) {
465 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
466 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
467 struct iovec iovec
[5] = {};
472 xsprintf(header_priority
, "<%i>", level
);
473 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid_cached());
475 iovec
[0] = IOVEC_MAKE_STRING(header_priority
);
476 iovec
[1] = IOVEC_MAKE_STRING(program_invocation_short_name
);
477 iovec
[2] = IOVEC_MAKE_STRING(header_pid
);
478 iovec
[3] = IOVEC_MAKE_STRING(buffer
);
479 iovec
[4] = IOVEC_MAKE_STRING("\n");
481 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
487 static int log_do_header(
492 const char *file
, int line
, const char *func
,
493 const char *object_field
, const char *object
,
494 const char *extra_field
, const char *extra
) {
496 snprintf(header
, size
,
498 "SYSLOG_FACILITY=%i\n"
505 "SYSLOG_IDENTIFIER=%s\n",
508 isempty(file
) ? "" : "CODE_FILE=",
509 isempty(file
) ? "" : file
,
510 isempty(file
) ? "" : "\n",
511 line
? "CODE_LINE=" : "",
512 line
? 1 : 0, line
, /* %.0d means no output too, special case for 0 */
514 isempty(func
) ? "" : "CODE_FUNC=",
515 isempty(func
) ? "" : func
,
516 isempty(func
) ? "" : "\n",
517 error
? "ERRNO=" : "",
518 error
? 1 : 0, error
,
520 isempty(object
) ? "" : object_field
,
521 isempty(object
) ? "" : object
,
522 isempty(object
) ? "" : "\n",
523 isempty(extra
) ? "" : extra_field
,
524 isempty(extra
) ? "" : extra
,
525 isempty(extra
) ? "" : "\n",
526 program_invocation_short_name
);
531 static int write_to_journal(
537 const char *object_field
,
539 const char *extra_field
,
541 const char *buffer
) {
543 char header
[LINE_MAX
];
544 struct iovec iovec
[4] = {};
545 struct msghdr mh
= {};
550 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
);
552 iovec
[0] = IOVEC_MAKE_STRING(header
);
553 iovec
[1] = IOVEC_MAKE_STRING("MESSAGE=");
554 iovec
[2] = IOVEC_MAKE_STRING(buffer
);
555 iovec
[3] = IOVEC_MAKE_STRING("\n");
558 mh
.msg_iovlen
= ELEMENTSOF(iovec
);
560 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) < 0)
566 int log_dispatch_internal(
572 const char *object_field
,
575 const char *extra_field
,
583 if (log_target
== LOG_TARGET_NULL
)
586 /* Patch in LOG_DAEMON facility if necessary */
587 if ((level
& LOG_FACMASK
) == 0)
588 level
= log_facility
| LOG_PRI(level
);
590 if (open_when_needed
)
597 buffer
+= strspn(buffer
, NEWLINE
);
602 if ((e
= strpbrk(buffer
, NEWLINE
)))
605 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
606 LOG_TARGET_JOURNAL_OR_KMSG
,
607 LOG_TARGET_JOURNAL
)) {
609 k
= write_to_journal(level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
, buffer
);
617 if (IN_SET(log_target
, LOG_TARGET_SYSLOG_OR_KMSG
,
618 LOG_TARGET_SYSLOG
)) {
620 k
= write_to_syslog(level
, error
, file
, line
, func
, buffer
);
629 IN_SET(log_target
, LOG_TARGET_AUTO
,
631 LOG_TARGET_SYSLOG_OR_KMSG
,
632 LOG_TARGET_JOURNAL_OR_KMSG
,
635 k
= write_to_kmsg(level
, error
, file
, line
, func
, buffer
);
643 (void) write_to_console(level
, error
, file
, line
, func
, buffer
);
648 if (open_when_needed
)
654 int log_dump_internal(
662 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
665 /* This modifies the buffer... */
670 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
673 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
676 int log_internalv_realm(
685 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
686 char buffer
[LINE_MAX
];
692 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
695 /* Make sure that %m maps to the specified error */
699 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
701 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
704 int log_internal_realm(
710 const char *format
, ...) {
715 va_start(ap
, format
);
716 r
= log_internalv_realm(level
, error
, file
, line
, func
, format
, ap
);
722 int log_object_internalv(
728 const char *object_field
,
730 const char *extra_field
,
741 if (_likely_(LOG_PRI(level
) > log_max_level
[LOG_REALM_SYSTEMD
]))
744 /* Make sure that %m maps to the specified error */
748 /* Prepend the object name before the message */
753 buffer
= newa(char, n
+ 2 + LINE_MAX
);
754 b
= stpcpy(stpcpy(buffer
, object
), ": ");
756 b
= buffer
= newa(char, LINE_MAX
);
758 vsnprintf(b
, LINE_MAX
, format
, ap
);
760 return log_dispatch_internal(level
, error
, file
, line
, func
,
761 object_field
, object
, extra_field
, extra
, buffer
);
764 int log_object_internal(
770 const char *object_field
,
772 const char *extra_field
,
774 const char *format
, ...) {
779 va_start(ap
, format
);
780 r
= log_object_internalv(level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
, format
, ap
);
786 static void log_assert(
792 const char *format
) {
794 static char buffer
[LINE_MAX
];
795 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
797 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
800 DISABLE_WARNING_FORMAT_NONLITERAL
;
801 xsprintf(buffer
, format
, text
, file
, line
, func
);
804 log_abort_msg
= buffer
;
806 log_dispatch_internal(level
, 0, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
809 noreturn
void log_assert_failed_realm(
816 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_CRIT
), text
, file
, line
, func
,
817 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
821 noreturn
void log_assert_failed_unreachable_realm(
828 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_CRIT
), text
, file
, line
, func
,
829 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
833 void log_assert_failed_return_realm(
840 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_DEBUG
), text
, file
, line
, func
,
841 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
844 int log_oom_internal(LogRealm realm
, const char *file
, int line
, const char *func
) {
845 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm
, LOG_ERR
),
846 ENOMEM
, file
, line
, func
, "Out of memory.");
849 int log_format_iovec(
853 bool newline_separator
,
858 static const char nl
= '\n';
860 while (format
&& *n
+ 1 < iovec_len
) {
865 /* We need to copy the va_list structure,
866 * since vasprintf() leaves it afterwards at
867 * an undefined location */
873 r
= vasprintf(&m
, format
, aq
);
878 /* Now, jump enough ahead, so that we point to
879 * the next format string */
880 VA_FORMAT_ADVANCE(format
, ap
);
882 iovec
[(*n
)++] = IOVEC_MAKE_STRING(m
);
884 if (newline_separator
) {
885 iovec
[*n
].iov_base
= (char*) &nl
;
886 iovec
[*n
].iov_len
= 1;
890 format
= va_arg(ap
, char *);
895 int log_struct_internal(
901 const char *format
, ...) {
903 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
912 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
915 if (log_target
== LOG_TARGET_NULL
)
918 if ((level
& LOG_FACMASK
) == 0)
919 level
= log_facility
| LOG_PRI(level
);
921 if (IN_SET(log_target
,
923 LOG_TARGET_JOURNAL_OR_KMSG
,
924 LOG_TARGET_JOURNAL
)) {
926 if (open_when_needed
)
929 if (journal_fd
>= 0) {
930 char header
[LINE_MAX
];
931 struct iovec iovec
[17] = {};
937 bool fallback
= false;
939 /* If the journal is available do structured logging */
940 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
);
941 iovec
[n
++] = IOVEC_MAKE_STRING(header
);
943 va_start(ap
, format
);
944 r
= log_format_iovec(iovec
, ELEMENTSOF(iovec
), &n
, true, error
, format
, ap
);
949 (void) sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
);
953 for (i
= 1; i
< n
; i
+= 2)
954 free(iovec
[i
].iov_base
);
957 if (open_when_needed
)
965 /* Fallback if journal logging is not available or didn't work. */
967 va_start(ap
, format
);
975 vsnprintf(buf
, sizeof(buf
), format
, aq
);
978 if (startswith(buf
, "MESSAGE=")) {
983 VA_FORMAT_ADVANCE(format
, ap
);
985 format
= va_arg(ap
, char *);
990 if (open_when_needed
)
996 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buf
+ 8);
999 int log_struct_iovec_internal(
1005 const struct iovec input_iovec
[],
1006 size_t n_input_iovec
) {
1008 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
1016 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
1019 if (log_target
== LOG_TARGET_NULL
)
1022 if ((level
& LOG_FACMASK
) == 0)
1023 level
= log_facility
| LOG_PRI(level
);
1025 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
1026 LOG_TARGET_JOURNAL_OR_KMSG
,
1027 LOG_TARGET_JOURNAL
) &&
1030 struct iovec iovec
[1 + n_input_iovec
*2];
1031 char header
[LINE_MAX
];
1032 struct msghdr mh
= {
1034 .msg_iovlen
= 1 + n_input_iovec
*2,
1037 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
);
1038 iovec
[0] = IOVEC_MAKE_STRING(header
);
1040 for (i
= 0; i
< n_input_iovec
; i
++) {
1041 iovec
[1+i
*2] = input_iovec
[i
];
1042 iovec
[1+i
*2+1] = IOVEC_MAKE_STRING("\n");
1045 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) >= 0)
1049 for (i
= 0; i
< n_input_iovec
; i
++) {
1050 if (input_iovec
[i
].iov_len
< STRLEN("MESSAGE="))
1053 if (memcmp(input_iovec
[i
].iov_base
, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
1057 if (_unlikely_(i
>= n_input_iovec
)) /* Couldn't find MESSAGE=? */
1060 m
= strndupa(input_iovec
[i
].iov_base
+ STRLEN("MESSAGE="),
1061 input_iovec
[i
].iov_len
- STRLEN("MESSAGE="));
1063 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, m
);
1066 int log_set_target_from_string(const char *e
) {
1069 t
= log_target_from_string(e
);
1077 int log_set_max_level_from_string_realm(LogRealm realm
, const char *e
) {
1080 t
= log_level_from_string(e
);
1084 log_set_max_level_realm(realm
, t
);
1088 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
1091 * The systemd.log_xyz= settings are parsed by all tools, and
1094 * However, "quiet" is only parsed by PID 1, and only turns of
1095 * status output to /dev/console, but does not alter the log
1099 if (streq(key
, "debug") && !value
)
1100 log_set_max_level(LOG_DEBUG
);
1102 else if (proc_cmdline_key_streq(key
, "systemd.log_target")) {
1104 if (proc_cmdline_value_missing(key
, value
))
1107 if (log_set_target_from_string(value
) < 0)
1108 log_warning("Failed to parse log target '%s'. Ignoring.", value
);
1110 } else if (proc_cmdline_key_streq(key
, "systemd.log_level")) {
1112 if (proc_cmdline_value_missing(key
, value
))
1115 if (log_set_max_level_from_string(value
) < 0)
1116 log_warning("Failed to parse log level '%s'. Ignoring.", value
);
1118 } else if (proc_cmdline_key_streq(key
, "systemd.log_color")) {
1120 if (log_show_color_from_string(value
?: "1") < 0)
1121 log_warning("Failed to parse log color setting '%s'. Ignoring.", value
);
1123 } else if (proc_cmdline_key_streq(key
, "systemd.log_location")) {
1125 if (log_show_location_from_string(value
?: "1") < 0)
1126 log_warning("Failed to parse log location setting '%s'. Ignoring.", value
);
1132 void log_parse_environment_realm(LogRealm realm
) {
1133 /* Do not call from library code. */
1137 if (get_ctty_devnr(0, NULL
) < 0)
1138 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1140 (void) proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_STRIP_RD_PREFIX
);
1142 e
= getenv("SYSTEMD_LOG_TARGET");
1143 if (e
&& log_set_target_from_string(e
) < 0)
1144 log_warning("Failed to parse log target '%s'. Ignoring.", e
);
1146 e
= getenv("SYSTEMD_LOG_LEVEL");
1147 if (e
&& log_set_max_level_from_string_realm(realm
, e
) < 0)
1148 log_warning("Failed to parse log level '%s'. Ignoring.", e
);
1150 e
= getenv("SYSTEMD_LOG_COLOR");
1151 if (e
&& log_show_color_from_string(e
) < 0)
1152 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1154 e
= getenv("SYSTEMD_LOG_LOCATION");
1155 if (e
&& log_show_location_from_string(e
) < 0)
1156 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1159 LogTarget
log_get_target(void) {
1163 int log_get_max_level_realm(LogRealm realm
) {
1164 return log_max_level
[realm
];
1167 void log_show_color(bool b
) {
1171 bool log_get_show_color(void) {
1175 void log_show_location(bool b
) {
1179 bool log_get_show_location(void) {
1180 return show_location
;
1183 int log_show_color_from_string(const char *e
) {
1186 t
= parse_boolean(e
);
1194 int log_show_location_from_string(const char *e
) {
1197 t
= parse_boolean(e
);
1201 log_show_location(t
);
1205 bool log_on_console(void) {
1206 if (IN_SET(log_target
, LOG_TARGET_CONSOLE
,
1207 LOG_TARGET_CONSOLE_PREFIXED
))
1210 return syslog_fd
< 0 && kmsg_fd
< 0 && journal_fd
< 0;
1213 static const char *const log_target_table
[_LOG_TARGET_MAX
] = {
1214 [LOG_TARGET_CONSOLE
] = "console",
1215 [LOG_TARGET_CONSOLE_PREFIXED
] = "console-prefixed",
1216 [LOG_TARGET_KMSG
] = "kmsg",
1217 [LOG_TARGET_JOURNAL
] = "journal",
1218 [LOG_TARGET_JOURNAL_OR_KMSG
] = "journal-or-kmsg",
1219 [LOG_TARGET_SYSLOG
] = "syslog",
1220 [LOG_TARGET_SYSLOG_OR_KMSG
] = "syslog-or-kmsg",
1221 [LOG_TARGET_AUTO
] = "auto",
1222 [LOG_TARGET_SAFE
] = "safe",
1223 [LOG_TARGET_NULL
] = "null"
1226 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);
1228 void log_received_signal(int level
, const struct signalfd_siginfo
*si
) {
1229 if (si
->ssi_pid
> 0) {
1230 _cleanup_free_
char *p
= NULL
;
1232 get_process_comm(si
->ssi_pid
, &p
);
1235 "Received SIG%s from PID %"PRIu32
" (%s).",
1236 signal_to_string(si
->ssi_signo
),
1237 si
->ssi_pid
, strna(p
));
1241 signal_to_string(si
->ssi_signo
));
1245 int log_syntax_internal(
1248 const char *config_file
,
1249 unsigned config_line
,
1254 const char *format
, ...) {
1257 char buffer
[LINE_MAX
];
1259 const char *unit_fmt
= NULL
;
1264 if (_likely_(LOG_PRI(level
) > log_max_level
[LOG_REALM_SYSTEMD
]))
1267 if (log_target
== LOG_TARGET_NULL
)
1273 va_start(ap
, format
);
1274 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
1278 unit_fmt
= getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1280 return log_struct_internal(
1281 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
1284 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
1285 "CONFIG_FILE=%s", config_file
,
1286 "CONFIG_LINE=%u", config_line
,
1287 LOG_MESSAGE("%s:%u: %s", config_file
, config_line
, buffer
),
1292 void log_set_upgrade_syslog_to_journal(bool b
) {
1293 upgrade_syslog_to_journal
= b
;
1296 void log_set_always_reopen_console(bool b
) {
1297 always_reopen_console
= b
;
1300 void log_set_open_when_needed(bool b
) {
1301 open_when_needed
= b
;