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