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 #if 0 /// UNNEEDED by elogind
78 static bool upgrade_syslog_to_journal = false;
80 static bool always_reopen_console = false;
81 static bool open_when_needed = false;
82 static bool prohibit_ipc = false;
84 /* Akin to glibc's __abort_msg; which is private and we hence cannot
86 static char *log_abort_msg = NULL;
88 /* An assert to use in logging functions that does not call recursively
89 * into our logging functions (since that might lead to a loop). */
90 #define assert_raw(expr) \
92 if (_unlikely_(!(expr))) { \
93 fputs(#expr "\n", stderr); \
98 static void log_close_console(void) {
99 console_fd = safe_close_above_stdio(console_fd);
102 static int log_open_console(void) {
104 if (!always_reopen_console) {
105 console_fd = STDERR_FILENO;
109 if (console_fd < 3) {
110 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
114 console_fd = fd_move_above_stdio(console_fd);
120 static void log_close_kmsg(void) {
121 kmsg_fd = safe_close(kmsg_fd);
124 static int log_open_kmsg(void) {
129 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
133 kmsg_fd = fd_move_above_stdio(kmsg_fd);
137 static void log_close_syslog(void) {
138 syslog_fd = safe_close(syslog_fd);
141 static int create_log_socket(int type) {
145 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
149 fd = fd_move_above_stdio(fd);
150 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
152 /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
153 * in the unlikely case of a deadlock. */
154 if (getpid_cached() == 1)
155 timeval_store(&tv, 10 * USEC_PER_MSEC);
157 timeval_store(&tv, 10 * USEC_PER_SEC);
158 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
163 static int log_open_syslog(void) {
165 static const union sockaddr_union sa = {
166 .un.sun_family = AF_UNIX,
167 .un.sun_path = "/dev/log",
175 syslog_fd = create_log_socket(SOCK_DGRAM);
181 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
182 safe_close(syslog_fd);
184 /* Some legacy syslog systems still use stream
185 * sockets. They really shouldn't. But what can we
187 syslog_fd = create_log_socket(SOCK_STREAM);
193 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
198 syslog_is_stream = true;
200 syslog_is_stream = false;
209 static void log_close_journal(void) {
210 #if 0 /// elogind does not support journald
211 journal_fd = safe_close(journal_fd);
215 #if 0 /// UNNEEDED by elogind
216 static int log_open_journal(void) {
218 static const union sockaddr_union sa = {
219 .un.sun_family = AF_UNIX,
220 .un.sun_path = "/run/systemd/journal/socket",
228 journal_fd = create_log_socket(SOCK_DGRAM);
229 if (journal_fd < 0) {
234 if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
250 /* Do not call from library code. */
252 /* If we don't use the console we close it here, to not get
253 * killed by SAK. If we don't use syslog we close it here so
254 * that we are not confused by somebody deleting the socket in
255 * the fs, and to make sure we don't use it if prohibit_ipc is
256 * set. If we don't use /dev/kmsg we still keep it open,
257 * because there is no reason to close it. */
259 if (log_target == LOG_TARGET_NULL) {
266 if (log_target != LOG_TARGET_AUTO ||
267 getpid_cached() == 1 ||
268 isatty(STDERR_FILENO) <= 0) {
270 #if 0 /// elogind does not support logging to systemd-journald
272 IN_SET(log_target, LOG_TARGET_AUTO,
273 LOG_TARGET_JOURNAL_OR_KMSG,
274 LOG_TARGET_JOURNAL)) {
275 r = log_open_journal();
285 IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
286 LOG_TARGET_SYSLOG)) {
287 r = log_open_syslog();
295 if (IN_SET(log_target, LOG_TARGET_AUTO,
296 LOG_TARGET_JOURNAL_OR_KMSG,
297 LOG_TARGET_SYSLOG_OR_KMSG,
312 return log_open_console();
315 void log_set_target(LogTarget target) {
317 assert(target < _LOG_TARGET_MAX);
319 #if 0 /// elogind does not support logging to systemd-journald
320 if (upgrade_syslog_to_journal) {
321 if (target == LOG_TARGET_SYSLOG)
322 target = LOG_TARGET_JOURNAL;
323 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
324 target = LOG_TARGET_JOURNAL_OR_KMSG;
331 void log_close(void) {
332 /* Do not call from library code. */
340 #if 0 /// UNNEEDED by elogind
341 void log_forget_fds(void) {
342 /* Do not call from library code. */
344 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
348 void log_set_max_level_realm(LogRealm realm, int level) {
349 assert((level & LOG_PRIMASK) == level);
350 assert(realm < ELEMENTSOF(log_max_level));
352 log_max_level[realm] = level;
355 void log_set_facility(int facility) {
356 log_facility = facility;
359 static int write_to_console(
365 const char *buffer) {
367 char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
368 struct iovec iovec[6] = {};
375 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
376 xsprintf(prefix, "<%i>", level);
377 iovec[n++] = IOVEC_MAKE_STRING(prefix);
380 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
383 (void) snprintf(location, sizeof location, "(%s:%i) ", file, line);
384 iovec[n++] = IOVEC_MAKE_STRING(location);
388 iovec[n++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED);
389 iovec[n++] = IOVEC_MAKE_STRING(buffer);
391 iovec[n++] = IOVEC_MAKE_STRING(ANSI_NORMAL);
392 iovec[n++] = IOVEC_MAKE_STRING("\n");
394 if (writev(console_fd, iovec, n) < 0) {
396 if (errno == EIO && getpid_cached() == 1) {
398 /* If somebody tried to kick us from our
399 * console tty (via vhangup() or suchlike),
400 * try to reconnect */
408 if (writev(console_fd, iovec, n) < 0)
417 static int write_to_syslog(
423 const char *buffer) {
425 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
427 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
428 struct iovec iovec[5] = {};
429 struct msghdr msghdr = {
431 .msg_iovlen = ELEMENTSOF(iovec),
439 xsprintf(header_priority, "<%i>", level);
441 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
446 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
449 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
451 iovec[0] = IOVEC_MAKE_STRING(header_priority);
452 iovec[1] = IOVEC_MAKE_STRING(header_time);
453 iovec[2] = IOVEC_MAKE_STRING(program_invocation_short_name);
454 iovec[3] = IOVEC_MAKE_STRING(header_pid);
455 iovec[4] = IOVEC_MAKE_STRING(buffer);
457 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
458 if (syslog_is_stream)
464 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
468 if (!syslog_is_stream ||
469 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
472 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
478 static int write_to_kmsg(
484 const char *buffer) {
486 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
487 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
488 struct iovec iovec[5] = {};
493 xsprintf(header_priority, "<%i>", level);
494 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
496 iovec[0] = IOVEC_MAKE_STRING(header_priority);
497 iovec[1] = IOVEC_MAKE_STRING(program_invocation_short_name);
498 iovec[2] = IOVEC_MAKE_STRING(header_pid);
499 iovec[3] = IOVEC_MAKE_STRING(buffer);
500 iovec[4] = IOVEC_MAKE_STRING("\n");
502 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
508 static int log_do_header(
513 const char *file, int line, const char *func,
514 const char *object_field, const char *object,
515 const char *extra_field, const char *extra) {
518 r = snprintf(header, size,
520 "SYSLOG_FACILITY=%i\n"
521 "%s%.256s%s" /* CODE_FILE */
522 "%s%.*i%s" /* CODE_LINE */
523 "%s%.256s%s" /* CODE_FUNC */
524 "%s%.*i%s" /* ERRNO */
525 "%s%.256s%s" /* object */
526 "%s%.256s%s" /* extra */
527 "SYSLOG_IDENTIFIER=%.256s\n",
530 isempty(file) ? "" : "CODE_FILE=",
531 isempty(file) ? "" : file,
532 isempty(file) ? "" : "\n",
533 line ? "CODE_LINE=" : "",
534 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
536 isempty(func) ? "" : "CODE_FUNC=",
537 isempty(func) ? "" : func,
538 isempty(func) ? "" : "\n",
539 error ? "ERRNO=" : "",
540 error ? 1 : 0, error,
542 isempty(object) ? "" : object_field,
543 isempty(object) ? "" : object,
544 isempty(object) ? "" : "\n",
545 isempty(extra) ? "" : extra_field,
546 isempty(extra) ? "" : extra,
547 isempty(extra) ? "" : "\n",
548 program_invocation_short_name);
549 assert_raw((size_t) r < size);
554 #if 0 /// UNNEEDED by elogind
555 static int write_to_journal(
561 const char *object_field,
563 const char *extra_field,
565 const char *buffer) {
567 char header[LINE_MAX];
568 struct iovec iovec[4] = {};
569 struct msghdr mh = {};
574 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
576 iovec[0] = IOVEC_MAKE_STRING(header);
577 iovec[1] = IOVEC_MAKE_STRING("MESSAGE=");
578 iovec[2] = IOVEC_MAKE_STRING(buffer);
579 iovec[3] = IOVEC_MAKE_STRING("\n");
582 mh.msg_iovlen = ELEMENTSOF(iovec);
584 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
591 int log_dispatch_internal(
597 const char *object_field,
599 const char *extra_field,
608 if (log_target == LOG_TARGET_NULL)
611 /* Patch in LOG_DAEMON facility if necessary */
612 if ((level & LOG_FACMASK) == 0)
613 level = log_facility | LOG_PRI(level);
615 if (open_when_needed)
622 buffer += strspn(buffer, NEWLINE);
627 if ((e = strpbrk(buffer, NEWLINE)))
630 #if 0 /// elogind does not support logging to systemd-journald
631 if (IN_SET(log_target, LOG_TARGET_AUTO,
632 LOG_TARGET_JOURNAL_OR_KMSG,
633 LOG_TARGET_JOURNAL)) {
635 k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
636 if (k < 0 && k != -EAGAIN)
641 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
642 LOG_TARGET_SYSLOG)) {
644 k = write_to_syslog(level, error, file, line, func, buffer);
645 if (k < 0 && k != -EAGAIN)
650 IN_SET(log_target, LOG_TARGET_AUTO,
651 LOG_TARGET_SYSLOG_OR_KMSG,
652 LOG_TARGET_JOURNAL_OR_KMSG,
658 k = write_to_kmsg(level, error, file, line, func, buffer);
666 (void) write_to_console(level, error, file, line, func, buffer);
671 if (open_when_needed)
677 int log_dump_internal(
685 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
688 /* This modifies the buffer... */
693 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
696 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
699 int log_internalv_realm(
708 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
709 char buffer[LINE_MAX];
715 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
718 /* Make sure that %m maps to the specified error */
722 (void) vsnprintf(buffer, sizeof buffer, format, ap);
724 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
727 int log_internal_realm(
733 const char *format, ...) {
738 va_start(ap, format);
739 r = log_internalv_realm(level, error, file, line, func, format, ap);
746 static int log_object_internalv(
752 const char *object_field,
754 const char *extra_field,
765 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
768 /* Make sure that %m maps to the specified error */
772 /* Prepend the object name before the message */
777 buffer = newa(char, n + 2 + LINE_MAX);
778 b = stpcpy(stpcpy(buffer, object), ": ");
780 b = buffer = newa(char, LINE_MAX);
782 (void) vsnprintf(b, LINE_MAX, format, ap);
784 return log_dispatch_internal(level, error, file, line, func,
785 object_field, object, extra_field, extra, buffer);
788 int log_object_internal(
794 const char *object_field,
796 const char *extra_field,
798 const char *format, ...) {
803 va_start(ap, format);
804 r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
810 static void log_assert(
816 const char *format) {
818 static char buffer[LINE_MAX];
819 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
821 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
824 DISABLE_WARNING_FORMAT_NONLITERAL;
825 (void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
828 log_abort_msg = buffer;
830 log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
833 noreturn void log_assert_failed_realm(
840 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
841 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
845 noreturn void log_assert_failed_unreachable_realm(
852 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
853 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
857 void log_assert_failed_return_realm(
864 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
865 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
868 int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
869 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
870 ENOMEM, file, line, func, "Out of memory.");
873 int log_format_iovec(
877 bool newline_separator,
882 static const char nl = '\n';
884 while (format && *n + 1 < iovec_len) {
889 /* We need to copy the va_list structure,
890 * since vasprintf() leaves it afterwards at
891 * an undefined location */
897 r = vasprintf(&m, format, aq);
902 /* Now, jump enough ahead, so that we point to
903 * the next format string */
904 VA_FORMAT_ADVANCE(format, ap);
906 iovec[(*n)++] = IOVEC_MAKE_STRING(m);
908 if (newline_separator) {
909 iovec[*n].iov_base = (char*) &nl;
910 iovec[*n].iov_len = 1;
914 format = va_arg(ap, char *);
919 int log_struct_internal(
925 const char *format, ...) {
927 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
936 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
939 if (log_target == LOG_TARGET_NULL)
942 if ((level & LOG_FACMASK) == 0)
943 level = log_facility | LOG_PRI(level);
945 #if 0 /// elogind does not support logging to systemd-journald
946 if (IN_SET(log_target,
948 LOG_TARGET_JOURNAL_OR_KMSG,
949 LOG_TARGET_JOURNAL)) {
951 if (open_when_needed)
954 if (journal_fd >= 0) {
955 char header[LINE_MAX];
956 struct iovec iovec[17] = {};
962 bool fallback = false;
964 /* If the journal is available do structured logging */
965 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
966 iovec[n++] = IOVEC_MAKE_STRING(header);
968 va_start(ap, format);
969 r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
974 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
978 for (i = 1; i < n; i += 2)
979 free(iovec[i].iov_base);
982 if (open_when_needed)
991 /* Fallback if journal logging is not available or didn't work. */
993 va_start(ap, format);
1001 (void) vsnprintf(buf, sizeof buf, format, aq);
1004 if (startswith(buf, "MESSAGE=")) {
1009 VA_FORMAT_ADVANCE(format, ap);
1011 format = va_arg(ap, char *);
1016 if (open_when_needed)
1022 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
1025 int log_struct_iovec_internal(
1031 const struct iovec input_iovec[],
1032 size_t n_input_iovec) {
1034 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
1042 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
1045 if (log_target == LOG_TARGET_NULL)
1048 if ((level & LOG_FACMASK) == 0)
1049 level = log_facility | LOG_PRI(level);
1051 if (IN_SET(log_target, LOG_TARGET_AUTO,
1052 LOG_TARGET_JOURNAL_OR_KMSG,
1053 LOG_TARGET_JOURNAL) &&
1056 struct iovec iovec[1 + n_input_iovec*2];
1057 char header[LINE_MAX];
1058 struct msghdr mh = {
1060 .msg_iovlen = 1 + n_input_iovec*2,
1063 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
1064 iovec[0] = IOVEC_MAKE_STRING(header);
1066 for (i = 0; i < n_input_iovec; i++) {
1067 iovec[1+i*2] = input_iovec[i];
1068 iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
1071 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0)
1075 for (i = 0; i < n_input_iovec; i++) {
1076 if (input_iovec[i].iov_len < STRLEN("MESSAGE="))
1079 if (memcmp(input_iovec[i].iov_base, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
1083 if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
1086 m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
1087 input_iovec[i].iov_len - STRLEN("MESSAGE="));
1089 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
1092 int log_set_target_from_string(const char *e) {
1095 t = log_target_from_string(e);
1103 int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
1106 t = log_level_from_string(e);
1110 log_set_max_level_realm(realm, t);
1114 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
1117 * The systemd.log_xyz= settings are parsed by all tools, and
1120 * However, "quiet" is only parsed by PID 1, and only turns of
1121 * status output to /dev/console, but does not alter the log
1125 if (streq(key, "debug") && !value)
1126 log_set_max_level(LOG_DEBUG);
1128 else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1130 if (proc_cmdline_value_missing(key, value))
1133 if (log_set_target_from_string(value) < 0)
1134 log_warning("Failed to parse log target '%s'. Ignoring.", value);
1136 } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1138 if (proc_cmdline_value_missing(key, value))
1141 if (log_set_max_level_from_string(value) < 0)
1142 log_warning("Failed to parse log level '%s'. Ignoring.", value);
1144 } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
1146 if (log_show_color_from_string(value ?: "1") < 0)
1147 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1149 } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
1151 if (log_show_location_from_string(value ?: "1") < 0)
1152 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1158 void log_parse_environment_realm(LogRealm realm) {
1159 /* Do not call from library code. */
1163 if (get_ctty_devnr(0, NULL) < 0)
1164 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1166 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
1168 e = getenv("SYSTEMD_LOG_TARGET");
1169 if (e && log_set_target_from_string(e) < 0)
1170 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1172 e = getenv("SYSTEMD_LOG_LEVEL");
1173 if (e && log_set_max_level_from_string_realm(realm, e) < 0)
1174 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1176 e = getenv("SYSTEMD_LOG_COLOR");
1177 if (e && log_show_color_from_string(e) < 0)
1178 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1180 e = getenv("SYSTEMD_LOG_LOCATION");
1181 if (e && log_show_location_from_string(e) < 0)
1182 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1185 LogTarget log_get_target(void) {
1189 int log_get_max_level_realm(LogRealm realm) {
1190 return log_max_level[realm];
1193 void log_show_color(bool b) {
1197 bool log_get_show_color(void) {
1201 void log_show_location(bool b) {
1205 bool log_get_show_location(void) {
1206 return show_location;
1209 int log_show_color_from_string(const char *e) {
1212 t = parse_boolean(e);
1220 int log_show_location_from_string(const char *e) {
1223 t = parse_boolean(e);
1227 log_show_location(t);
1231 bool log_on_console(void) {
1232 if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1233 LOG_TARGET_CONSOLE_PREFIXED))
1236 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1239 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1240 [LOG_TARGET_CONSOLE] = "console",
1241 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1242 [LOG_TARGET_KMSG] = "kmsg",
1243 #if 0 /// elogind does not support logging to systemd-journald
1244 [LOG_TARGET_JOURNAL] = "journal",
1245 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1247 [LOG_TARGET_SYSLOG] = "syslog",
1248 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1249 [LOG_TARGET_AUTO] = "auto",
1250 [LOG_TARGET_NULL] = "null",
1253 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1255 #if 0 /// UNNEEDED by elogind
1256 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1259 if (pid_is_valid(si->ssi_pid)) {
1260 _cleanup_free_ char *p = NULL;
1262 (void) get_process_comm(si->ssi_pid, &p);
1265 "Received SIG%s from PID %"PRIu32" (%s).",
1266 signal_to_string(si->ssi_signo),
1267 si->ssi_pid, strna(p));
1271 signal_to_string(si->ssi_signo));
1275 int log_syntax_internal(
1278 const char *config_file,
1279 unsigned config_line,
1284 const char *format, ...) {
1287 char buffer[LINE_MAX];
1289 const char *unit_fmt = NULL;
1294 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
1297 if (log_target == LOG_TARGET_NULL)
1303 va_start(ap, format);
1304 (void) vsnprintf(buffer, sizeof buffer, format, ap);
1308 unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1310 return log_struct_internal(
1311 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
1314 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1315 "CONFIG_FILE=%s", config_file,
1316 "CONFIG_LINE=%u", config_line,
1317 LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
1322 int log_syntax_invalid_utf8_internal(
1325 const char *config_file,
1326 unsigned config_line,
1330 const char *rvalue) {
1332 _cleanup_free_ char *p = NULL;
1335 p = utf8_escape_invalid(rvalue);
1337 log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
1338 "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
1343 #if 0 /// UNNEEDED by elogind
1344 void log_set_upgrade_syslog_to_journal(bool b) {
1345 upgrade_syslog_to_journal = b;
1347 /* Make the change effective immediately */
1349 if (log_target == LOG_TARGET_SYSLOG)
1350 log_target = LOG_TARGET_JOURNAL;
1351 else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
1352 log_target = LOG_TARGET_JOURNAL_OR_KMSG;
1356 void log_set_always_reopen_console(bool b) {
1357 always_reopen_console = b;
1361 void log_set_open_when_needed(bool b) {
1362 open_when_needed = b;
1365 void log_set_prohibit_ipc(bool b) {
1369 int log_emergency_level(void) {
1370 /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1371 * then the system of the whole system is obviously affected. */
1373 return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;