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