2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/signalfd.h>
29 #include <sys/socket.h>
36 #include "sd-messages.h"
38 #include "alloc-util.h"
40 #include "format-util.h"
45 #include "parse-util.h"
46 #include "proc-cmdline.h"
47 #include "process-util.h"
48 #include "signal-util.h"
49 #include "socket-util.h"
50 #include "stdio-util.h"
51 #include "string-table.h"
52 #include "string-util.h"
53 #include "syslog-util.h"
54 #include "terminal-util.h"
55 #include "time-util.h"
58 #define SNDBUF_SIZE (8*1024*1024)
60 static LogTarget log_target
= LOG_TARGET_CONSOLE
;
61 static int log_max_level
[] = {LOG_INFO
, LOG_INFO
};
62 assert_cc(ELEMENTSOF(log_max_level
) == _LOG_REALM_MAX
);
63 static int log_facility
= LOG_DAEMON
;
65 static int console_fd
= STDERR_FILENO
;
66 static int syslog_fd
= -1;
67 static int kmsg_fd
= -1;
68 static int journal_fd
= -1;
70 static bool syslog_is_stream
= false;
72 static bool show_color
= false;
73 static bool show_location
= false;
75 static bool upgrade_syslog_to_journal
= false;
76 static bool always_reopen_console
= false;
77 static bool open_when_needed
= false;
79 /* Akin to glibc's __abort_msg; which is private and we hence cannot
81 static char *log_abort_msg
= NULL
;
83 void log_close_console(void) {
88 if (getpid_cached() == 1) {
90 safe_close(console_fd
);
96 static int log_open_console(void) {
101 if (always_reopen_console
) {
102 console_fd
= open_terminal("/dev/console", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
106 console_fd
= STDERR_FILENO
;
111 void log_close_kmsg(void) {
112 kmsg_fd
= safe_close(kmsg_fd
);
115 static int log_open_kmsg(void) {
120 kmsg_fd
= open("/dev/kmsg", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
127 void log_close_syslog(void) {
128 syslog_fd
= safe_close(syslog_fd
);
131 static int create_log_socket(int type
) {
135 fd
= socket(AF_UNIX
, type
|SOCK_CLOEXEC
, 0);
139 (void) fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
141 /* We need a blocking fd here since we'd otherwise lose
142 messages way too early. However, let's not hang forever in the
143 unlikely case of a deadlock. */
144 if (getpid_cached() == 1)
145 timeval_store(&tv
, 10 * USEC_PER_MSEC
);
147 timeval_store(&tv
, 10 * USEC_PER_SEC
);
148 (void) setsockopt(fd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
153 static int log_open_syslog(void) {
155 static const union sockaddr_union sa
= {
156 .un
.sun_family
= AF_UNIX
,
157 .un
.sun_path
= "/dev/log",
165 syslog_fd
= create_log_socket(SOCK_DGRAM
);
171 if (connect(syslog_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
172 safe_close(syslog_fd
);
174 /* Some legacy syslog systems still use stream
175 * sockets. They really shouldn't. But what can we
177 syslog_fd
= create_log_socket(SOCK_STREAM
);
183 if (connect(syslog_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
188 syslog_is_stream
= true;
190 syslog_is_stream
= false;
199 void log_close_journal(void) {
200 journal_fd
= safe_close(journal_fd
);
203 static int log_open_journal(void) {
205 static const union sockaddr_union sa
= {
206 .un
.sun_family
= AF_UNIX
,
207 .un
.sun_path
= "/run/systemd/journal/socket",
215 journal_fd
= create_log_socket(SOCK_DGRAM
);
216 if (journal_fd
< 0) {
221 if (connect(journal_fd
, &sa
.sa
, SOCKADDR_UN_LEN(sa
.un
)) < 0) {
236 /* Do not call from library code. */
238 /* If we don't use the console we close it here, to not get
239 * killed by SAK. If we don't use syslog we close it here so
240 * that we are not confused by somebody deleting the socket in
241 * the fs. If we don't use /dev/kmsg we still keep it open,
242 * because there is no reason to close it. */
244 if (log_target
== LOG_TARGET_NULL
) {
251 if (!IN_SET(log_target
, LOG_TARGET_AUTO
, LOG_TARGET_SAFE
) ||
252 getpid_cached() == 1 ||
253 isatty(STDERR_FILENO
) <= 0) {
255 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
256 LOG_TARGET_JOURNAL_OR_KMSG
,
257 LOG_TARGET_JOURNAL
)) {
258 r
= log_open_journal();
266 if (IN_SET(log_target
, LOG_TARGET_SYSLOG_OR_KMSG
,
267 LOG_TARGET_SYSLOG
)) {
268 r
= log_open_syslog();
276 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
278 LOG_TARGET_JOURNAL_OR_KMSG
,
279 LOG_TARGET_SYSLOG_OR_KMSG
,
294 return log_open_console();
297 void log_set_target(LogTarget target
) {
299 assert(target
< _LOG_TARGET_MAX
);
301 if (upgrade_syslog_to_journal
) {
302 if (target
== LOG_TARGET_SYSLOG
)
303 target
= LOG_TARGET_JOURNAL
;
304 else if (target
== LOG_TARGET_SYSLOG_OR_KMSG
)
305 target
= LOG_TARGET_JOURNAL_OR_KMSG
;
311 void log_close(void) {
312 /* Do not call from library code. */
320 void log_forget_fds(void) {
321 /* Do not call from library code. */
323 console_fd
= kmsg_fd
= syslog_fd
= journal_fd
= -1;
326 void log_set_max_level_realm(LogRealm realm
, int level
) {
327 assert((level
& LOG_PRIMASK
) == level
);
328 assert(realm
< ELEMENTSOF(log_max_level
));
330 log_max_level
[realm
] = level
;
333 void log_set_facility(int facility
) {
334 log_facility
= facility
;
337 static int write_to_console(
343 const char *buffer
) {
345 char location
[256], prefix
[1 + DECIMAL_STR_MAX(int) + 2];
346 struct iovec iovec
[6] = {};
353 if (log_target
== LOG_TARGET_CONSOLE_PREFIXED
) {
354 xsprintf(prefix
, "<%i>", level
);
355 iovec
[n
++] = IOVEC_MAKE_STRING(prefix
);
358 highlight
= LOG_PRI(level
) <= LOG_ERR
&& show_color
;
361 snprintf(location
, sizeof(location
), "(%s:%i) ", file
, line
);
362 iovec
[n
++] = IOVEC_MAKE_STRING(location
);
366 iovec
[n
++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED
);
367 iovec
[n
++] = IOVEC_MAKE_STRING(buffer
);
369 iovec
[n
++] = IOVEC_MAKE_STRING(ANSI_NORMAL
);
370 iovec
[n
++] = IOVEC_MAKE_STRING("\n");
372 if (writev(console_fd
, iovec
, n
) < 0) {
374 if (errno
== EIO
&& getpid_cached() == 1) {
376 /* If somebody tried to kick us from our
377 * console tty (via vhangup() or suchlike),
378 * try to reconnect */
386 if (writev(console_fd
, iovec
, n
) < 0)
395 static int write_to_syslog(
401 const char *buffer
) {
403 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
405 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
406 struct iovec iovec
[5] = {};
407 struct msghdr msghdr
= {
409 .msg_iovlen
= ELEMENTSOF(iovec
),
417 xsprintf(header_priority
, "<%i>", level
);
419 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
424 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
427 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid_cached());
429 iovec
[0] = IOVEC_MAKE_STRING(header_priority
);
430 iovec
[1] = IOVEC_MAKE_STRING(header_time
);
431 iovec
[2] = IOVEC_MAKE_STRING(program_invocation_short_name
);
432 iovec
[3] = IOVEC_MAKE_STRING(header_pid
);
433 iovec
[4] = IOVEC_MAKE_STRING(buffer
);
435 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
436 if (syslog_is_stream
)
442 n
= sendmsg(syslog_fd
, &msghdr
, MSG_NOSIGNAL
);
446 if (!syslog_is_stream
||
447 (size_t) n
>= IOVEC_TOTAL_SIZE(iovec
, ELEMENTSOF(iovec
)))
450 IOVEC_INCREMENT(iovec
, ELEMENTSOF(iovec
), n
);
456 static int write_to_kmsg(
462 const char *buffer
) {
464 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
465 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
466 struct iovec iovec
[5] = {};
471 xsprintf(header_priority
, "<%i>", level
);
472 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid_cached());
474 iovec
[0] = IOVEC_MAKE_STRING(header_priority
);
475 iovec
[1] = IOVEC_MAKE_STRING(program_invocation_short_name
);
476 iovec
[2] = IOVEC_MAKE_STRING(header_pid
);
477 iovec
[3] = IOVEC_MAKE_STRING(buffer
);
478 iovec
[4] = IOVEC_MAKE_STRING("\n");
480 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
486 static int log_do_header(
491 const char *file
, int line
, const char *func
,
492 const char *object_field
, const char *object
,
493 const char *extra_field
, const char *extra
) {
495 snprintf(header
, size
,
497 "SYSLOG_FACILITY=%i\n"
504 "SYSLOG_IDENTIFIER=%s\n",
507 isempty(file
) ? "" : "CODE_FILE=",
508 isempty(file
) ? "" : file
,
509 isempty(file
) ? "" : "\n",
510 line
? "CODE_LINE=" : "",
511 line
? 1 : 0, line
, /* %.0d means no output too, special case for 0 */
513 isempty(func
) ? "" : "CODE_FUNC=",
514 isempty(func
) ? "" : func
,
515 isempty(func
) ? "" : "\n",
516 error
? "ERRNO=" : "",
517 error
? 1 : 0, error
,
519 isempty(object
) ? "" : object_field
,
520 isempty(object
) ? "" : object
,
521 isempty(object
) ? "" : "\n",
522 isempty(extra
) ? "" : extra_field
,
523 isempty(extra
) ? "" : extra
,
524 isempty(extra
) ? "" : "\n",
525 program_invocation_short_name
);
530 static int write_to_journal(
536 const char *object_field
,
538 const char *extra_field
,
540 const char *buffer
) {
542 char header
[LINE_MAX
];
543 struct iovec iovec
[4] = {};
544 struct msghdr mh
= {};
549 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
);
551 iovec
[0] = IOVEC_MAKE_STRING(header
);
552 iovec
[1] = IOVEC_MAKE_STRING("MESSAGE=");
553 iovec
[2] = IOVEC_MAKE_STRING(buffer
);
554 iovec
[3] = IOVEC_MAKE_STRING("\n");
557 mh
.msg_iovlen
= ELEMENTSOF(iovec
);
559 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) < 0)
565 int log_dispatch_internal(
571 const char *object_field
,
574 const char *extra_field
,
582 if (log_target
== LOG_TARGET_NULL
)
585 /* Patch in LOG_DAEMON facility if necessary */
586 if ((level
& LOG_FACMASK
) == 0)
587 level
= log_facility
| LOG_PRI(level
);
589 if (open_when_needed
)
596 buffer
+= strspn(buffer
, NEWLINE
);
601 if ((e
= strpbrk(buffer
, NEWLINE
)))
604 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
605 LOG_TARGET_JOURNAL_OR_KMSG
,
606 LOG_TARGET_JOURNAL
)) {
608 k
= write_to_journal(level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
, buffer
);
616 if (IN_SET(log_target
, LOG_TARGET_SYSLOG_OR_KMSG
,
617 LOG_TARGET_SYSLOG
)) {
619 k
= write_to_syslog(level
, error
, file
, line
, func
, buffer
);
628 IN_SET(log_target
, LOG_TARGET_AUTO
,
630 LOG_TARGET_SYSLOG_OR_KMSG
,
631 LOG_TARGET_JOURNAL_OR_KMSG
,
634 k
= write_to_kmsg(level
, error
, file
, line
, func
, buffer
);
642 (void) write_to_console(level
, error
, file
, line
, func
, buffer
);
647 if (open_when_needed
)
653 int log_dump_internal(
661 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
664 /* This modifies the buffer... */
669 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
672 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
675 int log_internalv_realm(
684 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
685 char buffer
[LINE_MAX
];
691 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
694 /* Make sure that %m maps to the specified error */
698 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
700 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
703 int log_internal_realm(
709 const char *format
, ...) {
714 va_start(ap
, format
);
715 r
= log_internalv_realm(level
, error
, file
, line
, func
, format
, ap
);
721 int log_object_internalv(
727 const char *object_field
,
729 const char *extra_field
,
740 if (_likely_(LOG_PRI(level
) > log_max_level
[LOG_REALM_SYSTEMD
]))
743 /* Make sure that %m maps to the specified error */
747 /* Prepend the object name before the message */
752 buffer
= newa(char, n
+ 2 + LINE_MAX
);
753 b
= stpcpy(stpcpy(buffer
, object
), ": ");
755 b
= buffer
= newa(char, LINE_MAX
);
757 vsnprintf(b
, LINE_MAX
, format
, ap
);
759 return log_dispatch_internal(level
, error
, file
, line
, func
,
760 object_field
, object
, extra_field
, extra
, buffer
);
763 int log_object_internal(
769 const char *object_field
,
771 const char *extra_field
,
773 const char *format
, ...) {
778 va_start(ap
, format
);
779 r
= log_object_internalv(level
, error
, file
, line
, func
, object_field
, object
, extra_field
, extra
, format
, ap
);
785 static void log_assert(
791 const char *format
) {
793 static char buffer
[LINE_MAX
];
794 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
796 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
799 DISABLE_WARNING_FORMAT_NONLITERAL
;
800 snprintf(buffer
, sizeof buffer
, format
, text
, file
, line
, func
);
803 log_abort_msg
= buffer
;
805 log_dispatch_internal(level
, 0, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buffer
);
808 noreturn
void log_assert_failed_realm(
815 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_CRIT
), text
, file
, line
, func
,
816 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
820 noreturn
void log_assert_failed_unreachable_realm(
827 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_CRIT
), text
, file
, line
, func
,
828 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
832 void log_assert_failed_return_realm(
839 log_assert(LOG_REALM_PLUS_LEVEL(realm
, LOG_DEBUG
), text
, file
, line
, func
,
840 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
843 int log_oom_internal(LogRealm realm
, const char *file
, int line
, const char *func
) {
844 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm
, LOG_ERR
),
845 ENOMEM
, file
, line
, func
, "Out of memory.");
848 int log_format_iovec(
852 bool newline_separator
,
857 static const char nl
= '\n';
859 while (format
&& *n
+ 1 < iovec_len
) {
864 /* We need to copy the va_list structure,
865 * since vasprintf() leaves it afterwards at
866 * an undefined location */
872 r
= vasprintf(&m
, format
, aq
);
877 /* Now, jump enough ahead, so that we point to
878 * the next format string */
879 VA_FORMAT_ADVANCE(format
, ap
);
881 iovec
[(*n
)++] = IOVEC_MAKE_STRING(m
);
883 if (newline_separator
) {
884 iovec
[*n
].iov_base
= (char*) &nl
;
885 iovec
[*n
].iov_len
= 1;
889 format
= va_arg(ap
, char *);
894 int log_struct_internal(
900 const char *format
, ...) {
902 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
911 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
914 if (log_target
== LOG_TARGET_NULL
)
917 if ((level
& LOG_FACMASK
) == 0)
918 level
= log_facility
| LOG_PRI(level
);
920 if (IN_SET(log_target
,
922 LOG_TARGET_JOURNAL_OR_KMSG
,
923 LOG_TARGET_JOURNAL
)) {
925 if (open_when_needed
)
928 if (journal_fd
>= 0) {
929 char header
[LINE_MAX
];
930 struct iovec iovec
[17] = {};
936 bool fallback
= false;
938 /* If the journal is available do structured logging */
939 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
);
940 iovec
[n
++] = IOVEC_MAKE_STRING(header
);
942 va_start(ap
, format
);
943 r
= log_format_iovec(iovec
, ELEMENTSOF(iovec
), &n
, true, error
, format
, ap
);
948 (void) sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
);
952 for (i
= 1; i
< n
; i
+= 2)
953 free(iovec
[i
].iov_base
);
956 if (open_when_needed
)
964 /* Fallback if journal logging is not available or didn't work. */
966 va_start(ap
, format
);
974 vsnprintf(buf
, sizeof(buf
), format
, aq
);
977 if (startswith(buf
, "MESSAGE=")) {
982 VA_FORMAT_ADVANCE(format
, ap
);
984 format
= va_arg(ap
, char *);
989 if (open_when_needed
)
995 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, buf
+ 8);
998 int log_struct_iovec_internal(
1004 const struct iovec input_iovec
[],
1005 size_t n_input_iovec
) {
1007 LogRealm realm
= LOG_REALM_REMOVE_LEVEL(level
);
1015 if (_likely_(LOG_PRI(level
) > log_max_level
[realm
]))
1018 if (log_target
== LOG_TARGET_NULL
)
1021 if ((level
& LOG_FACMASK
) == 0)
1022 level
= log_facility
| LOG_PRI(level
);
1024 if (IN_SET(log_target
, LOG_TARGET_AUTO
,
1025 LOG_TARGET_JOURNAL_OR_KMSG
,
1026 LOG_TARGET_JOURNAL
) &&
1029 struct iovec iovec
[1 + n_input_iovec
*2];
1030 char header
[LINE_MAX
];
1031 struct msghdr mh
= {
1033 .msg_iovlen
= 1 + n_input_iovec
*2,
1036 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
);
1037 iovec
[0] = IOVEC_MAKE_STRING(header
);
1039 for (i
= 0; i
< n_input_iovec
; i
++) {
1040 iovec
[1+i
*2] = input_iovec
[i
];
1041 iovec
[1+i
*2+1] = IOVEC_MAKE_STRING("\n");
1044 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) >= 0)
1048 for (i
= 0; i
< n_input_iovec
; i
++) {
1049 if (input_iovec
[i
].iov_len
< strlen("MESSAGE="))
1052 if (memcmp(input_iovec
[i
].iov_base
, "MESSAGE=", strlen("MESSAGE=")) == 0)
1056 if (_unlikely_(i
>= n_input_iovec
)) /* Couldn't find MESSAGE=? */
1059 m
= strndupa(input_iovec
[i
].iov_base
+ strlen("MESSAGE="),
1060 input_iovec
[i
].iov_len
- strlen("MESSAGE="));
1062 return log_dispatch_internal(level
, error
, file
, line
, func
, NULL
, NULL
, NULL
, NULL
, m
);
1065 int log_set_target_from_string(const char *e
) {
1068 t
= log_target_from_string(e
);
1076 int log_set_max_level_from_string_realm(LogRealm realm
, const char *e
) {
1079 t
= log_level_from_string(e
);
1083 log_set_max_level_realm(realm
, t
);
1087 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
1090 * The systemd.log_xyz= settings are parsed by all tools, and
1093 * However, "quiet" is only parsed by PID 1, and only turns of
1094 * status output to /dev/console, but does not alter the log
1098 if (streq(key
, "debug") && !value
)
1099 log_set_max_level(LOG_DEBUG
);
1101 else if (proc_cmdline_key_streq(key
, "systemd.log_target")) {
1103 if (proc_cmdline_value_missing(key
, value
))
1106 if (log_set_target_from_string(value
) < 0)
1107 log_warning("Failed to parse log target '%s'. Ignoring.", value
);
1109 } else if (proc_cmdline_key_streq(key
, "systemd.log_level")) {
1111 if (proc_cmdline_value_missing(key
, value
))
1114 if (log_set_max_level_from_string(value
) < 0)
1115 log_warning("Failed to parse log level '%s'. Ignoring.", value
);
1117 } else if (proc_cmdline_key_streq(key
, "systemd.log_color")) {
1119 if (log_show_color_from_string(value
?: "1") < 0)
1120 log_warning("Failed to parse log color setting '%s'. Ignoring.", value
);
1122 } else if (proc_cmdline_key_streq(key
, "systemd.log_location")) {
1124 if (log_show_location_from_string(value
?: "1") < 0)
1125 log_warning("Failed to parse log location setting '%s'. Ignoring.", value
);
1131 void log_parse_environment_realm(LogRealm realm
) {
1132 /* Do not call from library code. */
1136 if (get_ctty_devnr(0, NULL
) < 0)
1137 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1139 (void) proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_STRIP_RD_PREFIX
);
1141 e
= getenv("SYSTEMD_LOG_TARGET");
1142 if (e
&& log_set_target_from_string(e
) < 0)
1143 log_warning("Failed to parse log target '%s'. Ignoring.", e
);
1145 e
= getenv("SYSTEMD_LOG_LEVEL");
1146 if (e
&& log_set_max_level_from_string_realm(realm
, e
) < 0)
1147 log_warning("Failed to parse log level '%s'. Ignoring.", e
);
1149 e
= getenv("SYSTEMD_LOG_COLOR");
1150 if (e
&& log_show_color_from_string(e
) < 0)
1151 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1153 e
= getenv("SYSTEMD_LOG_LOCATION");
1154 if (e
&& log_show_location_from_string(e
) < 0)
1155 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1158 LogTarget
log_get_target(void) {
1162 int log_get_max_level_realm(LogRealm realm
) {
1163 return log_max_level
[realm
];
1166 void log_show_color(bool b
) {
1170 bool log_get_show_color(void) {
1174 void log_show_location(bool b
) {
1178 bool log_get_show_location(void) {
1179 return show_location
;
1182 int log_show_color_from_string(const char *e
) {
1185 t
= parse_boolean(e
);
1193 int log_show_location_from_string(const char *e
) {
1196 t
= parse_boolean(e
);
1200 log_show_location(t
);
1204 bool log_on_console(void) {
1205 if (IN_SET(log_target
, LOG_TARGET_CONSOLE
,
1206 LOG_TARGET_CONSOLE_PREFIXED
))
1209 return syslog_fd
< 0 && kmsg_fd
< 0 && journal_fd
< 0;
1212 static const char *const log_target_table
[_LOG_TARGET_MAX
] = {
1213 [LOG_TARGET_CONSOLE
] = "console",
1214 [LOG_TARGET_CONSOLE_PREFIXED
] = "console-prefixed",
1215 [LOG_TARGET_KMSG
] = "kmsg",
1216 [LOG_TARGET_JOURNAL
] = "journal",
1217 [LOG_TARGET_JOURNAL_OR_KMSG
] = "journal-or-kmsg",
1218 [LOG_TARGET_SYSLOG
] = "syslog",
1219 [LOG_TARGET_SYSLOG_OR_KMSG
] = "syslog-or-kmsg",
1220 [LOG_TARGET_AUTO
] = "auto",
1221 [LOG_TARGET_SAFE
] = "safe",
1222 [LOG_TARGET_NULL
] = "null"
1225 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);
1227 void log_received_signal(int level
, const struct signalfd_siginfo
*si
) {
1228 if (si
->ssi_pid
> 0) {
1229 _cleanup_free_
char *p
= NULL
;
1231 get_process_comm(si
->ssi_pid
, &p
);
1234 "Received SIG%s from PID %"PRIu32
" (%s).",
1235 signal_to_string(si
->ssi_signo
),
1236 si
->ssi_pid
, strna(p
));
1240 signal_to_string(si
->ssi_signo
));
1244 int log_syntax_internal(
1247 const char *config_file
,
1248 unsigned config_line
,
1253 const char *format
, ...) {
1256 char buffer
[LINE_MAX
];
1258 const char *unit_fmt
= NULL
;
1263 if (_likely_(LOG_PRI(level
) > log_max_level
[LOG_REALM_SYSTEMD
]))
1266 if (log_target
== LOG_TARGET_NULL
)
1272 va_start(ap
, format
);
1273 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
1277 unit_fmt
= getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1279 return log_struct_internal(
1280 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
1283 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
1284 "CONFIG_FILE=%s", config_file
,
1285 "CONFIG_LINE=%u", config_line
,
1286 LOG_MESSAGE("%s:%u: %s", config_file
, config_line
, buffer
),
1291 void log_set_upgrade_syslog_to_journal(bool b
) {
1292 upgrade_syslog_to_journal
= b
;
1295 void log_set_always_reopen_console(bool b
) {
1296 always_reopen_console
= b
;
1299 void log_set_open_when_needed(bool b
) {
1300 open_when_needed
= b
;