1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include <sys/socket.h>
32 #include "sd-messages.h"
37 #include "socket-util.h"
38 #include "formats-util.h"
39 #include "process-util.h"
40 #include "terminal-util.h"
41 #include "signal-util.h"
43 #define SNDBUF_SIZE (8*1024*1024)
45 static LogTarget log_target = LOG_TARGET_CONSOLE;
46 static int log_max_level = LOG_INFO;
47 static int log_facility = LOG_DAEMON;
49 static int console_fd = STDERR_FILENO;
50 static int syslog_fd = -1;
51 static int kmsg_fd = -1;
52 static int journal_fd = -1;
54 static bool syslog_is_stream = false;
56 static bool show_color = false;
57 static bool show_location = false;
59 static bool upgrade_syslog_to_journal = false;
61 /* Akin to glibc's __abort_msg; which is private and we hence cannot
63 static char *log_abort_msg = NULL;
65 void log_close_console(void) {
72 safe_close(console_fd);
78 static int log_open_console(void) {
84 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
88 console_fd = STDERR_FILENO;
93 void log_close_kmsg(void) {
94 kmsg_fd = safe_close(kmsg_fd);
97 static int log_open_kmsg(void) {
102 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
109 void log_close_syslog(void) {
110 syslog_fd = safe_close(syslog_fd);
113 static int create_log_socket(int type) {
117 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
121 fd_inc_sndbuf(fd, SNDBUF_SIZE);
123 /* We need a blocking fd here since we'd otherwise lose
124 messages way too early. However, let's not hang forever in the
125 unlikely case of a deadlock. */
127 timeval_store(&tv, 10 * USEC_PER_MSEC);
129 timeval_store(&tv, 10 * USEC_PER_SEC);
130 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
135 static int log_open_syslog(void) {
137 static const union sockaddr_union sa = {
138 .un.sun_family = AF_UNIX,
139 .un.sun_path = "/dev/log",
147 syslog_fd = create_log_socket(SOCK_DGRAM);
153 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
154 safe_close(syslog_fd);
156 /* Some legacy syslog systems still use stream
157 * sockets. They really shouldn't. But what can we
159 syslog_fd = create_log_socket(SOCK_STREAM);
165 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
170 syslog_is_stream = true;
172 syslog_is_stream = false;
181 void log_close_journal(void) {
182 journal_fd = safe_close(journal_fd);
185 static int log_open_journal(void) {
187 static const union sockaddr_union sa = {
188 .un.sun_family = AF_UNIX,
189 .un.sun_path = "/run/systemd/journal/socket",
197 journal_fd = create_log_socket(SOCK_DGRAM);
198 if (journal_fd < 0) {
203 if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
218 /* If we don't use the console we close it here, to not get
219 * killed by SAK. If we don't use syslog we close it here so
220 * that we are not confused by somebody deleting the socket in
221 * the fs. If we don't use /dev/kmsg we still keep it open,
222 * because there is no reason to close it. */
224 if (log_target == LOG_TARGET_NULL) {
231 if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
233 isatty(STDERR_FILENO) <= 0) {
235 if (log_target == LOG_TARGET_AUTO ||
236 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
237 log_target == LOG_TARGET_JOURNAL) {
238 r = log_open_journal();
246 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
247 log_target == LOG_TARGET_SYSLOG) {
248 r = log_open_syslog();
256 if (log_target == LOG_TARGET_AUTO ||
257 log_target == LOG_TARGET_SAFE ||
258 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
259 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
260 log_target == LOG_TARGET_KMSG) {
274 return log_open_console();
277 void log_set_target(LogTarget target) {
279 assert(target < _LOG_TARGET_MAX);
281 if (upgrade_syslog_to_journal) {
282 if (target == LOG_TARGET_SYSLOG)
283 target = LOG_TARGET_JOURNAL;
284 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
285 target = LOG_TARGET_JOURNAL_OR_KMSG;
291 void log_close(void) {
298 void log_forget_fds(void) {
299 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
302 void log_set_max_level(int level) {
303 assert((level & LOG_PRIMASK) == level);
305 log_max_level = level;
308 void log_set_facility(int facility) {
309 log_facility = facility;
312 static int write_to_console(
318 const char *object_field,
320 const char *buffer) {
322 char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2];
323 struct iovec iovec[6] = {};
330 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
331 sprintf(prefix, "<%i>", level);
332 IOVEC_SET_STRING(iovec[n++], prefix);
335 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
338 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
339 IOVEC_SET_STRING(iovec[n++], location);
343 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
344 IOVEC_SET_STRING(iovec[n++], buffer);
346 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
347 IOVEC_SET_STRING(iovec[n++], "\n");
349 if (writev(console_fd, iovec, n) < 0) {
351 if (errno == EIO && getpid() == 1) {
353 /* If somebody tried to kick us from our
354 * console tty (via vhangup() or suchlike),
355 * try to reconnect */
363 if (writev(console_fd, iovec, n) < 0)
372 static int write_to_syslog(
378 const char *object_field,
380 const char *buffer) {
382 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
384 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
385 struct iovec iovec[5] = {};
386 struct msghdr msghdr = {
388 .msg_iovlen = ELEMENTSOF(iovec),
396 xsprintf(header_priority, "<%i>", level);
398 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
403 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
406 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
408 IOVEC_SET_STRING(iovec[0], header_priority);
409 IOVEC_SET_STRING(iovec[1], header_time);
410 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
411 IOVEC_SET_STRING(iovec[3], header_pid);
412 IOVEC_SET_STRING(iovec[4], buffer);
414 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
415 if (syslog_is_stream)
421 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
425 if (!syslog_is_stream ||
426 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
429 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
435 static int write_to_kmsg(
441 const char *object_field,
443 const char *buffer) {
445 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
446 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
447 struct iovec iovec[5] = {};
452 xsprintf(header_priority, "<%i>", level);
453 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
455 IOVEC_SET_STRING(iovec[0], header_priority);
456 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
457 IOVEC_SET_STRING(iovec[2], header_pid);
458 IOVEC_SET_STRING(iovec[3], buffer);
459 IOVEC_SET_STRING(iovec[4], "\n");
461 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
467 static int log_do_header(
472 const char *file, int line, const char *func,
473 const char *object_field, const char *object) {
475 snprintf(header, size,
477 "SYSLOG_FACILITY=%i\n"
483 "SYSLOG_IDENTIFIER=%s\n",
486 isempty(file) ? "" : "CODE_FILE=",
487 isempty(file) ? "" : file,
488 isempty(file) ? "" : "\n",
489 line ? "CODE_LINE=" : "",
490 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
492 isempty(func) ? "" : "CODE_FUNCTION=",
493 isempty(func) ? "" : func,
494 isempty(func) ? "" : "\n",
495 error ? "ERRNO=" : "",
496 error ? 1 : 0, error,
498 isempty(object) ? "" : object_field,
499 isempty(object) ? "" : object,
500 isempty(object) ? "" : "\n",
501 program_invocation_short_name);
506 static int write_to_journal(
512 const char *object_field,
514 const char *buffer) {
516 char header[LINE_MAX];
517 struct iovec iovec[4] = {};
518 struct msghdr mh = {};
523 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
525 IOVEC_SET_STRING(iovec[0], header);
526 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
527 IOVEC_SET_STRING(iovec[2], buffer);
528 IOVEC_SET_STRING(iovec[3], "\n");
531 mh.msg_iovlen = ELEMENTSOF(iovec);
533 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
539 static int log_dispatch(
545 const char *object_field,
551 if (log_target == LOG_TARGET_NULL)
554 /* Patch in LOG_DAEMON facility if necessary */
555 if ((level & LOG_FACMASK) == 0)
556 level = log_facility | LOG_PRI(level);
565 buffer += strspn(buffer, NEWLINE);
570 if ((e = strpbrk(buffer, NEWLINE)))
573 if (log_target == LOG_TARGET_AUTO ||
574 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
575 log_target == LOG_TARGET_JOURNAL) {
577 k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
585 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
586 log_target == LOG_TARGET_SYSLOG) {
588 k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
597 (log_target == LOG_TARGET_AUTO ||
598 log_target == LOG_TARGET_SAFE ||
599 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
600 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
601 log_target == LOG_TARGET_KMSG)) {
603 k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
611 (void) write_to_console(level, error, file, line, func, object_field, object, buffer);
619 int log_dump_internal(
629 /* This modifies the buffer... */
634 if (_likely_(LOG_PRI(level) > log_max_level))
637 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
650 char buffer[LINE_MAX];
655 if (_likely_(LOG_PRI(level) > log_max_level))
658 /* Make sure that %m maps to the specified error */
662 vsnprintf(buffer, sizeof(buffer), format, ap);
664 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
673 const char *format, ...) {
678 va_start(ap, format);
679 r = log_internalv(level, error, file, line, func, format, ap);
685 int log_object_internalv(
691 const char *object_field,
703 if (_likely_(LOG_PRI(level) > log_max_level))
706 /* Make sure that %m maps to the specified error */
710 /* Prepend the object name before the message */
715 l = n + 2 + LINE_MAX;
717 buffer = newa(char, l);
718 b = stpcpy(stpcpy(buffer, object), ": ");
721 b = buffer = newa(char, l);
724 vsnprintf(b, l, format, ap);
726 return log_dispatch(level, error, file, line, func, object_field, object, buffer);
729 int log_object_internal(
735 const char *object_field,
737 const char *format, ...) {
742 va_start(ap, format);
743 r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap);
749 static void log_assert(
755 const char *format) {
757 static char buffer[LINE_MAX];
759 if (_likely_(LOG_PRI(level) > log_max_level))
762 DISABLE_WARNING_FORMAT_NONLITERAL;
763 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
766 log_abort_msg = buffer;
768 log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
771 noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
772 log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
776 noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
777 log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
781 void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
783 log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
786 int log_oom_internal(const char *file, int line, const char *func) {
787 log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
791 int log_struct_internal(
797 const char *format, ...) {
807 if (_likely_(LOG_PRI(level) > log_max_level))
810 if (log_target == LOG_TARGET_NULL)
813 if ((level & LOG_FACMASK) == 0)
814 level = log_facility | LOG_PRI(level);
816 if ((log_target == LOG_TARGET_AUTO ||
817 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
818 log_target == LOG_TARGET_JOURNAL) &&
820 char header[LINE_MAX];
821 struct iovec iovec[17] = {};
826 static const char nl = '\n';
827 bool fallback = false;
829 /* If the journal is available do structured logging */
830 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
831 IOVEC_SET_STRING(iovec[n++], header);
833 va_start(ap, format);
834 while (format && n + 1 < ELEMENTSOF(iovec)) {
838 /* We need to copy the va_list structure,
839 * since vasprintf() leaves it afterwards at
840 * an undefined location */
846 if (vasprintf(&m, format, aq) < 0) {
853 /* Now, jump enough ahead, so that we point to
854 * the next format string */
855 VA_FORMAT_ADVANCE(format, ap);
857 IOVEC_SET_STRING(iovec[n++], m);
859 iovec[n].iov_base = (char*) &nl;
860 iovec[n].iov_len = 1;
863 format = va_arg(ap, char *);
868 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
872 for (i = 1; i < n; i += 2)
873 free(iovec[i].iov_base);
879 /* Fallback if journal logging is not available or didn't work. */
881 va_start(ap, format);
889 vsnprintf(buf, sizeof(buf), format, aq);
892 if (startswith(buf, "MESSAGE=")) {
897 VA_FORMAT_ADVANCE(format, ap);
899 format = va_arg(ap, char *);
906 return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
909 int log_set_target_from_string(const char *e) {
912 t = log_target_from_string(e);
920 int log_set_max_level_from_string(const char *e) {
923 t = log_level_from_string(e);
927 log_set_max_level(t);
931 static int parse_proc_cmdline_item(const char *key, const char *value) {
934 * The systemd.log_xyz= settings are parsed by all tools, and
937 * However, "quiet" is only parsed by PID 1, and only turns of
938 * status output to /dev/console, but does not alter the log
942 if (streq(key, "debug") && !value)
943 log_set_max_level(LOG_DEBUG);
945 else if (streq(key, "systemd.log_target") && value) {
947 if (log_set_target_from_string(value) < 0)
948 log_warning("Failed to parse log target '%s'. Ignoring.", value);
950 } else if (streq(key, "systemd.log_level") && value) {
952 if (log_set_max_level_from_string(value) < 0)
953 log_warning("Failed to parse log level '%s'. Ignoring.", value);
955 } else if (streq(key, "systemd.log_color") && value) {
957 if (log_show_color_from_string(value) < 0)
958 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
960 } else if (streq(key, "systemd.log_location") && value) {
962 if (log_show_location_from_string(value) < 0)
963 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
969 void log_parse_environment(void) {
972 if (get_ctty_devnr(0, NULL) < 0)
973 /* Only try to read the command line in daemons.
974 We assume that anything that has a controlling
975 tty is user stuff. */
976 (void) parse_proc_cmdline(parse_proc_cmdline_item);
978 e = secure_getenv("SYSTEMD_LOG_TARGET");
979 if (e && log_set_target_from_string(e) < 0)
980 log_warning("Failed to parse log target '%s'. Ignoring.", e);
982 e = secure_getenv("SYSTEMD_LOG_LEVEL");
983 if (e && log_set_max_level_from_string(e) < 0)
984 log_warning("Failed to parse log level '%s'. Ignoring.", e);
986 e = secure_getenv("SYSTEMD_LOG_COLOR");
987 if (e && log_show_color_from_string(e) < 0)
988 log_warning("Failed to parse bool '%s'. Ignoring.", e);
990 e = secure_getenv("SYSTEMD_LOG_LOCATION");
991 if (e && log_show_location_from_string(e) < 0)
992 log_warning("Failed to parse bool '%s'. Ignoring.", e);
995 LogTarget log_get_target(void) {
999 int log_get_max_level(void) {
1000 return log_max_level;
1003 void log_show_color(bool b) {
1007 bool log_get_show_color(void) {
1011 void log_show_location(bool b) {
1015 bool log_get_show_location(void) {
1016 return show_location;
1019 int log_show_color_from_string(const char *e) {
1022 t = parse_boolean(e);
1030 int log_show_location_from_string(const char *e) {
1033 t = parse_boolean(e);
1037 log_show_location(t);
1041 bool log_on_console(void) {
1042 if (log_target == LOG_TARGET_CONSOLE ||
1043 log_target == LOG_TARGET_CONSOLE_PREFIXED)
1046 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1049 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1050 [LOG_TARGET_CONSOLE] = "console",
1051 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1052 [LOG_TARGET_KMSG] = "kmsg",
1053 [LOG_TARGET_JOURNAL] = "journal",
1054 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1055 [LOG_TARGET_SYSLOG] = "syslog",
1056 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1057 [LOG_TARGET_AUTO] = "auto",
1058 [LOG_TARGET_SAFE] = "safe",
1059 [LOG_TARGET_NULL] = "null"
1062 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1064 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1065 if (si->ssi_pid > 0) {
1066 _cleanup_free_ char *p = NULL;
1068 get_process_comm(si->ssi_pid, &p);
1071 "Received SIG%s from PID %"PRIu32" (%s).",
1072 signal_to_string(si->ssi_signo),
1073 si->ssi_pid, strna(p));
1077 signal_to_string(si->ssi_signo));
1081 void log_set_upgrade_syslog_to_journal(bool b) {
1082 upgrade_syslog_to_journal = b;
1085 int log_syntax_internal(
1088 const char *config_file,
1089 unsigned config_line,
1094 const char *format, ...) {
1097 char buffer[LINE_MAX];
1104 if (_likely_(LOG_PRI(level) > log_max_level))
1107 if (log_target == LOG_TARGET_NULL)
1113 va_start(ap, format);
1114 vsnprintf(buffer, sizeof(buffer), format, ap);
1118 r = log_struct_internal(
1121 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1122 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1123 "CONFIG_FILE=%s", config_file,
1124 "CONFIG_LINE=%u", config_line,
1125 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1128 r = log_struct_internal(
1131 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1132 "CONFIG_FILE=%s", config_file,
1133 "CONFIG_LINE=%u", config_line,
1134 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),