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