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 static void log_close_console(void) {
94 safe_close(console_fd);
99 static int log_open_console(void) {
101 if (!always_reopen_console) {
102 console_fd = STDERR_FILENO;
106 if (console_fd < 3) {
107 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
111 console_fd = fd_move_above_stdio(console_fd);
117 static void log_close_kmsg(void) {
118 kmsg_fd = safe_close(kmsg_fd);
121 static int log_open_kmsg(void) {
126 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
130 kmsg_fd = fd_move_above_stdio(kmsg_fd);
134 static void log_close_syslog(void) {
135 syslog_fd = safe_close(syslog_fd);
138 static int create_log_socket(int type) {
142 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
146 fd = fd_move_above_stdio(fd);
147 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
149 /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
150 * in the unlikely case of a deadlock. */
151 if (getpid_cached() == 1)
152 timeval_store(&tv, 10 * USEC_PER_MSEC);
154 timeval_store(&tv, 10 * USEC_PER_SEC);
155 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
160 static int log_open_syslog(void) {
162 static const union sockaddr_union sa = {
163 .un.sun_family = AF_UNIX,
164 .un.sun_path = "/dev/log",
172 syslog_fd = create_log_socket(SOCK_DGRAM);
178 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
179 safe_close(syslog_fd);
181 /* Some legacy syslog systems still use stream
182 * sockets. They really shouldn't. But what can we
184 syslog_fd = create_log_socket(SOCK_STREAM);
190 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
195 syslog_is_stream = true;
197 syslog_is_stream = false;
206 static void log_close_journal(void) {
207 #if 0 /// elogind does not support journald
208 journal_fd = safe_close(journal_fd);
212 #if 0 /// UNNEEDED by elogind
213 static int log_open_journal(void) {
215 static const union sockaddr_union sa = {
216 .un.sun_family = AF_UNIX,
217 .un.sun_path = "/run/systemd/journal/socket",
225 journal_fd = create_log_socket(SOCK_DGRAM);
226 if (journal_fd < 0) {
231 if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
247 /* Do not call from library code. */
249 /* If we don't use the console we close it here, to not get
250 * killed by SAK. If we don't use syslog we close it here so
251 * that we are not confused by somebody deleting the socket in
252 * the fs, and to make sure we don't use it if prohibit_ipc is
253 * set. If we don't use /dev/kmsg we still keep it open,
254 * because there is no reason to close it. */
256 if (log_target == LOG_TARGET_NULL) {
263 if (log_target != LOG_TARGET_AUTO ||
264 getpid_cached() == 1 ||
265 isatty(STDERR_FILENO) <= 0) {
267 #if 0 /// elogind does not support logging to systemd-journald
269 IN_SET(log_target, LOG_TARGET_AUTO,
270 LOG_TARGET_JOURNAL_OR_KMSG,
271 LOG_TARGET_JOURNAL)) {
272 r = log_open_journal();
282 IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
283 LOG_TARGET_SYSLOG)) {
284 r = log_open_syslog();
292 if (IN_SET(log_target, LOG_TARGET_AUTO,
293 LOG_TARGET_JOURNAL_OR_KMSG,
294 LOG_TARGET_SYSLOG_OR_KMSG,
309 return log_open_console();
312 void log_set_target(LogTarget target) {
314 assert(target < _LOG_TARGET_MAX);
316 #if 0 /// elogind does not support logging to systemd-journald
317 if (upgrade_syslog_to_journal) {
318 if (target == LOG_TARGET_SYSLOG)
319 target = LOG_TARGET_JOURNAL;
320 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
321 target = LOG_TARGET_JOURNAL_OR_KMSG;
328 void log_close(void) {
329 /* Do not call from library code. */
337 #if 0 /// UNNEEDED by elogind
338 void log_forget_fds(void) {
339 /* Do not call from library code. */
341 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
345 void log_set_max_level_realm(LogRealm realm, int level) {
346 assert((level & LOG_PRIMASK) == level);
347 assert(realm < ELEMENTSOF(log_max_level));
349 log_max_level[realm] = level;
352 void log_set_facility(int facility) {
353 log_facility = facility;
356 static int write_to_console(
362 const char *buffer) {
364 char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
365 struct iovec iovec[6] = {};
372 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
373 xsprintf(prefix, "<%i>", level);
374 iovec[n++] = IOVEC_MAKE_STRING(prefix);
377 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
380 (void) snprintf(location, sizeof location, "(%s:%i) ", file, line);
381 iovec[n++] = IOVEC_MAKE_STRING(location);
385 iovec[n++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED);
386 iovec[n++] = IOVEC_MAKE_STRING(buffer);
388 iovec[n++] = IOVEC_MAKE_STRING(ANSI_NORMAL);
389 iovec[n++] = IOVEC_MAKE_STRING("\n");
391 if (writev(console_fd, iovec, n) < 0) {
393 if (errno == EIO && getpid_cached() == 1) {
395 /* If somebody tried to kick us from our
396 * console tty (via vhangup() or suchlike),
397 * try to reconnect */
405 if (writev(console_fd, iovec, n) < 0)
414 static int write_to_syslog(
420 const char *buffer) {
422 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
424 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
425 struct iovec iovec[5] = {};
426 struct msghdr msghdr = {
428 .msg_iovlen = ELEMENTSOF(iovec),
436 xsprintf(header_priority, "<%i>", level);
438 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
443 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
446 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
448 iovec[0] = IOVEC_MAKE_STRING(header_priority);
449 iovec[1] = IOVEC_MAKE_STRING(header_time);
450 iovec[2] = IOVEC_MAKE_STRING(program_invocation_short_name);
451 iovec[3] = IOVEC_MAKE_STRING(header_pid);
452 iovec[4] = IOVEC_MAKE_STRING(buffer);
454 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
455 if (syslog_is_stream)
461 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
465 if (!syslog_is_stream ||
466 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
469 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
475 static int write_to_kmsg(
481 const char *buffer) {
483 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
484 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
485 struct iovec iovec[5] = {};
490 xsprintf(header_priority, "<%i>", level);
491 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
493 iovec[0] = IOVEC_MAKE_STRING(header_priority);
494 iovec[1] = IOVEC_MAKE_STRING(program_invocation_short_name);
495 iovec[2] = IOVEC_MAKE_STRING(header_pid);
496 iovec[3] = IOVEC_MAKE_STRING(buffer);
497 iovec[4] = IOVEC_MAKE_STRING("\n");
499 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
505 static int log_do_header(
510 const char *file, int line, const char *func,
511 const char *object_field, const char *object,
512 const char *extra_field, const char *extra) {
515 r = snprintf(header, size,
517 "SYSLOG_FACILITY=%i\n"
518 "%s%.256s%s" /* CODE_FILE */
519 "%s%.*i%s" /* CODE_LINE */
520 "%s%.256s%s" /* CODE_FUNC */
521 "%s%.*i%s" /* ERRNO */
522 "%s%.256s%s" /* object */
523 "%s%.256s%s" /* extra */
524 "SYSLOG_IDENTIFIER=%.256s\n",
527 isempty(file) ? "" : "CODE_FILE=",
528 isempty(file) ? "" : file,
529 isempty(file) ? "" : "\n",
530 line ? "CODE_LINE=" : "",
531 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
533 isempty(func) ? "" : "CODE_FUNC=",
534 isempty(func) ? "" : func,
535 isempty(func) ? "" : "\n",
536 error ? "ERRNO=" : "",
537 error ? 1 : 0, error,
539 isempty(object) ? "" : object_field,
540 isempty(object) ? "" : object,
541 isempty(object) ? "" : "\n",
542 isempty(extra) ? "" : extra_field,
543 isempty(extra) ? "" : extra,
544 isempty(extra) ? "" : "\n",
545 program_invocation_short_name);
546 assert((size_t) r < size);
551 #if 0 /// UNNEEDED by elogind
552 static int write_to_journal(
558 const char *object_field,
560 const char *extra_field,
562 const char *buffer) {
564 char header[LINE_MAX];
565 struct iovec iovec[4] = {};
566 struct msghdr mh = {};
571 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
573 iovec[0] = IOVEC_MAKE_STRING(header);
574 iovec[1] = IOVEC_MAKE_STRING("MESSAGE=");
575 iovec[2] = IOVEC_MAKE_STRING(buffer);
576 iovec[3] = IOVEC_MAKE_STRING("\n");
579 mh.msg_iovlen = ELEMENTSOF(iovec);
581 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
588 int log_dispatch_internal(
594 const char *object_field,
596 const char *extra_field,
605 if (log_target == LOG_TARGET_NULL)
608 /* Patch in LOG_DAEMON facility if necessary */
609 if ((level & LOG_FACMASK) == 0)
610 level = log_facility | LOG_PRI(level);
612 if (open_when_needed)
619 buffer += strspn(buffer, NEWLINE);
624 if ((e = strpbrk(buffer, NEWLINE)))
627 #if 0 /// elogind does not support logging to systemd-journald
628 if (IN_SET(log_target, LOG_TARGET_AUTO,
629 LOG_TARGET_JOURNAL_OR_KMSG,
630 LOG_TARGET_JOURNAL)) {
632 k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
633 if (k < 0 && k != -EAGAIN)
638 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
639 LOG_TARGET_SYSLOG)) {
641 k = write_to_syslog(level, error, file, line, func, buffer);
642 if (k < 0 && k != -EAGAIN)
647 IN_SET(log_target, LOG_TARGET_AUTO,
648 LOG_TARGET_SYSLOG_OR_KMSG,
649 LOG_TARGET_JOURNAL_OR_KMSG,
655 k = write_to_kmsg(level, error, file, line, func, buffer);
663 (void) write_to_console(level, error, file, line, func, buffer);
668 if (open_when_needed)
674 int log_dump_internal(
682 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
685 /* This modifies the buffer... */
690 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
693 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
696 int log_internalv_realm(
705 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
706 char buffer[LINE_MAX];
712 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
715 /* Make sure that %m maps to the specified error */
719 (void) vsnprintf(buffer, sizeof buffer, format, ap);
721 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
724 int log_internal_realm(
730 const char *format, ...) {
735 va_start(ap, format);
736 r = log_internalv_realm(level, error, file, line, func, format, ap);
743 static int log_object_internalv(
749 const char *object_field,
751 const char *extra_field,
762 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
765 /* Make sure that %m maps to the specified error */
769 /* Prepend the object name before the message */
774 buffer = newa(char, n + 2 + LINE_MAX);
775 b = stpcpy(stpcpy(buffer, object), ": ");
777 b = buffer = newa(char, LINE_MAX);
779 (void) vsnprintf(b, LINE_MAX, format, ap);
781 return log_dispatch_internal(level, error, file, line, func,
782 object_field, object, extra_field, extra, buffer);
785 int log_object_internal(
791 const char *object_field,
793 const char *extra_field,
795 const char *format, ...) {
800 va_start(ap, format);
801 r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
807 static void log_assert(
813 const char *format) {
815 static char buffer[LINE_MAX];
816 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
818 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
821 DISABLE_WARNING_FORMAT_NONLITERAL;
822 (void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
825 log_abort_msg = buffer;
827 log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
830 noreturn void log_assert_failed_realm(
837 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
838 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
842 noreturn void log_assert_failed_unreachable_realm(
849 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
850 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
854 void log_assert_failed_return_realm(
861 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
862 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
865 int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
866 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
867 ENOMEM, file, line, func, "Out of memory.");
870 int log_format_iovec(
874 bool newline_separator,
879 static const char nl = '\n';
881 while (format && *n + 1 < iovec_len) {
886 /* We need to copy the va_list structure,
887 * since vasprintf() leaves it afterwards at
888 * an undefined location */
894 r = vasprintf(&m, format, aq);
899 /* Now, jump enough ahead, so that we point to
900 * the next format string */
901 VA_FORMAT_ADVANCE(format, ap);
903 iovec[(*n)++] = IOVEC_MAKE_STRING(m);
905 if (newline_separator) {
906 iovec[*n].iov_base = (char*) &nl;
907 iovec[*n].iov_len = 1;
911 format = va_arg(ap, char *);
916 int log_struct_internal(
922 const char *format, ...) {
924 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
933 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
936 if (log_target == LOG_TARGET_NULL)
939 if ((level & LOG_FACMASK) == 0)
940 level = log_facility | LOG_PRI(level);
942 #if 0 /// elogind does not support logging to systemd-journald
943 if (IN_SET(log_target,
945 LOG_TARGET_JOURNAL_OR_KMSG,
946 LOG_TARGET_JOURNAL)) {
948 if (open_when_needed)
951 if (journal_fd >= 0) {
952 char header[LINE_MAX];
953 struct iovec iovec[17] = {};
959 bool fallback = false;
961 /* If the journal is available do structured logging */
962 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
963 iovec[n++] = IOVEC_MAKE_STRING(header);
965 va_start(ap, format);
966 r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
971 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
975 for (i = 1; i < n; i += 2)
976 free(iovec[i].iov_base);
979 if (open_when_needed)
988 /* Fallback if journal logging is not available or didn't work. */
990 va_start(ap, format);
998 (void) vsnprintf(buf, sizeof buf, format, aq);
1001 if (startswith(buf, "MESSAGE=")) {
1006 VA_FORMAT_ADVANCE(format, ap);
1008 format = va_arg(ap, char *);
1013 if (open_when_needed)
1019 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
1022 int log_struct_iovec_internal(
1028 const struct iovec input_iovec[],
1029 size_t n_input_iovec) {
1031 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
1039 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
1042 if (log_target == LOG_TARGET_NULL)
1045 if ((level & LOG_FACMASK) == 0)
1046 level = log_facility | LOG_PRI(level);
1048 if (IN_SET(log_target, LOG_TARGET_AUTO,
1049 LOG_TARGET_JOURNAL_OR_KMSG,
1050 LOG_TARGET_JOURNAL) &&
1053 struct iovec iovec[1 + n_input_iovec*2];
1054 char header[LINE_MAX];
1055 struct msghdr mh = {
1057 .msg_iovlen = 1 + n_input_iovec*2,
1060 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
1061 iovec[0] = IOVEC_MAKE_STRING(header);
1063 for (i = 0; i < n_input_iovec; i++) {
1064 iovec[1+i*2] = input_iovec[i];
1065 iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
1068 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0)
1072 for (i = 0; i < n_input_iovec; i++) {
1073 if (input_iovec[i].iov_len < STRLEN("MESSAGE="))
1076 if (memcmp(input_iovec[i].iov_base, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
1080 if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
1083 m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
1084 input_iovec[i].iov_len - STRLEN("MESSAGE="));
1086 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
1089 int log_set_target_from_string(const char *e) {
1092 t = log_target_from_string(e);
1100 int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
1103 t = log_level_from_string(e);
1107 log_set_max_level_realm(realm, t);
1111 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
1114 * The systemd.log_xyz= settings are parsed by all tools, and
1117 * However, "quiet" is only parsed by PID 1, and only turns of
1118 * status output to /dev/console, but does not alter the log
1122 if (streq(key, "debug") && !value)
1123 log_set_max_level(LOG_DEBUG);
1125 else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1127 if (proc_cmdline_value_missing(key, value))
1130 if (log_set_target_from_string(value) < 0)
1131 log_warning("Failed to parse log target '%s'. Ignoring.", value);
1133 } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1135 if (proc_cmdline_value_missing(key, value))
1138 if (log_set_max_level_from_string(value) < 0)
1139 log_warning("Failed to parse log level '%s'. Ignoring.", value);
1141 } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
1143 if (log_show_color_from_string(value ?: "1") < 0)
1144 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1146 } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
1148 if (log_show_location_from_string(value ?: "1") < 0)
1149 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1155 void log_parse_environment_realm(LogRealm realm) {
1156 /* Do not call from library code. */
1160 if (get_ctty_devnr(0, NULL) < 0)
1161 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1163 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
1165 e = getenv("SYSTEMD_LOG_TARGET");
1166 if (e && log_set_target_from_string(e) < 0)
1167 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1169 e = getenv("SYSTEMD_LOG_LEVEL");
1170 if (e && log_set_max_level_from_string_realm(realm, e) < 0)
1171 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1173 e = getenv("SYSTEMD_LOG_COLOR");
1174 if (e && log_show_color_from_string(e) < 0)
1175 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1177 e = getenv("SYSTEMD_LOG_LOCATION");
1178 if (e && log_show_location_from_string(e) < 0)
1179 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1182 LogTarget log_get_target(void) {
1186 int log_get_max_level_realm(LogRealm realm) {
1187 return log_max_level[realm];
1190 void log_show_color(bool b) {
1194 bool log_get_show_color(void) {
1198 void log_show_location(bool b) {
1202 bool log_get_show_location(void) {
1203 return show_location;
1206 int log_show_color_from_string(const char *e) {
1209 t = parse_boolean(e);
1217 int log_show_location_from_string(const char *e) {
1220 t = parse_boolean(e);
1224 log_show_location(t);
1228 bool log_on_console(void) {
1229 if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1230 LOG_TARGET_CONSOLE_PREFIXED))
1233 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1236 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1237 [LOG_TARGET_CONSOLE] = "console",
1238 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1239 [LOG_TARGET_KMSG] = "kmsg",
1240 #if 0 /// elogind does not support logging to systemd-journald
1241 [LOG_TARGET_JOURNAL] = "journal",
1242 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1244 [LOG_TARGET_SYSLOG] = "syslog",
1245 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1246 [LOG_TARGET_AUTO] = "auto",
1247 [LOG_TARGET_NULL] = "null",
1250 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1252 #if 0 /// UNNEEDED by elogind
1253 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1256 if (pid_is_valid(si->ssi_pid)) {
1257 _cleanup_free_ char *p = NULL;
1259 (void) get_process_comm(si->ssi_pid, &p);
1262 "Received SIG%s from PID %"PRIu32" (%s).",
1263 signal_to_string(si->ssi_signo),
1264 si->ssi_pid, strna(p));
1268 signal_to_string(si->ssi_signo));
1272 int log_syntax_internal(
1275 const char *config_file,
1276 unsigned config_line,
1281 const char *format, ...) {
1284 char buffer[LINE_MAX];
1286 const char *unit_fmt = NULL;
1291 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
1294 if (log_target == LOG_TARGET_NULL)
1300 va_start(ap, format);
1301 (void) vsnprintf(buffer, sizeof buffer, format, ap);
1305 unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1307 return log_struct_internal(
1308 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
1311 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1312 "CONFIG_FILE=%s", config_file,
1313 "CONFIG_LINE=%u", config_line,
1314 LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
1319 int log_syntax_invalid_utf8_internal(
1322 const char *config_file,
1323 unsigned config_line,
1327 const char *rvalue) {
1329 _cleanup_free_ char *p = NULL;
1332 p = utf8_escape_invalid(rvalue);
1334 log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
1335 "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
1340 #if 0 /// UNNEEDED by elogind
1341 void log_set_upgrade_syslog_to_journal(bool b) {
1342 upgrade_syslog_to_journal = b;
1344 /* Make the change effective immediately */
1346 if (log_target == LOG_TARGET_SYSLOG)
1347 log_target = LOG_TARGET_JOURNAL;
1348 else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
1349 log_target = LOG_TARGET_JOURNAL_OR_KMSG;
1353 void log_set_always_reopen_console(bool b) {
1354 always_reopen_console = b;
1358 void log_set_open_when_needed(bool b) {
1359 open_when_needed = b;
1362 void log_set_prohibit_ipc(bool b) {
1366 int log_emergency_level(void) {
1367 /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1368 * then the system of the whole system is obviously affected. */
1370 return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;