]>
git.ipfire.org Git - people/ms/systemd.git/blob - log.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
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 General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include <sys/socket.h>
34 #define SYSLOG_TIMEOUT_USEC (5*USEC_PER_SEC)
35 #define LOG_BUFFER_MAX 1024
37 static LogTarget log_target
= LOG_TARGET_CONSOLE
;
38 static int log_max_level
= LOG_DEBUG
;
40 static int syslog_fd
= -1;
41 static int kmsg_fd
= -1;
43 /* Akin to glibc's __abort_msg; which is private and we hance cannot
45 static char *log_abort_msg
= NULL
;
47 void log_close_kmsg(void) {
50 close_nointr_nofail(kmsg_fd
);
55 int log_open_kmsg(void) {
57 if (log_target
!= LOG_TARGET_KMSG
) {
65 if ((kmsg_fd
= open("/dev/kmsg", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
)) < 0) {
66 log_info("Failed to open syslog for logging: %s", strerror(errno
));
70 log_info("Succesfully opened /dev/kmsg for logging.");
75 void log_close_syslog(void) {
78 close_nointr_nofail(syslog_fd
);
83 int log_open_syslog(void) {
86 struct sockaddr_un un
;
91 if (log_target
!= LOG_TARGET_SYSLOG
) {
99 if ((syslog_fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0)) < 0)
102 /* Make sure we don't block for more than 5s when talking to
104 timeval_store(&tv
, SYSLOG_TIMEOUT_USEC
);
105 if (setsockopt(syslog_fd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
)) < 0) {
112 sa
.un
.sun_family
= AF_UNIX
;
113 strncpy(sa
.un
.sun_path
, "/dev/log", sizeof(sa
.un
.sun_path
));
115 if (connect(syslog_fd
, &sa
.sa
, sizeof(sa
)) < 0) {
119 log_info("Failed to open syslog for logging: %s", strerror(-r
));
123 log_info("Succesfully opened syslog for logging.");
128 void log_set_target(LogTarget target
) {
130 assert(target
< _LOG_TARGET_MAX
);
135 void log_set_max_level(int level
) {
136 assert((level
& LOG_PRIMASK
) == level
);
138 log_max_level
= level
;
141 static void write_to_console(
149 const char *prefix
, *suffix
;
151 if (LOG_PRI(level
) <= LOG_ERR
) {
152 prefix
= "\x1B[1;31m";
159 fprintf(stderr
, "(%s:%u) %s", file
, line
, prefix
);
160 vfprintf(stderr
, format
, ap
);
161 fprintf(stderr
, "%s\n", suffix
);
164 static int write_to_syslog(
172 char header_priority
[16], header_time
[64], header_pid
[16];
173 char buffer
[LOG_BUFFER_MAX
];
174 struct iovec iovec
[5];
175 struct msghdr msghdr
;
182 snprintf(header_priority
, sizeof(header_priority
), "<%i>", LOG_MAKEPRI(LOG_DAEMON
, LOG_PRI(level
)));
183 char_array_0(header_priority
);
185 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
186 if (!(tm
= localtime(&t
)))
189 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
192 snprintf(header_pid
, sizeof(header_pid
), "[%llu]: ", (unsigned long long) getpid());
193 char_array_0(header_pid
);
195 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
196 char_array_0(buffer
);
199 IOVEC_SET_STRING(iovec
[0], header_priority
);
200 IOVEC_SET_STRING(iovec
[1], header_time
);
201 IOVEC_SET_STRING(iovec
[2], __progname
);
202 IOVEC_SET_STRING(iovec
[3], header_pid
);
203 IOVEC_SET_STRING(iovec
[4], buffer
);
206 msghdr
.msg_iov
= iovec
;
207 msghdr
.msg_iovlen
= ELEMENTSOF(iovec
);
209 if (sendmsg(syslog_fd
, &msghdr
, 0) < 0)
215 static int write_to_kmsg(
223 char header_priority
[16], header_pid
[16];
224 char buffer
[LOG_BUFFER_MAX
];
225 struct iovec iovec
[5];
230 snprintf(header_priority
, sizeof(header_priority
), "<%i>", LOG_PRI(level
));
231 char_array_0(header_priority
);
233 snprintf(header_pid
, sizeof(header_pid
), "[%llu]: ", (unsigned long long) getpid());
234 char_array_0(header_pid
);
236 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
237 char_array_0(buffer
);
240 IOVEC_SET_STRING(iovec
[0], header_priority
);
241 IOVEC_SET_STRING(iovec
[1], __progname
);
242 IOVEC_SET_STRING(iovec
[2], header_pid
);
243 IOVEC_SET_STRING(iovec
[3], buffer
);
244 IOVEC_SET_STRING(iovec
[4], (char*) "\n");
246 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
252 #define LOG_DISPATCH(level,file,line,func,format) \
255 bool written = false; \
256 if (log_target == LOG_TARGET_KMSG) { \
257 va_start(_ap, format); \
258 written = write_to_kmsg(level, file, line, func, format, _ap) >= 0; \
260 } else if (log_target == LOG_TARGET_SYSLOG) { \
261 va_start(_ap, format); \
262 written = write_to_syslog(level, file, line, func, format, _ap) >= 0; \
266 va_start(_ap, format); \
267 write_to_console(level, file, line, func, format, _ap); \
277 const char *format
, ...) {
281 if (_likely(LOG_PRI(level
) > log_max_level
))
285 LOG_DISPATCH(level
, file
, line
, func
, format
);
293 const char *format
, ...) {
295 static char buffer
[LOG_BUFFER_MAX
];
297 int saved_errno
= errno
;
299 va_start(ap
, format
);
300 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
303 char_array_0(buffer
);
304 log_abort_msg
= buffer
;
306 LOG_DISPATCH(LOG_CRIT
, file
, line
, func
, format
);
309 /* If the user chose to ignore this SIGABRT, we are happy to go on, as if nothing happened. */
313 int log_set_target_from_string(const char *e
) {
316 if ((t
= log_target_from_string(e
)) < 0)
323 int log_set_max_level_from_string(const char *e
) {
326 if ((t
= log_level_from_string(e
)) < 0)
329 log_set_max_level(t
);
333 void log_parse_environment(void) {
336 if ((e
= getenv("SYSTEMD_LOG_TARGET")))
337 if (log_set_target_from_string(e
) < 0)
338 log_warning("Failed to parse log target %s. Ignoring.", e
);
340 if ((e
= getenv("SYSTEMD_LOG_LEVEL")))
341 if (log_set_max_level_from_string(e
) < 0)
342 log_warning("Failed to parse log level %s. Ignoring.", e
);
345 LogTarget
log_get_target(void) {
349 int log_get_max_level(void) {
350 return log_max_level
;
353 static const char *const log_target_table
[] = {
354 [LOG_TARGET_CONSOLE
] = "console",
355 [LOG_TARGET_SYSLOG
] = "syslog",
356 [LOG_TARGET_KMSG
] = "kmsg",
359 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);