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 /// elogind does not support logging to systemd-journald
249 if (log_target == LOG_TARGET_AUTO ||
250 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
251 log_target == LOG_TARGET_JOURNAL) {
252 r = log_open_journal();
260 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
261 log_target == LOG_TARGET_SYSLOG) {
262 r = log_open_syslog();
264 /// UNNEEDED by elogind log_close_journal();
270 if (log_target == LOG_TARGET_AUTO ||
271 log_target == LOG_TARGET_SAFE ||
272 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
273 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
274 log_target == LOG_TARGET_KMSG) {
277 /// UNNEEDED by elogind log_close_journal();
285 /// UNNEEDED by elogind log_close_journal();
288 return log_open_console();
291 void log_set_target(LogTarget target) {
293 assert(target < _LOG_TARGET_MAX);
295 /// elogind does not support logging to systemd-journald
297 if (upgrade_syslog_to_journal) {
298 if (target == LOG_TARGET_SYSLOG)
299 target = LOG_TARGET_JOURNAL;
300 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
301 target = LOG_TARGET_JOURNAL_OR_KMSG;
308 void log_close(void) {
309 /// UNNEDED by elogind log_close_journal();
315 #if 0 /// UNNEEDED by elogind
316 void log_forget_fds(void) {
317 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
321 void log_set_max_level(int level) {
322 assert((level & LOG_PRIMASK) == level);
324 log_max_level = level;
327 void log_set_facility(int facility) {
328 log_facility = facility;
331 static int write_to_console(
337 const char *object_field,
339 const char *buffer) {
341 char location[64], prefix[1 + DECIMAL_STR_MAX(int) + 2];
342 struct iovec iovec[6] = {};
349 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
350 sprintf(prefix, "<%i>", level);
351 IOVEC_SET_STRING(iovec[n++], prefix);
354 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
357 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
358 IOVEC_SET_STRING(iovec[n++], location);
362 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED);
363 IOVEC_SET_STRING(iovec[n++], buffer);
365 IOVEC_SET_STRING(iovec[n++], ANSI_NORMAL);
366 IOVEC_SET_STRING(iovec[n++], "\n");
368 if (writev(console_fd, iovec, n) < 0) {
370 if (errno == EIO && getpid() == 1) {
372 /* If somebody tried to kick us from our
373 * console tty (via vhangup() or suchlike),
374 * try to reconnect */
382 if (writev(console_fd, iovec, n) < 0)
391 static int write_to_syslog(
397 const char *object_field,
399 const char *buffer) {
401 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
403 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
404 struct iovec iovec[5] = {};
405 struct msghdr msghdr = {
407 .msg_iovlen = ELEMENTSOF(iovec),
415 xsprintf(header_priority, "<%i>", level);
417 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
422 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
425 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
427 IOVEC_SET_STRING(iovec[0], header_priority);
428 IOVEC_SET_STRING(iovec[1], header_time);
429 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
430 IOVEC_SET_STRING(iovec[3], header_pid);
431 IOVEC_SET_STRING(iovec[4], buffer);
433 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
434 if (syslog_is_stream)
440 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
444 if (!syslog_is_stream ||
445 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
448 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
454 static int write_to_kmsg(
460 const char *object_field,
462 const char *buffer) {
464 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
465 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
466 struct iovec iovec[5] = {};
471 xsprintf(header_priority, "<%i>", level);
472 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
474 IOVEC_SET_STRING(iovec[0], header_priority);
475 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
476 IOVEC_SET_STRING(iovec[2], header_pid);
477 IOVEC_SET_STRING(iovec[3], buffer);
478 IOVEC_SET_STRING(iovec[4], "\n");
480 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
486 #if 0 /// UNNEEDED by elogind
487 static int log_do_header(
492 const char *file, int line, const char *func,
493 const char *object_field, const char *object) {
495 snprintf(header, size,
497 "SYSLOG_FACILITY=%i\n"
503 "SYSLOG_IDENTIFIER=%s\n",
506 isempty(file) ? "" : "CODE_FILE=",
507 isempty(file) ? "" : file,
508 isempty(file) ? "" : "\n",
509 line ? "CODE_LINE=" : "",
510 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
512 isempty(func) ? "" : "CODE_FUNCTION=",
513 isempty(func) ? "" : func,
514 isempty(func) ? "" : "\n",
515 error ? "ERRNO=" : "",
516 error ? 1 : 0, error,
518 isempty(object) ? "" : object_field,
519 isempty(object) ? "" : object,
520 isempty(object) ? "" : "\n",
521 program_invocation_short_name);
526 static int write_to_journal(
532 const char *object_field,
534 const char *buffer) {
536 char header[LINE_MAX];
537 struct iovec iovec[4] = {};
538 struct msghdr mh = {};
543 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
545 IOVEC_SET_STRING(iovec[0], header);
546 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
547 IOVEC_SET_STRING(iovec[2], buffer);
548 IOVEC_SET_STRING(iovec[3], "\n");
551 mh.msg_iovlen = ELEMENTSOF(iovec);
553 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
560 static int log_dispatch(
566 const char *object_field,
572 if (log_target == LOG_TARGET_NULL)
575 /* Patch in LOG_DAEMON facility if necessary */
576 if ((level & LOG_FACMASK) == 0)
577 level = log_facility | LOG_PRI(level);
586 buffer += strspn(buffer, NEWLINE);
591 if ((e = strpbrk(buffer, NEWLINE)))
594 /// elogind does not support logging to systemd-journald
596 if (log_target == LOG_TARGET_AUTO ||
597 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
598 log_target == LOG_TARGET_JOURNAL) {
600 k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
609 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
610 log_target == LOG_TARGET_SYSLOG) {
612 k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
621 (log_target == LOG_TARGET_AUTO ||
622 log_target == LOG_TARGET_SAFE ||
623 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
624 /// UNNEEDED by elogind log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
625 log_target == LOG_TARGET_KMSG)) {
627 k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
635 (void) write_to_console(level, error, file, line, func, object_field, object, buffer);
643 int log_dump_internal(
653 /* This modifies the buffer... */
658 if (_likely_(LOG_PRI(level) > log_max_level))
661 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
674 char buffer[LINE_MAX];
679 if (_likely_(LOG_PRI(level) > log_max_level))
682 /* Make sure that %m maps to the specified error */
686 vsnprintf(buffer, sizeof(buffer), format, ap);
688 return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
697 const char *format, ...) {
702 va_start(ap, format);
703 r = log_internalv(level, error, file, line, func, format, ap);
709 int log_object_internalv(
715 const char *object_field,
727 if (_likely_(LOG_PRI(level) > log_max_level))
730 /* Make sure that %m maps to the specified error */
734 /* Prepend the object name before the message */
739 l = n + 2 + LINE_MAX;
741 buffer = newa(char, l);
742 b = stpcpy(stpcpy(buffer, object), ": ");
745 b = buffer = newa(char, l);
748 vsnprintf(b, l, format, ap);
750 return log_dispatch(level, error, file, line, func, object_field, object, buffer);
753 int log_object_internal(
759 const char *object_field,
761 const char *format, ...) {
766 va_start(ap, format);
767 r = log_object_internalv(level, error, file, line, func, object_field, object, format, ap);
773 static void log_assert(
779 const char *format) {
781 static char buffer[LINE_MAX];
783 if (_likely_(LOG_PRI(level) > log_max_level))
786 DISABLE_WARNING_FORMAT_NONLITERAL;
787 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
790 log_abort_msg = buffer;
792 log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
795 noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
796 log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
800 noreturn void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
801 log_assert(LOG_CRIT, text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
805 void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
807 log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
810 int log_oom_internal(const char *file, int line, const char *func) {
811 log_internal(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
815 int log_struct_internal(
821 const char *format, ...) {
831 if (_likely_(LOG_PRI(level) > log_max_level))
834 if (log_target == LOG_TARGET_NULL)
837 if ((level & LOG_FACMASK) == 0)
838 level = log_facility | LOG_PRI(level);
840 /// 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 /// elogind does not support logging to systemd-journald
1082 [LOG_TARGET_JOURNAL] = "journal",
1083 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1085 [LOG_TARGET_SYSLOG] = "syslog",
1086 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1087 [LOG_TARGET_AUTO] = "auto",
1088 [LOG_TARGET_SAFE] = "safe",
1089 [LOG_TARGET_NULL] = "null"
1092 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1094 #if 0 /// UNNEEDED by elogind
1095 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1096 if (si->ssi_pid > 0) {
1097 _cleanup_free_ char *p = NULL;
1099 get_process_comm(si->ssi_pid, &p);
1102 "Received SIG%s from PID %"PRIu32" (%s).",
1103 signal_to_string(si->ssi_signo),
1104 si->ssi_pid, strna(p));
1108 signal_to_string(si->ssi_signo));
1112 void log_set_upgrade_syslog_to_journal(bool b) {
1113 upgrade_syslog_to_journal = b;
1117 int log_syntax_internal(
1120 const char *config_file,
1121 unsigned config_line,
1126 const char *format, ...) {
1129 char buffer[LINE_MAX];
1136 if (_likely_(LOG_PRI(level) > log_max_level))
1139 if (log_target == LOG_TARGET_NULL)
1145 va_start(ap, format);
1146 vsnprintf(buffer, sizeof(buffer), format, ap);
1150 r = log_struct_internal(
1153 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1154 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1155 "CONFIG_FILE=%s", config_file,
1156 "CONFIG_LINE=%u", config_line,
1157 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1160 r = log_struct_internal(
1163 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1164 "CONFIG_FILE=%s", config_file,
1165 "CONFIG_LINE=%u", config_line,
1166 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),