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 /// UNNEEDED by elogind
300 void log_forget_fds(void) {
301 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
305 void log_set_max_level(int level) {
306 assert((level & LOG_PRIMASK) == level);
308 log_max_level = level;
311 void log_set_facility(int facility) {
312 log_facility = facility;
315 static int write_to_console(
321 const char *object_field,
323 const char *buffer) {
325 char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2];
326 struct iovec iovec[6] = {};
333 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
334 sprintf(prefix, "<%i>", level);
335 IOVEC_SET_STRING(iovec[n++], prefix);
338 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
341 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
342 IOVEC_SET_STRING(iovec[n++], location);
346 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
347 IOVEC_SET_STRING(iovec[n++], buffer);
349 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
350 IOVEC_SET_STRING(iovec[n++], "\n");
352 if (writev(console_fd, iovec, n) < 0) {
354 if (errno == EIO && getpid() == 1) {
356 /* If somebody tried to kick us from our
357 * console tty (via vhangup() or suchlike),
358 * try to reconnect */
366 if (writev(console_fd, iovec, n) < 0)
375 static int write_to_syslog(
381 const char *object_field,
383 const char *buffer) {
385 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
387 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
388 struct iovec iovec[5] = {};
389 struct msghdr msghdr = {
391 .msg_iovlen = ELEMENTSOF(iovec),
399 xsprintf(header_priority, "<%i>", level);
401 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
406 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
409 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
411 IOVEC_SET_STRING(iovec[0], header_priority);
412 IOVEC_SET_STRING(iovec[1], header_time);
413 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
414 IOVEC_SET_STRING(iovec[3], header_pid);
415 IOVEC_SET_STRING(iovec[4], buffer);
417 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
418 if (syslog_is_stream)
424 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
428 if (!syslog_is_stream ||
429 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
432 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
438 static int write_to_kmsg(
444 const char *object_field,
446 const char *buffer) {
448 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
449 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
450 struct iovec iovec[5] = {};
455 xsprintf(header_priority, "<%i>", level);
456 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
458 IOVEC_SET_STRING(iovec[0], header_priority);
459 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
460 IOVEC_SET_STRING(iovec[2], header_pid);
461 IOVEC_SET_STRING(iovec[3], buffer);
462 IOVEC_SET_STRING(iovec[4], "\n");
464 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
470 static int log_do_header(
475 const char *file, int line, const char *func,
476 const char *object_field, const char *object) {
478 snprintf(header, size,
480 "SYSLOG_FACILITY=%i\n"
486 "SYSLOG_IDENTIFIER=%s\n",
489 isempty(file) ? "" : "CODE_FILE=",
490 isempty(file) ? "" : file,
491 isempty(file) ? "" : "\n",
492 line ? "CODE_LINE=" : "",
493 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
495 isempty(func) ? "" : "CODE_FUNCTION=",
496 isempty(func) ? "" : func,
497 isempty(func) ? "" : "\n",
498 error ? "ERRNO=" : "",
499 error ? 1 : 0, error,
501 isempty(object) ? "" : object_field,
502 isempty(object) ? "" : object,
503 isempty(object) ? "" : "\n",
504 program_invocation_short_name);
509 static int write_to_journal(
515 const char *object_field,
517 const char *buffer) {
519 char header[LINE_MAX];
520 struct iovec iovec[4] = {};
521 struct msghdr mh = {};
526 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
528 IOVEC_SET_STRING(iovec[0], header);
529 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
530 IOVEC_SET_STRING(iovec[2], buffer);
531 IOVEC_SET_STRING(iovec[3], "\n");
534 mh.msg_iovlen = ELEMENTSOF(iovec);
536 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
542 static int log_dispatch(
548 const char *object_field,
554 if (log_target == LOG_TARGET_NULL)
557 /* Patch in LOG_DAEMON facility if necessary */
558 if ((level & LOG_FACMASK) == 0)
559 level = log_facility | LOG_PRI(level);
568 buffer += strspn(buffer, NEWLINE);
573 if ((e = strpbrk(buffer, NEWLINE)))
576 if (log_target == LOG_TARGET_AUTO ||
577 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
578 log_target == LOG_TARGET_JOURNAL) {
580 k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
588 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
589 log_target == LOG_TARGET_SYSLOG) {
591 k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
600 (log_target == LOG_TARGET_AUTO ||
601 log_target == LOG_TARGET_SAFE ||
602 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
603 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
604 log_target == LOG_TARGET_KMSG)) {
606 k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
614 (void) write_to_console(level, error, file, line, func, object_field, object, buffer);
622 int log_dump_internal(
632 /* This modifies the buffer... */
637 if (_likely_(LOG_PRI(level) > log_max_level))
640 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
653 char buffer[LINE_MAX];
658 if (_likely_(LOG_PRI(level) > log_max_level))
661 /* Make sure that %m maps to the specified error */
665 vsnprintf(buffer, sizeof(buffer), format, ap);
667 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
676 const char *format, ...) {
681 va_start(ap, format);
682 r = log_internalv(level, error, file, line, func, format, ap);
688 int log_object_internalv(
694 const char *object_field,
706 if (_likely_(LOG_PRI(level) > log_max_level))
709 /* Make sure that %m maps to the specified error */
713 /* Prepend the object name before the message */
718 l = n + 2 + LINE_MAX;
720 buffer = newa(char, l);
721 b = stpcpy(stpcpy(buffer, object), ": ");
724 b = buffer = newa(char, l);
727 vsnprintf(b, l, format, ap);
729 return log_dispatch(level, error, file, line, func, object_field, object, buffer);
732 int log_object_internal(
738 const char *object_field,
740 const char *format, ...) {
745 va_start(ap, format);
746 r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap);
752 static void log_assert(
758 const char *format) {
760 static char buffer[LINE_MAX];
762 if (_likely_(LOG_PRI(level) > log_max_level))
765 DISABLE_WARNING_FORMAT_NONLITERAL;
766 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
769 log_abort_msg = buffer;
771 log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
774 noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
775 log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
779 noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
780 log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
784 void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
786 log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
789 int log_oom_internal(const char *file, int line, const char *func) {
790 log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
794 int log_struct_internal(
800 const char *format, ...) {
810 if (_likely_(LOG_PRI(level) > log_max_level))
813 if (log_target == LOG_TARGET_NULL)
816 if ((level & LOG_FACMASK) == 0)
817 level = log_facility | LOG_PRI(level);
819 if ((log_target == LOG_TARGET_AUTO ||
820 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
821 log_target == LOG_TARGET_JOURNAL) &&
823 char header[LINE_MAX];
824 struct iovec iovec[17] = {};
829 static const char nl = '\n';
830 bool fallback = false;
832 /* If the journal is available do structured logging */
833 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
834 IOVEC_SET_STRING(iovec[n++], header);
836 va_start(ap, format);
837 while (format && n + 1 < ELEMENTSOF(iovec)) {
841 /* We need to copy the va_list structure,
842 * since vasprintf() leaves it afterwards at
843 * an undefined location */
849 if (vasprintf(&m, format, aq) < 0) {
856 /* Now, jump enough ahead, so that we point to
857 * the next format string */
858 VA_FORMAT_ADVANCE(format, ap);
860 IOVEC_SET_STRING(iovec[n++], m);
862 iovec[n].iov_base = (char*) &nl;
863 iovec[n].iov_len = 1;
866 format = va_arg(ap, char *);
871 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
875 for (i = 1; i < n; i += 2)
876 free(iovec[i].iov_base);
882 /* Fallback if journal logging is not available or didn't work. */
884 va_start(ap, format);
892 vsnprintf(buf, sizeof(buf), format, aq);
895 if (startswith(buf, "MESSAGE=")) {
900 VA_FORMAT_ADVANCE(format, ap);
902 format = va_arg(ap, char *);
909 return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
912 int log_set_target_from_string(const char *e) {
915 t = log_target_from_string(e);
923 int log_set_max_level_from_string(const char *e) {
926 t = log_level_from_string(e);
930 log_set_max_level(t);
934 static int parse_proc_cmdline_item(const char *key, const char *value) {
937 * The systemd.log_xyz= settings are parsed by all tools, and
940 * However, "quiet" is only parsed by PID 1, and only turns of
941 * status output to /dev/console, but does not alter the log
945 if (streq(key, "debug") && !value)
946 log_set_max_level(LOG_DEBUG);
948 else if (streq(key, "systemd.log_target") && value) {
950 if (log_set_target_from_string(value) < 0)
951 log_warning("Failed to parse log target '%s'. Ignoring.", value);
953 } else if (streq(key, "systemd.log_level") && value) {
955 if (log_set_max_level_from_string(value) < 0)
956 log_warning("Failed to parse log level '%s'. Ignoring.", value);
958 } else if (streq(key, "systemd.log_color") && value) {
960 if (log_show_color_from_string(value) < 0)
961 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
963 } else if (streq(key, "systemd.log_location") && value) {
965 if (log_show_location_from_string(value) < 0)
966 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
972 void log_parse_environment(void) {
975 if (get_ctty_devnr(0, NULL) < 0)
976 /* Only try to read the command line in daemons.
977 We assume that anything that has a controlling
978 tty is user stuff. */
979 (void) parse_proc_cmdline(parse_proc_cmdline_item);
981 e = secure_getenv("SYSTEMD_LOG_TARGET");
982 if (e && log_set_target_from_string(e) < 0)
983 log_warning("Failed to parse log target '%s'. Ignoring.", e);
985 e = secure_getenv("SYSTEMD_LOG_LEVEL");
986 if (e && log_set_max_level_from_string(e) < 0)
987 log_warning("Failed to parse log level '%s'. Ignoring.", e);
989 e = secure_getenv("SYSTEMD_LOG_COLOR");
990 if (e && log_show_color_from_string(e) < 0)
991 log_warning("Failed to parse bool '%s'. Ignoring.", e);
993 e = secure_getenv("SYSTEMD_LOG_LOCATION");
994 if (e && log_show_location_from_string(e) < 0)
995 log_warning("Failed to parse bool '%s'. Ignoring.", e);
998 LogTarget log_get_target(void) {
1002 int log_get_max_level(void) {
1003 return log_max_level;
1006 void log_show_color(bool b) {
1010 bool log_get_show_color(void) {
1014 void log_show_location(bool b) {
1018 bool log_get_show_location(void) {
1019 return show_location;
1022 int log_show_color_from_string(const char *e) {
1025 t = parse_boolean(e);
1033 int log_show_location_from_string(const char *e) {
1036 t = parse_boolean(e);
1040 log_show_location(t);
1044 bool log_on_console(void) {
1045 if (log_target == LOG_TARGET_CONSOLE ||
1046 log_target == LOG_TARGET_CONSOLE_PREFIXED)
1049 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1052 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1053 [LOG_TARGET_CONSOLE] = "console",
1054 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1055 [LOG_TARGET_KMSG] = "kmsg",
1056 [LOG_TARGET_JOURNAL] = "journal",
1057 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1058 [LOG_TARGET_SYSLOG] = "syslog",
1059 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1060 [LOG_TARGET_AUTO] = "auto",
1061 [LOG_TARGET_SAFE] = "safe",
1062 [LOG_TARGET_NULL] = "null"
1065 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1067 /// UNNEEDED by elogind
1069 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1070 if (si->ssi_pid > 0) {
1071 _cleanup_free_ char *p = NULL;
1073 get_process_comm(si->ssi_pid, &p);
1076 "Received SIG%s from PID %"PRIu32" (%s).",
1077 signal_to_string(si->ssi_signo),
1078 si->ssi_pid, strna(p));
1082 signal_to_string(si->ssi_signo));
1086 void log_set_upgrade_syslog_to_journal(bool b) {
1087 upgrade_syslog_to_journal = b;
1091 int log_syntax_internal(
1094 const char *config_file,
1095 unsigned config_line,
1100 const char *format, ...) {
1103 char buffer[LINE_MAX];
1110 if (_likely_(LOG_PRI(level) > log_max_level))
1113 if (log_target == LOG_TARGET_NULL)
1119 va_start(ap, format);
1120 vsnprintf(buffer, sizeof(buffer), format, ap);
1124 r = log_struct_internal(
1127 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1128 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1129 "CONFIG_FILE=%s", config_file,
1130 "CONFIG_LINE=%u", config_line,
1131 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1134 r = log_struct_internal(
1137 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1138 "CONFIG_FILE=%s", config_file,
1139 "CONFIG_LINE=%u", config_line,
1140 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),