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>
31 #include "parse-printf-format.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 /// UNNEEDED by elogind 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 /// UNNEEDED by elogind
183 void log_close_journal(void) {
184 journal_fd = safe_close(journal_fd);
187 static int log_open_journal(void) {
189 static const union sockaddr_union sa = {
190 .un.sun_family = AF_UNIX,
191 .un.sun_path = "/run/systemd/journal/socket",
199 journal_fd = create_log_socket(SOCK_DGRAM);
200 if (journal_fd < 0) {
205 if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
221 /* If we don't use the console we close it here, to not get
222 * killed by SAK. If we don't use syslog we close it here so
223 * that we are not confused by somebody deleting the socket in
224 * the fs. If we don't use /dev/kmsg we still keep it open,
225 * because there is no reason to close it. */
227 if (log_target == LOG_TARGET_NULL) {
228 /// UNNEEDED by elogind log_close_journal();
234 if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
236 isatty(STDERR_FILENO) <= 0) {
238 /// elogind does not support logging to systemd-journald
240 if (log_target == LOG_TARGET_AUTO ||
241 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
242 log_target == LOG_TARGET_JOURNAL) {
243 r = log_open_journal();
251 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
252 log_target == LOG_TARGET_SYSLOG) {
253 r = log_open_syslog();
255 /// UNNEEDED by elogind log_close_journal();
261 if (log_target == LOG_TARGET_AUTO ||
262 log_target == LOG_TARGET_SAFE ||
263 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
264 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
265 log_target == LOG_TARGET_KMSG) {
268 /// UNNEEDED by elogind log_close_journal();
276 /// UNNEEDED by elogind log_close_journal();
279 return log_open_console();
282 void log_set_target(LogTarget target) {
284 assert(target < _LOG_TARGET_MAX);
286 /// elogind does not support logging to systemd-journald
288 if (upgrade_syslog_to_journal) {
289 if (target == LOG_TARGET_SYSLOG)
290 target = LOG_TARGET_JOURNAL;
291 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
292 target = LOG_TARGET_JOURNAL_OR_KMSG;
299 void log_close(void) {
300 /// UNNEDED by elogind log_close_journal();
306 /// UNNEEDED by elogind
308 void log_forget_fds(void) {
309 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
313 void log_set_max_level(int level) {
314 assert((level & LOG_PRIMASK) == level);
316 log_max_level = level;
319 void log_set_facility(int facility) {
320 log_facility = facility;
323 static int write_to_console(
329 const char *object_field,
331 const char *buffer) {
333 char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2];
334 struct iovec iovec[6] = {};
341 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
342 sprintf(prefix, "<%i>", level);
343 IOVEC_SET_STRING(iovec[n++], prefix);
346 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
349 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
350 IOVEC_SET_STRING(iovec[n++], location);
354 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
355 IOVEC_SET_STRING(iovec[n++], buffer);
357 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
358 IOVEC_SET_STRING(iovec[n++], "\n");
360 if (writev(console_fd, iovec, n) < 0) {
362 if (errno == EIO && getpid() == 1) {
364 /* If somebody tried to kick us from our
365 * console tty (via vhangup() or suchlike),
366 * try to reconnect */
374 if (writev(console_fd, iovec, n) < 0)
383 static int write_to_syslog(
389 const char *object_field,
391 const char *buffer) {
393 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
395 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
396 struct iovec iovec[5] = {};
397 struct msghdr msghdr = {
399 .msg_iovlen = ELEMENTSOF(iovec),
407 xsprintf(header_priority, "<%i>", level);
409 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
414 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
417 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
419 IOVEC_SET_STRING(iovec[0], header_priority);
420 IOVEC_SET_STRING(iovec[1], header_time);
421 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
422 IOVEC_SET_STRING(iovec[3], header_pid);
423 IOVEC_SET_STRING(iovec[4], buffer);
425 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
426 if (syslog_is_stream)
432 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
436 if (!syslog_is_stream ||
437 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
440 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
446 static int write_to_kmsg(
452 const char *object_field,
454 const char *buffer) {
456 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
457 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
458 struct iovec iovec[5] = {};
463 xsprintf(header_priority, "<%i>", level);
464 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
466 IOVEC_SET_STRING(iovec[0], header_priority);
467 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
468 IOVEC_SET_STRING(iovec[2], header_pid);
469 IOVEC_SET_STRING(iovec[3], buffer);
470 IOVEC_SET_STRING(iovec[4], "\n");
472 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
478 /// UNNEEDED by elogind
480 static int log_do_header(
485 const char *file, int line, const char *func,
486 const char *object_field, const char *object) {
488 snprintf(header, size,
490 "SYSLOG_FACILITY=%i\n"
496 "SYSLOG_IDENTIFIER=%s\n",
499 isempty(file) ? "" : "CODE_FILE=",
500 isempty(file) ? "" : file,
501 isempty(file) ? "" : "\n",
502 line ? "CODE_LINE=" : "",
503 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
505 isempty(func) ? "" : "CODE_FUNCTION=",
506 isempty(func) ? "" : func,
507 isempty(func) ? "" : "\n",
508 error ? "ERRNO=" : "",
509 error ? 1 : 0, error,
511 isempty(object) ? "" : object_field,
512 isempty(object) ? "" : object,
513 isempty(object) ? "" : "\n",
514 program_invocation_short_name);
519 static int write_to_journal(
525 const char *object_field,
527 const char *buffer) {
529 char header[LINE_MAX];
530 struct iovec iovec[4] = {};
531 struct msghdr mh = {};
536 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
538 IOVEC_SET_STRING(iovec[0], header);
539 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
540 IOVEC_SET_STRING(iovec[2], buffer);
541 IOVEC_SET_STRING(iovec[3], "\n");
544 mh.msg_iovlen = ELEMENTSOF(iovec);
546 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
553 static int log_dispatch(
559 const char *object_field,
565 if (log_target == LOG_TARGET_NULL)
568 /* Patch in LOG_DAEMON facility if necessary */
569 if ((level & LOG_FACMASK) == 0)
570 level = log_facility | LOG_PRI(level);
579 buffer += strspn(buffer, NEWLINE);
584 if ((e = strpbrk(buffer, NEWLINE)))
587 /// elogind does not support logging to systemd-journald
589 if (log_target == LOG_TARGET_AUTO ||
590 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
591 log_target == LOG_TARGET_JOURNAL) {
593 k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
602 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
603 log_target == LOG_TARGET_SYSLOG) {
605 k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
614 (log_target == LOG_TARGET_AUTO ||
615 log_target == LOG_TARGET_SAFE ||
616 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
617 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
618 log_target == LOG_TARGET_KMSG)) {
620 k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
628 (void) write_to_console(level, error, file, line, func, object_field, object, buffer);
636 int log_dump_internal(
646 /* This modifies the buffer... */
651 if (_likely_(LOG_PRI(level) > log_max_level))
654 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
667 char buffer[LINE_MAX];
672 if (_likely_(LOG_PRI(level) > log_max_level))
675 /* Make sure that %m maps to the specified error */
679 vsnprintf(buffer, sizeof(buffer), format, ap);
681 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
690 const char *format, ...) {
695 va_start(ap, format);
696 r = log_internalv(level, error, file, line, func, format, ap);
702 int log_object_internalv(
708 const char *object_field,
720 if (_likely_(LOG_PRI(level) > log_max_level))
723 /* Make sure that %m maps to the specified error */
727 /* Prepend the object name before the message */
732 l = n + 2 + LINE_MAX;
734 buffer = newa(char, l);
735 b = stpcpy(stpcpy(buffer, object), ": ");
738 b = buffer = newa(char, l);
741 vsnprintf(b, l, format, ap);
743 return log_dispatch(level, error, file, line, func, object_field, object, buffer);
746 int log_object_internal(
752 const char *object_field,
754 const char *format, ...) {
759 va_start(ap, format);
760 r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap);
766 static void log_assert(
772 const char *format) {
774 static char buffer[LINE_MAX];
776 if (_likely_(LOG_PRI(level) > log_max_level))
779 DISABLE_WARNING_FORMAT_NONLITERAL;
780 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
783 log_abort_msg = buffer;
785 log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
788 noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
789 log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
793 noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
794 log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
798 void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
800 log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
803 int log_oom_internal(const char *file, int line, const char *func) {
804 log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
808 int log_struct_internal(
814 const char *format, ...) {
824 if (_likely_(LOG_PRI(level) > log_max_level))
827 if (log_target == LOG_TARGET_NULL)
830 if ((level & LOG_FACMASK) == 0)
831 level = log_facility | LOG_PRI(level);
833 /// elogind does not support logging to systemd-journald
835 if ((log_target == LOG_TARGET_AUTO ||
836 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
837 log_target == LOG_TARGET_JOURNAL) &&
839 char header[LINE_MAX];
840 struct iovec iovec[17] = {};
845 static const char nl = '\n';
846 bool fallback = false;
848 /* If the journal is available do structured logging */
849 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
850 IOVEC_SET_STRING(iovec[n++], header);
852 va_start(ap, format);
853 while (format && n + 1 < ELEMENTSOF(iovec)) {
857 /* We need to copy the va_list structure,
858 * since vasprintf() leaves it afterwards at
859 * an undefined location */
865 if (vasprintf(&m, format, aq) < 0) {
872 /* Now, jump enough ahead, so that we point to
873 * the next format string */
874 VA_FORMAT_ADVANCE(format, ap);
876 IOVEC_SET_STRING(iovec[n++], m);
878 iovec[n].iov_base = (char*) &nl;
879 iovec[n].iov_len = 1;
882 format = va_arg(ap, char *);
887 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
891 for (i = 1; i < n; i += 2)
892 free(iovec[i].iov_base);
899 /* Fallback if journal logging is not available or didn't work. */
901 va_start(ap, format);
909 vsnprintf(buf, sizeof(buf), format, aq);
912 if (startswith(buf, "MESSAGE=")) {
917 VA_FORMAT_ADVANCE(format, ap);
919 format = va_arg(ap, char *);
926 return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
929 int log_set_target_from_string(const char *e) {
932 t = log_target_from_string(e);
940 int log_set_max_level_from_string(const char *e) {
943 t = log_level_from_string(e);
947 log_set_max_level(t);
951 static int parse_proc_cmdline_item(const char *key, const char *value) {
954 * The systemd.log_xyz= settings are parsed by all tools, and
957 * However, "quiet" is only parsed by PID 1, and only turns of
958 * status output to /dev/console, but does not alter the log
962 if (streq(key, "debug") && !value)
963 log_set_max_level(LOG_DEBUG);
965 else if (streq(key, "systemd.log_target") && value) {
967 if (log_set_target_from_string(value) < 0)
968 log_warning("Failed to parse log target '%s'. Ignoring.", value);
970 } else if (streq(key, "systemd.log_level") && value) {
972 if (log_set_max_level_from_string(value) < 0)
973 log_warning("Failed to parse log level '%s'. Ignoring.", value);
975 } else if (streq(key, "systemd.log_color") && value) {
977 if (log_show_color_from_string(value) < 0)
978 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
980 } else if (streq(key, "systemd.log_location") && value) {
982 if (log_show_location_from_string(value) < 0)
983 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
989 void log_parse_environment(void) {
992 if (get_ctty_devnr(0, NULL) < 0)
993 /* Only try to read the command line in daemons.
994 We assume that anything that has a controlling
995 tty is user stuff. */
996 (void) parse_proc_cmdline(parse_proc_cmdline_item);
998 e = secure_getenv("SYSTEMD_LOG_TARGET");
999 if (e && log_set_target_from_string(e) < 0)
1000 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1002 e = secure_getenv("SYSTEMD_LOG_LEVEL");
1003 if (e && log_set_max_level_from_string(e) < 0)
1004 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1006 e = secure_getenv("SYSTEMD_LOG_COLOR");
1007 if (e && log_show_color_from_string(e) < 0)
1008 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1010 e = secure_getenv("SYSTEMD_LOG_LOCATION");
1011 if (e && log_show_location_from_string(e) < 0)
1012 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1015 LogTarget log_get_target(void) {
1019 int log_get_max_level(void) {
1020 return log_max_level;
1023 void log_show_color(bool b) {
1027 bool log_get_show_color(void) {
1031 void log_show_location(bool b) {
1035 bool log_get_show_location(void) {
1036 return show_location;
1039 int log_show_color_from_string(const char *e) {
1042 t = parse_boolean(e);
1050 int log_show_location_from_string(const char *e) {
1053 t = parse_boolean(e);
1057 log_show_location(t);
1061 bool log_on_console(void) {
1062 if (log_target == LOG_TARGET_CONSOLE ||
1063 log_target == LOG_TARGET_CONSOLE_PREFIXED)
1066 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1069 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1070 [LOG_TARGET_CONSOLE] = "console",
1071 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1072 [LOG_TARGET_KMSG] = "kmsg",
1073 /// elogind does not support logging to systemd-journald
1075 [LOG_TARGET_JOURNAL] = "journal",
1076 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1078 [LOG_TARGET_SYSLOG] = "syslog",
1079 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1080 [LOG_TARGET_AUTO] = "auto",
1081 [LOG_TARGET_SAFE] = "safe",
1082 [LOG_TARGET_NULL] = "null"
1085 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1087 /// UNNEEDED by elogind
1089 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1090 if (si->ssi_pid > 0) {
1091 _cleanup_free_ char *p = NULL;
1093 get_process_comm(si->ssi_pid, &p);
1096 "Received SIG%s from PID %"PRIu32" (%s).",
1097 signal_to_string(si->ssi_signo),
1098 si->ssi_pid, strna(p));
1102 signal_to_string(si->ssi_signo));
1106 void log_set_upgrade_syslog_to_journal(bool b) {
1107 upgrade_syslog_to_journal = b;
1111 int log_syntax_internal(
1114 const char *config_file,
1115 unsigned config_line,
1120 const char *format, ...) {
1123 char buffer[LINE_MAX];
1130 if (_likely_(LOG_PRI(level) > log_max_level))
1133 if (log_target == LOG_TARGET_NULL)
1139 va_start(ap, format);
1140 vsnprintf(buffer, sizeof(buffer), format, ap);
1144 r = log_struct_internal(
1147 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1148 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1149 "CONFIG_FILE=%s", config_file,
1150 "CONFIG_LINE=%u", config_line,
1151 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1154 r = log_struct_internal(
1157 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1158 "CONFIG_FILE=%s", config_file,
1159 "CONFIG_LINE=%u", config_line,
1160 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),