/src/systemd/src/basic/log.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
2 | | #pragma once |
3 | | |
4 | | #include <stdarg.h> |
5 | | #include <stdbool.h> |
6 | | #include <stdlib.h> |
7 | | #include <string.h> |
8 | | #include <syslog.h> |
9 | | |
10 | | #include "macro.h" |
11 | | #include "ratelimit.h" |
12 | | |
13 | | /* Some structures we reference but don't want to pull in headers for */ |
14 | | struct iovec; |
15 | | struct signalfd_siginfo; |
16 | | |
17 | | typedef enum LogTarget{ |
18 | | LOG_TARGET_CONSOLE, |
19 | | LOG_TARGET_CONSOLE_PREFIXED, |
20 | | LOG_TARGET_KMSG, |
21 | | LOG_TARGET_JOURNAL, |
22 | | LOG_TARGET_JOURNAL_OR_KMSG, |
23 | | LOG_TARGET_SYSLOG, |
24 | | LOG_TARGET_SYSLOG_OR_KMSG, |
25 | | LOG_TARGET_AUTO, /* console if stderr is not journal, JOURNAL_OR_KMSG otherwise */ |
26 | | LOG_TARGET_NULL, |
27 | | _LOG_TARGET_MAX, |
28 | | _LOG_TARGET_INVALID = -EINVAL, |
29 | | } LogTarget; |
30 | | |
31 | | /* This log level disables logging completely. It can only be passed to log_set_max_level() and cannot be |
32 | | * used a regular log level. */ |
33 | | #define LOG_NULL (LOG_EMERG - 1) |
34 | | |
35 | | /* Note to readers: << and >> have lower precedence (are evaluated earlier) than & and | */ |
36 | | #define SYNTHETIC_ERRNO(num) (1 << 30 | (num)) |
37 | | #define IS_SYNTHETIC_ERRNO(val) ((val) >> 30 & 1) |
38 | 462k | #define ERRNO_VALUE(val) (abs(val) & ~(1 << 30)) |
39 | | |
40 | | /* The callback function to be invoked when syntax warnings are seen |
41 | | * in the unit files. */ |
42 | | typedef void (*log_syntax_callback_t)(const char *unit, int level, void *userdata); |
43 | | void set_log_syntax_callback(log_syntax_callback_t cb, void *userdata); |
44 | | |
45 | 0 | static inline void clear_log_syntax_callback(dummy_t *dummy) { |
46 | 0 | set_log_syntax_callback(/* cb= */ NULL, /* userdata= */ NULL); |
47 | 0 | } Unexecuted instantiation: fuzz-link-parser.c:clear_log_syntax_callback Unexecuted instantiation: link-config.c:clear_log_syntax_callback Unexecuted instantiation: link-config-gperf.c:clear_log_syntax_callback |
48 | | |
49 | | const char *log_target_to_string(LogTarget target) _const_; |
50 | | LogTarget log_target_from_string(const char *s) _pure_; |
51 | | void log_set_target(LogTarget target); |
52 | | int log_set_target_from_string(const char *e); |
53 | | LogTarget log_get_target(void) _pure_; |
54 | | |
55 | | void log_set_max_level(int level); |
56 | | int log_set_max_level_from_string(const char *e); |
57 | | int log_get_max_level(void) _pure_; |
58 | | |
59 | | void log_set_facility(int facility); |
60 | | |
61 | | void log_show_color(bool b); |
62 | | bool log_get_show_color(void) _pure_; |
63 | | void log_show_location(bool b); |
64 | | bool log_get_show_location(void) _pure_; |
65 | | void log_show_time(bool b); |
66 | | bool log_get_show_time(void) _pure_; |
67 | | void log_show_tid(bool b); |
68 | | bool log_get_show_tid(void) _pure_; |
69 | | |
70 | | int log_show_color_from_string(const char *e); |
71 | | int log_show_location_from_string(const char *e); |
72 | | int log_show_time_from_string(const char *e); |
73 | | int log_show_tid_from_string(const char *e); |
74 | | |
75 | | /* Functions below that open and close logs or configure logging based on the |
76 | | * environment should not be called from library code — this is always a job |
77 | | * for the application itself. */ |
78 | | |
79 | | assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1); |
80 | 0 | #define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1]) |
81 | | |
82 | | int log_open(void); |
83 | | void log_close(void); |
84 | | void log_forget_fds(void); |
85 | | |
86 | | void log_parse_environment_variables(void); |
87 | | void log_parse_environment(void); |
88 | | |
89 | | int log_dispatch_internal( |
90 | | int level, |
91 | | int error, |
92 | | const char *file, |
93 | | int line, |
94 | | const char *func, |
95 | | const char *object_field, |
96 | | const char *object, |
97 | | const char *extra, |
98 | | const char *extra_field, |
99 | | char *buffer); |
100 | | |
101 | | int log_internal( |
102 | | int level, |
103 | | int error, |
104 | | const char *file, |
105 | | int line, |
106 | | const char *func, |
107 | | const char *format, ...) _printf_(6,7); |
108 | | |
109 | | int log_internalv( |
110 | | int level, |
111 | | int error, |
112 | | const char *file, |
113 | | int line, |
114 | | const char *func, |
115 | | const char *format, |
116 | | va_list ap) _printf_(6,0); |
117 | | |
118 | | int log_object_internalv( |
119 | | int level, |
120 | | int error, |
121 | | const char *file, |
122 | | int line, |
123 | | const char *func, |
124 | | const char *object_field, |
125 | | const char *object, |
126 | | const char *extra_field, |
127 | | const char *extra, |
128 | | const char *format, |
129 | | va_list ap) _printf_(10,0); |
130 | | |
131 | | int log_object_internal( |
132 | | int level, |
133 | | int error, |
134 | | const char *file, |
135 | | int line, |
136 | | const char *func, |
137 | | const char *object_field, |
138 | | const char *object, |
139 | | const char *extra_field, |
140 | | const char *extra, |
141 | | const char *format, ...) _printf_(10,11); |
142 | | |
143 | | int log_struct_internal( |
144 | | int level, |
145 | | int error, |
146 | | const char *file, |
147 | | int line, |
148 | | const char *func, |
149 | | const char *format, ...) _printf_(6,0) _sentinel_; |
150 | | |
151 | | int log_oom_internal( |
152 | | int level, |
153 | | const char *file, |
154 | | int line, |
155 | | const char *func); |
156 | | |
157 | | int log_format_iovec( |
158 | | struct iovec *iovec, |
159 | | size_t iovec_len, |
160 | | size_t *n, |
161 | | bool newline_separator, |
162 | | int error, |
163 | | const char *format, |
164 | | va_list ap) _printf_(6, 0); |
165 | | |
166 | | int log_struct_iovec_internal( |
167 | | int level, |
168 | | int error, |
169 | | const char *file, |
170 | | int line, |
171 | | const char *func, |
172 | | const struct iovec *input_iovec, |
173 | | size_t n_input_iovec); |
174 | | |
175 | | /* This modifies the buffer passed! */ |
176 | | int log_dump_internal( |
177 | | int level, |
178 | | int error, |
179 | | const char *file, |
180 | | int line, |
181 | | const char *func, |
182 | | char *buffer); |
183 | | |
184 | | /* Logging for various assertions */ |
185 | | _noreturn_ void log_assert_failed( |
186 | | const char *text, |
187 | | const char *file, |
188 | | int line, |
189 | | const char *func); |
190 | | |
191 | | _noreturn_ void log_assert_failed_unreachable( |
192 | | const char *file, |
193 | | int line, |
194 | | const char *func); |
195 | | |
196 | | void log_assert_failed_return( |
197 | | const char *text, |
198 | | const char *file, |
199 | | int line, |
200 | | const char *func); |
201 | | |
202 | | #define log_dispatch(level, error, buffer) \ |
203 | | log_dispatch_internal(level, error, PROJECT_FILE, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer) |
204 | | |
205 | | /* Logging with level */ |
206 | | #define log_full_errno_zerook(level, error, ...) \ |
207 | 17.0k | ({ \ |
208 | 17.0k | int _level = (level), _e = (error); \ |
209 | 17.0k | _e = (log_get_max_level() >= LOG_PRI(_level)) \ |
210 | 17.0k | ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ |
211 | 17.0k | : -ERRNO_VALUE(_e); \ |
212 | 17.0k | _e < 0 ? _e : -ESTRPIPE; \ |
213 | 17.0k | }) |
214 | | |
215 | | #if BUILD_MODE_DEVELOPER && !defined(TEST_CODE) |
216 | 129 | # define ASSERT_NON_ZERO(x) assert((x) != 0) |
217 | | #else |
218 | | # define ASSERT_NON_ZERO(x) |
219 | | #endif |
220 | | |
221 | | #define log_full_errno(level, error, ...) \ |
222 | 129 | ({ \ |
223 | 129 | int _error = (error); \ |
224 | 129 | ASSERT_NON_ZERO(_error); \ |
225 | 129 | log_full_errno_zerook(level, _error, __VA_ARGS__); \ |
226 | 129 | }) |
227 | | |
228 | | #define log_full(level, fmt, ...) \ |
229 | 16.9k | ({ \ |
230 | 16.9k | if (BUILD_MODE_DEVELOPER) \ |
231 | 16.9k | assert(!strstr(fmt, "%m")); \ |
232 | 16.9k | (void) log_full_errno_zerook(level, 0, fmt, ##__VA_ARGS__); \ |
233 | 16.9k | }) |
234 | | |
235 | | int log_emergency_level(void); |
236 | | |
237 | | /* Normal logging */ |
238 | 8.80k | #define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__) |
239 | 0 | #define log_info(...) log_full(LOG_INFO, __VA_ARGS__) |
240 | | #define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__) |
241 | 8.13k | #define log_warning(...) log_full(LOG_WARNING, __VA_ARGS__) |
242 | | #define log_error(...) log_full(LOG_ERR, __VA_ARGS__) |
243 | | #define log_emergency(...) log_full(log_emergency_level(), __VA_ARGS__) |
244 | | |
245 | | /* Logging triggered by an errno-like error */ |
246 | | #define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__) |
247 | | #define log_info_errno(error, ...) log_full_errno(LOG_INFO, error, __VA_ARGS__) |
248 | | #define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__) |
249 | 129 | #define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__) |
250 | 0 | #define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__) |
251 | | #define log_emergency_errno(error, ...) log_full_errno(log_emergency_level(), error, __VA_ARGS__) |
252 | | |
253 | | /* This logs at the specified level the first time it is called, and then |
254 | | * logs at debug. If the specified level is debug, this logs only the first |
255 | | * time it is called. */ |
256 | | #define log_once(level, ...) \ |
257 | | ({ \ |
258 | | if (ONCE) \ |
259 | | log_full(level, __VA_ARGS__); \ |
260 | | else if (LOG_PRI(level) != LOG_DEBUG) \ |
261 | | log_debug(__VA_ARGS__); \ |
262 | | }) |
263 | | |
264 | | #define log_once_errno(level, error, ...) \ |
265 | | ({ \ |
266 | | int _err = (error); \ |
267 | | if (ONCE) \ |
268 | | _err = log_full_errno(level, _err, __VA_ARGS__); \ |
269 | | else if (LOG_PRI(level) != LOG_DEBUG) \ |
270 | | _err = log_debug_errno(_err, __VA_ARGS__); \ |
271 | | else \ |
272 | | _err = -ERRNO_VALUE(_err); \ |
273 | | _err; \ |
274 | | }) |
275 | | |
276 | | #if LOG_TRACE |
277 | | # define log_trace(...) log_debug(__VA_ARGS__) |
278 | | # define log_trace_errno(...) log_debug_errno(__VA_ARGS__) |
279 | | #else |
280 | | # define log_trace(...) do {} while (0) |
281 | | # define log_trace_errno(e, ...) (-ERRNO_VALUE(e)) |
282 | | #endif |
283 | | |
284 | | /* Structured logging */ |
285 | | #define log_struct_errno(level, error, ...) \ |
286 | | log_struct_internal(level, error, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__, NULL) |
287 | | #define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__) |
288 | | |
289 | | #define log_struct_iovec_errno(level, error, iovec, n_iovec) \ |
290 | | log_struct_iovec_internal(level, error, PROJECT_FILE, __LINE__, __func__, iovec, n_iovec) |
291 | | #define log_struct_iovec(level, iovec, n_iovec) log_struct_iovec_errno(level, 0, iovec, n_iovec) |
292 | | |
293 | | /* This modifies the buffer passed! */ |
294 | | #define log_dump(level, buffer) \ |
295 | | log_dump_internal(level, 0, PROJECT_FILE, __LINE__, __func__, buffer) |
296 | | |
297 | 0 | #define log_oom() log_oom_internal(LOG_ERR, PROJECT_FILE, __LINE__, __func__) |
298 | | #define log_oom_debug() log_oom_internal(LOG_DEBUG, PROJECT_FILE, __LINE__, __func__) |
299 | | |
300 | | bool log_on_console(void) _pure_; |
301 | | |
302 | | /* Helper to wrap the main message in structured logging. The macro doesn't do much, |
303 | | * except to provide visual grouping of the format string and its arguments. */ |
304 | | #if LOG_MESSAGE_VERIFICATION || defined(__COVERITY__) |
305 | | /* Do a fake formatting of the message string to let the scanner verify the arguments against the format |
306 | | * message. The variable will never be set to true, but we don't tell the compiler that :) */ |
307 | | extern bool _log_message_dummy; |
308 | | # define LOG_MESSAGE(fmt, ...) "MESSAGE=%.0d" fmt, (_log_message_dummy && printf(fmt, ##__VA_ARGS__)), ##__VA_ARGS__ |
309 | | #else |
310 | | # define LOG_MESSAGE(fmt, ...) "MESSAGE=" fmt, ##__VA_ARGS__ |
311 | | #endif |
312 | | |
313 | | void log_received_signal(int level, const struct signalfd_siginfo *si); |
314 | | |
315 | | /* If turned on, any requests for a log target involving "syslog" will be implicitly upgraded to the equivalent journal target */ |
316 | | void log_set_upgrade_syslog_to_journal(bool b); |
317 | | |
318 | | /* If turned on, and log_open() is called, we'll not use STDERR_FILENO for logging ever, but rather open /dev/console */ |
319 | | void log_set_always_reopen_console(bool b); |
320 | | |
321 | | /* If turned on, we'll open the log stream implicitly if needed on each individual log call. This is normally not |
322 | | * desired as we want to reuse our logging streams. It is useful however */ |
323 | | void log_set_open_when_needed(bool b); |
324 | | |
325 | | /* If turned on, then we'll never use IPC-based logging, i.e. never log to syslog or the journal. We'll only log to |
326 | | * stderr, the console or kmsg */ |
327 | | void log_set_prohibit_ipc(bool b); |
328 | | |
329 | | int log_dup_console(void); |
330 | | |
331 | | int log_syntax_internal( |
332 | | const char *unit, |
333 | | int level, |
334 | | const char *config_file, |
335 | | unsigned config_line, |
336 | | int error, |
337 | | const char *file, |
338 | | int line, |
339 | | const char *func, |
340 | | const char *format, ...) _printf_(9, 10); |
341 | | |
342 | | int log_syntax_invalid_utf8_internal( |
343 | | const char *unit, |
344 | | int level, |
345 | | const char *config_file, |
346 | | unsigned config_line, |
347 | | const char *file, |
348 | | int line, |
349 | | const char *func, |
350 | | const char *rvalue); |
351 | | |
352 | | #define log_syntax(unit, level, config_file, config_line, error, ...) \ |
353 | 428k | ({ \ |
354 | 428k | int _level = (level), _e = (error); \ |
355 | 428k | (log_get_max_level() >= LOG_PRI(_level)) \ |
356 | 428k | ? log_syntax_internal(unit, _level, config_file, config_line, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ |
357 | 428k | : -ERRNO_VALUE(_e); \ |
358 | 428k | }) |
359 | | |
360 | | #define log_syntax_invalid_utf8(unit, level, config_file, config_line, rvalue) \ |
361 | | ({ \ |
362 | | int _level = (level); \ |
363 | | (log_get_max_level() >= LOG_PRI(_level)) \ |
364 | | ? log_syntax_invalid_utf8_internal(unit, _level, config_file, config_line, PROJECT_FILE, __LINE__, __func__, rvalue) \ |
365 | | : -EINVAL; \ |
366 | | }) |
367 | | |
368 | | #define DEBUG_LOGGING _unlikely_(log_get_max_level() >= LOG_DEBUG) |
369 | | |
370 | | void log_setup(void); |
371 | | |
372 | | typedef struct LogRateLimit { |
373 | | int error; |
374 | | int level; |
375 | | RateLimit ratelimit; |
376 | | } LogRateLimit; |
377 | | |
378 | | #define log_ratelimit_internal(_level, _error, _format, _file, _line, _func, ...) \ |
379 | | ({ \ |
380 | | int _log_ratelimit_error = (_error); \ |
381 | | int _log_ratelimit_level = (_level); \ |
382 | | static LogRateLimit _log_ratelimit = { \ |
383 | | .ratelimit = { \ |
384 | | .interval = 1 * USEC_PER_SEC, \ |
385 | | .burst = 1, \ |
386 | | }, \ |
387 | | }; \ |
388 | | unsigned _num_dropped_errors = ratelimit_num_dropped(&_log_ratelimit.ratelimit); \ |
389 | | if (_log_ratelimit_error != _log_ratelimit.error || _log_ratelimit_level != _log_ratelimit.level) { \ |
390 | | ratelimit_reset(&_log_ratelimit.ratelimit); \ |
391 | | _log_ratelimit.error = _log_ratelimit_error; \ |
392 | | _log_ratelimit.level = _log_ratelimit_level; \ |
393 | | } \ |
394 | | if (ratelimit_below(&_log_ratelimit.ratelimit)) \ |
395 | | _log_ratelimit_error = _num_dropped_errors > 0 \ |
396 | | ? log_internal(_log_ratelimit_level, _log_ratelimit_error, _file, _line, _func, _format " (Dropped %u similar message(s))", __VA_ARGS__, _num_dropped_errors) \ |
397 | | : log_internal(_log_ratelimit_level, _log_ratelimit_error, _file, _line, _func, _format, __VA_ARGS__); \ |
398 | | _log_ratelimit_error; \ |
399 | | }) |
400 | | |
401 | | #define log_ratelimit_full_errno(level, error, format, ...) \ |
402 | | ({ \ |
403 | | int _level = (level), _e = (error); \ |
404 | | _e = (log_get_max_level() >= LOG_PRI(_level)) \ |
405 | | ? log_ratelimit_internal(_level, _e, format, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ |
406 | | : -ERRNO_VALUE(_e); \ |
407 | | _e < 0 ? _e : -ESTRPIPE; \ |
408 | | }) |