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