]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/log.c
basic/log: add an assert that does not recurse into logging functions
[thirdparty/systemd.git] / src / basic / log.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <inttypes.h>
24 #include <limits.h>
25 #include <stdarg.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/signalfd.h>
30 #include <sys/socket.h>
31 #include <sys/time.h>
32 #include <sys/uio.h>
33 #include <sys/un.h>
34 #include <time.h>
35 #include <unistd.h>
36
37 #include "sd-messages.h"
38
39 #include "alloc-util.h"
40 #include "fd-util.h"
41 #include "format-util.h"
42 #include "io-util.h"
43 #include "log.h"
44 #include "macro.h"
45 #include "missing.h"
46 #include "parse-util.h"
47 #include "proc-cmdline.h"
48 #include "process-util.h"
49 #include "signal-util.h"
50 #include "socket-util.h"
51 #include "stdio-util.h"
52 #include "string-table.h"
53 #include "string-util.h"
54 #include "syslog-util.h"
55 #include "terminal-util.h"
56 #include "time-util.h"
57 #include "utf8.h"
58 #include "util.h"
59
60 #define SNDBUF_SIZE (8*1024*1024)
61
62 static LogTarget log_target = LOG_TARGET_CONSOLE;
63 static int log_max_level[] = {LOG_INFO, LOG_INFO};
64 assert_cc(ELEMENTSOF(log_max_level) == _LOG_REALM_MAX);
65 static int log_facility = LOG_DAEMON;
66
67 static int console_fd = STDERR_FILENO;
68 static int syslog_fd = -1;
69 static int kmsg_fd = -1;
70 static int journal_fd = -1;
71
72 static bool syslog_is_stream = false;
73
74 static bool show_color = false;
75 static bool show_location = false;
76
77 static bool upgrade_syslog_to_journal = false;
78 static bool always_reopen_console = false;
79 static bool open_when_needed = false;
80 static bool prohibit_ipc = false;
81
82 /* Akin to glibc's __abort_msg; which is private and we hence cannot
83 * use here. */
84 static char *log_abort_msg = NULL;
85
86 /* An assert to use in logging functions that does not call recursively
87 * into our logging functions (since that might lead to a loop). */
88 #define assert_raw(expr) \
89 do { \
90 if (_unlikely_(!(expr))) { \
91 fputs(#expr "\n", stderr); \
92 abort(); \
93 } \
94 } while (false)
95
96 static void log_close_console(void) {
97
98 if (console_fd < 0)
99 return;
100
101 if (console_fd >= 3)
102 safe_close(console_fd);
103
104 console_fd = -1;
105 }
106
107 static int log_open_console(void) {
108
109 if (!always_reopen_console) {
110 console_fd = STDERR_FILENO;
111 return 0;
112 }
113
114 if (console_fd < 3) {
115 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
116 if (console_fd < 0)
117 return console_fd;
118
119 console_fd = fd_move_above_stdio(console_fd);
120 }
121
122 return 0;
123 }
124
125 static void log_close_kmsg(void) {
126 kmsg_fd = safe_close(kmsg_fd);
127 }
128
129 static int log_open_kmsg(void) {
130
131 if (kmsg_fd >= 0)
132 return 0;
133
134 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
135 if (kmsg_fd < 0)
136 return -errno;
137
138 kmsg_fd = fd_move_above_stdio(kmsg_fd);
139 return 0;
140 }
141
142 static void log_close_syslog(void) {
143 syslog_fd = safe_close(syslog_fd);
144 }
145
146 static int create_log_socket(int type) {
147 struct timeval tv;
148 int fd;
149
150 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
151 if (fd < 0)
152 return -errno;
153
154 fd = fd_move_above_stdio(fd);
155 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
156
157 /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
158 * in the unlikely case of a deadlock. */
159 if (getpid_cached() == 1)
160 timeval_store(&tv, 10 * USEC_PER_MSEC);
161 else
162 timeval_store(&tv, 10 * USEC_PER_SEC);
163 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
164
165 return fd;
166 }
167
168 static int log_open_syslog(void) {
169
170 static const union sockaddr_union sa = {
171 .un.sun_family = AF_UNIX,
172 .un.sun_path = "/dev/log",
173 };
174
175 int r;
176
177 if (syslog_fd >= 0)
178 return 0;
179
180 syslog_fd = create_log_socket(SOCK_DGRAM);
181 if (syslog_fd < 0) {
182 r = syslog_fd;
183 goto fail;
184 }
185
186 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
187 safe_close(syslog_fd);
188
189 /* Some legacy syslog systems still use stream
190 * sockets. They really shouldn't. But what can we
191 * do... */
192 syslog_fd = create_log_socket(SOCK_STREAM);
193 if (syslog_fd < 0) {
194 r = syslog_fd;
195 goto fail;
196 }
197
198 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
199 r = -errno;
200 goto fail;
201 }
202
203 syslog_is_stream = true;
204 } else
205 syslog_is_stream = false;
206
207 return 0;
208
209 fail:
210 log_close_syslog();
211 return r;
212 }
213
214 static void log_close_journal(void) {
215 journal_fd = safe_close(journal_fd);
216 }
217
218 static int log_open_journal(void) {
219
220 static const union sockaddr_union sa = {
221 .un.sun_family = AF_UNIX,
222 .un.sun_path = "/run/systemd/journal/socket",
223 };
224
225 int r;
226
227 if (journal_fd >= 0)
228 return 0;
229
230 journal_fd = create_log_socket(SOCK_DGRAM);
231 if (journal_fd < 0) {
232 r = journal_fd;
233 goto fail;
234 }
235
236 if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
237 r = -errno;
238 goto fail;
239 }
240
241 return 0;
242
243 fail:
244 log_close_journal();
245 return r;
246 }
247
248 int log_open(void) {
249 int r;
250
251 /* Do not call from library code. */
252
253 /* If we don't use the console we close it here, to not get
254 * killed by SAK. If we don't use syslog we close it here so
255 * that we are not confused by somebody deleting the socket in
256 * the fs, and to make sure we don't use it if prohibit_ipc is
257 * set. If we don't use /dev/kmsg we still keep it open,
258 * because there is no reason to close it. */
259
260 if (log_target == LOG_TARGET_NULL) {
261 log_close_journal();
262 log_close_syslog();
263 log_close_console();
264 return 0;
265 }
266
267 if (log_target != LOG_TARGET_AUTO ||
268 getpid_cached() == 1 ||
269 isatty(STDERR_FILENO) <= 0) {
270
271 if (!prohibit_ipc &&
272 IN_SET(log_target, LOG_TARGET_AUTO,
273 LOG_TARGET_JOURNAL_OR_KMSG,
274 LOG_TARGET_JOURNAL)) {
275 r = log_open_journal();
276 if (r >= 0) {
277 log_close_syslog();
278 log_close_console();
279 return r;
280 }
281 }
282
283 if (!prohibit_ipc &&
284 IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
285 LOG_TARGET_SYSLOG)) {
286 r = log_open_syslog();
287 if (r >= 0) {
288 log_close_journal();
289 log_close_console();
290 return r;
291 }
292 }
293
294 if (IN_SET(log_target, LOG_TARGET_AUTO,
295 LOG_TARGET_JOURNAL_OR_KMSG,
296 LOG_TARGET_SYSLOG_OR_KMSG,
297 LOG_TARGET_KMSG)) {
298 r = log_open_kmsg();
299 if (r >= 0) {
300 log_close_journal();
301 log_close_syslog();
302 log_close_console();
303 return r;
304 }
305 }
306 }
307
308 log_close_journal();
309 log_close_syslog();
310
311 return log_open_console();
312 }
313
314 void log_set_target(LogTarget target) {
315 assert(target >= 0);
316 assert(target < _LOG_TARGET_MAX);
317
318 if (upgrade_syslog_to_journal) {
319 if (target == LOG_TARGET_SYSLOG)
320 target = LOG_TARGET_JOURNAL;
321 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
322 target = LOG_TARGET_JOURNAL_OR_KMSG;
323 }
324
325 log_target = target;
326 }
327
328 void log_close(void) {
329 /* Do not call from library code. */
330
331 log_close_journal();
332 log_close_syslog();
333 log_close_kmsg();
334 log_close_console();
335 }
336
337 void log_forget_fds(void) {
338 /* Do not call from library code. */
339
340 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
341 }
342
343 void log_set_max_level_realm(LogRealm realm, int level) {
344 assert((level & LOG_PRIMASK) == level);
345 assert(realm < ELEMENTSOF(log_max_level));
346
347 log_max_level[realm] = level;
348 }
349
350 void log_set_facility(int facility) {
351 log_facility = facility;
352 }
353
354 static int write_to_console(
355 int level,
356 int error,
357 const char *file,
358 int line,
359 const char *func,
360 const char *buffer) {
361
362 char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
363 struct iovec iovec[6] = {};
364 unsigned n = 0;
365 bool highlight;
366
367 if (console_fd < 0)
368 return 0;
369
370 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
371 xsprintf(prefix, "<%i>", level);
372 iovec[n++] = IOVEC_MAKE_STRING(prefix);
373 }
374
375 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
376
377 if (show_location) {
378 (void) snprintf(location, sizeof location, "(%s:%i) ", file, line);
379 iovec[n++] = IOVEC_MAKE_STRING(location);
380 }
381
382 if (highlight)
383 iovec[n++] = IOVEC_MAKE_STRING(ANSI_HIGHLIGHT_RED);
384 iovec[n++] = IOVEC_MAKE_STRING(buffer);
385 if (highlight)
386 iovec[n++] = IOVEC_MAKE_STRING(ANSI_NORMAL);
387 iovec[n++] = IOVEC_MAKE_STRING("\n");
388
389 if (writev(console_fd, iovec, n) < 0) {
390
391 if (errno == EIO && getpid_cached() == 1) {
392
393 /* If somebody tried to kick us from our
394 * console tty (via vhangup() or suchlike),
395 * try to reconnect */
396
397 log_close_console();
398 log_open_console();
399
400 if (console_fd < 0)
401 return 0;
402
403 if (writev(console_fd, iovec, n) < 0)
404 return -errno;
405 } else
406 return -errno;
407 }
408
409 return 1;
410 }
411
412 static int write_to_syslog(
413 int level,
414 int error,
415 const char *file,
416 int line,
417 const char *func,
418 const char *buffer) {
419
420 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
421 header_time[64],
422 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
423 struct iovec iovec[5] = {};
424 struct msghdr msghdr = {
425 .msg_iov = iovec,
426 .msg_iovlen = ELEMENTSOF(iovec),
427 };
428 time_t t;
429 struct tm *tm;
430
431 if (syslog_fd < 0)
432 return 0;
433
434 xsprintf(header_priority, "<%i>", level);
435
436 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
437 tm = localtime(&t);
438 if (!tm)
439 return -EINVAL;
440
441 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
442 return -EINVAL;
443
444 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
445
446 iovec[0] = IOVEC_MAKE_STRING(header_priority);
447 iovec[1] = IOVEC_MAKE_STRING(header_time);
448 iovec[2] = IOVEC_MAKE_STRING(program_invocation_short_name);
449 iovec[3] = IOVEC_MAKE_STRING(header_pid);
450 iovec[4] = IOVEC_MAKE_STRING(buffer);
451
452 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
453 if (syslog_is_stream)
454 iovec[4].iov_len++;
455
456 for (;;) {
457 ssize_t n;
458
459 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
460 if (n < 0)
461 return -errno;
462
463 if (!syslog_is_stream ||
464 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
465 break;
466
467 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
468 }
469
470 return 1;
471 }
472
473 static int write_to_kmsg(
474 int level,
475 int error,
476 const char *file,
477 int line,
478 const char *func,
479 const char *buffer) {
480
481 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
482 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
483 struct iovec iovec[5] = {};
484
485 if (kmsg_fd < 0)
486 return 0;
487
488 xsprintf(header_priority, "<%i>", level);
489 xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
490
491 iovec[0] = IOVEC_MAKE_STRING(header_priority);
492 iovec[1] = IOVEC_MAKE_STRING(program_invocation_short_name);
493 iovec[2] = IOVEC_MAKE_STRING(header_pid);
494 iovec[3] = IOVEC_MAKE_STRING(buffer);
495 iovec[4] = IOVEC_MAKE_STRING("\n");
496
497 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
498 return -errno;
499
500 return 1;
501 }
502
503 static int log_do_header(
504 char *header,
505 size_t size,
506 int level,
507 int error,
508 const char *file, int line, const char *func,
509 const char *object_field, const char *object,
510 const char *extra_field, const char *extra) {
511 int r;
512
513 r = snprintf(header, size,
514 "PRIORITY=%i\n"
515 "SYSLOG_FACILITY=%i\n"
516 "%s%.256s%s" /* CODE_FILE */
517 "%s%.*i%s" /* CODE_LINE */
518 "%s%.256s%s" /* CODE_FUNC */
519 "%s%.*i%s" /* ERRNO */
520 "%s%.256s%s" /* object */
521 "%s%.256s%s" /* extra */
522 "SYSLOG_IDENTIFIER=%.256s\n",
523 LOG_PRI(level),
524 LOG_FAC(level),
525 isempty(file) ? "" : "CODE_FILE=",
526 isempty(file) ? "" : file,
527 isempty(file) ? "" : "\n",
528 line ? "CODE_LINE=" : "",
529 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
530 line ? "\n" : "",
531 isempty(func) ? "" : "CODE_FUNC=",
532 isempty(func) ? "" : func,
533 isempty(func) ? "" : "\n",
534 error ? "ERRNO=" : "",
535 error ? 1 : 0, error,
536 error ? "\n" : "",
537 isempty(object) ? "" : object_field,
538 isempty(object) ? "" : object,
539 isempty(object) ? "" : "\n",
540 isempty(extra) ? "" : extra_field,
541 isempty(extra) ? "" : extra,
542 isempty(extra) ? "" : "\n",
543 program_invocation_short_name);
544 assert_raw((size_t) r < size);
545
546 return 0;
547 }
548
549 static int write_to_journal(
550 int level,
551 int error,
552 const char *file,
553 int line,
554 const char *func,
555 const char *object_field,
556 const char *object,
557 const char *extra_field,
558 const char *extra,
559 const char *buffer) {
560
561 char header[LINE_MAX];
562 struct iovec iovec[4] = {};
563 struct msghdr mh = {};
564
565 if (journal_fd < 0)
566 return 0;
567
568 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
569
570 iovec[0] = IOVEC_MAKE_STRING(header);
571 iovec[1] = IOVEC_MAKE_STRING("MESSAGE=");
572 iovec[2] = IOVEC_MAKE_STRING(buffer);
573 iovec[3] = IOVEC_MAKE_STRING("\n");
574
575 mh.msg_iov = iovec;
576 mh.msg_iovlen = ELEMENTSOF(iovec);
577
578 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
579 return -errno;
580
581 return 1;
582 }
583
584 int log_dispatch_internal(
585 int level,
586 int error,
587 const char *file,
588 int line,
589 const char *func,
590 const char *object_field,
591 const char *object,
592 const char *extra_field,
593 const char *extra,
594 char *buffer) {
595
596 assert_raw(buffer);
597
598 if (error < 0)
599 error = -error;
600
601 if (log_target == LOG_TARGET_NULL)
602 return -error;
603
604 /* Patch in LOG_DAEMON facility if necessary */
605 if ((level & LOG_FACMASK) == 0)
606 level = log_facility | LOG_PRI(level);
607
608 if (open_when_needed)
609 log_open();
610
611 do {
612 char *e;
613 int k = 0;
614
615 buffer += strspn(buffer, NEWLINE);
616
617 if (buffer[0] == 0)
618 break;
619
620 if ((e = strpbrk(buffer, NEWLINE)))
621 *(e++) = 0;
622
623 if (IN_SET(log_target, LOG_TARGET_AUTO,
624 LOG_TARGET_JOURNAL_OR_KMSG,
625 LOG_TARGET_JOURNAL)) {
626
627 k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
628 if (k < 0 && k != -EAGAIN)
629 log_close_journal();
630 }
631
632 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
633 LOG_TARGET_SYSLOG)) {
634
635 k = write_to_syslog(level, error, file, line, func, buffer);
636 if (k < 0 && k != -EAGAIN)
637 log_close_syslog();
638 }
639
640 if (k <= 0 &&
641 IN_SET(log_target, LOG_TARGET_AUTO,
642 LOG_TARGET_SYSLOG_OR_KMSG,
643 LOG_TARGET_JOURNAL_OR_KMSG,
644 LOG_TARGET_KMSG)) {
645
646 if (k < 0)
647 log_open_kmsg();
648
649 k = write_to_kmsg(level, error, file, line, func, buffer);
650 if (k < 0) {
651 log_close_kmsg();
652 log_open_console();
653 }
654 }
655
656 if (k <= 0)
657 (void) write_to_console(level, error, file, line, func, buffer);
658
659 buffer = e;
660 } while (buffer);
661
662 if (open_when_needed)
663 log_close();
664
665 return -error;
666 }
667
668 int log_dump_internal(
669 int level,
670 int error,
671 const char *file,
672 int line,
673 const char *func,
674 char *buffer) {
675
676 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
677 PROTECT_ERRNO;
678
679 /* This modifies the buffer... */
680
681 if (error < 0)
682 error = -error;
683
684 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
685 return -error;
686
687 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
688 }
689
690 int log_internalv_realm(
691 int level,
692 int error,
693 const char *file,
694 int line,
695 const char *func,
696 const char *format,
697 va_list ap) {
698
699 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
700 char buffer[LINE_MAX];
701 PROTECT_ERRNO;
702
703 if (error < 0)
704 error = -error;
705
706 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
707 return -error;
708
709 /* Make sure that %m maps to the specified error */
710 if (error != 0)
711 errno = error;
712
713 (void) vsnprintf(buffer, sizeof buffer, format, ap);
714
715 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
716 }
717
718 int log_internal_realm(
719 int level,
720 int error,
721 const char *file,
722 int line,
723 const char *func,
724 const char *format, ...) {
725
726 va_list ap;
727 int r;
728
729 va_start(ap, format);
730 r = log_internalv_realm(level, error, file, line, func, format, ap);
731 va_end(ap);
732
733 return r;
734 }
735
736 _printf_(10,0)
737 static int log_object_internalv(
738 int level,
739 int error,
740 const char *file,
741 int line,
742 const char *func,
743 const char *object_field,
744 const char *object,
745 const char *extra_field,
746 const char *extra,
747 const char *format,
748 va_list ap) {
749
750 PROTECT_ERRNO;
751 char *buffer, *b;
752
753 if (error < 0)
754 error = -error;
755
756 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
757 return -error;
758
759 /* Make sure that %m maps to the specified error */
760 if (error != 0)
761 errno = error;
762
763 /* Prepend the object name before the message */
764 if (object) {
765 size_t n;
766
767 n = strlen(object);
768 buffer = newa(char, n + 2 + LINE_MAX);
769 b = stpcpy(stpcpy(buffer, object), ": ");
770 } else
771 b = buffer = newa(char, LINE_MAX);
772
773 (void) vsnprintf(b, LINE_MAX, format, ap);
774
775 return log_dispatch_internal(level, error, file, line, func,
776 object_field, object, extra_field, extra, buffer);
777 }
778
779 int log_object_internal(
780 int level,
781 int error,
782 const char *file,
783 int line,
784 const char *func,
785 const char *object_field,
786 const char *object,
787 const char *extra_field,
788 const char *extra,
789 const char *format, ...) {
790
791 va_list ap;
792 int r;
793
794 va_start(ap, format);
795 r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
796 va_end(ap);
797
798 return r;
799 }
800
801 static void log_assert(
802 int level,
803 const char *text,
804 const char *file,
805 int line,
806 const char *func,
807 const char *format) {
808
809 static char buffer[LINE_MAX];
810 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
811
812 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
813 return;
814
815 DISABLE_WARNING_FORMAT_NONLITERAL;
816 (void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
817 REENABLE_WARNING;
818
819 log_abort_msg = buffer;
820
821 log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
822 }
823
824 noreturn void log_assert_failed_realm(
825 LogRealm realm,
826 const char *text,
827 const char *file,
828 int line,
829 const char *func) {
830 log_open();
831 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
832 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
833 abort();
834 }
835
836 noreturn void log_assert_failed_unreachable_realm(
837 LogRealm realm,
838 const char *text,
839 const char *file,
840 int line,
841 const char *func) {
842 log_open();
843 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
844 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
845 abort();
846 }
847
848 void log_assert_failed_return_realm(
849 LogRealm realm,
850 const char *text,
851 const char *file,
852 int line,
853 const char *func) {
854 PROTECT_ERRNO;
855 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
856 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
857 }
858
859 int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
860 return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
861 ENOMEM, file, line, func, "Out of memory.");
862 }
863
864 int log_format_iovec(
865 struct iovec *iovec,
866 size_t iovec_len,
867 size_t *n,
868 bool newline_separator,
869 int error,
870 const char *format,
871 va_list ap) {
872
873 static const char nl = '\n';
874
875 while (format && *n + 1 < iovec_len) {
876 va_list aq;
877 char *m;
878 int r;
879
880 /* We need to copy the va_list structure,
881 * since vasprintf() leaves it afterwards at
882 * an undefined location */
883
884 if (error != 0)
885 errno = error;
886
887 va_copy(aq, ap);
888 r = vasprintf(&m, format, aq);
889 va_end(aq);
890 if (r < 0)
891 return -EINVAL;
892
893 /* Now, jump enough ahead, so that we point to
894 * the next format string */
895 VA_FORMAT_ADVANCE(format, ap);
896
897 iovec[(*n)++] = IOVEC_MAKE_STRING(m);
898
899 if (newline_separator) {
900 iovec[*n].iov_base = (char*) &nl;
901 iovec[*n].iov_len = 1;
902 (*n)++;
903 }
904
905 format = va_arg(ap, char *);
906 }
907 return 0;
908 }
909
910 int log_struct_internal(
911 int level,
912 int error,
913 const char *file,
914 int line,
915 const char *func,
916 const char *format, ...) {
917
918 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
919 char buf[LINE_MAX];
920 bool found = false;
921 PROTECT_ERRNO;
922 va_list ap;
923
924 if (error < 0)
925 error = -error;
926
927 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
928 return -error;
929
930 if (log_target == LOG_TARGET_NULL)
931 return -error;
932
933 if ((level & LOG_FACMASK) == 0)
934 level = log_facility | LOG_PRI(level);
935
936 if (IN_SET(log_target,
937 LOG_TARGET_AUTO,
938 LOG_TARGET_JOURNAL_OR_KMSG,
939 LOG_TARGET_JOURNAL)) {
940
941 if (open_when_needed)
942 log_open_journal();
943
944 if (journal_fd >= 0) {
945 char header[LINE_MAX];
946 struct iovec iovec[17] = {};
947 size_t n = 0, i;
948 int r;
949 struct msghdr mh = {
950 .msg_iov = iovec,
951 };
952 bool fallback = false;
953
954 /* If the journal is available do structured logging */
955 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
956 iovec[n++] = IOVEC_MAKE_STRING(header);
957
958 va_start(ap, format);
959 r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
960 if (r < 0)
961 fallback = true;
962 else {
963 mh.msg_iovlen = n;
964 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
965 }
966
967 va_end(ap);
968 for (i = 1; i < n; i += 2)
969 free(iovec[i].iov_base);
970
971 if (!fallback) {
972 if (open_when_needed)
973 log_close();
974
975 return -error;
976 }
977 }
978 }
979
980 /* Fallback if journal logging is not available or didn't work. */
981
982 va_start(ap, format);
983 while (format) {
984 va_list aq;
985
986 if (error != 0)
987 errno = error;
988
989 va_copy(aq, ap);
990 (void) vsnprintf(buf, sizeof buf, format, aq);
991 va_end(aq);
992
993 if (startswith(buf, "MESSAGE=")) {
994 found = true;
995 break;
996 }
997
998 VA_FORMAT_ADVANCE(format, ap);
999
1000 format = va_arg(ap, char *);
1001 }
1002 va_end(ap);
1003
1004 if (!found) {
1005 if (open_when_needed)
1006 log_close();
1007
1008 return -error;
1009 }
1010
1011 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
1012 }
1013
1014 int log_struct_iovec_internal(
1015 int level,
1016 int error,
1017 const char *file,
1018 int line,
1019 const char *func,
1020 const struct iovec input_iovec[],
1021 size_t n_input_iovec) {
1022
1023 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
1024 PROTECT_ERRNO;
1025 size_t i;
1026 char *m;
1027
1028 if (error < 0)
1029 error = -error;
1030
1031 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
1032 return -error;
1033
1034 if (log_target == LOG_TARGET_NULL)
1035 return -error;
1036
1037 if ((level & LOG_FACMASK) == 0)
1038 level = log_facility | LOG_PRI(level);
1039
1040 if (IN_SET(log_target, LOG_TARGET_AUTO,
1041 LOG_TARGET_JOURNAL_OR_KMSG,
1042 LOG_TARGET_JOURNAL) &&
1043 journal_fd >= 0) {
1044
1045 struct iovec iovec[1 + n_input_iovec*2];
1046 char header[LINE_MAX];
1047 struct msghdr mh = {
1048 .msg_iov = iovec,
1049 .msg_iovlen = 1 + n_input_iovec*2,
1050 };
1051
1052 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
1053 iovec[0] = IOVEC_MAKE_STRING(header);
1054
1055 for (i = 0; i < n_input_iovec; i++) {
1056 iovec[1+i*2] = input_iovec[i];
1057 iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
1058 }
1059
1060 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0)
1061 return -error;
1062 }
1063
1064 for (i = 0; i < n_input_iovec; i++) {
1065 if (input_iovec[i].iov_len < STRLEN("MESSAGE="))
1066 continue;
1067
1068 if (memcmp(input_iovec[i].iov_base, "MESSAGE=", STRLEN("MESSAGE=")) == 0)
1069 break;
1070 }
1071
1072 if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
1073 return -error;
1074
1075 m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
1076 input_iovec[i].iov_len - STRLEN("MESSAGE="));
1077
1078 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
1079 }
1080
1081 int log_set_target_from_string(const char *e) {
1082 LogTarget t;
1083
1084 t = log_target_from_string(e);
1085 if (t < 0)
1086 return -EINVAL;
1087
1088 log_set_target(t);
1089 return 0;
1090 }
1091
1092 int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
1093 int t;
1094
1095 t = log_level_from_string(e);
1096 if (t < 0)
1097 return -EINVAL;
1098
1099 log_set_max_level_realm(realm, t);
1100 return 0;
1101 }
1102
1103 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
1104
1105 /*
1106 * The systemd.log_xyz= settings are parsed by all tools, and
1107 * so is "debug".
1108 *
1109 * However, "quiet" is only parsed by PID 1, and only turns of
1110 * status output to /dev/console, but does not alter the log
1111 * level.
1112 */
1113
1114 if (streq(key, "debug") && !value)
1115 log_set_max_level(LOG_DEBUG);
1116
1117 else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1118
1119 if (proc_cmdline_value_missing(key, value))
1120 return 0;
1121
1122 if (log_set_target_from_string(value) < 0)
1123 log_warning("Failed to parse log target '%s'. Ignoring.", value);
1124
1125 } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1126
1127 if (proc_cmdline_value_missing(key, value))
1128 return 0;
1129
1130 if (log_set_max_level_from_string(value) < 0)
1131 log_warning("Failed to parse log level '%s'. Ignoring.", value);
1132
1133 } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
1134
1135 if (log_show_color_from_string(value ?: "1") < 0)
1136 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1137
1138 } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
1139
1140 if (log_show_location_from_string(value ?: "1") < 0)
1141 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1142 }
1143
1144 return 0;
1145 }
1146
1147 void log_parse_environment_realm(LogRealm realm) {
1148 /* Do not call from library code. */
1149
1150 const char *e;
1151
1152 if (get_ctty_devnr(0, NULL) < 0)
1153 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1154 user stuff. */
1155 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
1156
1157 e = getenv("SYSTEMD_LOG_TARGET");
1158 if (e && log_set_target_from_string(e) < 0)
1159 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1160
1161 e = getenv("SYSTEMD_LOG_LEVEL");
1162 if (e && log_set_max_level_from_string_realm(realm, e) < 0)
1163 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1164
1165 e = getenv("SYSTEMD_LOG_COLOR");
1166 if (e && log_show_color_from_string(e) < 0)
1167 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1168
1169 e = getenv("SYSTEMD_LOG_LOCATION");
1170 if (e && log_show_location_from_string(e) < 0)
1171 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1172 }
1173
1174 LogTarget log_get_target(void) {
1175 return log_target;
1176 }
1177
1178 int log_get_max_level_realm(LogRealm realm) {
1179 return log_max_level[realm];
1180 }
1181
1182 void log_show_color(bool b) {
1183 show_color = b;
1184 }
1185
1186 bool log_get_show_color(void) {
1187 return show_color;
1188 }
1189
1190 void log_show_location(bool b) {
1191 show_location = b;
1192 }
1193
1194 bool log_get_show_location(void) {
1195 return show_location;
1196 }
1197
1198 int log_show_color_from_string(const char *e) {
1199 int t;
1200
1201 t = parse_boolean(e);
1202 if (t < 0)
1203 return t;
1204
1205 log_show_color(t);
1206 return 0;
1207 }
1208
1209 int log_show_location_from_string(const char *e) {
1210 int t;
1211
1212 t = parse_boolean(e);
1213 if (t < 0)
1214 return t;
1215
1216 log_show_location(t);
1217 return 0;
1218 }
1219
1220 bool log_on_console(void) {
1221 if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1222 LOG_TARGET_CONSOLE_PREFIXED))
1223 return true;
1224
1225 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1226 }
1227
1228 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1229 [LOG_TARGET_CONSOLE] = "console",
1230 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1231 [LOG_TARGET_KMSG] = "kmsg",
1232 [LOG_TARGET_JOURNAL] = "journal",
1233 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1234 [LOG_TARGET_SYSLOG] = "syslog",
1235 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1236 [LOG_TARGET_AUTO] = "auto",
1237 [LOG_TARGET_NULL] = "null",
1238 };
1239
1240 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1241
1242 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1243 assert(si);
1244
1245 if (pid_is_valid(si->ssi_pid)) {
1246 _cleanup_free_ char *p = NULL;
1247
1248 (void) get_process_comm(si->ssi_pid, &p);
1249
1250 log_full(level,
1251 "Received SIG%s from PID %"PRIu32" (%s).",
1252 signal_to_string(si->ssi_signo),
1253 si->ssi_pid, strna(p));
1254 } else
1255 log_full(level,
1256 "Received SIG%s.",
1257 signal_to_string(si->ssi_signo));
1258 }
1259
1260 int log_syntax_internal(
1261 const char *unit,
1262 int level,
1263 const char *config_file,
1264 unsigned config_line,
1265 int error,
1266 const char *file,
1267 int line,
1268 const char *func,
1269 const char *format, ...) {
1270
1271 PROTECT_ERRNO;
1272 char buffer[LINE_MAX];
1273 va_list ap;
1274 const char *unit_fmt = NULL;
1275
1276 if (error < 0)
1277 error = -error;
1278
1279 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
1280 return -error;
1281
1282 if (log_target == LOG_TARGET_NULL)
1283 return -error;
1284
1285 if (error != 0)
1286 errno = error;
1287
1288 va_start(ap, format);
1289 (void) vsnprintf(buffer, sizeof buffer, format, ap);
1290 va_end(ap);
1291
1292 if (unit)
1293 unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1294
1295 return log_struct_internal(
1296 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
1297 error,
1298 file, line, func,
1299 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1300 "CONFIG_FILE=%s", config_file,
1301 "CONFIG_LINE=%u", config_line,
1302 LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
1303 unit_fmt, unit,
1304 NULL);
1305 }
1306
1307 int log_syntax_invalid_utf8_internal(
1308 const char *unit,
1309 int level,
1310 const char *config_file,
1311 unsigned config_line,
1312 const char *file,
1313 int line,
1314 const char *func,
1315 const char *rvalue) {
1316
1317 _cleanup_free_ char *p = NULL;
1318
1319 if (rvalue)
1320 p = utf8_escape_invalid(rvalue);
1321
1322 log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
1323 "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
1324
1325 return -EINVAL;
1326 }
1327
1328 void log_set_upgrade_syslog_to_journal(bool b) {
1329 upgrade_syslog_to_journal = b;
1330
1331 /* Make the change effective immediately */
1332 if (b) {
1333 if (log_target == LOG_TARGET_SYSLOG)
1334 log_target = LOG_TARGET_JOURNAL;
1335 else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
1336 log_target = LOG_TARGET_JOURNAL_OR_KMSG;
1337 }
1338 }
1339
1340 void log_set_always_reopen_console(bool b) {
1341 always_reopen_console = b;
1342 }
1343
1344 void log_set_open_when_needed(bool b) {
1345 open_when_needed = b;
1346 }
1347
1348 void log_set_prohibit_ipc(bool b) {
1349 prohibit_ipc = b;
1350 }
1351
1352 int log_emergency_level(void) {
1353 /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1354 * then the system of the whole system is obviously affected. */
1355
1356 return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;
1357 }