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 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 void log_close_journal(void) {
192 journal_fd
= safe_close(journal_fd
);
195 static int log_open_journal(void) {
197 static const union sockaddr_union sa
= {
198 .un
.sun_family
= AF_UNIX
,
199 .un
.sun_path
= "/run/systemd/journal/socket",
207 journal_fd
= create_log_socket(SOCK_DGRAM
);
208 if (journal_fd
< 0) {
213 if (connect(journal_fd
, &sa
.sa
, offsetof(struct sockaddr_un
, sun_path
) + strlen(sa
.un
.sun_path
)) < 0) {
228 /* If we don't use the console we close it here, to not get
229 * killed by SAK. If we don't use syslog we close it here so
230 * that we are not confused by somebody deleting the socket in
231 * the fs. If we don't use /dev/kmsg we still keep it open,
232 * because there is no reason to close it. */
234 if (log_target
== LOG_TARGET_NULL
) {
241 if ((log_target
!= LOG_TARGET_AUTO
&& log_target
!= LOG_TARGET_SAFE
) ||
243 isatty(STDERR_FILENO
) <= 0) {
245 if (log_target
== LOG_TARGET_AUTO
||
246 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
247 log_target
== LOG_TARGET_JOURNAL
) {
248 r
= log_open_journal();
256 if (log_target
== LOG_TARGET_SYSLOG_OR_KMSG
||
257 log_target
== LOG_TARGET_SYSLOG
) {
258 r
= log_open_syslog();
266 if (log_target
== LOG_TARGET_AUTO
||
267 log_target
== LOG_TARGET_SAFE
||
268 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
269 log_target
== LOG_TARGET_SYSLOG_OR_KMSG
||
270 log_target
== LOG_TARGET_KMSG
) {
284 return log_open_console();
287 void log_set_target(LogTarget target
) {
289 assert(target
< _LOG_TARGET_MAX
);
291 if (upgrade_syslog_to_journal
) {
292 if (target
== LOG_TARGET_SYSLOG
)
293 target
= LOG_TARGET_JOURNAL
;
294 else if (target
== LOG_TARGET_SYSLOG_OR_KMSG
)
295 target
= LOG_TARGET_JOURNAL_OR_KMSG
;
301 void log_close(void) {
308 void log_forget_fds(void) {
309 console_fd
= kmsg_fd
= syslog_fd
= journal_fd
= -1;
312 void log_set_max_level(int level
) {
313 assert((level
& LOG_PRIMASK
) == level
);
315 log_max_level
= level
;
318 void log_set_facility(int facility
) {
319 log_facility
= facility
;
322 static int write_to_console(
328 const char *object_field
,
330 const char *buffer
) {
332 char location
[64], prefix
[1 + DECIMAL_STR_MAX(int) + 2];
333 struct iovec iovec
[6] = {};
340 if (log_target
== LOG_TARGET_CONSOLE_PREFIXED
) {
341 sprintf(prefix
, "<%i>", level
);
342 IOVEC_SET_STRING(iovec
[n
++], prefix
);
345 highlight
= LOG_PRI(level
) <= LOG_ERR
&& show_color
;
348 snprintf(location
, sizeof(location
), "(%s:%i) ", file
, line
);
349 IOVEC_SET_STRING(iovec
[n
++], location
);
353 IOVEC_SET_STRING(iovec
[n
++], ANSI_HIGHLIGHT_RED
);
354 IOVEC_SET_STRING(iovec
[n
++], buffer
);
356 IOVEC_SET_STRING(iovec
[n
++], ANSI_NORMAL
);
357 IOVEC_SET_STRING(iovec
[n
++], "\n");
359 if (writev(console_fd
, iovec
, n
) < 0) {
361 if (errno
== EIO
&& getpid() == 1) {
363 /* If somebody tried to kick us from our
364 * console tty (via vhangup() or suchlike),
365 * try to reconnect */
373 if (writev(console_fd
, iovec
, n
) < 0)
382 static int write_to_syslog(
388 const char *object_field
,
390 const char *buffer
) {
392 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
394 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
395 struct iovec iovec
[5] = {};
396 struct msghdr msghdr
= {
398 .msg_iovlen
= ELEMENTSOF(iovec
),
406 xsprintf(header_priority
, "<%i>", level
);
408 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
413 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
416 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid());
418 IOVEC_SET_STRING(iovec
[0], header_priority
);
419 IOVEC_SET_STRING(iovec
[1], header_time
);
420 IOVEC_SET_STRING(iovec
[2], program_invocation_short_name
);
421 IOVEC_SET_STRING(iovec
[3], header_pid
);
422 IOVEC_SET_STRING(iovec
[4], buffer
);
424 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
425 if (syslog_is_stream
)
431 n
= sendmsg(syslog_fd
, &msghdr
, MSG_NOSIGNAL
);
435 if (!syslog_is_stream
||
436 (size_t) n
>= IOVEC_TOTAL_SIZE(iovec
, ELEMENTSOF(iovec
)))
439 IOVEC_INCREMENT(iovec
, ELEMENTSOF(iovec
), n
);
445 static int write_to_kmsg(
451 const char *object_field
,
453 const char *buffer
) {
455 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
456 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
457 struct iovec iovec
[5] = {};
462 xsprintf(header_priority
, "<%i>", level
);
463 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid());
465 IOVEC_SET_STRING(iovec
[0], header_priority
);
466 IOVEC_SET_STRING(iovec
[1], program_invocation_short_name
);
467 IOVEC_SET_STRING(iovec
[2], header_pid
);
468 IOVEC_SET_STRING(iovec
[3], buffer
);
469 IOVEC_SET_STRING(iovec
[4], "\n");
471 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
477 static int log_do_header(
482 const char *file
, int line
, const char *func
,
483 const char *object_field
, const char *object
) {
485 snprintf(header
, size
,
487 "SYSLOG_FACILITY=%i\n"
493 "SYSLOG_IDENTIFIER=%s\n",
496 isempty(file
) ? "" : "CODE_FILE=",
497 isempty(file
) ? "" : file
,
498 isempty(file
) ? "" : "\n",
499 line
? "CODE_LINE=" : "",
500 line
? 1 : 0, line
, /* %.0d means no output too, special case for 0 */
502 isempty(func
) ? "" : "CODE_FUNCTION=",
503 isempty(func
) ? "" : func
,
504 isempty(func
) ? "" : "\n",
505 error
? "ERRNO=" : "",
506 error
? 1 : 0, error
,
508 isempty(object
) ? "" : object_field
,
509 isempty(object
) ? "" : object
,
510 isempty(object
) ? "" : "\n",
511 program_invocation_short_name
);
516 static int write_to_journal(
522 const char *object_field
,
524 const char *buffer
) {
526 char header
[LINE_MAX
];
527 struct iovec iovec
[4] = {};
528 struct msghdr mh
= {};
533 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, object_field
, object
);
535 IOVEC_SET_STRING(iovec
[0], header
);
536 IOVEC_SET_STRING(iovec
[1], "MESSAGE=");
537 IOVEC_SET_STRING(iovec
[2], buffer
);
538 IOVEC_SET_STRING(iovec
[3], "\n");
541 mh
.msg_iovlen
= ELEMENTSOF(iovec
);
543 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) < 0)
549 static int log_dispatch(
555 const char *object_field
,
561 if (log_target
== LOG_TARGET_NULL
)
564 /* Patch in LOG_DAEMON facility if necessary */
565 if ((level
& LOG_FACMASK
) == 0)
566 level
= log_facility
| LOG_PRI(level
);
575 buffer
+= strspn(buffer
, NEWLINE
);
580 if ((e
= strpbrk(buffer
, NEWLINE
)))
583 if (log_target
== LOG_TARGET_AUTO
||
584 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
585 log_target
== LOG_TARGET_JOURNAL
) {
587 k
= write_to_journal(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
595 if (log_target
== LOG_TARGET_SYSLOG_OR_KMSG
||
596 log_target
== LOG_TARGET_SYSLOG
) {
598 k
= write_to_syslog(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
607 (log_target
== LOG_TARGET_AUTO
||
608 log_target
== LOG_TARGET_SAFE
||
609 log_target
== LOG_TARGET_SYSLOG_OR_KMSG
||
610 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
611 log_target
== LOG_TARGET_KMSG
)) {
613 k
= write_to_kmsg(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
621 (void) write_to_console(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
629 int log_dump_internal(
639 /* This modifies the buffer... */
644 if (_likely_(LOG_PRI(level
) > log_max_level
))
647 return log_dispatch(level
, error
, file
, line
, func
, NULL
, NULL
, buffer
);
660 char buffer
[LINE_MAX
];
665 if (_likely_(LOG_PRI(level
) > log_max_level
))
668 /* Make sure that %m maps to the specified error */
672 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
674 return log_dispatch(level
, error
, file
, line
, func
, NULL
, NULL
, buffer
);
683 const char *format
, ...) {
688 va_start(ap
, format
);
689 r
= log_internalv(level
, error
, file
, line
, func
, format
, ap
);
695 int log_object_internalv(
701 const char *object_field
,
713 if (_likely_(LOG_PRI(level
) > log_max_level
))
716 /* Make sure that %m maps to the specified error */
720 /* Prepend the object name before the message */
725 l
= n
+ 2 + LINE_MAX
;
727 buffer
= newa(char, l
);
728 b
= stpcpy(stpcpy(buffer
, object
), ": ");
731 b
= buffer
= newa(char, l
);
734 vsnprintf(b
, l
, format
, ap
);
736 return log_dispatch(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
739 int log_object_internal(
745 const char *object_field
,
747 const char *format
, ...) {
752 va_start(ap
, format
);
753 r
= log_object_internalv(level
, error
, file
, line
, func
, object_field
, object
, format
, ap
);
759 static void log_assert(
765 const char *format
) {
767 static char buffer
[LINE_MAX
];
769 if (_likely_(LOG_PRI(level
) > log_max_level
))
772 DISABLE_WARNING_FORMAT_NONLITERAL
;
773 snprintf(buffer
, sizeof(buffer
), format
, text
, file
, line
, func
);
776 log_abort_msg
= buffer
;
778 log_dispatch(level
, 0, file
, line
, func
, NULL
, NULL
, buffer
);
781 noreturn
void log_assert_failed(const char *text
, const char *file
, int line
, const char *func
) {
782 log_assert(LOG_CRIT
, text
, file
, line
, func
, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
786 noreturn
void log_assert_failed_unreachable(const char *text
, const char *file
, int line
, const char *func
) {
787 log_assert(LOG_CRIT
, text
, file
, line
, func
, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
791 void log_assert_failed_return(const char *text
, const char *file
, int line
, const char *func
) {
793 log_assert(LOG_DEBUG
, text
, file
, line
, func
, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
796 int log_oom_internal(const char *file
, int line
, const char *func
) {
797 log_internal(LOG_ERR
, ENOMEM
, file
, line
, func
, "Out of memory.");
801 int log_struct_internal(
807 const char *format
, ...) {
817 if (_likely_(LOG_PRI(level
) > log_max_level
))
820 if (log_target
== LOG_TARGET_NULL
)
823 if ((level
& LOG_FACMASK
) == 0)
824 level
= log_facility
| LOG_PRI(level
);
826 if ((log_target
== LOG_TARGET_AUTO
||
827 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
828 log_target
== LOG_TARGET_JOURNAL
) &&
830 char header
[LINE_MAX
];
831 struct iovec iovec
[17] = {};
836 static const char nl
= '\n';
837 bool fallback
= false;
839 /* If the journal is available do structured logging */
840 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
);
841 IOVEC_SET_STRING(iovec
[n
++], header
);
843 va_start(ap
, format
);
844 while (format
&& n
+ 1 < ELEMENTSOF(iovec
)) {
848 /* We need to copy the va_list structure,
849 * since vasprintf() leaves it afterwards at
850 * an undefined location */
856 if (vasprintf(&m
, format
, aq
) < 0) {
863 /* Now, jump enough ahead, so that we point to
864 * the next format string */
865 VA_FORMAT_ADVANCE(format
, ap
);
867 IOVEC_SET_STRING(iovec
[n
++], m
);
869 iovec
[n
].iov_base
= (char*) &nl
;
870 iovec
[n
].iov_len
= 1;
873 format
= va_arg(ap
, char *);
878 (void) sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
);
882 for (i
= 1; i
< n
; i
+= 2)
883 free(iovec
[i
].iov_base
);
889 /* Fallback if journal logging is not available or didn't work. */
891 va_start(ap
, format
);
899 vsnprintf(buf
, sizeof(buf
), format
, aq
);
902 if (startswith(buf
, "MESSAGE=")) {
907 VA_FORMAT_ADVANCE(format
, ap
);
909 format
= va_arg(ap
, char *);
916 return log_dispatch(level
, error
, file
, line
, func
, NULL
, NULL
, buf
+ 8);
919 int log_set_target_from_string(const char *e
) {
922 t
= log_target_from_string(e
);
930 int log_set_max_level_from_string(const char *e
) {
933 t
= log_level_from_string(e
);
937 log_set_max_level(t
);
941 static int parse_proc_cmdline_item(const char *key
, const char *value
) {
944 * The systemd.log_xyz= settings are parsed by all tools, and
947 * However, "quiet" is only parsed by PID 1, and only turns of
948 * status output to /dev/console, but does not alter the log
952 if (streq(key
, "debug") && !value
)
953 log_set_max_level(LOG_DEBUG
);
955 else if (streq(key
, "systemd.log_target") && value
) {
957 if (log_set_target_from_string(value
) < 0)
958 log_warning("Failed to parse log target '%s'. Ignoring.", value
);
960 } else if (streq(key
, "systemd.log_level") && value
) {
962 if (log_set_max_level_from_string(value
) < 0)
963 log_warning("Failed to parse log level '%s'. Ignoring.", value
);
965 } else if (streq(key
, "systemd.log_color") && value
) {
967 if (log_show_color_from_string(value
) < 0)
968 log_warning("Failed to parse log color setting '%s'. Ignoring.", value
);
970 } else if (streq(key
, "systemd.log_location") && value
) {
972 if (log_show_location_from_string(value
) < 0)
973 log_warning("Failed to parse log location setting '%s'. Ignoring.", value
);
979 void log_parse_environment(void) {
982 if (get_ctty_devnr(0, NULL
) < 0)
983 /* Only try to read the command line in daemons.
984 We assume that anything that has a controlling
985 tty is user stuff. */
986 (void) parse_proc_cmdline(parse_proc_cmdline_item
);
988 e
= secure_getenv("SYSTEMD_LOG_TARGET");
989 if (e
&& log_set_target_from_string(e
) < 0)
990 log_warning("Failed to parse log target '%s'. Ignoring.", e
);
992 e
= secure_getenv("SYSTEMD_LOG_LEVEL");
993 if (e
&& log_set_max_level_from_string(e
) < 0)
994 log_warning("Failed to parse log level '%s'. Ignoring.", e
);
996 e
= secure_getenv("SYSTEMD_LOG_COLOR");
997 if (e
&& log_show_color_from_string(e
) < 0)
998 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1000 e
= secure_getenv("SYSTEMD_LOG_LOCATION");
1001 if (e
&& log_show_location_from_string(e
) < 0)
1002 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1005 LogTarget
log_get_target(void) {
1009 int log_get_max_level(void) {
1010 return log_max_level
;
1013 void log_show_color(bool b
) {
1017 bool log_get_show_color(void) {
1021 void log_show_location(bool b
) {
1025 bool log_get_show_location(void) {
1026 return show_location
;
1029 int log_show_color_from_string(const char *e
) {
1032 t
= parse_boolean(e
);
1040 int log_show_location_from_string(const char *e
) {
1043 t
= parse_boolean(e
);
1047 log_show_location(t
);
1051 bool log_on_console(void) {
1052 if (log_target
== LOG_TARGET_CONSOLE
||
1053 log_target
== LOG_TARGET_CONSOLE_PREFIXED
)
1056 return syslog_fd
< 0 && kmsg_fd
< 0 && journal_fd
< 0;
1059 static const char *const log_target_table
[_LOG_TARGET_MAX
] = {
1060 [LOG_TARGET_CONSOLE
] = "console",
1061 [LOG_TARGET_CONSOLE_PREFIXED
] = "console-prefixed",
1062 [LOG_TARGET_KMSG
] = "kmsg",
1063 [LOG_TARGET_JOURNAL
] = "journal",
1064 [LOG_TARGET_JOURNAL_OR_KMSG
] = "journal-or-kmsg",
1065 [LOG_TARGET_SYSLOG
] = "syslog",
1066 [LOG_TARGET_SYSLOG_OR_KMSG
] = "syslog-or-kmsg",
1067 [LOG_TARGET_AUTO
] = "auto",
1068 [LOG_TARGET_SAFE
] = "safe",
1069 [LOG_TARGET_NULL
] = "null"
1072 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);
1074 void log_received_signal(int level
, const struct signalfd_siginfo
*si
) {
1075 if (si
->ssi_pid
> 0) {
1076 _cleanup_free_
char *p
= NULL
;
1078 get_process_comm(si
->ssi_pid
, &p
);
1081 "Received SIG%s from PID %"PRIu32
" (%s).",
1082 signal_to_string(si
->ssi_signo
),
1083 si
->ssi_pid
, strna(p
));
1087 signal_to_string(si
->ssi_signo
));
1091 void log_set_upgrade_syslog_to_journal(bool b
) {
1092 upgrade_syslog_to_journal
= b
;
1095 int log_syntax_internal(
1098 const char *config_file
,
1099 unsigned config_line
,
1104 const char *format
, ...) {
1107 char buffer
[LINE_MAX
];
1114 if (_likely_(LOG_PRI(level
) > log_max_level
))
1117 if (log_target
== LOG_TARGET_NULL
)
1123 va_start(ap
, format
);
1124 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
1128 r
= log_struct_internal(
1131 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit
,
1132 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION
),
1133 "CONFIG_FILE=%s", config_file
,
1134 "CONFIG_LINE=%u", config_line
,
1135 LOG_MESSAGE("[%s:%u] %s", config_file
, config_line
, buffer
),
1138 r
= log_struct_internal(
1141 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION
),
1142 "CONFIG_FILE=%s", config_file
,
1143 "CONFIG_LINE=%u", config_line
,
1144 LOG_MESSAGE("[%s:%u] %s", config_file
, config_line
, buffer
),