]>
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)
67 void log_close_syslog(void) {
70 close_nointr(syslog_fd
);
75 int log_open_syslog(void) {
78 struct sockaddr_un un
;
83 if (log_target
!= LOG_TARGET_SYSLOG
) {
91 if ((syslog_fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0)) < 0)
94 /* Make sure we don't block for more than 5s when talking to
96 timeval_store(&tv
, SYSLOG_TIMEOUT_USEC
);
97 if (setsockopt(syslog_fd
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
)) < 0) {
104 sa
.un
.sun_family
= AF_UNIX
;
105 strncpy(sa
.un
.sun_path
, "/dev/log", sizeof(sa
.un
.sun_path
));
107 if (connect(syslog_fd
, &sa
.sa
, sizeof(sa
)) < 0) {
116 void log_set_target(LogTarget target
) {
118 assert(target
< _LOG_TARGET_MAX
);
123 void log_set_max_level(int level
) {
124 assert((level
& LOG_PRIMASK
) == level
);
126 log_max_level
= level
;
129 static void write_to_console(
137 const char *prefix
, *suffix
;
139 if (LOG_PRI(level
) <= LOG_ERR
) {
140 prefix
= "\x1B[1;31m";
147 fprintf(stderr
, "(%s:%u) %s", file
, line
, prefix
);
148 vfprintf(stderr
, format
, ap
);
149 fprintf(stderr
, "%s\n", suffix
);
152 static int write_to_syslog(
160 char header_priority
[16], header_time
[64], header_pid
[16];
161 char buffer
[LOG_BUFFER_MAX
];
162 struct iovec iovec
[5];
163 struct msghdr msghdr
;
170 snprintf(header_priority
, sizeof(header_priority
), "<%i>", LOG_MAKEPRI(LOG_DAEMON
, LOG_PRI(level
)));
171 char_array_0(header_priority
);
173 t
= (time_t) (now(CLOCK_REALTIME
) / USEC_PER_SEC
);
174 if (!(tm
= localtime(&t
)))
177 if (strftime(header_time
, sizeof(header_time
), "%h %e %T ", tm
) <= 0)
180 snprintf(header_pid
, sizeof(header_pid
), "[%llu]: ", (unsigned long long) getpid());
181 char_array_0(header_pid
);
183 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
184 char_array_0(buffer
);
187 IOVEC_SET_STRING(iovec
[0], header_priority
);
188 IOVEC_SET_STRING(iovec
[1], header_time
);
189 IOVEC_SET_STRING(iovec
[2], __progname
);
190 IOVEC_SET_STRING(iovec
[3], header_pid
);
191 IOVEC_SET_STRING(iovec
[4], buffer
);
194 msghdr
.msg_iov
= iovec
;
195 msghdr
.msg_iovlen
= ELEMENTSOF(iovec
);
197 if (sendmsg(syslog_fd
, &msghdr
, 0) < 0)
203 static int write_to_kmsg(
211 char header_priority
[16], header_pid
[16];
212 char buffer
[LOG_BUFFER_MAX
];
213 struct iovec iovec
[5];
218 snprintf(header_priority
, sizeof(header_priority
), "<%i>", LOG_PRI(level
));
219 char_array_0(header_priority
);
221 snprintf(header_pid
, sizeof(header_pid
), "[%llu]: ", (unsigned long long) getpid());
222 char_array_0(header_pid
);
224 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
225 char_array_0(buffer
);
228 IOVEC_SET_STRING(iovec
[0], header_priority
);
229 IOVEC_SET_STRING(iovec
[1], __progname
);
230 IOVEC_SET_STRING(iovec
[2], header_pid
);
231 IOVEC_SET_STRING(iovec
[3], buffer
);
232 IOVEC_SET_STRING(iovec
[4], (char*) "\n");
234 if (writev(kmsg_fd
, iovec
, ELEMENTSOF(iovec
)) < 0)
245 const char *format
, ...) {
251 if (LOG_PRI(level
) > log_max_level
)
257 if (log_target
== LOG_TARGET_KMSG
) {
258 va_start(ap
, format
);
259 written
= write_to_kmsg(level
, file
, line
, func
, format
, ap
) >= 0;
261 } else if (log_target
== LOG_TARGET_SYSLOG
) {
262 va_start(ap
, format
);
263 written
= write_to_syslog(level
, file
, line
, func
, format
, ap
) >= 0;
268 va_start(ap
, format
);
269 write_to_console(level
, file
, line
, func
, format
, ap
);
276 int log_set_target_from_string(const char *e
) {
279 if ((t
= log_target_from_string(e
)) < 0)
286 int log_set_max_level_from_string(const char *e
) {
289 if ((t
= log_level_from_string(e
)) < 0)
292 log_set_max_level(t
);
296 void log_parse_environment(void) {
299 if ((e
= getenv("SYSTEMD_LOG_TARGET")))
300 if (log_set_target_from_string(e
) < 0)
301 log_warning("Failed to parse log target %s. Ignoring.", e
);
303 if ((e
= getenv("SYSTEMD_LOG_LEVEL")))
304 if (log_set_max_level_from_string(e
) < 0)
305 log_warning("Failed to parse log level %s. Ignoring.", e
);
308 static const char *const log_target_table
[] = {
309 [LOG_TARGET_CONSOLE
] = "console",
310 [LOG_TARGET_SYSLOG
] = "syslog",
311 [LOG_TARGET_KMSG
] = "kmsg",
314 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);