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