chiark / gitweb /
journald: allow additional payload in server_driver_message
[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_format_iovec(
817                 struct iovec *iovec,
818                 unsigned iovec_len,
819                 unsigned *n,
820                 bool newline_separator,
821                 int error,
822                 const char *format,
823                 va_list ap) {
824
825         static const char nl = '\n';
826
827         while (format && *n + 1 < iovec_len) {
828                 va_list aq;
829                 char *m;
830                 int r;
831
832                 /* We need to copy the va_list structure,
833                  * since vasprintf() leaves it afterwards at
834                  * an undefined location */
835
836                 if (error != 0)
837                         errno = error;
838
839                 va_copy(aq, ap);
840                 r = vasprintf(&m, format, aq);
841                 va_end(aq);
842                 if (r < 0)
843                         return -EINVAL;
844
845                 /* Now, jump enough ahead, so that we point to
846                  * the next format string */
847                 VA_FORMAT_ADVANCE(format, ap);
848
849                 IOVEC_SET_STRING(iovec[(*n)++], m);
850
851                 if (newline_separator) {
852                         iovec[*n].iov_base = (char*) &nl;
853                         iovec[*n].iov_len = 1;
854                         (*n)++;
855                 }
856
857                 format = va_arg(ap, char *);
858         }
859         return 0;
860 }
861
862 int log_struct_internal(
863                 int level,
864                 int error,
865                 const char *file,
866                 int line,
867                 const char *func,
868                 const char *format, ...) {
869
870         char buf[LINE_MAX];
871         bool found = false;
872         PROTECT_ERRNO;
873         va_list ap;
874
875         if (error < 0)
876                 error = -error;
877
878         if (_likely_(LOG_PRI(level) > log_max_level))
879                 return -error;
880
881         if (log_target == LOG_TARGET_NULL)
882                 return -error;
883
884         if ((level & LOG_FACMASK) == 0)
885                 level = log_facility | LOG_PRI(level);
886
887 #if 0 /// elogind does not support logging to systemd-journald
888         if ((log_target == LOG_TARGET_AUTO ||
889              log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
890              log_target == LOG_TARGET_JOURNAL) &&
891             journal_fd >= 0) {
892                 char header[LINE_MAX];
893                 struct iovec iovec[17] = {};
894                 unsigned n = 0, i;
895                 int r;
896                 struct msghdr mh = {
897                         .msg_iov = iovec,
898                 };
899                 bool fallback = false;
900
901                 /* If the journal is available do structured logging */
902                 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
903                 IOVEC_SET_STRING(iovec[n++], header);
904
905                 va_start(ap, format);
906                 r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
907                 if (r < 0)
908                         fallback = true;
909                 else {
910                         mh.msg_iovlen = n;
911                         (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
912                 }
913
914                 va_end(ap);
915                 for (i = 1; i < n; i += 2)
916                         free(iovec[i].iov_base);
917
918                 if (!fallback)
919                         return -error;
920         }
921 #endif // 0
922
923         /* Fallback if journal logging is not available or didn't work. */
924
925         va_start(ap, format);
926         while (format) {
927                 va_list aq;
928
929                 if (error != 0)
930                         errno = error;
931
932                 va_copy(aq, ap);
933                 vsnprintf(buf, sizeof(buf), format, aq);
934                 va_end(aq);
935
936                 if (startswith(buf, "MESSAGE=")) {
937                         found = true;
938                         break;
939                 }
940
941                 VA_FORMAT_ADVANCE(format, ap);
942
943                 format = va_arg(ap, char *);
944         }
945         va_end(ap);
946
947         if (!found)
948                 return -error;
949
950         return log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
951 }
952
953 int log_set_target_from_string(const char *e) {
954         LogTarget t;
955
956         t = log_target_from_string(e);
957         if (t < 0)
958                 return -EINVAL;
959
960         log_set_target(t);
961         return 0;
962 }
963
964 int log_set_max_level_from_string(const char *e) {
965         int t;
966
967         t = log_level_from_string(e);
968         if (t < 0)
969                 return -EINVAL;
970
971         log_set_max_level(t);
972         return 0;
973 }
974
975 static int parse_proc_cmdline_item(const char *key, const char *value) {
976
977         /*
978          * The systemd.log_xyz= settings are parsed by all tools, and
979          * so is "debug".
980          *
981          * However, "quiet" is only parsed by PID 1, and only turns of
982          * status output to /dev/console, but does not alter the log
983          * level.
984          */
985
986         if (streq(key, "debug") && !value)
987                 log_set_max_level(LOG_DEBUG);
988
989         else if (streq(key, "systemd.log_target") && value) {
990
991                 if (log_set_target_from_string(value) < 0)
992                         log_warning("Failed to parse log target '%s'. Ignoring.", value);
993
994         } else if (streq(key, "systemd.log_level") && value) {
995
996                 if (log_set_max_level_from_string(value) < 0)
997                         log_warning("Failed to parse log level '%s'. Ignoring.", value);
998
999         } else if (streq(key, "systemd.log_color") && value) {
1000
1001                 if (log_show_color_from_string(value) < 0)
1002                         log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1003
1004         } else if (streq(key, "systemd.log_location") && value) {
1005
1006                 if (log_show_location_from_string(value) < 0)
1007                         log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1008         }
1009
1010         return 0;
1011 }
1012
1013 void log_parse_environment(void) {
1014         const char *e;
1015
1016         if (get_ctty_devnr(0, NULL) < 0)
1017                 /* Only try to read the command line in daemons.
1018                    We assume that anything that has a controlling
1019                    tty is user stuff. */
1020                 (void) parse_proc_cmdline(parse_proc_cmdline_item);
1021
1022         e = secure_getenv("SYSTEMD_LOG_TARGET");
1023         if (e && log_set_target_from_string(e) < 0)
1024                 log_warning("Failed to parse log target '%s'. Ignoring.", e);
1025
1026         e = secure_getenv("SYSTEMD_LOG_LEVEL");
1027         if (e && log_set_max_level_from_string(e) < 0)
1028                 log_warning("Failed to parse log level '%s'. Ignoring.", e);
1029
1030         e = secure_getenv("SYSTEMD_LOG_COLOR");
1031         if (e && log_show_color_from_string(e) < 0)
1032                 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1033
1034         e = secure_getenv("SYSTEMD_LOG_LOCATION");
1035         if (e && log_show_location_from_string(e) < 0)
1036                 log_warning("Failed to parse bool '%s'. Ignoring.", e);
1037 }
1038
1039 LogTarget log_get_target(void) {
1040         return log_target;
1041 }
1042
1043 int log_get_max_level(void) {
1044         return log_max_level;
1045 }
1046
1047 void log_show_color(bool b) {
1048         show_color = b;
1049 }
1050
1051 bool log_get_show_color(void) {
1052         return show_color;
1053 }
1054
1055 void log_show_location(bool b) {
1056         show_location = b;
1057 }
1058
1059 bool log_get_show_location(void) {
1060         return show_location;
1061 }
1062
1063 int log_show_color_from_string(const char *e) {
1064         int t;
1065
1066         t = parse_boolean(e);
1067         if (t < 0)
1068                 return t;
1069
1070         log_show_color(t);
1071         return 0;
1072 }
1073
1074 int log_show_location_from_string(const char *e) {
1075         int t;
1076
1077         t = parse_boolean(e);
1078         if (t < 0)
1079                 return t;
1080
1081         log_show_location(t);
1082         return 0;
1083 }
1084
1085 bool log_on_console(void) {
1086         if (log_target == LOG_TARGET_CONSOLE ||
1087             log_target == LOG_TARGET_CONSOLE_PREFIXED)
1088                 return true;
1089
1090         return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1091 }
1092
1093 static const char *const log_target_table[_LOG_TARGET_MAX] = {
1094         [LOG_TARGET_CONSOLE] = "console",
1095         [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1096         [LOG_TARGET_KMSG] = "kmsg",
1097 #if 0 /// elogind does not support logging to systemd-journald
1098         [LOG_TARGET_JOURNAL] = "journal",
1099         [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1100 #endif // 0
1101         [LOG_TARGET_SYSLOG] = "syslog",
1102         [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
1103         [LOG_TARGET_AUTO] = "auto",
1104         [LOG_TARGET_SAFE] = "safe",
1105         [LOG_TARGET_NULL] = "null"
1106 };
1107
1108 DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1109
1110 #if 0 /// UNNEEDED by elogind
1111 void log_received_signal(int level, const struct signalfd_siginfo *si) {
1112         if (si->ssi_pid > 0) {
1113                 _cleanup_free_ char *p = NULL;
1114
1115                 get_process_comm(si->ssi_pid, &p);
1116
1117                 log_full(level,
1118                          "Received SIG%s from PID %"PRIu32" (%s).",
1119                          signal_to_string(si->ssi_signo),
1120                          si->ssi_pid, strna(p));
1121         } else
1122                 log_full(level,
1123                          "Received SIG%s.",
1124                          signal_to_string(si->ssi_signo));
1125
1126 }
1127
1128 void log_set_upgrade_syslog_to_journal(bool b) {
1129         upgrade_syslog_to_journal = b;
1130 }
1131 #endif // 0
1132
1133 int log_syntax_internal(
1134                 const char *unit,
1135                 int level,
1136                 const char *config_file,
1137                 unsigned config_line,
1138                 int error,
1139                 const char *file,
1140                 int line,
1141                 const char *func,
1142                 const char *format, ...) {
1143
1144         PROTECT_ERRNO;
1145         char buffer[LINE_MAX];
1146         int r;
1147         va_list ap;
1148
1149         if (error < 0)
1150                 error = -error;
1151
1152         if (_likely_(LOG_PRI(level) > log_max_level))
1153                 return -error;
1154
1155         if (log_target == LOG_TARGET_NULL)
1156                 return -error;
1157
1158         if (error != 0)
1159                 errno = error;
1160
1161         va_start(ap, format);
1162         vsnprintf(buffer, sizeof(buffer), format, ap);
1163         va_end(ap);
1164
1165         if (unit)
1166                 r = log_struct_internal(
1167                                 level, error,
1168                                 file, line, func,
1169                                 getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
1170                                 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1171                                 "CONFIG_FILE=%s", config_file,
1172                                 "CONFIG_LINE=%u", config_line,
1173                                 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1174                                 NULL);
1175         else
1176                 r = log_struct_internal(
1177                                 level, error,
1178                                 file, line, func,
1179                                 LOG_MESSAGE_ID(SD_MESSAGE_INVALID_CONFIGURATION),
1180                                 "CONFIG_FILE=%s", config_file,
1181                                 "CONFIG_LINE=%u", config_line,
1182                                 LOG_MESSAGE("[%s:%u] %s", config_file, config_line, buffer),
1183                                 NULL);
1184
1185         return r;
1186 }