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