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>
34 #include "socket-util.h"
36 #define SNDBUF_SIZE (8*1024*1024)
38 static LogTarget log_target = LOG_TARGET_CONSOLE;
39 static int log_max_level = LOG_INFO;
40 static int log_facility = LOG_DAEMON;
42 static int console_fd = STDERR_FILENO;
43 static int syslog_fd = -1;
44 static int kmsg_fd = -1;
45 static int journal_fd = -1;
47 static bool syslog_is_stream = false;
49 static bool show_color = false;
50 static bool show_location = false;
52 /* Akin to glibc's __abort_msg; which is private and we hence cannot
54 static char *log_abort_msg = NULL;
56 void log_close_console(void) {
63 close_nointr_nofail(console_fd);
69 static int log_open_console(void) {
76 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
78 log_error("Failed to open /dev/console for logging: %s", strerror(-console_fd));
82 log_debug("Successfully opened /dev/console for logging.");
84 console_fd = STDERR_FILENO;
89 void log_close_kmsg(void) {
94 close_nointr_nofail(kmsg_fd);
98 static int log_open_kmsg(void) {
103 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
105 log_error("Failed to open /dev/kmsg for logging: %s", strerror(errno));
109 log_debug("Successfully opened /dev/kmsg for logging.");
114 void log_close_syslog(void) {
119 close_nointr_nofail(syslog_fd);
123 static int create_log_socket(int type) {
126 /* All output to the syslog/journal fds we do asynchronously,
127 * and if the buffers are full we just drop the messages */
129 fd = socket(AF_UNIX, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
133 fd_inc_sndbuf(fd, SNDBUF_SIZE);
138 static int log_open_syslog(void) {
139 union sockaddr_union sa;
146 sa.un.sun_family = AF_UNIX;
147 strncpy(sa.un.sun_path, "/dev/log", sizeof(sa.un.sun_path));
149 syslog_fd = create_log_socket(SOCK_DGRAM);
155 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
156 close_nointr_nofail(syslog_fd);
158 /* Some legacy syslog systems still use stream
159 * sockets. They really shouldn't. But what can we
161 syslog_fd = create_log_socket(SOCK_STREAM);
167 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
172 syslog_is_stream = true;
174 syslog_is_stream = false;
176 log_debug("Successfully opened syslog for logging.");
182 log_debug("Failed to open syslog for logging: %s", strerror(-r));
186 void log_close_journal(void) {
191 close_nointr_nofail(journal_fd);
195 static int log_open_journal(void) {
196 union sockaddr_union sa;
202 journal_fd = create_log_socket(SOCK_DGRAM);
203 if (journal_fd < 0) {
209 sa.un.sun_family = AF_UNIX;
210 strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
212 if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
217 log_debug("Successfully opened journal for logging.");
223 log_debug("Failed to open journal for logging: %s", strerror(-r));
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) {
243 if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
245 isatty(STDERR_FILENO) <= 0) {
247 if (log_target == LOG_TARGET_AUTO ||
248 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
249 log_target == LOG_TARGET_JOURNAL) {
250 r = log_open_journal();
258 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
259 log_target == LOG_TARGET_SYSLOG) {
260 r = log_open_syslog();
268 if (log_target == LOG_TARGET_AUTO ||
269 log_target == LOG_TARGET_SAFE ||
270 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
271 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
272 log_target == LOG_TARGET_KMSG) {
286 /* Get the real /dev/console if we are PID=1, hence reopen */
288 return log_open_console();
291 void log_set_target(LogTarget target) {
293 assert(target < _LOG_TARGET_MAX);
298 void log_close(void) {
305 void log_forget_fds(void) {
306 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
309 void log_set_max_level(int level) {
310 assert((level & LOG_PRIMASK) == level);
312 log_max_level = level;
315 void log_set_facility(int facility) {
316 log_facility = facility;
319 static int write_to_console(
324 const char *buffer) {
327 struct iovec iovec[5];
334 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
339 snprintf(location, sizeof(location), "(%s:%u) ", file, line);
340 char_array_0(location);
341 IOVEC_SET_STRING(iovec[n++], location);
345 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
346 IOVEC_SET_STRING(iovec[n++], buffer);
348 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
349 IOVEC_SET_STRING(iovec[n++], "\n");
351 if (writev(console_fd, iovec, n) < 0)
357 static int write_to_syslog(
362 const char *buffer) {
364 char header_priority[16], header_time[64], header_pid[16];
365 struct iovec iovec[5];
366 struct msghdr msghdr;
373 snprintf(header_priority, sizeof(header_priority), "<%i>", level);
374 char_array_0(header_priority);
376 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
377 if (!(tm = localtime(&t)))
380 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
383 snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
384 char_array_0(header_pid);
387 IOVEC_SET_STRING(iovec[0], header_priority);
388 IOVEC_SET_STRING(iovec[1], header_time);
389 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
390 IOVEC_SET_STRING(iovec[3], header_pid);
391 IOVEC_SET_STRING(iovec[4], buffer);
393 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
394 if (syslog_is_stream)
398 msghdr.msg_iov = iovec;
399 msghdr.msg_iovlen = ELEMENTSOF(iovec);
404 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
408 if (!syslog_is_stream ||
409 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
412 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
418 static int write_to_kmsg(
423 const char *buffer) {
425 char header_priority[16], header_pid[16];
426 struct iovec iovec[5];
431 snprintf(header_priority, sizeof(header_priority), "<%i>", level);
432 char_array_0(header_priority);
434 snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
435 char_array_0(header_pid);
438 IOVEC_SET_STRING(iovec[0], header_priority);
439 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
440 IOVEC_SET_STRING(iovec[2], header_pid);
441 IOVEC_SET_STRING(iovec[3], buffer);
442 IOVEC_SET_STRING(iovec[4], "\n");
444 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
450 static int write_to_journal(
455 const char *buffer) {
457 char header[LINE_MAX];
458 struct iovec iovec[3];
464 snprintf(header, sizeof(header),
466 "SYSLOG_FACILITY=%i\n"
470 "SYSLOG_IDENTIFIER=%s\n"
477 program_invocation_short_name);
479 char_array_0(header);
482 IOVEC_SET_STRING(iovec[0], header);
483 IOVEC_SET_STRING(iovec[1], buffer);
484 IOVEC_SET_STRING(iovec[2], "\n");
488 mh.msg_iovlen = ELEMENTSOF(iovec);
490 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
496 static int log_dispatch(
505 if (log_target == LOG_TARGET_NULL)
508 /* Patch in LOG_DAEMON facility if necessary */
509 if ((level & LOG_FACMASK) == 0)
510 level = log_facility | LOG_PRI(level);
516 buffer += strspn(buffer, NEWLINE);
521 if ((e = strpbrk(buffer, NEWLINE)))
524 if (log_target == LOG_TARGET_AUTO ||
525 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
526 log_target == LOG_TARGET_JOURNAL) {
528 k = write_to_journal(level, file, line, func, buffer);
537 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
538 log_target == LOG_TARGET_SYSLOG) {
540 k = write_to_syslog(level, file, line, func, buffer);
550 (log_target == LOG_TARGET_AUTO ||
551 log_target == LOG_TARGET_SAFE ||
552 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
553 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
554 log_target == LOG_TARGET_KMSG)) {
556 k = write_to_kmsg(level, file, line, func, buffer);
565 k = write_to_console(level, file, line, func, buffer);
576 int log_dump_internal(
585 /* This modifies the buffer... */
587 if (_likely_(LOG_PRI(level) > log_max_level))
591 r = log_dispatch(level, file, line, func, buffer);
605 char buffer[LINE_MAX];
608 if (_likely_(LOG_PRI(level) > log_max_level))
612 vsnprintf(buffer, sizeof(buffer), format, ap);
613 char_array_0(buffer);
615 r = log_dispatch(level, file, line, func, buffer);
626 const char *format, ...) {
631 va_start(ap, format);
632 r = log_metav(level, file, line, func, format, ap);
638 #pragma GCC diagnostic push
639 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
640 _noreturn_ static void log_assert(const char *text, const char *file, int line, const char *func, const char *format) {
641 static char buffer[LINE_MAX];
643 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
645 char_array_0(buffer);
646 log_abort_msg = buffer;
648 log_dispatch(LOG_CRIT, file, line, func, buffer);
651 #pragma GCC diagnostic pop
653 _noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) {
654 log_assert(text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
657 _noreturn_ void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
658 log_assert(text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
661 int __log_oom(const char *file, int line, const char *func) {
662 log_meta(LOG_ERR, file, line, func, "Out of memory.");
666 int log_set_target_from_string(const char *e) {
669 t = log_target_from_string(e);
677 int log_set_max_level_from_string(const char *e) {
680 t = log_level_from_string(e);
684 log_set_max_level(t);
688 void log_parse_environment(void) {
691 if ((e = getenv("SYSTEMD_LOG_TARGET")))
692 if (log_set_target_from_string(e) < 0)
693 log_warning("Failed to parse log target %s. Ignoring.", e);
695 if ((e = getenv("SYSTEMD_LOG_LEVEL")))
696 if (log_set_max_level_from_string(e) < 0)
697 log_warning("Failed to parse log level %s. Ignoring.", e);
699 if ((e = getenv("SYSTEMD_LOG_COLOR")))
700 if (log_show_color_from_string(e) < 0)
701 log_warning("Failed to parse bool %s. Ignoring.", e);
703 if ((e = getenv("SYSTEMD_LOG_LOCATION")))
704 if (log_show_location_from_string(e) < 0)
705 log_warning("Failed to parse bool %s. Ignoring.", e);
708 LogTarget log_get_target(void) {
712 int log_get_max_level(void) {
713 return log_max_level;
716 void log_show_color(bool b) {
720 void log_show_location(bool b) {
724 int log_show_color_from_string(const char *e) {
727 t = parse_boolean(e);
735 int log_show_location_from_string(const char *e) {
738 t = parse_boolean(e);
742 log_show_location(t);
746 static const char *const log_target_table[] = {
747 [LOG_TARGET_CONSOLE] = "console",
748 [LOG_TARGET_KMSG] = "kmsg",
749 [LOG_TARGET_JOURNAL] = "journal",
750 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
751 [LOG_TARGET_SYSLOG] = "syslog",
752 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
753 [LOG_TARGET_AUTO] = "auto",
754 [LOG_TARGET_SAFE] = "safe",
755 [LOG_TARGET_NULL] = "null"
758 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);