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 #if 0 /// UNNEEDED by elogind
192 void log_close_journal(void) {
193 journal_fd = safe_close(journal_fd);
196 static int log_open_journal(void) {
198 static const union sockaddr_union sa = {
199 .un.sun_family = AF_UNIX,
200 .un.sun_path = "/run/systemd/journal/socket",
208 journal_fd = create_log_socket(SOCK_DGRAM);
209 if (journal_fd < 0) {
214 if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
230 /* If we don't use the console we close it here, to not get
231 * killed by SAK. If we don't use syslog we close it here so
232 * that we are not confused by somebody deleting the socket in
233 * the fs. If we don't use /dev/kmsg we still keep it open,
234 * because there is no reason to close it. */
236 if (log_target == LOG_TARGET_NULL) {
237 /// UNNEEDED by elogind log_close_journal();
243 if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
245 isatty(STDERR_FILENO) <= 0) {
247 #if 0 /// elogind does not support logging to systemd-journald
248 if (log_target == LOG_TARGET_AUTO ||
249 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
250 log_target == LOG_TARGET_JOURNAL) {
251 r = log_open_journal();
259 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
260 log_target == LOG_TARGET_SYSLOG) {
261 r = log_open_syslog();
263 /// UNNEEDED by elogind log_close_journal();
269 if (log_target == LOG_TARGET_AUTO ||
270 log_target == LOG_TARGET_SAFE ||
271 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
272 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
273 log_target == LOG_TARGET_KMSG) {
276 /// UNNEEDED by elogind log_close_journal();
284 /// UNNEEDED by elogind log_close_journal();
287 return log_open_console();
290 void log_set_target(LogTarget target) {
292 assert(target < _LOG_TARGET_MAX);
294 #if 0 /// elogind does not support logging to systemd-journald
295 if (upgrade_syslog_to_journal) {
296 if (target == LOG_TARGET_SYSLOG)
297 target = LOG_TARGET_JOURNAL;
298 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
299 target = LOG_TARGET_JOURNAL_OR_KMSG;
306 void log_close(void) {
307 /// UNNEDED by elogind log_close_journal();
313 #if 0 /// UNNEEDED by elogind
314 void log_forget_fds(void) {
315 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
319 void log_set_max_level(int level) {
320 assert((level & LOG_PRIMASK) == level);
322 log_max_level = level;
325 void log_set_facility(int facility) {
326 log_facility = facility;
329 static int write_to_console(
335 const char *object_field,
337 const char *buffer) {
339 char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2];
340 struct iovec iovec[6] = {};
347 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
348 sprintf(prefix, "<%i>", level);
349 IOVEC_SET_STRING(iovec[n++], prefix);
352 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
355 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
356 IOVEC_SET_STRING(iovec[n++], location);
360 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED);
361 IOVEC_SET_STRING(iovec[n++], buffer);
363 IOVEC_SET_STRING(iovec[n++], ANSI_NORMAL);
364 IOVEC_SET_STRING(iovec[n++], "\n");
366 if (writev(console_fd, iovec, n) < 0) {
368 if (errno == EIO && getpid() == 1) {
370 /* If somebody tried to kick us from our
371 * console tty (via vhangup() or suchlike),
372 * try to reconnect */
380 if (writev(console_fd, iovec, n) < 0)
389 static int write_to_syslog(
395 const char *object_field,
397 const char *buffer) {
399 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
401 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
402 struct iovec iovec[5] = {};
403 struct msghdr msghdr = {
405 .msg_iovlen = ELEMENTSOF(iovec),
413 xsprintf(header_priority, "<%i>", level);
415 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
420 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
423 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
425 IOVEC_SET_STRING(iovec[0], header_priority);
426 IOVEC_SET_STRING(iovec[1], header_time);
427 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
428 IOVEC_SET_STRING(iovec[3], header_pid);
429 IOVEC_SET_STRING(iovec[4], buffer);
431 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
432 if (syslog_is_stream)
438 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
442 if (!syslog_is_stream ||
443 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
446 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
452 static int write_to_kmsg(
458 const char *object_field,
460 const char *buffer) {
462 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
463 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
464 struct iovec iovec[5] = {};
469 xsprintf(header_priority, "<%i>", level);
470 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
472 IOVEC_SET_STRING(iovec[0], header_priority);
473 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
474 IOVEC_SET_STRING(iovec[2], header_pid);
475 IOVEC_SET_STRING(iovec[3], buffer);
476 IOVEC_SET_STRING(iovec[4], "\n");
478 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
484 #if 0 /// UNNEEDED by elogind
485 static int log_do_header(
490 const char *file, int line, const char *func,
491 const char *object_field, const char *object) {
493 snprintf(header, size,
495 "SYSLOG_FACILITY=%i\n"
501 "SYSLOG_IDENTIFIER=%s\n",
504 isempty(file) ? "" : "CODE_FILE=",
505 isempty(file) ? "" : file,
506 isempty(file) ? "" : "\n",
507 line ? "CODE_LINE=" : "",
508 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
510 isempty(func) ? "" : "CODE_FUNCTION=",
511 isempty(func) ? "" : func,
512 isempty(func) ? "" : "\n",
513 error ? "ERRNO=" : "",
514 error ? 1 : 0, error,
516 isempty(object) ? "" : object_field,
517 isempty(object) ? "" : object,
518 isempty(object) ? "" : "\n",
519 program_invocation_short_name);
524 static int write_to_journal(
530 const char *object_field,
532 const char *buffer) {
534 char header[LINE_MAX];
535 struct iovec iovec[4] = {};
536 struct msghdr mh = {};
541 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
543 IOVEC_SET_STRING(iovec[0], header);
544 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
545 IOVEC_SET_STRING(iovec[2], buffer);
546 IOVEC_SET_STRING(iovec[3], "\n");
549 mh.msg_iovlen = ELEMENTSOF(iovec);
551 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
558 static int log_dispatch(
564 const char *object_field,
570 if (log_target == LOG_TARGET_NULL)
573 /* Patch in LOG_DAEMON facility if necessary */
574 if ((level & LOG_FACMASK) == 0)
575 level = log_facility | LOG_PRI(level);
584 buffer += strspn(buffer, NEWLINE);
589 if ((e = strpbrk(buffer, NEWLINE)))
592 #if 0 /// elogind does not support logging to systemd-journald
593 if (log_target == LOG_TARGET_AUTO ||
594 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
595 log_target == LOG_TARGET_JOURNAL) {
597 k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
606 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
607 log_target == LOG_TARGET_SYSLOG) {
609 k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
618 (log_target == LOG_TARGET_AUTO ||
619 log_target == LOG_TARGET_SAFE ||
620 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
621 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
622 log_target == LOG_TARGET_KMSG)) {
624 k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
632 (void) write_to_console(level, error, file, line, func, object_field, object, buffer);
640 int log_dump_internal(
650 /* This modifies the buffer... */
655 if (_likely_(LOG_PRI(level) > log_max_level))
658 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
671 char buffer[LINE_MAX];
676 if (_likely_(LOG_PRI(level) > log_max_level))
679 /* Make sure that %m maps to the specified error */
683 vsnprintf(buffer, sizeof(buffer), format, ap);
685 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
694 const char *format, ...) {
699 va_start(ap, format);
700 r = log_internalv(level, error, file, line, func, format, ap);
706 int log_object_internalv(
712 const char *object_field,
724 if (_likely_(LOG_PRI(level) > log_max_level))
727 /* Make sure that %m maps to the specified error */
731 /* Prepend the object name before the message */
736 l = n + 2 + LINE_MAX;
738 buffer = newa(char, l);
739 b = stpcpy(stpcpy(buffer, object), ": ");
742 b = buffer = newa(char, l);
745 vsnprintf(b, l, format, ap);
747 return log_dispatch(level, error, file, line, func, object_field, object, buffer);
750 int log_object_internal(
756 const char *object_field,
758 const char *format, ...) {
763 va_start(ap, format);
764 r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap);
770 static void log_assert(
776 const char *format) {
778 static char buffer[LINE_MAX];
780 if (_likely_(LOG_PRI(level) > log_max_level))
783 DISABLE_WARNING_FORMAT_NONLITERAL;
784 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
787 log_abort_msg = buffer;
789 log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
792 noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
793 log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
797 noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
798 log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
802 void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
804 log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
807 int log_oom_internal(const char *file, int line, const char *func) {
808 log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
812 int log_struct_internal(
818 const char *format, ...) {
828 if (_likely_(LOG_PRI(level) > log_max_level))
831 if (log_target == LOG_TARGET_NULL)
834 if ((level & LOG_FACMASK) == 0)
835 level = log_facility | LOG_PRI(level);
837 #if 0 /// elogind does not support logging to systemd-journald
838 if ((log_target == LOG_TARGET_AUTO ||
839 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
840 log_target == LOG_TARGET_JOURNAL) &&
842 char header[LINE_MAX];
843 struct iovec iovec[17] = {};
848 static const char nl = '\n';
849 bool fallback = false;
851 /* If the journal is available do structured logging */
852 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
853 IOVEC_SET_STRING(iovec[n++], header);
855 va_start(ap, format);
856 while (format && n + 1 < ELEMENTSOF(iovec)) {
860 /* We need to copy the va_list structure,
861 * since vasprintf() leaves it afterwards at
862 * an undefined location */
868 if (vasprintf(&m, format, aq) < 0) {
875 /* Now, jump enough ahead, so that we point to
876 * the next format string */
877 VA_FORMAT_ADVANCE(format, ap);
879 IOVEC_SET_STRING(iovec[n++], m);
881 iovec[n].iov_base = (char*) &nl;
882 iovec[n].iov_len = 1;
885 format = va_arg(ap, char *);
890 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
894 for (i = 1; i < n; i += 2)
895 free(iovec[i].iov_base);
902 /* Fallback if journal logging is not available or didn't work. */
904 va_start(ap, format);
912 vsnprintf(buf, sizeof(buf), format, aq);
915 if (startswith(buf, "MESSAGE=")) {
920 VA_FORMAT_ADVANCE(format, ap);
922 format = va_arg(ap, char *);
929 return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
932 int log_set_target_from_string(const char *e) {
935 t = log_target_from_string(e);
943 int log_set_max_level_from_string(const char *e) {
946 t = log_level_from_string(e);
950 log_set_max_level(t);
954 static int parse_proc_cmdline_item(const char *key, const char *value) {
957 * The systemd.log_xyz= settings are parsed by all tools, and
960 * However, "quiet" is only parsed by PID 1, and only turns of
961 * status output to /dev/console, but does not alter the log
965 if (streq(key, "debug") && !value)
966 log_set_max_level(LOG_DEBUG);
968 else if (streq(key, "systemd.log_target") && value) {
970 if (log_set_target_from_string(value) < 0)
971 log_warning("Failed to parse log target '%s'. Ignoring.", value);
973 } else if (streq(key, "systemd.log_level") && value) {
975 if (log_set_max_level_from_string(value) < 0)
976 log_warning("Failed to parse log level '%s'. Ignoring.", value);
978 } else if (streq(key, "systemd.log_color") && value) {
980 if (log_show_color_from_string(value) < 0)
981 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
983 } else if (streq(key, "systemd.log_location") && value) {
985 if (log_show_location_from_string(value) < 0)
986 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
992 void log_parse_environment(void) {
995 if (get_ctty_devnr(0, NULL) < 0)
996 /* Only try to read the command line in daemons.
997 We assume that anything that has a controlling
998 tty is user stuff. */
999 (void) parse_proc_cmdline(parse_proc_cmdline_item);
1001 e = secure_getenv("SYSTEMD_LOG_TARGET");
1002 if (e && log_set_target_from_string(e) < 0)
1003 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1005 e = secure_getenv("SYSTEMD_LOG_LEVEL");
1006 if (e && log_set_max_level_from_string(e) < 0)
1007 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1009 e = secure_getenv("SYSTEMD_LOG_COLOR");
1010 if (e && log_show_color_from_string(e) < 0)
1011 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1013 e = secure_getenv("SYSTEMD_LOG_LOCATION");
1014 if (e && log_show_location_from_string(e) < 0)
1015 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1018 LogTarget log_get_target(void) {
1022 int log_get_max_level(void) {
1023 return log_max_level;
1026 void log_show_color(bool b) {
1030 bool log_get_show_color(void) {
1034 void log_show_location(bool b) {
1038 bool log_get_show_location(void) {
1039 return show_location;
1042 int log_show_color_from_string(const char *e) {
1045 t = parse_boolean(e);
1053 int log_show_location_from_string(const char *e) {
1056 t = parse_boolean(e);
1060 log_show_location(t);
1064 bool log_on_console(void) {
1065 if (log_target == LOG_TARGET_CONSOLE ||
1066 log_target == LOG_TARGET_CONSOLE_PREFIXED)
1069 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1072 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1073 [LOG_TARGET_CONSOLE] = "console",
1074 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1075 [LOG_TARGET_KMSG] = "kmsg",
1076 #if 0 /// elogind does not support logging to systemd-journald
1077 [LOG_TARGET_JOURNAL] = "journal",
1078 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1080 [LOG_TARGET_SYSLOG] = "syslog",
1081 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1082 [LOG_TARGET_AUTO] = "auto",
1083 [LOG_TARGET_SAFE] = "safe",
1084 [LOG_TARGET_NULL] = "null"
1087 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1089 #if 0 /// UNNEEDED by elogind
1090 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1091 if (si->ssi_pid > 0) {
1092 _cleanup_free_ char *p = NULL;
1094 get_process_comm(si->ssi_pid, &p);
1097 "Received SIG%s from PID %"PRIu32" (%s).",
1098 signal_to_string(si->ssi_signo),
1099 si->ssi_pid, strna(p));
1103 signal_to_string(si->ssi_signo));
1107 void log_set_upgrade_syslog_to_journal(bool b) {
1108 upgrade_syslog_to_journal = b;
1112 int log_syntax_internal(
1115 const char *config_file,
1116 unsigned config_line,
1121 const char *format, ...) {
1124 char buffer[LINE_MAX];
1131 if (_likely_(LOG_PRI(level) > log_max_level))
1134 if (log_target == LOG_TARGET_NULL)
1140 va_start(ap, format);
1141 vsnprintf(buffer, sizeof(buffer), format, ap);
1145 r = log_struct_internal(
1148 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1149 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1150 "CONFIG_FILE=%s", config_file,
1151 "CONFIG_LINE=%u", config_line,
1152 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1155 r = log_struct_internal(
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),