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/>.
27 #include <sys/socket.h>
35 #define SNDBUF_SIZE (8*1024*1024)
37 static LogTarget log_target
= LOG_TARGET_CONSOLE
;
38 static int log_max_level
= LOG_WARNING
;
39 static int log_facility
= LOG_DAEMON
;
41 static int console_fd
= STDERR_FILENO
;
43 static bool show_location
= false;
45 /* Akin to glibc's __abort_msg; which is private and we hence cannot
47 static char *log_abort_msg
= NULL
;
49 void log_close_console(void) {
56 close_nointr_nofail(console_fd
);
62 static int log_open_console(void) {
69 console_fd
= open_terminal("/dev/console", O_WRONLY
|O_NOCTTY
|O_CLOEXEC
);
71 log_error("Failed to open /dev/console for logging: %s", strerror(-console_fd
));
75 log_debug("Successfully opened /dev/console for logging.");
77 console_fd
= STDERR_FILENO
;
84 return log_open_console();
88 void log_close(void) {
93 void log_set_max_level(int level
) {
94 assert((level
& LOG_PRIMASK
) == level
);
96 log_max_level
= level
;
99 void log_set_facility(int facility
) {
100 log_facility
= facility
;
103 static int write_to_console(
108 const char *buffer
) {
111 struct iovec iovec
[5];
119 IOVEC_SET_STRING(iovec
[n
++], "dracut-install: ");
122 snprintf(location
, sizeof(location
), "(%s:%u) ", file
, line
);
123 IOVEC_SET_STRING(iovec
[n
++], location
);
126 IOVEC_SET_STRING(iovec
[n
++], buffer
);
127 IOVEC_SET_STRING(iovec
[n
++], "\n");
129 if (writev(console_fd
, iovec
, n
) < 0)
135 static int log_dispatch(
144 if (log_target
== LOG_TARGET_NULL
)
147 /* Patch in LOG_DAEMON facility if necessary */
148 if ((level
& LOG_FACMASK
) == 0)
149 level
= log_facility
| LOG_PRI(level
);
155 buffer
+= strspn(buffer
, NEWLINE
);
160 if ((e
= strpbrk(buffer
, NEWLINE
)))
163 k
= write_to_console(level
, file
, line
, func
, buffer
);
180 char buffer
[LINE_MAX
];
183 if (_likely_(LOG_PRI(level
) > log_max_level
))
187 vsnprintf(buffer
, sizeof(buffer
), format
, ap
);
188 char_array_0(buffer
);
190 r
= log_dispatch(level
, file
, line
, func
, buffer
);
201 const char *format
, ...) {
206 va_start(ap
, format
);
207 r
= log_metav(level
, file
, line
, func
, format
, ap
);
213 #pragma GCC diagnostic push
214 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
215 _noreturn_
static void log_assert(const char *text
, const char *file
, int line
, const char *func
, const char *format
) {
216 static char buffer
[LINE_MAX
];
218 snprintf(buffer
, sizeof(buffer
), format
, text
, file
, line
, func
);
220 char_array_0(buffer
);
221 log_abort_msg
= buffer
;
223 log_dispatch(LOG_CRIT
, file
, line
, func
, buffer
);
226 #pragma GCC diagnostic pop
228 _noreturn_
void log_assert_failed(const char *text
, const char *file
, int line
, const char *func
) {
229 log_assert(text
, file
, line
, func
, "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
232 _noreturn_
void log_assert_failed_unreachable(const char *text
, const char *file
, int line
, const char *func
) {
233 log_assert(text
, file
, line
, func
, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
236 void log_set_target(LogTarget target
) {
238 assert(target
< _LOG_TARGET_MAX
);
243 int log_set_target_from_string(const char *e
) {
246 t
= log_target_from_string(e
);
254 int log_set_max_level_from_string(const char *e
) {
257 t
= log_level_from_string(e
);
261 log_set_max_level(t
);
265 void log_parse_environment(void) {
268 if ((e
= getenv("DRACUT_LOG_TARGET")))
269 if (log_set_target_from_string(e
) < 0)
270 log_warning("Failed to parse log target %s. Ignoring.", e
);
272 if ((e
= getenv("DRACUT_LOG_LEVEL")))
273 if (log_set_max_level_from_string(e
) < 0)
274 log_warning("Failed to parse log level %s. Ignoring.", e
);
278 LogTarget
log_get_target(void) {
282 int log_get_max_level(void) {
283 return log_max_level
;
287 static const char *const log_target_table
[] = {
288 [LOG_TARGET_CONSOLE
] = "console",
289 [LOG_TARGET_AUTO
] = "auto",
290 [LOG_TARGET_SAFE
] = "safe",
291 [LOG_TARGET_NULL
] = "null"
294 DEFINE_STRING_TABLE_LOOKUP(log_target
, LogTarget
);