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