]>
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 void log_close_kmsg(void) {
46 close_nointr(kmsg_fd
);
51 int log_open_kmsg(void) {
53 if (log_target
!= LOG_TARGET_KMSG
) {
61 if ((kmsg_fd
= open("/dev/kmsg", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
)) < 0) {
62 log_info("Failed to open syslog for logging: %s", strerror(errno
));
66 log_info("Succesfully opened /dev/kmsg for logging.");
71 void log_close_syslog(void) {
74 close_nointr(syslog_fd
);
79 int log_open_syslog(void) {
82 struct sockaddr_un un
;
87 if (log_target
!= LOG_TARGET_SYSLOG
) {
95 if ((syslog_fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0)) < 0)
98 /* Make sure we don't block for more than 5s when talking to
100 timeval_store(&tv
, SYSLOG_TIMEOUT_USEC
);
101 if (setsockopt(syslog_fd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
)) < 0) {
108 sa
.un
.sun_family
= AF_UNIX
;
109 strncpy(sa
.un
.sun_path
, "/dev/log", sizeof(sa
.un
.sun_path
));
111 if (connect(syslog_fd
, &sa
.sa
, sizeof(sa
)) < 0) {
115 log_info("Failed to open syslog for logging: %s", strerror(-r
));
119 log_info("Succesfully opened syslog for logging.");
124 void log_set_target(LogTarget target
) {
126 assert(target
< _LOG_TARGET_MAX
);
131 void log_set_max_level(int level
) {
132 assert((level
& LOG_PRIMASK
) == level
);
134 log_max_level
= level
;
137 static void write_to_console(
145 const char *prefix
, *suffix
;
147 if (LOG_PRI(level
) <= LOG_ERR
) {
148 prefix
= "\x1B[1;31m";
155 fprintf(stderr
, "(%s:%u) %s", file
, line
, prefix
);
156 vfprintf(stderr
, format
, ap
);
157 fprintf(stderr
, "%s\n", suffix
);
160 static int write_to_syslog(
168 char header_priority
[16], header_time
[64], header_pid
[16];
169 char buffer
[LOG_BUFFER_MAX
];
170 struct iovec iovec
[5];
171 struct msghdr msghdr
;
178 snprintf(header_priority
, sizeof(header_priority
), "<%i>", LOG_MAKEPRI(LOG_DAEMON
, LOG_PRI(level
)));
179 char_array_0(header_priority
);
181 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
182 if (!(tm
= localtime(&t
)))
185 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
188 snprintf(header_pid
, sizeof(header_pid
), "[%llu]: ", (unsigned long long) getpid());
189 char_array_0(header_pid
);
191 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
192 char_array_0(buffer
);
195 IOVEC_SET_STRING(iovec
[0], header_priority
);
196 IOVEC_SET_STRING(iovec
[1], header_time
);
197 IOVEC_SET_STRING(iovec
[2], __progname
);
198 IOVEC_SET_STRING(iovec
[3], header_pid
);
199 IOVEC_SET_STRING(iovec
[4], buffer
);
202 msghdr
.msg_iov
= iovec
;
203 msghdr
.msg_iovlen
= ELEMENTSOF(iovec
);
205 if (sendmsg(syslog_fd
, &msghdr
, 0) < 0)
211 static int write_to_kmsg(
219 char header_priority
[16], header_pid
[16];
220 char buffer
[LOG_BUFFER_MAX
];
221 struct iovec iovec
[5];
226 snprintf(header_priority
, sizeof(header_priority
), "<%i>", LOG_PRI(level
));
227 char_array_0(header_priority
);
229 snprintf(header_pid
, sizeof(header_pid
), "[%llu]: ", (unsigned long long) getpid());
230 char_array_0(header_pid
);
232 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
233 char_array_0(buffer
);
236 IOVEC_SET_STRING(iovec
[0], header_priority
);
237 IOVEC_SET_STRING(iovec
[1], __progname
);
238 IOVEC_SET_STRING(iovec
[2], header_pid
);
239 IOVEC_SET_STRING(iovec
[3], buffer
);
240 IOVEC_SET_STRING(iovec
[4], (char*) "\n");
242 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
253 const char *format
, ...) {
259 if (LOG_PRI(level
) > log_max_level
)
265 if (log_target
== LOG_TARGET_KMSG
) {
266 va_start(ap
, format
);
267 written
= write_to_kmsg(level
, file
, line
, func
, format
, ap
) >= 0;
269 } else if (log_target
== LOG_TARGET_SYSLOG
) {
270 va_start(ap
, format
);
271 written
= write_to_syslog(level
, file
, line
, func
, format
, ap
) >= 0;
276 va_start(ap
, format
);
277 write_to_console(level
, file
, line
, func
, format
, ap
);
284 int log_set_target_from_string(const char *e
) {
287 if ((t
= log_target_from_string(e
)) < 0)
294 int log_set_max_level_from_string(const char *e
) {
297 if ((t
= log_level_from_string(e
)) < 0)
300 log_set_max_level(t
);
304 void log_parse_environment(void) {
307 if ((e
= getenv("SYSTEMD_LOG_TARGET")))
308 if (log_set_target_from_string(e
) < 0)
309 log_warning("Failed to parse log target %s. Ignoring.", e
);
311 if ((e
= getenv("SYSTEMD_LOG_LEVEL")))
312 if (log_set_max_level_from_string(e
) < 0)
313 log_warning("Failed to parse log level %s. Ignoring.", e
);
316 LogTarget
log_get_target(void) {
320 int log_get_max_level(void) {
321 return log_max_level
;
324 static const char *const log_target_table
[] = {
325 [LOG_TARGET_CONSOLE
] = "console",
326 [LOG_TARGET_SYSLOG
] = "syslog",
327 [LOG_TARGET_KMSG
] = "kmsg",
330 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);