chiark / gitweb /
a506d30d3ab7cdae6721f49999f0cd8088775886
[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 (or "Success"). */
755         errno = error;
756
757         /* Prepend the object name before the message */
758         if (object) {
759                 size_t n;
760
761                 n = strlen(object);
762                 buffer = newa(char, n + 2 + LINE_MAX);
763                 b = stpcpy(stpcpy(buffer, object), ": ");
764         } else
765                 b = buffer = newa(char, LINE_MAX);
766
767         (void) vsnprintf(b, LINE_MAX, format, ap);
768
769         return log_dispatch_internal(level, error, file, line, func,
770                                      object_field, object, extra_field, extra, buffer);
771 }
772
773 int log_object_internal(
774                 int level,
775                 int error,
776                 const char *file,
777                 int line,
778                 const char *func,
779                 const char *object_field,
780                 const char *object,
781                 const char *extra_field,
782                 const char *extra,
783                 const char *format, ...) {
784
785         va_list ap;
786         int r;
787
788         va_start(ap, format);
789         r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
790         va_end(ap);
791
792         return r;
793 }
794
795 static void log_assert(
796                 int level,
797                 const char *text,
798                 const char *file,
799                 int line,
800                 const char *func,
801                 const char *format) {
802
803         static char buffer[LINE_MAX];
804         LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
805
806         if (_likely_(LOG_PRI(level) > log_max_level[realm]))
807                 return;
808
809         DISABLE_WARNING_FORMAT_NONLITERAL;
810         (void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
811         REENABLE_WARNING;
812
813         log_abort_msg = buffer;
814
815         log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
816 }
817
818 _noreturn_ void log_assert_failed_realm(
819                 LogRealm realm,
820                 const char *text,
821                 const char *file,
822                 int line,
823                 const char *func) {
824         log_open();
825         log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
826                    "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
827         abort();
828 }
829
830 _noreturn_ void log_assert_failed_unreachable_realm(
831                 LogRealm realm,
832                 const char *text,
833                 const char *file,
834                 int line,
835                 const char *func) {
836         log_open();
837         log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
838                    "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
839         abort();
840 }
841
842 void log_assert_failed_return_realm(
843                 LogRealm realm,
844                 const char *text,
845                 const char *file,
846                 int line,
847                 const char *func) {
848         PROTECT_ERRNO;
849         log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
850                    "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
851 }
852
853 int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
854         return log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
855                                   ENOMEM, file, line, func, "Out of memory.");
856 }
857
858 int log_format_iovec(
859                 struct iovec *iovec,
860                 size_t iovec_len,
861                 size_t *n,
862                 bool newline_separator,
863                 int error,
864                 const char *format,
865                 va_list ap) {
866
867         static const char nl = '\n';
868
869         while (format && *n + 1 < iovec_len) {
870                 va_list aq;
871                 char *m;
872                 int r;
873
874                 /* We need to copy the va_list structure,
875                  * since vasprintf() leaves it afterwards at
876                  * an undefined location */
877
878                 errno = error;
879
880                 va_copy(aq, ap);
881                 r = vasprintf(&m, format, aq);
882                 va_end(aq);
883                 if (r < 0)
884                         return -EINVAL;
885
886                 /* Now, jump enough ahead, so that we point to
887                  * the next format string */
888                 VA_FORMAT_ADVANCE(format, ap);
889
890                 iovec[(*n)++] = IOVEC_MAKE_STRING(m);
891
892                 if (newline_separator) {
893                         iovec[*n].iov_base = (char*) &nl;
894                         iovec[*n].iov_len = 1;
895                         (*n)++;
896                 }
897
898                 format = va_arg(ap, char *);
899         }
900         return 0;
901 }
902
903 int log_struct_internal(
904                 int level,
905                 int error,
906                 const char *file,
907                 int line,
908                 const char *func,
909                 const char *format, ...) {
910
911         LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
912         char buf[LINE_MAX];
913         bool found = false;
914         PROTECT_ERRNO;
915         va_list ap;
916
917         if (error < 0)
918                 error = -error;
919
920         if (_likely_(LOG_PRI(level) > log_max_level[realm]))
921                 return -error;
922
923         if (log_target == LOG_TARGET_NULL)
924                 return -error;
925
926         if ((level & LOG_FACMASK) == 0)
927                 level = log_facility | LOG_PRI(level);
928
929 #if 0 /// elogind does not support logging to systemd-journald
930         if (IN_SET(log_target,
931                    LOG_TARGET_AUTO,
932                    LOG_TARGET_JOURNAL_OR_KMSG,
933                    LOG_TARGET_JOURNAL)) {
934
935                 if (open_when_needed)
936                         log_open_journal();
937
938                 if (journal_fd >= 0) {
939                         char header[LINE_MAX];
940                         struct iovec iovec[17] = {};
941                         size_t n = 0, i;
942                         int r;
943                         struct msghdr mh = {
944                                 .msg_iov = iovec,
945                         };
946                         bool fallback = false;
947
948                         /* If the journal is available do structured logging */
949                         log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
950                         iovec[n++] = IOVEC_MAKE_STRING(header);
951
952                         va_start(ap, format);
953                         r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
954                         if (r < 0)
955                                 fallback = true;
956                         else {
957                                 mh.msg_iovlen = n;
958                                 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
959                         }
960
961                         va_end(ap);
962                         for (i = 1; i < n; i += 2)
963                                 free(iovec[i].iov_base);
964
965                         if (!fallback) {
966                                 if (open_when_needed)
967                                         log_close();
968
969                                 return -error;
970                         }
971                 }
972         }
973 #endif // 0
974
975         /* Fallback if journal logging is not available or didn't work. */
976
977         va_start(ap, format);
978         while (format) {
979                 va_list aq;
980
981                 errno = error;
982
983                 va_copy(aq, ap);
984                 (void) vsnprintf(buf, sizeof buf, format, aq);
985                 va_end(aq);
986
987                 if (startswith(buf, "MESSAGE=")) {
988                         found = true;
989                         break;
990                 }
991
992                 VA_FORMAT_ADVANCE(format, ap);
993
994                 format = va_arg(ap, char *);
995         }
996         va_end(ap);
997
998         if (!found) {
999                 if (open_when_needed)
1000                         log_close();
1001
1002                 return -error;
1003         }
1004
1005         return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
1006 }
1007
1008 int log_struct_iovec_internal(
1009                 int level,
1010                 int error,
1011                 const char *file,
1012                 int line,
1013                 const char *func,
1014                 const struct iovec input_iovec[],
1015                 size_t n_input_iovec) {
1016
1017         LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
1018         PROTECT_ERRNO;
1019         size_t i;
1020         char *m;
1021
1022         if (error < 0)
1023                 error = -error;
1024
1025         if (_likely_(LOG_PRI(level) > log_max_level[realm]))
1026                 return -error;
1027
1028         if (log_target == LOG_TARGET_NULL)
1029                 return -error;
1030
1031         if ((level & LOG_FACMASK) == 0)
1032                 level = log_facility | LOG_PRI(level);
1033
1034         if (IN_SET(log_target, LOG_TARGET_AUTO,
1035                                LOG_TARGET_JOURNAL_OR_KMSG,
1036                                LOG_TARGET_JOURNAL) &&
1037             journal_fd >= 0) {
1038
1039                 struct iovec iovec[1 + n_input_iovec*2];
1040                 char header[LINE_MAX];
1041                 struct msghdr mh = {
1042                         .msg_iov = iovec,
1043                         .msg_iovlen = 1 + n_input_iovec*2,
1044                 };
1045
1046                 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
1047                 iovec[0] = IOVEC_MAKE_STRING(header);
1048
1049                 for (i = 0; i < n_input_iovec; i++) {
1050                         iovec[1+i*2] = input_iovec[i];
1051                         iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
1052                 }
1053
1054                 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) >= 0)
1055                         return -error;
1056         }
1057
1058         for (i = 0; i < n_input_iovec; i++)
1059                 if (memory_startswith(input_iovec[i].iov_base, input_iovec[i].iov_len, "MESSAGE="))
1060                         break;
1061
1062         if (_unlikely_(i >= n_input_iovec)) /* Couldn't find MESSAGE=? */
1063                 return -error;
1064
1065         m = strndupa(input_iovec[i].iov_base + STRLEN("MESSAGE="),
1066                      input_iovec[i].iov_len - STRLEN("MESSAGE="));
1067
1068         return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
1069 }
1070
1071 int log_set_target_from_string(const char *e) {
1072         LogTarget t;
1073
1074         t = log_target_from_string(e);
1075         if (t < 0)
1076                 return -EINVAL;
1077
1078         log_set_target(t);
1079         return 0;
1080 }
1081
1082 int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
1083         int t;
1084
1085         t = log_level_from_string(e);
1086         if (t < 0)
1087                 return -EINVAL;
1088
1089         log_set_max_level_realm(realm, t);
1090         return 0;
1091 }
1092
1093 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
1094
1095         /*
1096          * The systemd.log_xyz= settings are parsed by all tools, and
1097          * so is "debug".
1098          *
1099          * However, "quiet" is only parsed by PID 1, and only turns of
1100          * status output to /dev/console, but does not alter the log
1101          * level.
1102          */
1103
1104         if (streq(key, "debug") && !value)
1105                 log_set_max_level(LOG_DEBUG);
1106
1107         else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1108
1109                 if (proc_cmdline_value_missing(key, value))
1110                         return 0;
1111
1112                 if (log_set_target_from_string(value) < 0)
1113                         log_warning("Failed to parse log target '%s'. Ignoring.", value);
1114
1115         } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1116
1117                 if (proc_cmdline_value_missing(key, value))
1118                         return 0;
1119
1120                 if (log_set_max_level_from_string(value) < 0)
1121                         log_warning("Failed to parse log level '%s'. Ignoring.", value);
1122
1123         } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
1124
1125                 if (log_show_color_from_string(value ?: "1") < 0)
1126                         log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1127
1128         } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
1129
1130                 if (log_show_location_from_string(value ?: "1") < 0)
1131                         log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1132         }
1133
1134         return 0;
1135 }
1136
1137 void log_parse_environment_realm(LogRealm realm) {
1138         /* Do not call from library code. */
1139
1140         const char *e;
1141
1142         if (get_ctty_devnr(0, NULL) < 0)
1143                 /* Only try to read the command line in daemons.  We assume that anything that has a controlling tty is
1144                    user stuff. */
1145                 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
1146
1147         e = getenv("SYSTEMD_LOG_TARGET");
1148         if (e && log_set_target_from_string(e) < 0)
1149                 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1150
1151         e = getenv("SYSTEMD_LOG_LEVEL");
1152         if (e && log_set_max_level_from_string_realm(realm, e) < 0)
1153                 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1154
1155         e = getenv("SYSTEMD_LOG_COLOR");
1156         if (e && log_show_color_from_string(e) < 0)
1157                 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1158
1159         e = getenv("SYSTEMD_LOG_LOCATION");
1160         if (e && log_show_location_from_string(e) < 0)
1161                 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1162 }
1163
1164 LogTarget log_get_target(void) {
1165         return log_target;
1166 }
1167
1168 int log_get_max_level_realm(LogRealm realm) {
1169         return log_max_level[realm];
1170 }
1171
1172 void log_show_color(bool b) {
1173         show_color = b;
1174 }
1175
1176 bool log_get_show_color(void) {
1177         return show_color;
1178 }
1179
1180 void log_show_location(bool b) {
1181         show_location = b;
1182 }
1183
1184 bool log_get_show_location(void) {
1185         return show_location;
1186 }
1187
1188 int log_show_color_from_string(const char *e) {
1189         int t;
1190
1191         t = parse_boolean(e);
1192         if (t < 0)
1193                 return t;
1194
1195         log_show_color(t);
1196         return 0;
1197 }
1198
1199 int log_show_location_from_string(const char *e) {
1200         int t;
1201
1202         t = parse_boolean(e);
1203         if (t < 0)
1204                 return t;
1205
1206         log_show_location(t);
1207         return 0;
1208 }
1209
1210 bool log_on_console(void) {
1211         if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1212                                LOG_TARGET_CONSOLE_PREFIXED))
1213                 return true;
1214
1215         return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1216 }
1217
1218 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1219         [LOG_TARGET_CONSOLE] = "console",
1220         [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1221         [LOG_TARGET_KMSG] = "kmsg",
1222 #if 0 /// elogind does not support logging to systemd-journald
1223         [LOG_TARGET_JOURNAL] = "journal",
1224         [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1225 #endif // 0
1226         [LOG_TARGET_SYSLOG] = "syslog",
1227         [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1228         [LOG_TARGET_AUTO] = "auto",
1229         [LOG_TARGET_NULL] = "null",
1230 };
1231
1232 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1233
1234 #if 0 /// UNNEEDED by elogind
1235 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1236         assert(si);
1237
1238         if (pid_is_valid(si->ssi_pid)) {
1239                 _cleanup_free_ char *p = NULL;
1240
1241                 (void) get_process_comm(si->ssi_pid, &p);
1242
1243                 log_full(level,
1244                          "Received SIG%s from PID %"PRIu32" (%s).",
1245                          signal_to_string(si->ssi_signo),
1246                          si->ssi_pid, strna(p));
1247         } else
1248                 log_full(level,
1249                          "Received SIG%s.",
1250                          signal_to_string(si->ssi_signo));
1251 }
1252
1253 #endif // 0
1254 int log_syntax_internal(
1255                 const char *unit,
1256                 int level,
1257                 const char *config_file,
1258                 unsigned config_line,
1259                 int error,
1260                 const char *file,
1261                 int line,
1262                 const char *func,
1263                 const char *format, ...) {
1264
1265         PROTECT_ERRNO;
1266         char buffer[LINE_MAX];
1267         va_list ap;
1268         const char *unit_fmt = NULL;
1269
1270         if (error < 0)
1271                 error = -error;
1272
1273         if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
1274                 return -error;
1275
1276         if (log_target == LOG_TARGET_NULL)
1277                 return -error;
1278
1279         errno = error;
1280
1281         va_start(ap, format);
1282         (void) vsnprintf(buffer, sizeof buffer, format, ap);
1283         va_end(ap);
1284
1285         if (unit)
1286                 unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1287
1288         return log_struct_internal(
1289                         LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
1290                         error,
1291                         file, line, func,
1292                         "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1293                         "CONFIG_FILE=%s", config_file,
1294                         "CONFIG_LINE=%u", config_line,
1295                         LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
1296                         unit_fmt, unit,
1297                         NULL);
1298 }
1299
1300 int log_syntax_invalid_utf8_internal(
1301                 const char *unit,
1302                 int level,
1303                 const char *config_file,
1304                 unsigned config_line,
1305                 const char *file,
1306                 int line,
1307                 const char *func,
1308                 const char *rvalue) {
1309
1310         _cleanup_free_ char *p = NULL;
1311
1312         if (rvalue)
1313                 p = utf8_escape_invalid(rvalue);
1314
1315         log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
1316                             "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
1317
1318         return -EINVAL;
1319 }
1320
1321 #if 0 /// UNNEEDED by elogind
1322 void log_set_upgrade_syslog_to_journal(bool b) {
1323         upgrade_syslog_to_journal = b;
1324
1325         /* Make the change effective immediately */
1326         if (b) {
1327                 if (log_target == LOG_TARGET_SYSLOG)
1328                         log_target = LOG_TARGET_JOURNAL;
1329                 else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
1330                         log_target = LOG_TARGET_JOURNAL_OR_KMSG;
1331         }
1332 }
1333
1334 void log_set_always_reopen_console(bool b) {
1335         always_reopen_console = b;
1336 }
1337 #endif // 0
1338
1339 void log_set_open_when_needed(bool b) {
1340         open_when_needed = b;
1341 }
1342
1343 void log_set_prohibit_ipc(bool b) {
1344         prohibit_ipc = b;
1345 }
1346
1347 int log_emergency_level(void) {
1348         /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1349          * then the system of the whole system is obviously affected. */
1350
1351         return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;
1352 }
1353
1354 int log_dup_console(void) {
1355         int copy;
1356
1357         /* Duplicate the fd we use for fd logging if it's < 3 and use the copy from now on. This call is useful
1358          * whenever we want to continue logging through the original fd, but want to rearrange stderr. */
1359
1360         if (console_fd >= 3)
1361                 return 0;
1362
1363         copy = fcntl(console_fd, F_DUPFD_CLOEXEC, 3);
1364         if (copy < 0)
1365                 return -errno;
1366
1367         console_fd = copy;
1368         return 0;
1369 }