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/>.
28 #include <sys/socket.h>
32 #include "sd-messages.h"
34 #include "alloc-util.h"
36 #include "formats-util.h"
41 #include "parse-util.h"
42 #include "proc-cmdline.h"
43 #include "process-util.h"
44 #include "signal-util.h"
45 #include "socket-util.h"
46 #include "stdio-util.h"
47 #include "string-table.h"
48 #include "string-util.h"
49 #include "syslog-util.h"
50 #include "terminal-util.h"
53 #define SNDBUF_SIZE (8*1024*1024)
55 static LogTarget log_target = LOG_TARGET_CONSOLE;
56 static int log_max_level = LOG_INFO;
57 static int log_facility = LOG_DAEMON;
59 static int console_fd = STDERR_FILENO;
60 static int syslog_fd = -1;
61 static int kmsg_fd = -1;
62 static int journal_fd = -1;
64 static bool syslog_is_stream = false;
66 static bool show_color = false;
67 static bool show_location = false;
69 /// UNNEEDED by elogind static bool upgrade_syslog_to_journal = false;
71 /* Akin to glibc's __abort_msg; which is private and we hence cannot
73 static char *log_abort_msg = NULL;
75 void log_close_console(void) {
82 safe_close(console_fd);
88 static int log_open_console(void) {
94 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
98 console_fd = STDERR_FILENO;
103 void log_close_kmsg(void) {
104 kmsg_fd = safe_close(kmsg_fd);
107 static int log_open_kmsg(void) {
112 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
119 void log_close_syslog(void) {
120 syslog_fd = safe_close(syslog_fd);
123 static int create_log_socket(int type) {
127 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
131 fd_inc_sndbuf(fd, SNDBUF_SIZE);
133 /* We need a blocking fd here since we'd otherwise lose
134 messages way too early. However, let's not hang forever in the
135 unlikely case of a deadlock. */
137 timeval_store(&tv, 10 * USEC_PER_MSEC);
139 timeval_store(&tv, 10 * USEC_PER_SEC);
140 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
145 static int log_open_syslog(void) {
147 static const union sockaddr_union sa = {
148 .un.sun_family = AF_UNIX,
149 .un.sun_path = "/dev/log",
157 syslog_fd = create_log_socket(SOCK_DGRAM);
163 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
164 safe_close(syslog_fd);
166 /* Some legacy syslog systems still use stream
167 * sockets. They really shouldn't. But what can we
169 syslog_fd = create_log_socket(SOCK_STREAM);
175 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
180 syslog_is_stream = true;
182 syslog_is_stream = false;
191 /// UNNEEDED by elogind
193 void log_close_journal(void) {
194 journal_fd = safe_close(journal_fd);
197 static int log_open_journal(void) {
199 static const union sockaddr_union sa = {
200 .un.sun_family = AF_UNIX,
201 .un.sun_path = "/run/systemd/journal/socket",
209 journal_fd = create_log_socket(SOCK_DGRAM);
210 if (journal_fd < 0) {
215 if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
231 /* If we don't use the console we close it here, to not get
232 * killed by SAK. If we don't use syslog we close it here so
233 * that we are not confused by somebody deleting the socket in
234 * the fs. If we don't use /dev/kmsg we still keep it open,
235 * because there is no reason to close it. */
237 if (log_target == LOG_TARGET_NULL) {
238 /// UNNEEDED by elogind log_close_journal();
244 if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
246 isatty(STDERR_FILENO) <= 0) {
248 /// elogind does not support logging to systemd-journald
250 if (log_target == LOG_TARGET_AUTO ||
251 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
252 log_target == LOG_TARGET_JOURNAL) {
253 r = log_open_journal();
261 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
262 log_target == LOG_TARGET_SYSLOG) {
263 r = log_open_syslog();
265 /// UNNEEDED by elogind log_close_journal();
271 if (log_target == LOG_TARGET_AUTO ||
272 log_target == LOG_TARGET_SAFE ||
273 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
274 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
275 log_target == LOG_TARGET_KMSG) {
278 /// UNNEEDED by elogind log_close_journal();
286 /// UNNEEDED by elogind log_close_journal();
289 return log_open_console();
292 void log_set_target(LogTarget target) {
294 assert(target < _LOG_TARGET_MAX);
296 /// elogind does not support logging to systemd-journald
298 if (upgrade_syslog_to_journal) {
299 if (target == LOG_TARGET_SYSLOG)
300 target = LOG_TARGET_JOURNAL;
301 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
302 target = LOG_TARGET_JOURNAL_OR_KMSG;
309 void log_close(void) {
310 /// UNNEDED by elogind log_close_journal();
316 /// UNNEEDED by elogind
318 void log_forget_fds(void) {
319 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
323 void log_set_max_level(int level) {
324 assert((level & LOG_PRIMASK) == level);
326 log_max_level = level;
329 void log_set_facility(int facility) {
330 log_facility = facility;
333 static int write_to_console(
339 const char *object_field,
341 const char *buffer) {
343 char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2];
344 struct iovec iovec[6] = {};
351 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
352 sprintf(prefix, "<%i>", level);
353 IOVEC_SET_STRING(iovec[n++], prefix);
356 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
359 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
360 IOVEC_SET_STRING(iovec[n++], location);
364 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED);
365 IOVEC_SET_STRING(iovec[n++], buffer);
367 IOVEC_SET_STRING(iovec[n++], ANSI_NORMAL);
368 IOVEC_SET_STRING(iovec[n++], "\n");
370 if (writev(console_fd, iovec, n) < 0) {
372 if (errno == EIO && getpid() == 1) {
374 /* If somebody tried to kick us from our
375 * console tty (via vhangup() or suchlike),
376 * try to reconnect */
384 if (writev(console_fd, iovec, n) < 0)
393 static int write_to_syslog(
399 const char *object_field,
401 const char *buffer) {
403 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
405 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
406 struct iovec iovec[5] = {};
407 struct msghdr msghdr = {
409 .msg_iovlen = ELEMENTSOF(iovec),
417 xsprintf(header_priority, "<%i>", level);
419 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
424 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
427 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
429 IOVEC_SET_STRING(iovec[0], header_priority);
430 IOVEC_SET_STRING(iovec[1], header_time);
431 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
432 IOVEC_SET_STRING(iovec[3], header_pid);
433 IOVEC_SET_STRING(iovec[4], buffer);
435 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
436 if (syslog_is_stream)
442 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
446 if (!syslog_is_stream ||
447 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
450 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
456 static int write_to_kmsg(
462 const char *object_field,
464 const char *buffer) {
466 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
467 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
468 struct iovec iovec[5] = {};
473 xsprintf(header_priority, "<%i>", level);
474 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
476 IOVEC_SET_STRING(iovec[0], header_priority);
477 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
478 IOVEC_SET_STRING(iovec[2], header_pid);
479 IOVEC_SET_STRING(iovec[3], buffer);
480 IOVEC_SET_STRING(iovec[4], "\n");
482 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
488 /// UNNEEDED by elogind
490 static int log_do_header(
495 const char *file, int line, const char *func,
496 const char *object_field, const char *object) {
498 snprintf(header, size,
500 "SYSLOG_FACILITY=%i\n"
506 "SYSLOG_IDENTIFIER=%s\n",
509 isempty(file) ? "" : "CODE_FILE=",
510 isempty(file) ? "" : file,
511 isempty(file) ? "" : "\n",
512 line ? "CODE_LINE=" : "",
513 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
515 isempty(func) ? "" : "CODE_FUNCTION=",
516 isempty(func) ? "" : func,
517 isempty(func) ? "" : "\n",
518 error ? "ERRNO=" : "",
519 error ? 1 : 0, error,
521 isempty(object) ? "" : object_field,
522 isempty(object) ? "" : object,
523 isempty(object) ? "" : "\n",
524 program_invocation_short_name);
529 static int write_to_journal(
535 const char *object_field,
537 const char *buffer) {
539 char header[LINE_MAX];
540 struct iovec iovec[4] = {};
541 struct msghdr mh = {};
546 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
548 IOVEC_SET_STRING(iovec[0], header);
549 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
550 IOVEC_SET_STRING(iovec[2], buffer);
551 IOVEC_SET_STRING(iovec[3], "\n");
554 mh.msg_iovlen = ELEMENTSOF(iovec);
556 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
563 static int log_dispatch(
569 const char *object_field,
575 if (log_target == LOG_TARGET_NULL)
578 /* Patch in LOG_DAEMON facility if necessary */
579 if ((level & LOG_FACMASK) == 0)
580 level = log_facility | LOG_PRI(level);
589 buffer += strspn(buffer, NEWLINE);
594 if ((e = strpbrk(buffer, NEWLINE)))
597 /// elogind does not support logging to systemd-journald
599 if (log_target == LOG_TARGET_AUTO ||
600 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
601 log_target == LOG_TARGET_JOURNAL) {
603 k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
612 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
613 log_target == LOG_TARGET_SYSLOG) {
615 k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
624 (log_target == LOG_TARGET_AUTO ||
625 log_target == LOG_TARGET_SAFE ||
626 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
627 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
628 log_target == LOG_TARGET_KMSG)) {
630 k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
638 (void) write_to_console(level, error, file, line, func, object_field, object, buffer);
646 int log_dump_internal(
656 /* This modifies the buffer... */
661 if (_likely_(LOG_PRI(level) > log_max_level))
664 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
677 char buffer[LINE_MAX];
682 if (_likely_(LOG_PRI(level) > log_max_level))
685 /* Make sure that %m maps to the specified error */
689 vsnprintf(buffer, sizeof(buffer), format, ap);
691 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
700 const char *format, ...) {
705 va_start(ap, format);
706 r = log_internalv(level, error, file, line, func, format, ap);
712 int log_object_internalv(
718 const char *object_field,
730 if (_likely_(LOG_PRI(level) > log_max_level))
733 /* Make sure that %m maps to the specified error */
737 /* Prepend the object name before the message */
742 l = n + 2 + LINE_MAX;
744 buffer = newa(char, l);
745 b = stpcpy(stpcpy(buffer, object), ": ");
748 b = buffer = newa(char, l);
751 vsnprintf(b, l, format, ap);
753 return log_dispatch(level, error, file, line, func, object_field, object, buffer);
756 int log_object_internal(
762 const char *object_field,
764 const char *format, ...) {
769 va_start(ap, format);
770 r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap);
776 static void log_assert(
782 const char *format) {
784 static char buffer[LINE_MAX];
786 if (_likely_(LOG_PRI(level) > log_max_level))
789 DISABLE_WARNING_FORMAT_NONLITERAL;
790 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
793 log_abort_msg = buffer;
795 log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
798 noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
799 log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
803 noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
804 log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
808 void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
810 log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
813 int log_oom_internal(const char *file, int line, const char *func) {
814 log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
818 int log_struct_internal(
824 const char *format, ...) {
834 if (_likely_(LOG_PRI(level) > log_max_level))
837 if (log_target == LOG_TARGET_NULL)
840 if ((level & LOG_FACMASK) == 0)
841 level = log_facility | LOG_PRI(level);
843 /// elogind does not support logging to systemd-journald
845 if ((log_target == LOG_TARGET_AUTO ||
846 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
847 log_target == LOG_TARGET_JOURNAL) &&
849 char header[LINE_MAX];
850 struct iovec iovec[17] = {};
855 static const char nl = '\n';
856 bool fallback = false;
858 /* If the journal is available do structured logging */
859 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
860 IOVEC_SET_STRING(iovec[n++], header);
862 va_start(ap, format);
863 while (format && n + 1 < ELEMENTSOF(iovec)) {
867 /* We need to copy the va_list structure,
868 * since vasprintf() leaves it afterwards at
869 * an undefined location */
875 if (vasprintf(&m, format, aq) < 0) {
882 /* Now, jump enough ahead, so that we point to
883 * the next format string */
884 VA_FORMAT_ADVANCE(format, ap);
886 IOVEC_SET_STRING(iovec[n++], m);
888 iovec[n].iov_base = (char*) &nl;
889 iovec[n].iov_len = 1;
892 format = va_arg(ap, char *);
897 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
901 for (i = 1; i < n; i += 2)
902 free(iovec[i].iov_base);
909 /* Fallback if journal logging is not available or didn't work. */
911 va_start(ap, format);
919 vsnprintf(buf, sizeof(buf), format, aq);
922 if (startswith(buf, "MESSAGE=")) {
927 VA_FORMAT_ADVANCE(format, ap);
929 format = va_arg(ap, char *);
936 return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
939 int log_set_target_from_string(const char *e) {
942 t = log_target_from_string(e);
950 int log_set_max_level_from_string(const char *e) {
953 t = log_level_from_string(e);
957 log_set_max_level(t);
961 static int parse_proc_cmdline_item(const char *key, const char *value) {
964 * The systemd.log_xyz= settings are parsed by all tools, and
967 * However, "quiet" is only parsed by PID 1, and only turns of
968 * status output to /dev/console, but does not alter the log
972 if (streq(key, "debug") && !value)
973 log_set_max_level(LOG_DEBUG);
975 else if (streq(key, "systemd.log_target") && value) {
977 if (log_set_target_from_string(value) < 0)
978 log_warning("Failed to parse log target '%s'. Ignoring.", value);
980 } else if (streq(key, "systemd.log_level") && value) {
982 if (log_set_max_level_from_string(value) < 0)
983 log_warning("Failed to parse log level '%s'. Ignoring.", value);
985 } else if (streq(key, "systemd.log_color") && value) {
987 if (log_show_color_from_string(value) < 0)
988 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
990 } else if (streq(key, "systemd.log_location") && value) {
992 if (log_show_location_from_string(value) < 0)
993 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
999 void log_parse_environment(void) {
1002 if (get_ctty_devnr(0, NULL) < 0)
1003 /* Only try to read the command line in daemons.
1004 We assume that anything that has a controlling
1005 tty is user stuff. */
1006 (void) parse_proc_cmdline(parse_proc_cmdline_item);
1008 e = secure_getenv("SYSTEMD_LOG_TARGET");
1009 if (e && log_set_target_from_string(e) < 0)
1010 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1012 e = secure_getenv("SYSTEMD_LOG_LEVEL");
1013 if (e && log_set_max_level_from_string(e) < 0)
1014 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1016 e = secure_getenv("SYSTEMD_LOG_COLOR");
1017 if (e && log_show_color_from_string(e) < 0)
1018 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1020 e = secure_getenv("SYSTEMD_LOG_LOCATION");
1021 if (e && log_show_location_from_string(e) < 0)
1022 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1025 LogTarget log_get_target(void) {
1029 int log_get_max_level(void) {
1030 return log_max_level;
1033 void log_show_color(bool b) {
1037 bool log_get_show_color(void) {
1041 void log_show_location(bool b) {
1045 bool log_get_show_location(void) {
1046 return show_location;
1049 int log_show_color_from_string(const char *e) {
1052 t = parse_boolean(e);
1060 int log_show_location_from_string(const char *e) {
1063 t = parse_boolean(e);
1067 log_show_location(t);
1071 bool log_on_console(void) {
1072 if (log_target == LOG_TARGET_CONSOLE ||
1073 log_target == LOG_TARGET_CONSOLE_PREFIXED)
1076 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1079 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1080 [LOG_TARGET_CONSOLE] = "console",
1081 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1082 [LOG_TARGET_KMSG] = "kmsg",
1083 /// elogind does not support logging to systemd-journald
1085 [LOG_TARGET_JOURNAL] = "journal",
1086 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1088 [LOG_TARGET_SYSLOG] = "syslog",
1089 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1090 [LOG_TARGET_AUTO] = "auto",
1091 [LOG_TARGET_SAFE] = "safe",
1092 [LOG_TARGET_NULL] = "null"
1095 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1097 /// UNNEEDED by elogind
1099 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1100 if (si->ssi_pid > 0) {
1101 _cleanup_free_ char *p = NULL;
1103 get_process_comm(si->ssi_pid, &p);
1106 "Received SIG%s from PID %"PRIu32" (%s).",
1107 signal_to_string(si->ssi_signo),
1108 si->ssi_pid, strna(p));
1112 signal_to_string(si->ssi_signo));
1116 void log_set_upgrade_syslog_to_journal(bool b) {
1117 upgrade_syslog_to_journal = b;
1121 int log_syntax_internal(
1124 const char *config_file,
1125 unsigned config_line,
1130 const char *format, ...) {
1133 char buffer[LINE_MAX];
1140 if (_likely_(LOG_PRI(level) > log_max_level))
1143 if (log_target == LOG_TARGET_NULL)
1149 va_start(ap, format);
1150 vsnprintf(buffer, sizeof(buffer), format, ap);
1154 r = log_struct_internal(
1157 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1158 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1159 "CONFIG_FILE=%s", config_file,
1160 "CONFIG_LINE=%u", config_line,
1161 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1164 r = log_struct_internal(
1167 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1168 "CONFIG_FILE=%s", config_file,
1169 "CONFIG_LINE=%u", config_line,
1170 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),