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