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"
42 #define SNDBUF_SIZE (8*1024*1024)
44 static LogTarget log_target = LOG_TARGET_CONSOLE;
45 static int log_max_level = LOG_INFO;
46 static int log_facility = LOG_DAEMON;
48 static int console_fd = STDERR_FILENO;
49 static int syslog_fd = -1;
50 static int kmsg_fd = -1;
51 static int journal_fd = -1;
53 static bool syslog_is_stream = false;
55 static bool show_color = false;
56 static bool show_location = false;
58 static bool upgrade_syslog_to_journal = false;
60 /* Akin to glibc's __abort_msg; which is private and we hence cannot
62 static char *log_abort_msg = NULL;
64 void log_close_console(void) {
71 safe_close(console_fd);
77 static int log_open_console(void) {
83 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
87 console_fd = STDERR_FILENO;
92 void log_close_kmsg(void) {
93 kmsg_fd = safe_close(kmsg_fd);
96 static int log_open_kmsg(void) {
101 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
108 void log_close_syslog(void) {
109 syslog_fd = safe_close(syslog_fd);
112 static int create_log_socket(int type) {
116 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
120 fd_inc_sndbuf(fd, SNDBUF_SIZE);
122 /* We need a blocking fd here since we'd otherwise lose
123 messages way too early. However, let's not hang forever in the
124 unlikely case of a deadlock. */
126 timeval_store(&tv, 10 * USEC_PER_MSEC);
128 timeval_store(&tv, 10 * USEC_PER_SEC);
129 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
134 static int log_open_syslog(void) {
136 static const union sockaddr_union sa = {
137 .un.sun_family = AF_UNIX,
138 .un.sun_path = "/dev/log",
146 syslog_fd = create_log_socket(SOCK_DGRAM);
152 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
153 safe_close(syslog_fd);
155 /* Some legacy syslog systems still use stream
156 * sockets. They really shouldn't. But what can we
158 syslog_fd = create_log_socket(SOCK_STREAM);
164 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
169 syslog_is_stream = true;
171 syslog_is_stream = false;
180 void log_close_journal(void) {
181 journal_fd = safe_close(journal_fd);
184 static int log_open_journal(void) {
186 static const union sockaddr_union sa = {
187 .un.sun_family = AF_UNIX,
188 .un.sun_path = "/run/systemd/journal/socket",
196 journal_fd = create_log_socket(SOCK_DGRAM);
197 if (journal_fd < 0) {
202 if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
217 /* If we don't use the console we close it here, to not get
218 * killed by SAK. If we don't use syslog we close it here so
219 * that we are not confused by somebody deleting the socket in
220 * the fs. If we don't use /dev/kmsg we still keep it open,
221 * because there is no reason to close it. */
223 if (log_target == LOG_TARGET_NULL) {
230 if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
232 isatty(STDERR_FILENO) <= 0) {
234 if (log_target == LOG_TARGET_AUTO ||
235 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
236 log_target == LOG_TARGET_JOURNAL) {
237 r = log_open_journal();
245 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
246 log_target == LOG_TARGET_SYSLOG) {
247 r = log_open_syslog();
255 if (log_target == LOG_TARGET_AUTO ||
256 log_target == LOG_TARGET_SAFE ||
257 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
258 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
259 log_target == LOG_TARGET_KMSG) {
273 return log_open_console();
276 void log_set_target(LogTarget target) {
278 assert(target < _LOG_TARGET_MAX);
280 if (upgrade_syslog_to_journal) {
281 if (target == LOG_TARGET_SYSLOG)
282 target = LOG_TARGET_JOURNAL;
283 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
284 target = LOG_TARGET_JOURNAL_OR_KMSG;
290 void log_close(void) {
297 void log_forget_fds(void) {
298 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
301 void log_set_max_level(int level) {
302 assert((level & LOG_PRIMASK) == level);
304 log_max_level = level;
307 void log_set_facility(int facility) {
308 log_facility = facility;
311 static int write_to_console(
317 const char *object_field,
319 const char *buffer) {
321 char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2];
322 struct iovec iovec[6] = {};
329 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
330 sprintf(prefix, "<%i>", level);
331 IOVEC_SET_STRING(iovec[n++], prefix);
334 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
337 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
338 IOVEC_SET_STRING(iovec[n++], location);
342 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
343 IOVEC_SET_STRING(iovec[n++], buffer);
345 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
346 IOVEC_SET_STRING(iovec[n++], "\n");
348 if (writev(console_fd, iovec, n) < 0) {
350 if (errno == EIO && getpid() == 1) {
352 /* If somebody tried to kick us from our
353 * console tty (via vhangup() or suchlike),
354 * try to reconnect */
362 if (writev(console_fd, iovec, n) < 0)
371 static int write_to_syslog(
377 const char *object_field,
379 const char *buffer) {
381 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
383 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
384 struct iovec iovec[5] = {};
385 struct msghdr msghdr = {
387 .msg_iovlen = ELEMENTSOF(iovec),
395 xsprintf(header_priority, "<%i>", level);
397 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
402 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
405 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
407 IOVEC_SET_STRING(iovec[0], header_priority);
408 IOVEC_SET_STRING(iovec[1], header_time);
409 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
410 IOVEC_SET_STRING(iovec[3], header_pid);
411 IOVEC_SET_STRING(iovec[4], buffer);
413 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
414 if (syslog_is_stream)
420 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
424 if (!syslog_is_stream ||
425 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
428 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
434 static int write_to_kmsg(
440 const char *object_field,
442 const char *buffer) {
444 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
445 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
446 struct iovec iovec[5] = {};
451 xsprintf(header_priority, "<%i>", level);
452 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
454 IOVEC_SET_STRING(iovec[0], header_priority);
455 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
456 IOVEC_SET_STRING(iovec[2], header_pid);
457 IOVEC_SET_STRING(iovec[3], buffer);
458 IOVEC_SET_STRING(iovec[4], "\n");
460 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
466 static int log_do_header(
471 const char *file, int line, const char *func,
472 const char *object_field, const char *object) {
474 snprintf(header, size,
476 "SYSLOG_FACILITY=%i\n"
482 "SYSLOG_IDENTIFIER=%s\n",
485 isempty(file) ? "" : "CODE_FILE=",
486 isempty(file) ? "" : file,
487 isempty(file) ? "" : "\n",
488 line ? "CODE_LINE=" : "",
489 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
491 isempty(func) ? "" : "CODE_FUNCTION=",
492 isempty(func) ? "" : func,
493 isempty(func) ? "" : "\n",
494 error ? "ERRNO=" : "",
495 error ? 1 : 0, error,
497 isempty(object) ? "" : object_field,
498 isempty(object) ? "" : object,
499 isempty(object) ? "" : "\n",
500 program_invocation_short_name);
505 static int write_to_journal(
511 const char *object_field,
513 const char *buffer) {
515 char header[LINE_MAX];
516 struct iovec iovec[4] = {};
517 struct msghdr mh = {};
522 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
524 IOVEC_SET_STRING(iovec[0], header);
525 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
526 IOVEC_SET_STRING(iovec[2], buffer);
527 IOVEC_SET_STRING(iovec[3], "\n");
530 mh.msg_iovlen = ELEMENTSOF(iovec);
532 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
538 static int log_dispatch(
544 const char *object_field,
550 if (log_target == LOG_TARGET_NULL)
553 /* Patch in LOG_DAEMON facility if necessary */
554 if ((level & LOG_FACMASK) == 0)
555 level = log_facility | LOG_PRI(level);
564 buffer += strspn(buffer, NEWLINE);
569 if ((e = strpbrk(buffer, NEWLINE)))
572 if (log_target == LOG_TARGET_AUTO ||
573 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
574 log_target == LOG_TARGET_JOURNAL) {
576 k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
584 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
585 log_target == LOG_TARGET_SYSLOG) {
587 k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
596 (log_target == LOG_TARGET_AUTO ||
597 log_target == LOG_TARGET_SAFE ||
598 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
599 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
600 log_target == LOG_TARGET_KMSG)) {
602 k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
610 (void) write_to_console(level, error, file, line, func, object_field, object, buffer);
618 int log_dump_internal(
628 /* This modifies the buffer... */
633 if (_likely_(LOG_PRI(level) > log_max_level))
636 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
649 char buffer[LINE_MAX];
654 if (_likely_(LOG_PRI(level) > log_max_level))
657 /* Make sure that %m maps to the specified error */
661 vsnprintf(buffer, sizeof(buffer), format, ap);
663 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
672 const char *format, ...) {
677 va_start(ap, format);
678 r = log_internalv(level, error, file, line, func, format, ap);
684 int log_object_internalv(
690 const char *object_field,
702 if (_likely_(LOG_PRI(level) > log_max_level))
705 /* Make sure that %m maps to the specified error */
709 /* Prepend the object name before the message */
714 l = n + 2 + LINE_MAX;
716 buffer = newa(char, l);
717 b = stpcpy(stpcpy(buffer, object), ": ");
720 b = buffer = newa(char, l);
723 vsnprintf(b, l, format, ap);
725 return log_dispatch(level, error, file, line, func, object_field, object, buffer);
728 int log_object_internal(
734 const char *object_field,
736 const char *format, ...) {
741 va_start(ap, format);
742 r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap);
748 static void log_assert(
754 const char *format) {
756 static char buffer[LINE_MAX];
758 if (_likely_(LOG_PRI(level) > log_max_level))
761 DISABLE_WARNING_FORMAT_NONLITERAL;
762 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
765 log_abort_msg = buffer;
767 log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
770 noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
771 log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
775 noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
776 log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
780 void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
782 log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
785 int log_oom_internal(const char *file, int line, const char *func) {
786 log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
790 int log_struct_internal(
796 const char *format, ...) {
806 if (_likely_(LOG_PRI(level) > log_max_level))
809 if (log_target == LOG_TARGET_NULL)
812 if ((level & LOG_FACMASK) == 0)
813 level = log_facility | LOG_PRI(level);
815 if ((log_target == LOG_TARGET_AUTO ||
816 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
817 log_target == LOG_TARGET_JOURNAL) &&
819 char header[LINE_MAX];
820 struct iovec iovec[17] = {};
825 static const char nl = '\n';
826 bool fallback = false;
828 /* If the journal is available do structured logging */
829 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
830 IOVEC_SET_STRING(iovec[n++], header);
832 va_start(ap, format);
833 while (format && n + 1 < ELEMENTSOF(iovec)) {
837 /* We need to copy the va_list structure,
838 * since vasprintf() leaves it afterwards at
839 * an undefined location */
845 if (vasprintf(&m, format, aq) < 0) {
852 /* Now, jump enough ahead, so that we point to
853 * the next format string */
854 VA_FORMAT_ADVANCE(format, ap);
856 IOVEC_SET_STRING(iovec[n++], m);
858 iovec[n].iov_base = (char*) &nl;
859 iovec[n].iov_len = 1;
862 format = va_arg(ap, char *);
867 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
871 for (i = 1; i < n; i += 2)
872 free(iovec[i].iov_base);
878 /* Fallback if journal logging is not available or didn't work. */
880 va_start(ap, format);
888 vsnprintf(buf, sizeof(buf), format, aq);
891 if (startswith(buf, "MESSAGE=")) {
896 VA_FORMAT_ADVANCE(format, ap);
898 format = va_arg(ap, char *);
905 return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
908 int log_set_target_from_string(const char *e) {
911 t = log_target_from_string(e);
919 int log_set_max_level_from_string(const char *e) {
922 t = log_level_from_string(e);
926 log_set_max_level(t);
930 static int parse_proc_cmdline_item(const char *key, const char *value) {
933 * The systemd.log_xyz= settings are parsed by all tools, and
936 * However, "quiet" is only parsed by PID 1, and only turns of
937 * status output to /dev/console, but does not alter the log
941 if (streq(key, "debug") && !value)
942 log_set_max_level(LOG_DEBUG);
944 else if (streq(key, "systemd.log_target") && value) {
946 if (log_set_target_from_string(value) < 0)
947 log_warning("Failed to parse log target '%s'. Ignoring.", value);
949 } else if (streq(key, "systemd.log_level") && value) {
951 if (log_set_max_level_from_string(value) < 0)
952 log_warning("Failed to parse log level '%s'. Ignoring.", value);
954 } else if (streq(key, "systemd.log_color") && value) {
956 if (log_show_color_from_string(value) < 0)
957 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
959 } else if (streq(key, "systemd.log_location") && value) {
961 if (log_show_location_from_string(value) < 0)
962 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
968 void log_parse_environment(void) {
971 if (get_ctty_devnr(0, NULL) < 0)
972 /* Only try to read the command line in daemons.
973 We assume that anything that has a controlling
974 tty is user stuff. */
975 (void) parse_proc_cmdline(parse_proc_cmdline_item);
977 e = secure_getenv("SYSTEMD_LOG_TARGET");
978 if (e && log_set_target_from_string(e) < 0)
979 log_warning("Failed to parse log target '%s'. Ignoring.", e);
981 e = secure_getenv("SYSTEMD_LOG_LEVEL");
982 if (e && log_set_max_level_from_string(e) < 0)
983 log_warning("Failed to parse log level '%s'. Ignoring.", e);
985 e = secure_getenv("SYSTEMD_LOG_COLOR");
986 if (e && log_show_color_from_string(e) < 0)
987 log_warning("Failed to parse bool '%s'. Ignoring.", e);
989 e = secure_getenv("SYSTEMD_LOG_LOCATION");
990 if (e && log_show_location_from_string(e) < 0)
991 log_warning("Failed to parse bool '%s'. Ignoring.", e);
994 LogTarget log_get_target(void) {
998 int log_get_max_level(void) {
999 return log_max_level;
1002 void log_show_color(bool b) {
1006 bool log_get_show_color(void) {
1010 void log_show_location(bool b) {
1014 bool log_get_show_location(void) {
1015 return show_location;
1018 int log_show_color_from_string(const char *e) {
1021 t = parse_boolean(e);
1029 int log_show_location_from_string(const char *e) {
1032 t = parse_boolean(e);
1036 log_show_location(t);
1040 bool log_on_console(void) {
1041 if (log_target == LOG_TARGET_CONSOLE ||
1042 log_target == LOG_TARGET_CONSOLE_PREFIXED)
1045 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1048 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1049 [LOG_TARGET_CONSOLE] = "console",
1050 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1051 [LOG_TARGET_KMSG] = "kmsg",
1052 [LOG_TARGET_JOURNAL] = "journal",
1053 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1054 [LOG_TARGET_SYSLOG] = "syslog",
1055 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1056 [LOG_TARGET_AUTO] = "auto",
1057 [LOG_TARGET_SAFE] = "safe",
1058 [LOG_TARGET_NULL] = "null"
1061 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1063 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1064 if (si->ssi_pid > 0) {
1065 _cleanup_free_ char *p = NULL;
1067 get_process_comm(si->ssi_pid, &p);
1070 "Received SIG%s from PID %"PRIu32" (%s).",
1071 signal_to_string(si->ssi_signo),
1072 si->ssi_pid, strna(p));
1076 signal_to_string(si->ssi_signo));
1080 void log_set_upgrade_syslog_to_journal(bool b) {
1081 upgrade_syslog_to_journal = b;
1084 int log_syntax_internal(
1087 const char *config_file,
1088 unsigned config_line,
1093 const char *format, ...) {
1096 char buffer[LINE_MAX];
1103 if (_likely_(LOG_PRI(level) > log_max_level))
1106 if (log_target == LOG_TARGET_NULL)
1112 va_start(ap, format);
1113 vsnprintf(buffer, sizeof(buffer), format, ap);
1117 r = log_struct_internal(
1120 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1121 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1122 "CONFIG_FILE=%s", config_file,
1123 "CONFIG_LINE=%u", config_line,
1124 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1127 r = log_struct_internal(
1130 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1131 "CONFIG_FILE=%s", config_file,
1132 "CONFIG_LINE=%u", config_line,
1133 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),