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