skipcpio: return something at end of program
[dracut.git] / install / log.c
blob127774f6ae692d569062b9c0000be1b7e6d8ebeb
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
3 /***
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/>.
20 ***/
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <stddef.h>
31 #include "log.h"
32 #include "util.h"
33 #include "macro.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
46 * use here. */
47 static char *log_abort_msg = NULL;
49 void log_close_console(void) {
51 if (console_fd < 0)
52 return;
54 if (getpid() == 1) {
55 if (console_fd >= 3)
56 close_nointr_nofail(console_fd);
58 console_fd = -1;
62 static int log_open_console(void) {
64 if (console_fd >= 0)
65 return 0;
67 if (getpid() == 1) {
69 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
70 if (console_fd < 0) {
71 log_error("Failed to open /dev/console for logging: %s", strerror(-console_fd));
72 return console_fd;
75 log_debug("Successfully opened /dev/console for logging.");
76 } else
77 console_fd = STDERR_FILENO;
79 return 0;
83 int log_open(void) {
84 return log_open_console();
88 void log_close(void) {
89 log_close_console();
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(
104 int level,
105 const char*file,
106 int line,
107 const char *func,
108 const char *buffer) {
110 char location[64];
111 struct iovec iovec[5];
112 unsigned n = 0;
114 if (console_fd < 0)
115 return 0;
117 zero(iovec);
119 IOVEC_SET_STRING(iovec[n++], "dracut-install: ");
121 if (show_location) {
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)
130 return -errno;
132 return 1;
135 static int log_dispatch(
136 int level,
137 const char*file,
138 int line,
139 const char *func,
140 char *buffer) {
142 int r = 0;
144 if (log_target == LOG_TARGET_NULL)
145 return 0;
147 /* Patch in LOG_DAEMON facility if necessary */
148 if ((level & LOG_FACMASK) == 0)
149 level = log_facility | LOG_PRI(level);
151 do {
152 char *e;
153 int k = 0;
155 buffer += strspn(buffer, NEWLINE);
157 if (buffer[0] == 0)
158 break;
160 if ((e = strpbrk(buffer, NEWLINE)))
161 *(e++) = 0;
163 k = write_to_console(level, file, line, func, buffer);
164 if (k < 0)
165 return k;
166 buffer = e;
167 } while (buffer);
169 return r;
172 int log_metav(
173 int level,
174 const char*file,
175 int line,
176 const char *func,
177 const char *format,
178 va_list ap) {
180 char buffer[LINE_MAX];
181 int saved_errno, r;
183 if (_likely_(LOG_PRI(level) > log_max_level))
184 return 0;
186 saved_errno = errno;
187 vsnprintf(buffer, sizeof(buffer), format, ap);
188 char_array_0(buffer);
190 r = log_dispatch(level, file, line, func, buffer);
191 errno = saved_errno;
193 return r;
196 int log_meta(
197 int level,
198 const char*file,
199 int line,
200 const char *func,
201 const char *format, ...) {
203 int r;
204 va_list ap;
206 va_start(ap, format);
207 r = log_metav(level, file, line, func, format, ap);
208 va_end(ap);
210 return r;
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);
224 abort();
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) {
237 assert(target >= 0);
238 assert(target < _LOG_TARGET_MAX);
240 log_target = target;
243 int log_set_target_from_string(const char *e) {
244 LogTarget t;
246 t = log_target_from_string(e);
247 if (t < 0)
248 return -EINVAL;
250 log_set_target(t);
251 return 0;
254 int log_set_max_level_from_string(const char *e) {
255 int t;
257 t = log_level_from_string(e);
258 if (t < 0)
259 return t;
261 log_set_max_level(t);
262 return 0;
265 void log_parse_environment(void) {
266 const char *e;
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) {
279 return log_target;
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);