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 "parse-printf-format.h"
32 #include <sys/socket.h>
36 #include "sd-messages.h"
38 #include "alloc-util.h"
40 #include "formats-util.h"
45 #include "parse-util.h"
46 #include "proc-cmdline.h"
47 #include "process-util.h"
48 #include "signal-util.h"
49 #include "socket-util.h"
50 #include "stdio-util.h"
51 #include "string-table.h"
52 #include "string-util.h"
53 #include "syslog-util.h"
54 #include "terminal-util.h"
57 #define SNDBUF_SIZE (8*1024*1024)
59 static LogTarget log_target = LOG_TARGET_CONSOLE;
60 static int log_max_level = LOG_INFO;
61 static int log_facility = LOG_DAEMON;
63 static int console_fd = STDERR_FILENO;
64 static int syslog_fd = -1;
65 static int kmsg_fd = -1;
66 static int journal_fd = -1;
68 static bool syslog_is_stream = false;
70 static bool show_color = false;
71 static bool show_location = false;
73 /// UNNEEDED by elogind static bool upgrade_syslog_to_journal = false;
75 /* Akin to glibc's __abort_msg; which is private and we hence cannot
77 static char *log_abort_msg = NULL;
79 void log_close_console(void) {
86 safe_close(console_fd);
92 static int log_open_console(void) {
98 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
102 console_fd = STDERR_FILENO;
107 void log_close_kmsg(void) {
108 kmsg_fd = safe_close(kmsg_fd);
111 static int log_open_kmsg(void) {
116 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
123 void log_close_syslog(void) {
124 syslog_fd = safe_close(syslog_fd);
127 static int create_log_socket(int type) {
131 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
135 fd_inc_sndbuf(fd, SNDBUF_SIZE);
137 /* We need a blocking fd here since we'd otherwise lose
138 messages way too early. However, let's not hang forever in the
139 unlikely case of a deadlock. */
141 timeval_store(&tv, 10 * USEC_PER_MSEC);
143 timeval_store(&tv, 10 * USEC_PER_SEC);
144 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
149 static int log_open_syslog(void) {
151 static const union sockaddr_union sa = {
152 .un.sun_family = AF_UNIX,
153 .un.sun_path = "/dev/log",
161 syslog_fd = create_log_socket(SOCK_DGRAM);
167 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
168 safe_close(syslog_fd);
170 /* Some legacy syslog systems still use stream
171 * sockets. They really shouldn't. But what can we
173 syslog_fd = create_log_socket(SOCK_STREAM);
179 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
184 syslog_is_stream = true;
186 syslog_is_stream = false;
195 #if 0 /// UNNEEDED by elogind
196 void log_close_journal(void) {
197 journal_fd = safe_close(journal_fd);
200 static int log_open_journal(void) {
202 static const union sockaddr_union sa = {
203 .un.sun_family = AF_UNIX,
204 .un.sun_path = "/run/systemd/journal/socket",
212 journal_fd = create_log_socket(SOCK_DGRAM);
213 if (journal_fd < 0) {
218 if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
234 /* If we don't use the console we close it here, to not get
235 * killed by SAK. If we don't use syslog we close it here so
236 * that we are not confused by somebody deleting the socket in
237 * the fs. If we don't use /dev/kmsg we still keep it open,
238 * because there is no reason to close it. */
240 if (log_target == LOG_TARGET_NULL) {
241 /// UNNEEDED by elogind log_close_journal();
247 if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
249 isatty(STDERR_FILENO) <= 0) {
251 #if 0 /// elogind does not support logging to systemd-journald
252 if (log_target == LOG_TARGET_AUTO ||
253 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
254 log_target == LOG_TARGET_JOURNAL) {
255 r = log_open_journal();
263 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
264 log_target == LOG_TARGET_SYSLOG) {
265 r = log_open_syslog();
267 /// UNNEEDED by elogind log_close_journal();
273 if (log_target == LOG_TARGET_AUTO ||
274 log_target == LOG_TARGET_SAFE ||
275 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
276 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
277 log_target == LOG_TARGET_KMSG) {
280 /// UNNEEDED by elogind log_close_journal();
288 /// UNNEEDED by elogind log_close_journal();
291 return log_open_console();
294 void log_set_target(LogTarget target) {
296 assert(target < _LOG_TARGET_MAX);
298 #if 0 /// elogind does not support logging to systemd-journald
299 if (upgrade_syslog_to_journal) {
300 if (target == LOG_TARGET_SYSLOG)
301 target = LOG_TARGET_JOURNAL;
302 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
303 target = LOG_TARGET_JOURNAL_OR_KMSG;
310 void log_close(void) {
311 /// UNNEDED by elogind log_close_journal();
317 #if 0 /// 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 #if 0 /// UNNEEDED by elogind
489 static int log_do_header(
494 const char *file, int line, const char *func,
495 const char *object_field, const char *object) {
497 snprintf(header, size,
499 "SYSLOG_FACILITY=%i\n"
505 "SYSLOG_IDENTIFIER=%s\n",
508 isempty(file) ? "" : "CODE_FILE=",
509 isempty(file) ? "" : file,
510 isempty(file) ? "" : "\n",
511 line ? "CODE_LINE=" : "",
512 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
514 isempty(func) ? "" : "CODE_FUNCTION=",
515 isempty(func) ? "" : func,
516 isempty(func) ? "" : "\n",
517 error ? "ERRNO=" : "",
518 error ? 1 : 0, error,
520 isempty(object) ? "" : object_field,
521 isempty(object) ? "" : object,
522 isempty(object) ? "" : "\n",
523 program_invocation_short_name);
528 static int write_to_journal(
534 const char *object_field,
536 const char *buffer) {
538 char header[LINE_MAX];
539 struct iovec iovec[4] = {};
540 struct msghdr mh = {};
545 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
547 IOVEC_SET_STRING(iovec[0], header);
548 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
549 IOVEC_SET_STRING(iovec[2], buffer);
550 IOVEC_SET_STRING(iovec[3], "\n");
553 mh.msg_iovlen = ELEMENTSOF(iovec);
555 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
562 static int log_dispatch(
568 const char *object_field,
574 if (log_target == LOG_TARGET_NULL)
577 /* Patch in LOG_DAEMON facility if necessary */
578 if ((level & LOG_FACMASK) == 0)
579 level = log_facility | LOG_PRI(level);
588 buffer += strspn(buffer, NEWLINE);
593 if ((e = strpbrk(buffer, NEWLINE)))
596 #if 0 /// elogind does not support logging to systemd-journald
597 if (log_target == LOG_TARGET_AUTO ||
598 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
599 log_target == LOG_TARGET_JOURNAL) {
601 k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
610 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
611 log_target == LOG_TARGET_SYSLOG) {
613 k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
622 (log_target == LOG_TARGET_AUTO ||
623 log_target == LOG_TARGET_SAFE ||
624 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
625 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
626 log_target == LOG_TARGET_KMSG)) {
628 k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
636 (void) write_to_console(level, error, file, line, func, object_field, object, buffer);
644 int log_dump_internal(
654 /* This modifies the buffer... */
659 if (_likely_(LOG_PRI(level) > log_max_level))
662 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
675 char buffer[LINE_MAX];
680 if (_likely_(LOG_PRI(level) > log_max_level))
683 /* Make sure that %m maps to the specified error */
687 vsnprintf(buffer, sizeof(buffer), format, ap);
689 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
698 const char *format, ...) {
703 va_start(ap, format);
704 r = log_internalv(level, error, file, line, func, format, ap);
710 int log_object_internalv(
716 const char *object_field,
728 if (_likely_(LOG_PRI(level) > log_max_level))
731 /* Make sure that %m maps to the specified error */
735 /* Prepend the object name before the message */
740 l = n + 2 + LINE_MAX;
742 buffer = newa(char, l);
743 b = stpcpy(stpcpy(buffer, object), ": ");
746 b = buffer = newa(char, l);
749 vsnprintf(b, l, format, ap);
751 return log_dispatch(level, error, file, line, func, object_field, object, buffer);
754 int log_object_internal(
760 const char *object_field,
762 const char *format, ...) {
767 va_start(ap, format);
768 r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap);
774 static void log_assert(
780 const char *format) {
782 static char buffer[LINE_MAX];
784 if (_likely_(LOG_PRI(level) > log_max_level))
787 DISABLE_WARNING_FORMAT_NONLITERAL;
788 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
791 log_abort_msg = buffer;
793 log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
796 noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
797 log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
801 noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
802 log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
806 void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
808 log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
811 int log_oom_internal(const char *file, int line, const char *func) {
812 log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
816 int log_struct_internal(
822 const char *format, ...) {
832 if (_likely_(LOG_PRI(level) > log_max_level))
835 if (log_target == LOG_TARGET_NULL)
838 if ((level & LOG_FACMASK) == 0)
839 level = log_facility | LOG_PRI(level);
841 #if 0 /// elogind does not support logging to systemd-journald
842 if ((log_target == LOG_TARGET_AUTO ||
843 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
844 log_target == LOG_TARGET_JOURNAL) &&
846 char header[LINE_MAX];
847 struct iovec iovec[17] = {};
852 static const char nl = '\n';
853 bool fallback = false;
855 /* If the journal is available do structured logging */
856 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
857 IOVEC_SET_STRING(iovec[n++], header);
859 va_start(ap, format);
860 while (format && n + 1 < ELEMENTSOF(iovec)) {
864 /* We need to copy the va_list structure,
865 * since vasprintf() leaves it afterwards at
866 * an undefined location */
872 if (vasprintf(&m, format, aq) < 0) {
879 /* Now, jump enough ahead, so that we point to
880 * the next format string */
881 VA_FORMAT_ADVANCE(format, ap);
883 IOVEC_SET_STRING(iovec[n++], m);
885 iovec[n].iov_base = (char*) &nl;
886 iovec[n].iov_len = 1;
889 format = va_arg(ap, char *);
894 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
898 for (i = 1; i < n; i += 2)
899 free(iovec[i].iov_base);
906 /* Fallback if journal logging is not available or didn't work. */
908 va_start(ap, format);
916 vsnprintf(buf, sizeof(buf), format, aq);
919 if (startswith(buf, "MESSAGE=")) {
924 VA_FORMAT_ADVANCE(format, ap);
926 format = va_arg(ap, char *);
933 return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
936 int log_set_target_from_string(const char *e) {
939 t = log_target_from_string(e);
947 int log_set_max_level_from_string(const char *e) {
950 t = log_level_from_string(e);
954 log_set_max_level(t);
958 static int parse_proc_cmdline_item(const char *key, const char *value) {
961 * The systemd.log_xyz= settings are parsed by all tools, and
964 * However, "quiet" is only parsed by PID 1, and only turns of
965 * status output to /dev/console, but does not alter the log
969 if (streq(key, "debug") && !value)
970 log_set_max_level(LOG_DEBUG);
972 else if (streq(key, "systemd.log_target") && value) {
974 if (log_set_target_from_string(value) < 0)
975 log_warning("Failed to parse log target '%s'. Ignoring.", value);
977 } else if (streq(key, "systemd.log_level") && value) {
979 if (log_set_max_level_from_string(value) < 0)
980 log_warning("Failed to parse log level '%s'. Ignoring.", value);
982 } else if (streq(key, "systemd.log_color") && value) {
984 if (log_show_color_from_string(value) < 0)
985 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
987 } else if (streq(key, "systemd.log_location") && value) {
989 if (log_show_location_from_string(value) < 0)
990 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
996 void log_parse_environment(void) {
999 if (get_ctty_devnr(0, NULL) < 0)
1000 /* Only try to read the command line in daemons.
1001 We assume that anything that has a controlling
1002 tty is user stuff. */
1003 (void) parse_proc_cmdline(parse_proc_cmdline_item);
1005 e = secure_getenv("SYSTEMD_LOG_TARGET");
1006 if (e && log_set_target_from_string(e) < 0)
1007 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1009 e = secure_getenv("SYSTEMD_LOG_LEVEL");
1010 if (e && log_set_max_level_from_string(e) < 0)
1011 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1013 e = secure_getenv("SYSTEMD_LOG_COLOR");
1014 if (e && log_show_color_from_string(e) < 0)
1015 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1017 e = secure_getenv("SYSTEMD_LOG_LOCATION");
1018 if (e && log_show_location_from_string(e) < 0)
1019 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1022 LogTarget log_get_target(void) {
1026 int log_get_max_level(void) {
1027 return log_max_level;
1030 void log_show_color(bool b) {
1034 bool log_get_show_color(void) {
1038 void log_show_location(bool b) {
1042 bool log_get_show_location(void) {
1043 return show_location;
1046 int log_show_color_from_string(const char *e) {
1049 t = parse_boolean(e);
1057 int log_show_location_from_string(const char *e) {
1060 t = parse_boolean(e);
1064 log_show_location(t);
1068 bool log_on_console(void) {
1069 if (log_target == LOG_TARGET_CONSOLE ||
1070 log_target == LOG_TARGET_CONSOLE_PREFIXED)
1073 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1076 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1077 [LOG_TARGET_CONSOLE] = "console",
1078 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1079 [LOG_TARGET_KMSG] = "kmsg",
1080 #if 0 /// elogind does not support logging to systemd-journald
1081 [LOG_TARGET_JOURNAL] = "journal",
1082 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1084 [LOG_TARGET_SYSLOG] = "syslog",
1085 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1086 [LOG_TARGET_AUTO] = "auto",
1087 [LOG_TARGET_SAFE] = "safe",
1088 [LOG_TARGET_NULL] = "null"
1091 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1093 #if 0 /// UNNEEDED by elogind
1094 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1095 if (si->ssi_pid > 0) {
1096 _cleanup_free_ char *p = NULL;
1098 get_process_comm(si->ssi_pid, &p);
1101 "Received SIG%s from PID %"PRIu32" (%s).",
1102 signal_to_string(si->ssi_signo),
1103 si->ssi_pid, strna(p));
1107 signal_to_string(si->ssi_signo));
1111 void log_set_upgrade_syslog_to_journal(bool b) {
1112 upgrade_syslog_to_journal = b;
1116 int log_syntax_internal(
1119 const char *config_file,
1120 unsigned config_line,
1125 const char *format, ...) {
1128 char buffer[LINE_MAX];
1135 if (_likely_(LOG_PRI(level) > log_max_level))
1138 if (log_target == LOG_TARGET_NULL)
1144 va_start(ap, format);
1145 vsnprintf(buffer, sizeof(buffer), format, ap);
1149 r = log_struct_internal(
1152 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1153 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1154 "CONFIG_FILE=%s", config_file,
1155 "CONFIG_LINE=%u", config_line,
1156 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1159 r = log_struct_internal(
1162 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1163 "CONFIG_FILE=%s", config_file,
1164 "CONFIG_LINE=%u", config_line,
1165 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),