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>
35 #include "socket-util.h"
37 #define SNDBUF_SIZE (8*1024*1024)
39 static LogTarget log_target = LOG_TARGET_CONSOLE;
40 static int log_max_level = LOG_INFO;
41 static int log_facility = LOG_DAEMON;
43 static int console_fd = STDERR_FILENO;
44 static int syslog_fd = -1;
45 static int kmsg_fd = -1;
46 static int journal_fd = -1;
48 static bool syslog_is_stream = false;
50 static bool show_color = false;
51 static bool show_location = false;
53 /* Akin to glibc's __abort_msg; which is private and we hence cannot
55 static char *log_abort_msg = NULL;
57 void log_close_console(void) {
64 close_nointr_nofail(console_fd);
70 static int log_open_console(void) {
76 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
80 console_fd = STDERR_FILENO;
85 void log_close_kmsg(void) {
90 close_nointr_nofail(kmsg_fd);
94 static int log_open_kmsg(void) {
99 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
106 void log_close_syslog(void) {
111 close_nointr_nofail(syslog_fd);
115 static int create_log_socket(int type) {
118 /* All output to the syslog/journal fds we do asynchronously,
119 * and if the buffers are full we just drop the messages */
121 fd = socket(AF_UNIX, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
125 fd_inc_sndbuf(fd, SNDBUF_SIZE);
130 static int log_open_syslog(void) {
131 union sockaddr_union sa;
138 sa.un.sun_family = AF_UNIX;
139 strncpy(sa.un.sun_path, "/dev/log", sizeof(sa.un.sun_path));
141 syslog_fd = create_log_socket(SOCK_DGRAM);
147 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
148 close_nointr_nofail(syslog_fd);
150 /* Some legacy syslog systems still use stream
151 * sockets. They really shouldn't. But what can we
153 syslog_fd = create_log_socket(SOCK_STREAM);
159 if (connect(syslog_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
164 syslog_is_stream = true;
166 syslog_is_stream = false;
175 void log_close_journal(void) {
180 close_nointr_nofail(journal_fd);
184 static int log_open_journal(void) {
185 union sockaddr_union sa;
191 journal_fd = create_log_socket(SOCK_DGRAM);
192 if (journal_fd < 0) {
198 sa.un.sun_family = AF_UNIX;
199 strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
201 if (connect(journal_fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) {
216 /* If we don't use the console we close it here, to not get
217 * killed by SAK. If we don't use syslog we close it here so
218 * that we are not confused by somebody deleting the socket in
219 * the fs. If we don't use /dev/kmsg we still keep it open,
220 * because there is no reason to close it. */
222 if (log_target == LOG_TARGET_NULL) {
229 if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
231 isatty(STDERR_FILENO) <= 0) {
233 if (log_target == LOG_TARGET_AUTO ||
234 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
235 log_target == LOG_TARGET_JOURNAL) {
236 r = log_open_journal();
244 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
245 log_target == LOG_TARGET_SYSLOG) {
246 r = log_open_syslog();
254 if (log_target == LOG_TARGET_AUTO ||
255 log_target == LOG_TARGET_SAFE ||
256 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
257 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
258 log_target == LOG_TARGET_KMSG) {
272 /* Get the real /dev/console if we are PID=1, hence reopen */
274 return log_open_console();
277 void log_set_target(LogTarget target) {
279 assert(target < _LOG_TARGET_MAX);
284 void log_close(void) {
291 void log_forget_fds(void) {
292 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
295 void log_set_max_level(int level) {
296 assert((level & LOG_PRIMASK) == level);
298 log_max_level = level;
301 void log_set_facility(int facility) {
302 log_facility = facility;
305 static int write_to_console(
310 const char *buffer) {
313 struct iovec iovec[5];
320 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
325 snprintf(location, sizeof(location), "(%s:%u) ", file, line);
326 char_array_0(location);
327 IOVEC_SET_STRING(iovec[n++], location);
331 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED_ON);
332 IOVEC_SET_STRING(iovec[n++], buffer);
334 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_OFF);
335 IOVEC_SET_STRING(iovec[n++], "\n");
337 if (writev(console_fd, iovec, n) < 0)
343 static int write_to_syslog(
348 const char *buffer) {
350 char header_priority[16], header_time[64], header_pid[16];
351 struct iovec iovec[5];
352 struct msghdr msghdr;
359 snprintf(header_priority, sizeof(header_priority), "<%i>", level);
360 char_array_0(header_priority);
362 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
363 if (!(tm = localtime(&t)))
366 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
369 snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
370 char_array_0(header_pid);
373 IOVEC_SET_STRING(iovec[0], header_priority);
374 IOVEC_SET_STRING(iovec[1], header_time);
375 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
376 IOVEC_SET_STRING(iovec[3], header_pid);
377 IOVEC_SET_STRING(iovec[4], buffer);
379 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
380 if (syslog_is_stream)
384 msghdr.msg_iov = iovec;
385 msghdr.msg_iovlen = ELEMENTSOF(iovec);
390 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
394 if (!syslog_is_stream ||
395 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
398 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
404 static int write_to_kmsg(
409 const char *buffer) {
411 char header_priority[16], header_pid[16];
412 struct iovec iovec[5];
417 snprintf(header_priority, sizeof(header_priority), "<%i>", level);
418 char_array_0(header_priority);
420 snprintf(header_pid, sizeof(header_pid), "[%lu]: ", (unsigned long) getpid());
421 char_array_0(header_pid);
424 IOVEC_SET_STRING(iovec[0], header_priority);
425 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
426 IOVEC_SET_STRING(iovec[2], header_pid);
427 IOVEC_SET_STRING(iovec[3], buffer);
428 IOVEC_SET_STRING(iovec[4], "\n");
430 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
436 static int write_to_journal(
441 const char *buffer) {
443 char header[LINE_MAX];
444 struct iovec iovec[3];
450 snprintf(header, sizeof(header),
452 "SYSLOG_FACILITY=%i\n"
456 "SYSLOG_IDENTIFIER=%s\n"
463 program_invocation_short_name);
465 char_array_0(header);
468 IOVEC_SET_STRING(iovec[0], header);
469 IOVEC_SET_STRING(iovec[1], buffer);
470 IOVEC_SET_STRING(iovec[2], "\n");
474 mh.msg_iovlen = ELEMENTSOF(iovec);
476 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
482 static int log_dispatch(
491 if (log_target == LOG_TARGET_NULL)
494 /* Patch in LOG_DAEMON facility if necessary */
495 if ((level & LOG_FACMASK) == 0)
496 level = log_facility | LOG_PRI(level);
502 buffer += strspn(buffer, NEWLINE);
507 if ((e = strpbrk(buffer, NEWLINE)))
510 if (log_target == LOG_TARGET_AUTO ||
511 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
512 log_target == LOG_TARGET_JOURNAL) {
514 k = write_to_journal(level, file, line, func, buffer);
523 if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
524 log_target == LOG_TARGET_SYSLOG) {
526 k = write_to_syslog(level, file, line, func, buffer);
536 (log_target == LOG_TARGET_AUTO ||
537 log_target == LOG_TARGET_SAFE ||
538 log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
539 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
540 log_target == LOG_TARGET_KMSG)) {
542 k = write_to_kmsg(level, file, line, func, buffer);
551 k = write_to_console(level, file, line, func, buffer);
562 int log_dump_internal(
571 /* This modifies the buffer... */
573 if (_likely_(LOG_PRI(level) > log_max_level))
577 r = log_dispatch(level, file, line, func, buffer);
591 char buffer[LINE_MAX];
594 if (_likely_(LOG_PRI(level) > log_max_level))
598 vsnprintf(buffer, sizeof(buffer), format, ap);
599 char_array_0(buffer);
601 r = log_dispatch(level, file, line, func, buffer);
612 const char *format, ...) {
617 va_start(ap, format);
618 r = log_metav(level, file, line, func, format, ap);
624 #pragma GCC diagnostic push
625 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
626 _noreturn_ static void log_assert(const char *text, const char *file, int line, const char *func, const char *format) {
627 static char buffer[LINE_MAX];
629 snprintf(buffer, sizeof(buffer), format, text, file, line, func);
631 char_array_0(buffer);
632 log_abort_msg = buffer;
634 log_dispatch(LOG_CRIT, file, line, func, buffer);
637 #pragma GCC diagnostic pop
639 _noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) {
640 log_assert(text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
643 _noreturn_ void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func) {
644 log_assert(text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
647 int log_oom_internal(const char *file, int line, const char *func) {
648 log_meta(LOG_ERR, file, line, func, "Out of memory.");
652 int log_struct_internal(
657 const char *format, ...) {
663 if (_likely_(LOG_PRI(level) > log_max_level))
666 if (log_target == LOG_TARGET_NULL)
669 if ((level & LOG_FACMASK) == 0)
670 level = log_facility | LOG_PRI(level);
674 if ((log_target == LOG_TARGET_AUTO ||
675 log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
676 log_target == LOG_TARGET_JOURNAL) &&
679 char header[LINE_MAX];
680 struct iovec iovec[17];
683 const char nl = '\n';
685 /* If the journal is available do structured logging */
687 snprintf(header, sizeof(header),
689 "SYSLOG_FACILITY=%i\n"
693 "SYSLOG_IDENTIFIER=%s\n",
699 program_invocation_short_name);
700 char_array_0(header);
703 IOVEC_SET_STRING(iovec[n++], header);
705 va_start(ap, format);
706 while (format && n + 1 < ELEMENTSOF(iovec)) {
709 if (vasprintf(&buf, format, ap) < 0) {
714 IOVEC_SET_STRING(iovec[n++], buf);
716 iovec[n].iov_base = (char*) &nl;
717 iovec[n].iov_len = 1;
720 format = va_arg(ap, char *);
728 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
734 for (i = 1; i < n; i += 2)
735 free(iovec[i].iov_base);
741 /* Fallback if journal logging is not available */
743 va_start(ap, format);
746 vsnprintf(buf, sizeof(buf), format, ap);
749 if (startswith(buf, "MESSAGE=")) {
754 format = va_arg(ap, char *);
759 r = log_dispatch(level, file, line, func, buf + 8);
768 int log_set_target_from_string(const char *e) {
771 t = log_target_from_string(e);
779 int log_set_max_level_from_string(const char *e) {
782 t = log_level_from_string(e);
786 log_set_max_level(t);
790 void log_parse_environment(void) {
793 e = secure_getenv("SYSTEMD_LOG_TARGET");
794 if (e && log_set_target_from_string(e) < 0)
795 log_warning("Failed to parse log target %s. Ignoring.", e);
797 e = secure_getenv("SYSTEMD_LOG_LEVEL");
798 if (e && log_set_max_level_from_string(e) < 0)
799 log_warning("Failed to parse log level %s. Ignoring.", e);
801 e = secure_getenv("SYSTEMD_LOG_COLOR");
802 if (e && log_show_color_from_string(e) < 0)
803 log_warning("Failed to parse bool %s. Ignoring.", e);
805 e = secure_getenv("SYSTEMD_LOG_LOCATION");
806 if (e && log_show_location_from_string(e) < 0)
807 log_warning("Failed to parse bool %s. Ignoring.", e);
810 LogTarget log_get_target(void) {
814 int log_get_max_level(void) {
815 return log_max_level;
818 void log_show_color(bool b) {
822 void log_show_location(bool b) {
826 int log_show_color_from_string(const char *e) {
829 t = parse_boolean(e);
837 int log_show_location_from_string(const char *e) {
840 t = parse_boolean(e);
844 log_show_location(t);
848 bool log_on_console(void) {
849 if (log_target == LOG_TARGET_CONSOLE)
852 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
855 static const char *const log_target_table[] = {
856 [LOG_TARGET_CONSOLE] = "console",
857 [LOG_TARGET_KMSG] = "kmsg",
858 [LOG_TARGET_JOURNAL] = "journal",
859 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
860 [LOG_TARGET_SYSLOG] = "syslog",
861 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
862 [LOG_TARGET_AUTO] = "auto",
863 [LOG_TARGET_SAFE] = "safe",
864 [LOG_TARGET_NULL] = "null"
867 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);