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