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;
83 /* Akin to glibc's __abort_msg; which is private and we hence cannot
85 static char *log_abort_msg = NULL;
87 void log_close_console(void) {
92 if (getpid_cached() == 1) {
94 safe_close(console_fd);
100 static int log_open_console(void) {
105 if (always_reopen_console) {
106 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
110 console_fd = STDERR_FILENO;
115 void log_close_kmsg(void) {
116 kmsg_fd = safe_close(kmsg_fd);
119 static int log_open_kmsg(void) {
124 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
131 void log_close_syslog(void) {
132 syslog_fd = safe_close(syslog_fd);
135 static int create_log_socket(int type) {
139 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
143 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
145 /* We need a blocking fd here since we'd otherwise lose
146 messages way too early. However, let's not hang forever in the
147 unlikely case of a deadlock. */
148 if (getpid_cached() == 1)
149 timeval_store(&tv, 10 * USEC_PER_MSEC);
151 timeval_store(&tv, 10 * USEC_PER_SEC);
152 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
157 static int log_open_syslog(void) {
159 static const union sockaddr_union sa = {
160 .un.sun_family = AF_UNIX,
161 .un.sun_path = "/dev/log",
169 syslog_fd = create_log_socket(SOCK_DGRAM);
175 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
176 safe_close(syslog_fd);
178 /* Some legacy syslog systems still use stream
179 * sockets. They really shouldn't. But what can we
181 syslog_fd = create_log_socket(SOCK_STREAM);
187 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
192 syslog_is_stream = true;
194 syslog_is_stream = false;
203 void log_close_journal(void) {
204 #if 0 /// elogind does not support journald
205 journal_fd = safe_close(journal_fd);
209 #if 0 /// UNNEEDED by elogind
210 static int log_open_journal(void) {
212 static const union sockaddr_union sa = {
213 .un.sun_family = AF_UNIX,
214 .un.sun_path = "/run/systemd/journal/socket",
222 journal_fd = create_log_socket(SOCK_DGRAM);
223 if (journal_fd < 0) {
228 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. If we don't use /dev/kmsg we still keep it open,
250 * because there is no reason to close it. */
252 if (log_target == LOG_TARGET_NULL) {
259 if (!IN_SET(log_target, LOG_TARGET_AUTO, LOG_TARGET_SAFE) ||
260 getpid_cached() == 1 ||
261 isatty(STDERR_FILENO) <= 0) {
263 #if 0 /// elogind does not support logging to systemd-journald
264 if (IN_SET(log_target, LOG_TARGET_AUTO,
265 LOG_TARGET_JOURNAL_OR_KMSG,
266 LOG_TARGET_JOURNAL)) {
267 r = log_open_journal();
276 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
277 LOG_TARGET_SYSLOG)) {
278 r = log_open_syslog();
286 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 0 /// elogind does not support logging to systemd-journald
312 if (upgrade_syslog_to_journal) {
313 if (target == LOG_TARGET_SYSLOG)
314 target = LOG_TARGET_JOURNAL;
315 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
316 target = LOG_TARGET_JOURNAL_OR_KMSG;
323 void log_close(void) {
324 /* Do not call from library code. */
332 #if 0 /// UNNEEDED by elogind
333 void log_forget_fds(void) {
334 /* Do not call from library code. */
336 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
340 void log_set_max_level_realm(LogRealm realm, int level) {
341 assert((level & LOG_PRIMASK) == level);
342 assert(realm < ELEMENTSOF(log_max_level));
344 log_max_level[realm] = level;
347 void log_set_facility(int facility) {
348 log_facility = facility;
351 static int write_to_console(
357 const char *buffer) {
359 char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
360 struct iovec iovec[6] = {};
367 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
368 xsprintf(prefix, "<%i>", level);
369 iovec[n++] = IOVEC_MAKE_STRING(prefix);
372 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
375 xsprintf(location, "(%s:%i) ", file, line);
376 iovec[n++] = IOVEC_MAKE_STRING(location);
380 iovec[n++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED);
381 iovec[n++] = IOVEC_MAKE_STRING(buffer);
383 iovec[n++] = IOVEC_MAKE_STRING(ANSI_NORMAL);
384 iovec[n++] = IOVEC_MAKE_STRING("\n");
386 if (writev(console_fd, iovec, n) < 0) {
388 if (errno == EIO && getpid_cached() == 1) {
390 /* If somebody tried to kick us from our
391 * console tty (via vhangup() or suchlike),
392 * try to reconnect */
400 if (writev(console_fd, iovec, n) < 0)
409 static int write_to_syslog(
415 const char *buffer) {
417 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
419 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
420 struct iovec iovec[5] = {};
421 struct msghdr msghdr = {
423 .msg_iovlen = ELEMENTSOF(iovec),
431 xsprintf(header_priority, "<%i>", level);
433 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
438 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
441 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
443 iovec[0] = IOVEC_MAKE_STRING(header_priority);
444 iovec[1] = IOVEC_MAKE_STRING(header_time);
445 iovec[2] = IOVEC_MAKE_STRING(program_invocation_short_name);
446 iovec[3] = IOVEC_MAKE_STRING(header_pid);
447 iovec[4] = IOVEC_MAKE_STRING(buffer);
449 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
450 if (syslog_is_stream)
456 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
460 if (!syslog_is_stream ||
461 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
464 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
470 static int write_to_kmsg(
476 const char *buffer) {
478 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
479 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
480 struct iovec iovec[5] = {};
485 xsprintf(header_priority, "<%i>", level);
486 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
488 iovec[0] = IOVEC_MAKE_STRING(header_priority);
489 iovec[1] = IOVEC_MAKE_STRING(program_invocation_short_name);
490 iovec[2] = IOVEC_MAKE_STRING(header_pid);
491 iovec[3] = IOVEC_MAKE_STRING(buffer);
492 iovec[4] = IOVEC_MAKE_STRING("\n");
494 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
500 static int log_do_header(
505 const char *file, int line, const char *func,
506 const char *object_field, const char *object,
507 const char *extra_field, const char *extra) {
509 snprintf(header, size,
511 "SYSLOG_FACILITY=%i\n"
518 "SYSLOG_IDENTIFIER=%s\n",
521 isempty(file) ? "" : "CODE_FILE=",
522 isempty(file) ? "" : file,
523 isempty(file) ? "" : "\n",
524 line ? "CODE_LINE=" : "",
525 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
527 isempty(func) ? "" : "CODE_FUNC=",
528 isempty(func) ? "" : func,
529 isempty(func) ? "" : "\n",
530 error ? "ERRNO=" : "",
531 error ? 1 : 0, error,
533 isempty(object) ? "" : object_field,
534 isempty(object) ? "" : object,
535 isempty(object) ? "" : "\n",
536 isempty(extra) ? "" : extra_field,
537 isempty(extra) ? "" : extra,
538 isempty(extra) ? "" : "\n",
539 program_invocation_short_name);
544 #if 0 /// UNNEEDED by elogind
545 static int write_to_journal(
551 const char *object_field,
553 const char *extra_field,
555 const char *buffer) {
557 char header[LINE_MAX];
558 struct iovec iovec[4] = {};
559 struct msghdr mh = {};
564 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
566 iovec[0] = IOVEC_MAKE_STRING(header);
567 iovec[1] = IOVEC_MAKE_STRING("MESSAGE=");
568 iovec[2] = IOVEC_MAKE_STRING(buffer);
569 iovec[3] = IOVEC_MAKE_STRING("\n");
572 mh.msg_iovlen = ELEMENTSOF(iovec);
574 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
581 int log_dispatch_internal(
587 const char *object_field,
590 const char *extra_field,
598 if (log_target == LOG_TARGET_NULL)
601 /* Patch in LOG_DAEMON facility if necessary */
602 if ((level & LOG_FACMASK) == 0)
603 level = log_facility | LOG_PRI(level);
605 if (open_when_needed)
612 buffer += strspn(buffer, NEWLINE);
617 if ((e = strpbrk(buffer, NEWLINE)))
620 #if 0 /// elogind does not support logging to systemd-journald
621 if (IN_SET(log_target, LOG_TARGET_AUTO,
622 LOG_TARGET_JOURNAL_OR_KMSG,
623 LOG_TARGET_JOURNAL)) {
625 k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
634 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
635 LOG_TARGET_SYSLOG)) {
637 k = write_to_syslog(level, error, file, line, func, buffer);
646 IN_SET(log_target, LOG_TARGET_AUTO,
648 LOG_TARGET_SYSLOG_OR_KMSG,
649 LOG_TARGET_JOURNAL_OR_KMSG,
652 k = write_to_kmsg(level, error, file, line, func, buffer);
660 (void) write_to_console(level, error, file, line, func, buffer);
665 if (open_when_needed)
671 int log_dump_internal(
679 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
682 /* This modifies the buffer... */
687 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
690 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
693 int log_internalv_realm(
702 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
703 char buffer[LINE_MAX];
709 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
712 /* Make sure that %m maps to the specified error */
716 vsnprintf(buffer, sizeof(buffer), format, ap);
718 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
721 int log_internal_realm(
727 const char *format, ...) {
732 va_start(ap, format);
733 r = log_internalv_realm(level, error, file, line, func, format, ap);
739 int log_object_internalv(
745 const char *object_field,
747 const char *extra_field,
758 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
761 /* Make sure that %m maps to the specified error */
765 /* Prepend the object name before the message */
770 buffer = newa(char, n + 2 + LINE_MAX);
771 b = stpcpy(stpcpy(buffer, object), ": ");
773 b = buffer = newa(char, LINE_MAX);
775 vsnprintf(b, LINE_MAX, format, ap);
777 return log_dispatch_internal(level, error, file, line, func,
778 object_field, object, extra_field, extra, buffer);
781 int log_object_internal(
787 const char *object_field,
789 const char *extra_field,
791 const char *format, ...) {
796 va_start(ap, format);
797 r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
803 static void log_assert(
809 const char *format) {
811 static char buffer[LINE_MAX];
812 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
814 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
817 DISABLE_WARNING_FORMAT_NONLITERAL;
818 xsprintf(buffer, format, text, file, line, func);
821 log_abort_msg = buffer;
823 log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
826 noreturn void log_assert_failed_realm(
833 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
834 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
838 noreturn void log_assert_failed_unreachable_realm(
845 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
846 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
850 void log_assert_failed_return_realm(
857 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
858 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
861 int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
862 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
863 ENOMEM, file, line, func, "Out of memory.");
866 int log_format_iovec(
870 bool newline_separator,
875 static const char nl = '\n';
877 while (format && *n + 1 < iovec_len) {
882 /* We need to copy the va_list structure,
883 * since vasprintf() leaves it afterwards at
884 * an undefined location */
890 r = vasprintf(&m, format, aq);
895 /* Now, jump enough ahead, so that we point to
896 * the next format string */
897 VA_FORMAT_ADVANCE(format, ap);
899 iovec[(*n)++] = IOVEC_MAKE_STRING(m);
901 if (newline_separator) {
902 iovec[*n].iov_base = (char*) &nl;
903 iovec[*n].iov_len = 1;
907 format = va_arg(ap, char *);
912 int log_struct_internal(
918 const char *format, ...) {
920 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
929 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
932 if (log_target == LOG_TARGET_NULL)
935 if ((level & LOG_FACMASK) == 0)
936 level = log_facility | LOG_PRI(level);
938 #if 0 /// elogind does not support logging to systemd-journald
939 if (IN_SET(log_target,
941 LOG_TARGET_JOURNAL_OR_KMSG,
942 LOG_TARGET_JOURNAL)) {
944 if (open_when_needed)
947 if (journal_fd >= 0) {
948 char header[LINE_MAX];
949 struct iovec iovec[17] = {};
955 bool fallback = false;
957 /* If the journal is available do structured logging */
958 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
959 iovec[n++] = IOVEC_MAKE_STRING(header);
961 va_start(ap, format);
962 r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
967 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
971 for (i = 1; i < n; i += 2)
972 free(iovec[i].iov_base);
975 if (open_when_needed)
984 /* Fallback if journal logging is not available or didn't work. */
986 va_start(ap, format);
994 vsnprintf(buf, sizeof(buf), format, aq);
997 if (startswith(buf, "MESSAGE=")) {
1002 VA_FORMAT_ADVANCE(format, ap);
1004 format = va_arg(ap, char *);
1009 if (open_when_needed)
1015 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
1018 int log_struct_iovec_internal(
1024 const struct iovec input_iovec[],
1025 size_t n_input_iovec) {
1027 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
1035 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
1038 if (log_target == LOG_TARGET_NULL)
1041 if ((level & LOG_FACMASK) == 0)
1042 level = log_facility | LOG_PRI(level);
1044 if (IN_SET(log_target, LOG_TARGET_AUTO,
1045 LOG_TARGET_JOURNAL_OR_KMSG,
1046 LOG_TARGET_JOURNAL) &&
1049 struct iovec iovec[1 + n_input_iovec*2];
1050 char header[LINE_MAX];
1051 struct msghdr mh = {
1053 .msg_iovlen = 1 + n_input_iovec*2,
1056 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
1057 iovec[0] = IOVEC_MAKE_STRING(header);
1059 for (i = 0; i < n_input_iovec; i++) {
1060 iovec[1+i*2] = input_iovec[i];
1061 iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
1064 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0)
1068 for (i = 0; i < n_input_iovec; i++) {
1069 if (input_iovec[i].iov_len < STRLEN("MESSAGE="))
1072 if (memcmp(input_iovec[i].iov_base, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
1076 if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
1079 m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
1080 input_iovec[i].iov_len - STRLEN("MESSAGE="));
1082 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
1085 int log_set_target_from_string(const char *e) {
1088 t = log_target_from_string(e);
1096 int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
1099 t = log_level_from_string(e);
1103 log_set_max_level_realm(realm, t);
1107 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
1110 * The systemd.log_xyz= settings are parsed by all tools, and
1113 * However, "quiet" is only parsed by PID 1, and only turns of
1114 * status output to /dev/console, but does not alter the log
1118 if (streq(key, "debug") && !value)
1119 log_set_max_level(LOG_DEBUG);
1121 else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1123 if (proc_cmdline_value_missing(key, value))
1126 if (log_set_target_from_string(value) < 0)
1127 log_warning("Failed to parse log target '%s'. Ignoring.", value);
1129 } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1131 if (proc_cmdline_value_missing(key, value))
1134 if (log_set_max_level_from_string(value) < 0)
1135 log_warning("Failed to parse log level '%s'. Ignoring.", value);
1137 } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
1139 if (log_show_color_from_string(value ?: "1") < 0)
1140 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1142 } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
1144 if (log_show_location_from_string(value ?: "1") < 0)
1145 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1151 void log_parse_environment_realm(LogRealm realm) {
1152 /* Do not call from library code. */
1156 if (get_ctty_devnr(0, NULL) < 0)
1157 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1159 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
1161 e = getenv("SYSTEMD_LOG_TARGET");
1162 if (e && log_set_target_from_string(e) < 0)
1163 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1165 e = getenv("SYSTEMD_LOG_LEVEL");
1166 if (e && log_set_max_level_from_string_realm(realm, e) < 0)
1167 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1169 e = getenv("SYSTEMD_LOG_COLOR");
1170 if (e && log_show_color_from_string(e) < 0)
1171 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1173 e = getenv("SYSTEMD_LOG_LOCATION");
1174 if (e && log_show_location_from_string(e) < 0)
1175 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1178 LogTarget log_get_target(void) {
1182 int log_get_max_level_realm(LogRealm realm) {
1183 return log_max_level[realm];
1186 void log_show_color(bool b) {
1190 bool log_get_show_color(void) {
1194 void log_show_location(bool b) {
1198 bool log_get_show_location(void) {
1199 return show_location;
1202 int log_show_color_from_string(const char *e) {
1205 t = parse_boolean(e);
1213 int log_show_location_from_string(const char *e) {
1216 t = parse_boolean(e);
1220 log_show_location(t);
1224 bool log_on_console(void) {
1225 if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1226 LOG_TARGET_CONSOLE_PREFIXED))
1229 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1232 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1233 [LOG_TARGET_CONSOLE] = "console",
1234 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1235 [LOG_TARGET_KMSG] = "kmsg",
1236 #if 0 /// elogind does not support logging to systemd-journald
1237 [LOG_TARGET_JOURNAL] = "journal",
1238 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1240 [LOG_TARGET_SYSLOG] = "syslog",
1241 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1242 [LOG_TARGET_AUTO] = "auto",
1243 [LOG_TARGET_SAFE] = "safe",
1244 [LOG_TARGET_NULL] = "null"
1247 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1249 #if 0 /// UNNEEDED by elogind
1250 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1253 if (pid_is_valid(si->ssi_pid)) {
1254 _cleanup_free_ char *p = NULL;
1256 (void) get_process_comm(si->ssi_pid, &p);
1259 "Received SIG%s from PID %"PRIu32" (%s).",
1260 signal_to_string(si->ssi_signo),
1261 si->ssi_pid, strna(p));
1265 signal_to_string(si->ssi_signo));
1269 int log_syntax_internal(
1272 const char *config_file,
1273 unsigned config_line,
1278 const char *format, ...) {
1281 char buffer[LINE_MAX];
1283 const char *unit_fmt = NULL;
1288 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
1291 if (log_target == LOG_TARGET_NULL)
1297 va_start(ap, format);
1298 vsnprintf(buffer, sizeof(buffer), format, ap);
1302 unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1304 return log_struct_internal(
1305 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
1308 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1309 "CONFIG_FILE=%s", config_file,
1310 "CONFIG_LINE=%u", config_line,
1311 LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
1316 int log_syntax_invalid_utf8_internal(
1319 const char *config_file,
1320 unsigned config_line,
1324 const char *rvalue) {
1326 _cleanup_free_ char *p = NULL;
1329 p = utf8_escape_invalid(rvalue);
1331 log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
1332 "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
1337 #if 0 /// UNNEEDED by elogind
1338 void log_set_upgrade_syslog_to_journal(bool b) {
1339 upgrade_syslog_to_journal = b;
1341 /* Make the change effective immediately */
1343 if (log_target == LOG_TARGET_SYSLOG)
1344 log_target = LOG_TARGET_JOURNAL;
1345 else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
1346 log_target = LOG_TARGET_JOURNAL_OR_KMSG;
1350 void log_set_always_reopen_console(bool b) {
1351 always_reopen_console = b;
1355 void log_set_open_when_needed(bool b) {
1356 open_when_needed = b;
1359 int log_emergency_level(void) {
1360 /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1361 * then the system of the whole system is obviously affected. */
1363 return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;