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