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"
35 #include "formats-util.h"
39 #include "parse-util.h"
40 #include "proc-cmdline.h"
41 #include "process-util.h"
42 #include "signal-util.h"
43 #include "socket-util.h"
44 #include "string-table.h"
45 #include "string-util.h"
46 #include "syslog-util.h"
47 #include "terminal-util.h"
50 #define SNDBUF_SIZE (8*1024*1024)
52 static LogTarget log_target
= LOG_TARGET_CONSOLE
;
53 static int log_max_level
= LOG_INFO
;
54 static int log_facility
= LOG_DAEMON
;
56 static int console_fd
= STDERR_FILENO
;
57 static int syslog_fd
= -1;
58 static int kmsg_fd
= -1;
59 static int journal_fd
= -1;
61 static bool syslog_is_stream
= false;
63 static bool show_color
= false;
64 static bool show_location
= false;
66 static bool upgrade_syslog_to_journal
= false;
68 /* Akin to glibc's __abort_msg; which is private and we hence cannot
70 static char *log_abort_msg
= NULL
;
72 void log_close_console(void) {
79 safe_close(console_fd
);
85 static int log_open_console(void) {
91 console_fd
= open_terminal("/dev/console", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
95 console_fd
= STDERR_FILENO
;
100 void log_close_kmsg(void) {
101 kmsg_fd
= safe_close(kmsg_fd
);
104 static int log_open_kmsg(void) {
109 kmsg_fd
= open("/dev/kmsg", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
116 void log_close_syslog(void) {
117 syslog_fd
= safe_close(syslog_fd
);
120 static int create_log_socket(int type
) {
124 fd
= socket(AF_UNIX
, type
|SOCK_CLOEXEC
, 0);
128 fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
130 /* We need a blocking fd here since we'd otherwise lose
131 messages way too early. However, let's not hang forever in the
132 unlikely case of a deadlock. */
134 timeval_store(&tv
, 10 * USEC_PER_MSEC
);
136 timeval_store(&tv
, 10 * USEC_PER_SEC
);
137 (void) setsockopt(fd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
));
142 static int log_open_syslog(void) {
144 static const union sockaddr_union sa
= {
145 .un
.sun_family
= AF_UNIX
,
146 .un
.sun_path
= "/dev/log",
154 syslog_fd
= create_log_socket(SOCK_DGRAM
);
160 if (connect(syslog_fd
, &sa
.sa
, offsetof(struct sockaddr_un
, sun_path
) + strlen(sa
.un
.sun_path
)) < 0) {
161 safe_close(syslog_fd
);
163 /* Some legacy syslog systems still use stream
164 * sockets. They really shouldn't. But what can we
166 syslog_fd
= create_log_socket(SOCK_STREAM
);
172 if (connect(syslog_fd
, &sa
.sa
, offsetof(struct sockaddr_un
, sun_path
) + strlen(sa
.un
.sun_path
)) < 0) {
177 syslog_is_stream
= true;
179 syslog_is_stream
= false;
188 void log_close_journal(void) {
189 journal_fd
= safe_close(journal_fd
);
192 static int log_open_journal(void) {
194 static const union sockaddr_union sa
= {
195 .un
.sun_family
= AF_UNIX
,
196 .un
.sun_path
= "/run/systemd/journal/socket",
204 journal_fd
= create_log_socket(SOCK_DGRAM
);
205 if (journal_fd
< 0) {
210 if (connect(journal_fd
, &sa
.sa
, offsetof(struct sockaddr_un
, sun_path
) + strlen(sa
.un
.sun_path
)) < 0) {
225 /* If we don't use the console we close it here, to not get
226 * killed by SAK. If we don't use syslog we close it here so
227 * that we are not confused by somebody deleting the socket in
228 * the fs. If we don't use /dev/kmsg we still keep it open,
229 * because there is no reason to close it. */
231 if (log_target
== LOG_TARGET_NULL
) {
238 if ((log_target
!= LOG_TARGET_AUTO
&& log_target
!= LOG_TARGET_SAFE
) ||
240 isatty(STDERR_FILENO
) <= 0) {
242 if (log_target
== LOG_TARGET_AUTO
||
243 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
244 log_target
== LOG_TARGET_JOURNAL
) {
245 r
= log_open_journal();
253 if (log_target
== LOG_TARGET_SYSLOG_OR_KMSG
||
254 log_target
== LOG_TARGET_SYSLOG
) {
255 r
= log_open_syslog();
263 if (log_target
== LOG_TARGET_AUTO
||
264 log_target
== LOG_TARGET_SAFE
||
265 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
266 log_target
== LOG_TARGET_SYSLOG_OR_KMSG
||
267 log_target
== LOG_TARGET_KMSG
) {
281 return log_open_console();
284 void log_set_target(LogTarget target
) {
286 assert(target
< _LOG_TARGET_MAX
);
288 if (upgrade_syslog_to_journal
) {
289 if (target
== LOG_TARGET_SYSLOG
)
290 target
= LOG_TARGET_JOURNAL
;
291 else if (target
== LOG_TARGET_SYSLOG_OR_KMSG
)
292 target
= LOG_TARGET_JOURNAL_OR_KMSG
;
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(
325 const char *object_field
,
327 const char *buffer
) {
329 char location
[64], prefix
[1 + DECIMAL_STR_MAX(int) + 2];
330 struct iovec iovec
[6] = {};
337 if (log_target
== LOG_TARGET_CONSOLE_PREFIXED
) {
338 sprintf(prefix
, "<%i>", level
);
339 IOVEC_SET_STRING(iovec
[n
++], prefix
);
342 highlight
= LOG_PRI(level
) <= LOG_ERR
&& show_color
;
345 snprintf(location
, sizeof(location
), "(%s:%i) ", file
, line
);
346 IOVEC_SET_STRING(iovec
[n
++], location
);
350 IOVEC_SET_STRING(iovec
[n
++], ANSI_HIGHLIGHT_RED
);
351 IOVEC_SET_STRING(iovec
[n
++], buffer
);
353 IOVEC_SET_STRING(iovec
[n
++], ANSI_NORMAL
);
354 IOVEC_SET_STRING(iovec
[n
++], "\n");
356 if (writev(console_fd
, iovec
, n
) < 0) {
358 if (errno
== EIO
&& getpid() == 1) {
360 /* If somebody tried to kick us from our
361 * console tty (via vhangup() or suchlike),
362 * try to reconnect */
370 if (writev(console_fd
, iovec
, n
) < 0)
379 static int write_to_syslog(
385 const char *object_field
,
387 const char *buffer
) {
389 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
391 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
392 struct iovec iovec
[5] = {};
393 struct msghdr msghdr
= {
395 .msg_iovlen
= ELEMENTSOF(iovec
),
403 xsprintf(header_priority
, "<%i>", level
);
405 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
410 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
413 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid());
415 IOVEC_SET_STRING(iovec
[0], header_priority
);
416 IOVEC_SET_STRING(iovec
[1], header_time
);
417 IOVEC_SET_STRING(iovec
[2], program_invocation_short_name
);
418 IOVEC_SET_STRING(iovec
[3], header_pid
);
419 IOVEC_SET_STRING(iovec
[4], buffer
);
421 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
422 if (syslog_is_stream
)
428 n
= sendmsg(syslog_fd
, &msghdr
, MSG_NOSIGNAL
);
432 if (!syslog_is_stream
||
433 (size_t) n
>= IOVEC_TOTAL_SIZE(iovec
, ELEMENTSOF(iovec
)))
436 IOVEC_INCREMENT(iovec
, ELEMENTSOF(iovec
), n
);
442 static int write_to_kmsg(
448 const char *object_field
,
450 const char *buffer
) {
452 char header_priority
[2 + DECIMAL_STR_MAX(int) + 1],
453 header_pid
[4 + DECIMAL_STR_MAX(pid_t
) + 1];
454 struct iovec iovec
[5] = {};
459 xsprintf(header_priority
, "<%i>", level
);
460 xsprintf(header_pid
, "["PID_FMT
"]: ", getpid());
462 IOVEC_SET_STRING(iovec
[0], header_priority
);
463 IOVEC_SET_STRING(iovec
[1], program_invocation_short_name
);
464 IOVEC_SET_STRING(iovec
[2], header_pid
);
465 IOVEC_SET_STRING(iovec
[3], buffer
);
466 IOVEC_SET_STRING(iovec
[4], "\n");
468 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
474 static int log_do_header(
479 const char *file
, int line
, const char *func
,
480 const char *object_field
, const char *object
) {
482 snprintf(header
, size
,
484 "SYSLOG_FACILITY=%i\n"
490 "SYSLOG_IDENTIFIER=%s\n",
493 isempty(file
) ? "" : "CODE_FILE=",
494 isempty(file
) ? "" : file
,
495 isempty(file
) ? "" : "\n",
496 line
? "CODE_LINE=" : "",
497 line
? 1 : 0, line
, /* %.0d means no output too, special case for 0 */
499 isempty(func
) ? "" : "CODE_FUNCTION=",
500 isempty(func
) ? "" : func
,
501 isempty(func
) ? "" : "\n",
502 error
? "ERRNO=" : "",
503 error
? 1 : 0, error
,
505 isempty(object
) ? "" : object_field
,
506 isempty(object
) ? "" : object
,
507 isempty(object
) ? "" : "\n",
508 program_invocation_short_name
);
513 static int write_to_journal(
519 const char *object_field
,
521 const char *buffer
) {
523 char header
[LINE_MAX
];
524 struct iovec iovec
[4] = {};
525 struct msghdr mh
= {};
530 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, object_field
, object
);
532 IOVEC_SET_STRING(iovec
[0], header
);
533 IOVEC_SET_STRING(iovec
[1], "MESSAGE=");
534 IOVEC_SET_STRING(iovec
[2], buffer
);
535 IOVEC_SET_STRING(iovec
[3], "\n");
538 mh
.msg_iovlen
= ELEMENTSOF(iovec
);
540 if (sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
) < 0)
546 static int log_dispatch(
552 const char *object_field
,
558 if (log_target
== LOG_TARGET_NULL
)
561 /* Patch in LOG_DAEMON facility if necessary */
562 if ((level
& LOG_FACMASK
) == 0)
563 level
= log_facility
| LOG_PRI(level
);
572 buffer
+= strspn(buffer
, NEWLINE
);
577 if ((e
= strpbrk(buffer
, NEWLINE
)))
580 if (log_target
== LOG_TARGET_AUTO
||
581 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
582 log_target
== LOG_TARGET_JOURNAL
) {
584 k
= write_to_journal(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
592 if (log_target
== LOG_TARGET_SYSLOG_OR_KMSG
||
593 log_target
== LOG_TARGET_SYSLOG
) {
595 k
= write_to_syslog(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
604 (log_target
== LOG_TARGET_AUTO
||
605 log_target
== LOG_TARGET_SAFE
||
606 log_target
== LOG_TARGET_SYSLOG_OR_KMSG
||
607 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
608 log_target
== LOG_TARGET_KMSG
)) {
610 k
= write_to_kmsg(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
618 (void) write_to_console(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
626 int log_dump_internal(
636 /* This modifies the buffer... */
641 if (_likely_(LOG_PRI(level
) > log_max_level
))
644 return log_dispatch(level
, error
, file
, line
, func
, NULL
, NULL
, buffer
);
657 char buffer
[LINE_MAX
];
662 if (_likely_(LOG_PRI(level
) > log_max_level
))
665 /* Make sure that %m maps to the specified error */
669 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
671 return log_dispatch(level
, error
, file
, line
, func
, NULL
, NULL
, buffer
);
680 const char *format
, ...) {
685 va_start(ap
, format
);
686 r
= log_internalv(level
, error
, file
, line
, func
, format
, ap
);
692 int log_object_internalv(
698 const char *object_field
,
710 if (_likely_(LOG_PRI(level
) > log_max_level
))
713 /* Make sure that %m maps to the specified error */
717 /* Prepend the object name before the message */
722 l
= n
+ 2 + LINE_MAX
;
724 buffer
= newa(char, l
);
725 b
= stpcpy(stpcpy(buffer
, object
), ": ");
728 b
= buffer
= newa(char, l
);
731 vsnprintf(b
, l
, format
, ap
);
733 return log_dispatch(level
, error
, file
, line
, func
, object_field
, object
, buffer
);
736 int log_object_internal(
742 const char *object_field
,
744 const char *format
, ...) {
749 va_start(ap
, format
);
750 r
= log_object_internalv(level
, error
, file
, line
, func
, object_field
, object
, format
, ap
);
756 static void log_assert(
762 const char *format
) {
764 static char buffer
[LINE_MAX
];
766 if (_likely_(LOG_PRI(level
) > log_max_level
))
769 DISABLE_WARNING_FORMAT_NONLITERAL
;
770 snprintf(buffer
, sizeof(buffer
), format
, text
, file
, line
, func
);
773 log_abort_msg
= buffer
;
775 log_dispatch(level
, 0, file
, line
, func
, NULL
, NULL
, buffer
);
778 noreturn
void log_assert_failed(const char *text
, const char *file
, int line
, const char *func
) {
779 log_assert(LOG_CRIT
, text
, file
, line
, func
, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
783 noreturn
void log_assert_failed_unreachable(const char *text
, const char *file
, int line
, const char *func
) {
784 log_assert(LOG_CRIT
, text
, file
, line
, func
, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
788 void log_assert_failed_return(const char *text
, const char *file
, int line
, const char *func
) {
790 log_assert(LOG_DEBUG
, text
, file
, line
, func
, "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
793 int log_oom_internal(const char *file
, int line
, const char *func
) {
794 log_internal(LOG_ERR
, ENOMEM
, file
, line
, func
, "Out of memory.");
798 int log_struct_internal(
804 const char *format
, ...) {
814 if (_likely_(LOG_PRI(level
) > log_max_level
))
817 if (log_target
== LOG_TARGET_NULL
)
820 if ((level
& LOG_FACMASK
) == 0)
821 level
= log_facility
| LOG_PRI(level
);
823 if ((log_target
== LOG_TARGET_AUTO
||
824 log_target
== LOG_TARGET_JOURNAL_OR_KMSG
||
825 log_target
== LOG_TARGET_JOURNAL
) &&
827 char header
[LINE_MAX
];
828 struct iovec iovec
[17] = {};
833 static const char nl
= '\n';
834 bool fallback
= false;
836 /* If the journal is available do structured logging */
837 log_do_header(header
, sizeof(header
), level
, error
, file
, line
, func
, NULL
, NULL
);
838 IOVEC_SET_STRING(iovec
[n
++], header
);
840 va_start(ap
, format
);
841 while (format
&& n
+ 1 < ELEMENTSOF(iovec
)) {
845 /* We need to copy the va_list structure,
846 * since vasprintf() leaves it afterwards at
847 * an undefined location */
853 if (vasprintf(&m
, format
, aq
) < 0) {
860 /* Now, jump enough ahead, so that we point to
861 * the next format string */
862 VA_FORMAT_ADVANCE(format
, ap
);
864 IOVEC_SET_STRING(iovec
[n
++], m
);
866 iovec
[n
].iov_base
= (char*) &nl
;
867 iovec
[n
].iov_len
= 1;
870 format
= va_arg(ap
, char *);
875 (void) sendmsg(journal_fd
, &mh
, MSG_NOSIGNAL
);
879 for (i
= 1; i
< n
; i
+= 2)
880 free(iovec
[i
].iov_base
);
886 /* Fallback if journal logging is not available or didn't work. */
888 va_start(ap
, format
);
896 vsnprintf(buf
, sizeof(buf
), format
, aq
);
899 if (startswith(buf
, "MESSAGE=")) {
904 VA_FORMAT_ADVANCE(format
, ap
);
906 format
= va_arg(ap
, char *);
913 return log_dispatch(level
, error
, file
, line
, func
, NULL
, NULL
, buf
+ 8);
916 int log_set_target_from_string(const char *e
) {
919 t
= log_target_from_string(e
);
927 int log_set_max_level_from_string(const char *e
) {
930 t
= log_level_from_string(e
);
934 log_set_max_level(t
);
938 static int parse_proc_cmdline_item(const char *key
, const char *value
) {
941 * The systemd.log_xyz= settings are parsed by all tools, and
944 * However, "quiet" is only parsed by PID 1, and only turns of
945 * status output to /dev/console, but does not alter the log
949 if (streq(key
, "debug") && !value
)
950 log_set_max_level(LOG_DEBUG
);
952 else if (streq(key
, "systemd.log_target") && value
) {
954 if (log_set_target_from_string(value
) < 0)
955 log_warning("Failed to parse log target '%s'. Ignoring.", value
);
957 } else if (streq(key
, "systemd.log_level") && value
) {
959 if (log_set_max_level_from_string(value
) < 0)
960 log_warning("Failed to parse log level '%s'. Ignoring.", value
);
962 } else if (streq(key
, "systemd.log_color") && value
) {
964 if (log_show_color_from_string(value
) < 0)
965 log_warning("Failed to parse log color setting '%s'. Ignoring.", value
);
967 } else if (streq(key
, "systemd.log_location") && value
) {
969 if (log_show_location_from_string(value
) < 0)
970 log_warning("Failed to parse log location setting '%s'. Ignoring.", value
);
976 void log_parse_environment(void) {
979 if (get_ctty_devnr(0, NULL
) < 0)
980 /* Only try to read the command line in daemons.
981 We assume that anything that has a controlling
982 tty is user stuff. */
983 (void) parse_proc_cmdline(parse_proc_cmdline_item
);
985 e
= secure_getenv("SYSTEMD_LOG_TARGET");
986 if (e
&& log_set_target_from_string(e
) < 0)
987 log_warning("Failed to parse log target '%s'. Ignoring.", e
);
989 e
= secure_getenv("SYSTEMD_LOG_LEVEL");
990 if (e
&& log_set_max_level_from_string(e
) < 0)
991 log_warning("Failed to parse log level '%s'. Ignoring.", e
);
993 e
= secure_getenv("SYSTEMD_LOG_COLOR");
994 if (e
&& log_show_color_from_string(e
) < 0)
995 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
997 e
= secure_getenv("SYSTEMD_LOG_LOCATION");
998 if (e
&& log_show_location_from_string(e
) < 0)
999 log_warning("Failed to parse bool '%s'. Ignoring.", e
);
1002 LogTarget
log_get_target(void) {
1006 int log_get_max_level(void) {
1007 return log_max_level
;
1010 void log_show_color(bool b
) {
1014 bool log_get_show_color(void) {
1018 void log_show_location(bool b
) {
1022 bool log_get_show_location(void) {
1023 return show_location
;
1026 int log_show_color_from_string(const char *e
) {
1029 t
= parse_boolean(e
);
1037 int log_show_location_from_string(const char *e
) {
1040 t
= parse_boolean(e
);
1044 log_show_location(t
);
1048 bool log_on_console(void) {
1049 if (log_target
== LOG_TARGET_CONSOLE
||
1050 log_target
== LOG_TARGET_CONSOLE_PREFIXED
)
1053 return syslog_fd
< 0 && kmsg_fd
< 0 && journal_fd
< 0;
1056 static const char *const log_target_table
[_LOG_TARGET_MAX
] = {
1057 [LOG_TARGET_CONSOLE
] = "console",
1058 [LOG_TARGET_CONSOLE_PREFIXED
] = "console-prefixed",
1059 [LOG_TARGET_KMSG
] = "kmsg",
1060 [LOG_TARGET_JOURNAL
] = "journal",
1061 [LOG_TARGET_JOURNAL_OR_KMSG
] = "journal-or-kmsg",
1062 [LOG_TARGET_SYSLOG
] = "syslog",
1063 [LOG_TARGET_SYSLOG_OR_KMSG
] = "syslog-or-kmsg",
1064 [LOG_TARGET_AUTO
] = "auto",
1065 [LOG_TARGET_SAFE
] = "safe",
1066 [LOG_TARGET_NULL
] = "null"
1069 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);
1071 void log_received_signal(int level
, const struct signalfd_siginfo
*si
) {
1072 if (si
->ssi_pid
> 0) {
1073 _cleanup_free_
char *p
= NULL
;
1075 get_process_comm(si
->ssi_pid
, &p
);
1078 "Received SIG%s from PID %"PRIu32
" (%s).",
1079 signal_to_string(si
->ssi_signo
),
1080 si
->ssi_pid
, strna(p
));
1084 signal_to_string(si
->ssi_signo
));
1088 void log_set_upgrade_syslog_to_journal(bool b
) {
1089 upgrade_syslog_to_journal
= b
;
1092 int log_syntax_internal(
1095 const char *config_file
,
1096 unsigned config_line
,
1101 const char *format
, ...) {
1104 char buffer
[LINE_MAX
];
1111 if (_likely_(LOG_PRI(level
) > log_max_level
))
1114 if (log_target
== LOG_TARGET_NULL
)
1120 va_start(ap
, format
);
1121 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
1125 r
= log_struct_internal(
1128 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit
,
1129 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION
),
1130 "CONFIG_FILE=%s", config_file
,
1131 "CONFIG_LINE=%u", config_line
,
1132 LOG_MESSAGE("[%s:%u] %s", config_file
, config_line
, buffer
),
1135 r
= log_struct_internal(
1138 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION
),
1139 "CONFIG_FILE=%s", config_file
,
1140 "CONFIG_LINE=%u", config_line
,
1141 LOG_MESSAGE("[%s:%u] %s", config_file
, config_line
, buffer
),