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