Coverage Report

Created: 2022-04-19 08:24

/src/systemd/src/basic/log.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3
#include <errno.h>
4
#include <fcntl.h>
5
#include <inttypes.h>
6
#include <limits.h>
7
#include <stdarg.h>
8
#include <stddef.h>
9
#include <sys/signalfd.h>
10
#include <sys/stat.h>
11
#include <sys/time.h>
12
#include <sys/uio.h>
13
#include <sys/un.h>
14
#include <unistd.h>
15
16
#include "sd-messages.h"
17
18
#include "alloc-util.h"
19
#include "errno-util.h"
20
#include "fd-util.h"
21
#include "format-util.h"
22
#include "io-util.h"
23
#include "log.h"
24
#include "macro.h"
25
#include "missing_syscall.h"
26
#include "parse-util.h"
27
#include "proc-cmdline.h"
28
#include "process-util.h"
29
#include "ratelimit.h"
30
#include "signal-util.h"
31
#include "socket-util.h"
32
#include "stdio-util.h"
33
#include "string-table.h"
34
#include "string-util.h"
35
#include "syslog-util.h"
36
#include "terminal-util.h"
37
#include "time-util.h"
38
#include "utf8.h"
39
40
0
#define SNDBUF_SIZE (8*1024*1024)
41
42
static log_syntax_callback_t log_syntax_callback = NULL;
43
static void *log_syntax_callback_userdata = NULL;
44
45
static LogTarget log_target = LOG_TARGET_CONSOLE;
46
static int log_max_level = LOG_INFO;
47
static int log_facility = LOG_DAEMON;
48
49
static int console_fd = STDERR_FILENO;
50
static int syslog_fd = -1;
51
static int kmsg_fd = -1;
52
static int journal_fd = -1;
53
54
static bool syslog_is_stream = false;
55
56
static int show_color = -1; /* tristate */
57
static bool show_location = false;
58
static bool show_time = false;
59
static bool show_tid = false;
60
61
static bool upgrade_syslog_to_journal = false;
62
static bool always_reopen_console = false;
63
static bool open_when_needed = false;
64
static bool prohibit_ipc = false;
65
66
/* Akin to glibc's __abort_msg; which is private and we hence cannot
67
 * use here. */
68
static char *log_abort_msg = NULL;
69
70
/* An assert to use in logging functions that does not call recursively
71
 * into our logging functions (since that might lead to a loop). */
72
#define assert_raw(expr)                                                \
73
0
        do {                                                            \
74
0
                if (_unlikely_(!(expr))) {                              \
75
0
                        fputs(#expr "\n", stderr);                      \
76
0
                        abort();                                        \
77
0
                }                                                       \
78
0
        } while (false)
79
80
0
static void log_close_console(void) {
81
0
        console_fd = safe_close_above_stdio(console_fd);
82
0
}
83
84
0
static int log_open_console(void) {
85
86
0
        if (!always_reopen_console) {
87
0
                console_fd = STDERR_FILENO;
88
0
                return 0;
89
0
        }
90
91
0
        if (console_fd < 3) {
92
0
                int fd;
93
94
0
                fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
95
0
                if (fd < 0)
96
0
                        return fd;
97
98
0
                console_fd = fd_move_above_stdio(fd);
99
0
        }
100
101
0
        return 0;
102
0
}
103
104
0
static void log_close_kmsg(void) {
105
0
        kmsg_fd = safe_close(kmsg_fd);
106
0
}
107
108
0
static int log_open_kmsg(void) {
109
110
0
        if (kmsg_fd >= 0)
111
0
                return 0;
112
113
0
        kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
114
0
        if (kmsg_fd < 0)
115
0
                return -errno;
116
117
0
        kmsg_fd = fd_move_above_stdio(kmsg_fd);
118
0
        return 0;
119
0
}
120
121
0
static void log_close_syslog(void) {
122
0
        syslog_fd = safe_close(syslog_fd);
123
0
}
124
125
0
static int create_log_socket(int type) {
126
0
        struct timeval tv;
127
0
        int fd;
128
129
0
        fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
130
0
        if (fd < 0)
131
0
                return -errno;
132
133
0
        fd = fd_move_above_stdio(fd);
134
0
        (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
135
136
        /* We need a blocking fd here since we'd otherwise lose messages way too early. However, let's not hang forever
137
         * in the unlikely case of a deadlock. */
138
0
        if (getpid_cached() == 1)
139
0
                timeval_store(&tv, 10 * USEC_PER_MSEC);
140
0
        else
141
0
                timeval_store(&tv, 10 * USEC_PER_SEC);
142
0
        (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
143
144
0
        return fd;
145
0
}
146
147
0
static int log_open_syslog(void) {
148
149
0
        static const union sockaddr_union sa = {
150
0
                .un.sun_family = AF_UNIX,
151
0
                .un.sun_path = "/dev/log",
152
0
        };
153
154
0
        int r;
155
156
0
        if (syslog_fd >= 0)
157
0
                return 0;
158
159
0
        syslog_fd = create_log_socket(SOCK_DGRAM);
160
0
        if (syslog_fd < 0) {
161
0
                r = syslog_fd;
162
0
                goto fail;
163
0
        }
164
165
0
        if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
166
0
                safe_close(syslog_fd);
167
168
                /* Some legacy syslog systems still use stream
169
                 * sockets. They really shouldn't. But what can we
170
                 * do... */
171
0
                syslog_fd = create_log_socket(SOCK_STREAM);
172
0
                if (syslog_fd < 0) {
173
0
                        r = syslog_fd;
174
0
                        goto fail;
175
0
                }
176
177
0
                if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
178
0
                        r = -errno;
179
0
                        goto fail;
180
0
                }
181
182
0
                syslog_is_stream = true;
183
0
        } else
184
0
                syslog_is_stream = false;
185
186
0
        return 0;
187
188
0
fail:
189
0
        log_close_syslog();
190
0
        return r;
191
0
}
192
193
0
static void log_close_journal(void) {
194
0
        journal_fd = safe_close(journal_fd);
195
0
}
196
197
0
static int log_open_journal(void) {
198
199
0
        static const union sockaddr_union sa = {
200
0
                .un.sun_family = AF_UNIX,
201
0
                .un.sun_path = "/run/systemd/journal/socket",
202
0
        };
203
204
0
        int r;
205
206
0
        if (journal_fd >= 0)
207
0
                return 0;
208
209
0
        journal_fd = create_log_socket(SOCK_DGRAM);
210
0
        if (journal_fd < 0) {
211
0
                r = journal_fd;
212
0
                goto fail;
213
0
        }
214
215
0
        if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
216
0
                r = -errno;
217
0
                goto fail;
218
0
        }
219
220
0
        return 0;
221
222
0
fail:
223
0
        log_close_journal();
224
0
        return r;
225
0
}
226
227
0
static bool stderr_is_journal(void) {
228
0
        _cleanup_free_ char *w = NULL;
229
0
        const char *e;
230
0
        uint64_t dev, ino;
231
0
        struct stat st;
232
233
0
        e = getenv("JOURNAL_STREAM");
234
0
        if (!e)
235
0
                return false;
236
237
0
        if (extract_first_word(&e, &w, ":", EXTRACT_DONT_COALESCE_SEPARATORS) <= 0)
238
0
                return false;
239
0
        if (!e)
240
0
                return false;
241
242
0
        if (safe_atou64(w, &dev) < 0)
243
0
                return false;
244
0
        if (safe_atou64(e, &ino) < 0)
245
0
                return false;
246
247
0
        if (fstat(STDERR_FILENO, &st) < 0)
248
0
                return false;
249
250
0
        return st.st_dev == dev && st.st_ino == ino;
251
0
}
252
253
0
int log_open(void) {
254
0
        int r;
255
256
        /* Do not call from library code. */
257
258
        /* This function is often called in preparation for logging. Let's make sure we don't clobber errno,
259
         * so that a call to a logging function immediately following a log_open() call can still easily
260
         * reference an error that happened immediately before the log_open() call. */
261
0
        PROTECT_ERRNO;
262
263
        /* If we don't use the console, we close it here to not get killed by SAK. If we don't use syslog, we
264
         * close it here too, so that we are not confused by somebody deleting the socket in the fs, and to
265
         * make sure we don't use it if prohibit_ipc is set. If we don't use /dev/kmsg we still keep it open,
266
         * because there is no reason to close it. */
267
268
0
        if (log_target == LOG_TARGET_NULL) {
269
0
                log_close_journal();
270
0
                log_close_syslog();
271
0
                log_close_console();
272
0
                return 0;
273
0
        }
274
275
0
        if (getpid_cached() == 1 ||
276
0
            stderr_is_journal() ||
277
0
            IN_SET(log_target,
278
0
                   LOG_TARGET_KMSG,
279
0
                   LOG_TARGET_JOURNAL,
280
0
                   LOG_TARGET_JOURNAL_OR_KMSG,
281
0
                   LOG_TARGET_SYSLOG,
282
0
                   LOG_TARGET_SYSLOG_OR_KMSG)) {
283
284
0
                if (!prohibit_ipc) {
285
0
                        if (IN_SET(log_target,
286
0
                                   LOG_TARGET_AUTO,
287
0
                                   LOG_TARGET_JOURNAL_OR_KMSG,
288
0
                                   LOG_TARGET_JOURNAL)) {
289
290
0
                                r = log_open_journal();
291
0
                                if (r >= 0) {
292
0
                                        log_close_syslog();
293
0
                                        log_close_console();
294
0
                                        return r;
295
0
                                }
296
0
                        }
297
298
0
                        if (IN_SET(log_target,
299
0
                                   LOG_TARGET_SYSLOG_OR_KMSG,
300
0
                                   LOG_TARGET_SYSLOG)) {
301
302
0
                                r = log_open_syslog();
303
0
                                if (r >= 0) {
304
0
                                        log_close_journal();
305
0
                                        log_close_console();
306
0
                                        return r;
307
0
                                }
308
0
                        }
309
0
                }
310
311
0
                if (IN_SET(log_target, LOG_TARGET_AUTO,
312
0
                                       LOG_TARGET_JOURNAL_OR_KMSG,
313
0
                                       LOG_TARGET_SYSLOG_OR_KMSG,
314
0
                                       LOG_TARGET_KMSG)) {
315
0
                        r = log_open_kmsg();
316
0
                        if (r >= 0) {
317
0
                                log_close_journal();
318
0
                                log_close_syslog();
319
0
                                log_close_console();
320
0
                                return r;
321
0
                        }
322
0
                }
323
0
        }
324
325
0
        log_close_journal();
326
0
        log_close_syslog();
327
328
0
        return log_open_console();
329
0
}
330
331
0
void log_set_target(LogTarget target) {
332
0
        assert(target >= 0);
333
0
        assert(target < _LOG_TARGET_MAX);
334
335
0
        if (upgrade_syslog_to_journal) {
336
0
                if (target == LOG_TARGET_SYSLOG)
337
0
                        target = LOG_TARGET_JOURNAL;
338
0
                else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
339
0
                        target = LOG_TARGET_JOURNAL_OR_KMSG;
340
0
        }
341
342
0
        log_target = target;
343
0
}
344
345
0
void log_close(void) {
346
        /* Do not call from library code. */
347
348
0
        log_close_journal();
349
0
        log_close_syslog();
350
0
        log_close_kmsg();
351
0
        log_close_console();
352
0
}
353
354
0
void log_forget_fds(void) {
355
        /* Do not call from library code. */
356
357
0
        console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
358
0
}
359
360
117k
void log_set_max_level(int level) {
361
117k
        assert(level == LOG_NULL || (level & LOG_PRIMASK) == level);
362
363
117k
        log_max_level = level;
364
117k
}
365
366
0
void log_set_facility(int facility) {
367
0
        log_facility = facility;
368
0
}
369
370
static int write_to_console(
371
                int level,
372
                int error,
373
                const char *file,
374
                int line,
375
                const char *func,
376
0
                const char *buffer) {
377
378
0
        char location[256],
379
0
             header_time[FORMAT_TIMESTAMP_MAX],
380
0
             prefix[1 + DECIMAL_STR_MAX(int) + 2],
381
0
             tid_string[3 + DECIMAL_STR_MAX(pid_t) + 1];
382
0
        struct iovec iovec[9];
383
0
        const char *on = NULL, *off = NULL;
384
0
        size_t n = 0;
385
386
0
        if (console_fd < 0)
387
0
                return 0;
388
389
0
        if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
390
0
                xsprintf(prefix, "<%i>", level);
391
0
                iovec[n++] = IOVEC_MAKE_STRING(prefix);
392
0
        }
393
394
0
        if (show_time &&
395
0
            format_timestamp(header_time, sizeof(header_time), now(CLOCK_REALTIME))) {
396
0
                iovec[n++] = IOVEC_MAKE_STRING(header_time);
397
0
                iovec[n++] = IOVEC_MAKE_STRING(" ");
398
0
        }
399
400
0
        if (show_tid) {
401
0
                xsprintf(tid_string, "(" PID_FMT ") ", gettid());
402
0
                iovec[n++] = IOVEC_MAKE_STRING(tid_string);
403
0
        }
404
405
0
        if (log_get_show_color())
406
0
                get_log_colors(LOG_PRI(level), &on, &off, NULL);
407
408
0
        if (show_location) {
409
0
                const char *lon = "", *loff = "";
410
0
                if (log_get_show_color()) {
411
0
                        lon = ansi_highlight_yellow4();
412
0
                        loff = ansi_normal();
413
0
                }
414
415
0
                (void) snprintf(location, sizeof location, "%s%s:%i%s: ", lon, file, line, loff);
416
0
                iovec[n++] = IOVEC_MAKE_STRING(location);
417
0
        }
418
419
0
        if (on)
420
0
                iovec[n++] = IOVEC_MAKE_STRING(on);
421
0
        iovec[n++] = IOVEC_MAKE_STRING(buffer);
422
0
        if (off)
423
0
                iovec[n++] = IOVEC_MAKE_STRING(off);
424
0
        iovec[n++] = IOVEC_MAKE_STRING("\n");
425
426
0
        if (writev(console_fd, iovec, n) < 0) {
427
428
0
                if (errno == EIO && getpid_cached() == 1) {
429
430
                        /* If somebody tried to kick us from our console tty (via vhangup() or suchlike), try
431
                         * to reconnect. */
432
433
0
                        log_close_console();
434
0
                        (void) log_open_console();
435
0
                        if (console_fd < 0)
436
0
                                return 0;
437
438
0
                        if (writev(console_fd, iovec, n) < 0)
439
0
                                return -errno;
440
0
                } else
441
0
                        return -errno;
442
0
        }
443
444
0
        return 1;
445
0
}
446
447
static int write_to_syslog(
448
                int level,
449
                int error,
450
                const char *file,
451
                int line,
452
                const char *func,
453
0
                const char *buffer) {
454
455
0
        char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
456
0
             header_time[64],
457
0
             header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
458
0
        time_t t;
459
0
        struct tm tm;
460
461
0
        if (syslog_fd < 0)
462
0
                return 0;
463
464
0
        xsprintf(header_priority, "<%i>", level);
465
466
0
        t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
467
0
        if (!localtime_r(&t, &tm))
468
0
                return -EINVAL;
469
470
0
        if (strftime(header_time, sizeof(header_time), "%h %e %T ", &tm) <= 0)
471
0
                return -EINVAL;
472
473
0
        xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
474
475
0
        struct iovec iovec[] = {
476
0
                IOVEC_MAKE_STRING(header_priority),
477
0
                IOVEC_MAKE_STRING(header_time),
478
0
                IOVEC_MAKE_STRING(program_invocation_short_name),
479
0
                IOVEC_MAKE_STRING(header_pid),
480
0
                IOVEC_MAKE_STRING(buffer),
481
0
        };
482
0
        const struct msghdr msghdr = {
483
0
                .msg_iov = iovec,
484
0
                .msg_iovlen = ELEMENTSOF(iovec),
485
0
        };
486
487
        /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
488
0
        if (syslog_is_stream)
489
0
                iovec[ELEMENTSOF(iovec) - 1].iov_len++;
490
491
0
        for (;;) {
492
0
                ssize_t n;
493
494
0
                n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
495
0
                if (n < 0)
496
0
                        return -errno;
497
498
0
                if (!syslog_is_stream)
499
0
                        break;
500
501
0
                if (IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n))
502
0
                        break;
503
0
        }
504
505
0
        return 1;
506
0
}
507
508
static int write_to_kmsg(
509
                int level,
510
                int error,
511
                const char *file,
512
                int line,
513
                const char *func,
514
0
                const char *buffer) {
515
516
        /* Set a ratelimit on the amount of messages logged to /dev/kmsg. This is mostly supposed to be a
517
         * safety catch for the case where start indiscriminately logging in a loop. It will not catch cases
518
         * where we log excessively, but not in a tight loop.
519
         *
520
         * Note that this ratelimit is per-emitter, so we might still overwhelm /dev/kmsg with multiple
521
         * loggers.
522
         */
523
0
        static thread_local RateLimit ratelimit = { 5 * USEC_PER_SEC, 200 };
524
525
0
        char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
526
0
             header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
527
528
0
        if (kmsg_fd < 0)
529
0
                return 0;
530
531
0
        if (!ratelimit_below(&ratelimit))
532
0
                return 0;
533
534
0
        xsprintf(header_priority, "<%i>", level);
535
0
        xsprintf(header_pid, "["PID_FMT"]: ", getpid_cached());
536
537
0
        const struct iovec iovec[] = {
538
0
                IOVEC_MAKE_STRING(header_priority),
539
0
                IOVEC_MAKE_STRING(program_invocation_short_name),
540
0
                IOVEC_MAKE_STRING(header_pid),
541
0
                IOVEC_MAKE_STRING(buffer),
542
0
                IOVEC_MAKE_STRING("\n"),
543
0
        };
544
545
0
        if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
546
0
                return -errno;
547
548
0
        return 1;
549
0
}
550
551
static int log_do_header(
552
                char *header,
553
                size_t size,
554
                int level,
555
                int error,
556
                const char *file, int line, const char *func,
557
                const char *object_field, const char *object,
558
0
                const char *extra_field, const char *extra) {
559
0
        int r;
560
561
0
        error = IS_SYNTHETIC_ERRNO(error) ? 0 : ERRNO_VALUE(error);
562
563
0
        r = snprintf(header, size,
564
0
                     "PRIORITY=%i\n"
565
0
                     "SYSLOG_FACILITY=%i\n"
566
0
                     "TID=" PID_FMT "\n"
567
0
                     "%s%.256s%s"        /* CODE_FILE */
568
0
                     "%s%.*i%s"          /* CODE_LINE */
569
0
                     "%s%.256s%s"        /* CODE_FUNC */
570
0
                     "%s%.*i%s"          /* ERRNO */
571
0
                     "%s%.256s%s"        /* object */
572
0
                     "%s%.256s%s"        /* extra */
573
0
                     "SYSLOG_IDENTIFIER=%.256s\n",
574
0
                     LOG_PRI(level),
575
0
                     LOG_FAC(level),
576
0
                     gettid(),
577
0
                     isempty(file) ? "" : "CODE_FILE=",
578
0
                     isempty(file) ? "" : file,
579
0
                     isempty(file) ? "" : "\n",
580
0
                     line ? "CODE_LINE=" : "",
581
0
                     line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
582
0
                     line ? "\n" : "",
583
0
                     isempty(func) ? "" : "CODE_FUNC=",
584
0
                     isempty(func) ? "" : func,
585
0
                     isempty(func) ? "" : "\n",
586
0
                     error ? "ERRNO=" : "",
587
0
                     error ? 1 : 0, error,
588
0
                     error ? "\n" : "",
589
0
                     isempty(object) ? "" : object_field,
590
0
                     isempty(object) ? "" : object,
591
0
                     isempty(object) ? "" : "\n",
592
0
                     isempty(extra) ? "" : extra_field,
593
0
                     isempty(extra) ? "" : extra,
594
0
                     isempty(extra) ? "" : "\n",
595
0
                     program_invocation_short_name);
596
0
        assert_raw((size_t) r < size);
597
598
0
        return 0;
599
0
}
600
601
static int write_to_journal(
602
                int level,
603
                int error,
604
                const char *file,
605
                int line,
606
                const char *func,
607
                const char *object_field,
608
                const char *object,
609
                const char *extra_field,
610
                const char *extra,
611
0
                const char *buffer) {
612
613
0
        char header[LINE_MAX];
614
615
0
        if (journal_fd < 0)
616
0
                return 0;
617
618
0
        log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
619
620
0
        struct iovec iovec[4] = {
621
0
                IOVEC_MAKE_STRING(header),
622
0
                IOVEC_MAKE_STRING("MESSAGE="),
623
0
                IOVEC_MAKE_STRING(buffer),
624
0
                IOVEC_MAKE_STRING("\n"),
625
0
        };
626
0
        const struct msghdr msghdr = {
627
0
                .msg_iov = iovec,
628
0
                .msg_iovlen = ELEMENTSOF(iovec),
629
0
        };
630
631
0
        if (sendmsg(journal_fd, &msghdr, MSG_NOSIGNAL) < 0)
632
0
                return -errno;
633
634
0
        return 1;
635
0
}
636
637
int log_dispatch_internal(
638
                int level,
639
                int error,
640
                const char *file,
641
                int line,
642
                const char *func,
643
                const char *object_field,
644
                const char *object,
645
                const char *extra_field,
646
                const char *extra,
647
0
                char *buffer) {
648
649
0
        assert_raw(buffer);
650
651
0
        if (log_target == LOG_TARGET_NULL)
652
0
                return -ERRNO_VALUE(error);
653
654
        /* Patch in LOG_DAEMON facility if necessary */
655
0
        if ((level & LOG_FACMASK) == 0)
656
0
                level |= log_facility;
657
658
0
        if (open_when_needed)
659
0
                (void) log_open();
660
661
0
        do {
662
0
                char *e;
663
0
                int k = 0;
664
665
0
                buffer += strspn(buffer, NEWLINE);
666
667
0
                if (buffer[0] == 0)
668
0
                        break;
669
670
0
                if ((e = strpbrk(buffer, NEWLINE)))
671
0
                        *(e++) = 0;
672
673
0
                if (IN_SET(log_target, LOG_TARGET_AUTO,
674
0
                                       LOG_TARGET_JOURNAL_OR_KMSG,
675
0
                                       LOG_TARGET_JOURNAL)) {
676
677
0
                        k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
678
0
                        if (k < 0 && k != -EAGAIN)
679
0
                                log_close_journal();
680
0
                }
681
682
0
                if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
683
0
                                       LOG_TARGET_SYSLOG)) {
684
685
0
                        k = write_to_syslog(level, error, file, line, func, buffer);
686
0
                        if (k < 0 && k != -EAGAIN)
687
0
                                log_close_syslog();
688
0
                }
689
690
0
                if (k <= 0 &&
691
0
                    IN_SET(log_target, LOG_TARGET_AUTO,
692
0
                                       LOG_TARGET_SYSLOG_OR_KMSG,
693
0
                                       LOG_TARGET_JOURNAL_OR_KMSG,
694
0
                                       LOG_TARGET_KMSG)) {
695
696
0
                        if (k < 0)
697
0
                                log_open_kmsg();
698
699
0
                        k = write_to_kmsg(level, error, file, line, func, buffer);
700
0
                        if (k < 0) {
701
0
                                log_close_kmsg();
702
0
                                (void) log_open_console();
703
0
                        }
704
0
                }
705
706
0
                if (k <= 0)
707
0
                        (void) write_to_console(level, error, file, line, func, buffer);
708
709
0
                buffer = e;
710
0
        } while (buffer);
711
712
0
        if (open_when_needed)
713
0
                log_close();
714
715
0
        return -ERRNO_VALUE(error);
716
0
}
717
718
int log_dump_internal(
719
                int level,
720
                int error,
721
                const char *file,
722
                int line,
723
                const char *func,
724
0
                char *buffer) {
725
726
0
        PROTECT_ERRNO;
727
728
        /* This modifies the buffer... */
729
730
0
        if (_likely_(LOG_PRI(level) > log_max_level))
731
0
                return -ERRNO_VALUE(error);
732
733
0
        return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
734
0
}
735
736
int log_internalv(
737
                int level,
738
                int error,
739
                const char *file,
740
                int line,
741
                const char *func,
742
                const char *format,
743
6
                va_list ap) {
744
745
6
        char buffer[LINE_MAX];
746
6
        PROTECT_ERRNO;
747
748
6
        if (_likely_(LOG_PRI(level) > log_max_level))
749
6
                return -ERRNO_VALUE(error);
750
751
        /* Make sure that %m maps to the specified error (or "Success"). */
752
0
        errno = ERRNO_VALUE(error);
753
754
0
        (void) vsnprintf(buffer, sizeof buffer, format, ap);
755
756
0
        return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
757
6
}
758
759
int log_internal(
760
                int level,
761
                int error,
762
                const char *file,
763
                int line,
764
                const char *func,
765
6
                const char *format, ...) {
766
767
6
        va_list ap;
768
6
        int r;
769
770
6
        va_start(ap, format);
771
6
        r = log_internalv(level, error, file, line, func, format, ap);
772
6
        va_end(ap);
773
774
6
        return r;
775
6
}
776
777
int log_object_internalv(
778
                int level,
779
                int error,
780
                const char *file,
781
                int line,
782
                const char *func,
783
                const char *object_field,
784
                const char *object,
785
                const char *extra_field,
786
                const char *extra,
787
                const char *format,
788
1.29M
                va_list ap) {
789
790
1.29M
        PROTECT_ERRNO;
791
1.29M
        char *buffer, *b;
792
793
1.29M
        if (_likely_(LOG_PRI(level) > log_max_level))
794
1.29M
                return -ERRNO_VALUE(error);
795
796
        /* Make sure that %m maps to the specified error (or "Success"). */
797
0
        errno = ERRNO_VALUE(error);
798
799
        /* Prepend the object name before the message */
800
0
        if (object) {
801
0
                size_t n;
802
803
0
                n = strlen(object);
804
0
                buffer = newa(char, n + 2 + LINE_MAX);
805
0
                b = stpcpy(stpcpy(buffer, object), ": ");
806
0
        } else
807
0
                b = buffer = newa(char, LINE_MAX);
808
809
0
        (void) vsnprintf(b, LINE_MAX, format, ap);
810
811
0
        return log_dispatch_internal(level, error, file, line, func,
812
0
                                     object_field, object, extra_field, extra, buffer);
813
1.29M
}
814
815
int log_object_internal(
816
                int level,
817
                int error,
818
                const char *file,
819
                int line,
820
                const char *func,
821
                const char *object_field,
822
                const char *object,
823
                const char *extra_field,
824
                const char *extra,
825
1.29M
                const char *format, ...) {
826
827
1.29M
        va_list ap;
828
1.29M
        int r;
829
830
1.29M
        va_start(ap, format);
831
1.29M
        r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
832
1.29M
        va_end(ap);
833
834
1.29M
        return r;
835
1.29M
}
836
837
static void log_assert(
838
                int level,
839
                const char *text,
840
                const char *file,
841
                int line,
842
                const char *func,
843
3.69k
                const char *format) {
844
845
3.69k
        static char buffer[LINE_MAX];
846
847
3.69k
        if (_likely_(LOG_PRI(level) > log_max_level))
848
3.69k
                return;
849
850
3.69k
        DISABLE_WARNING_FORMAT_NONLITERAL;
851
0
        (void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
852
0
        REENABLE_WARNING;
853
854
0
        log_abort_msg = buffer;
855
856
0
        log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
857
0
}
858
859
_noreturn_ void log_assert_failed(
860
                const char *text,
861
                const char *file,
862
                int line,
863
0
                const char *func) {
864
0
        log_assert(LOG_CRIT, text, file, line, func,
865
0
                   "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
866
0
        abort();
867
0
}
868
869
_noreturn_ void log_assert_failed_unreachable(
870
                const char *file,
871
                int line,
872
0
                const char *func) {
873
0
        log_assert(LOG_CRIT, "Code should not be reached", file, line, func,
874
0
                   "%s at %s:%u, function %s(). Aborting. 💥");
875
0
        abort();
876
0
}
877
878
void log_assert_failed_return(
879
                const char *text,
880
                const char *file,
881
                int line,
882
3.69k
                const char *func) {
883
3.69k
        PROTECT_ERRNO;
884
3.69k
        log_assert(LOG_DEBUG, text, file, line, func,
885
3.69k
                   "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
886
3.69k
}
887
888
6
int log_oom_internal(int level, const char *file, int line, const char *func) {
889
6
        return log_internal(level, ENOMEM, file, line, func, "Out of memory.");
890
6
}
891
892
int log_format_iovec(
893
                struct iovec *iovec,
894
                size_t iovec_len,
895
                size_t *n,
896
                bool newline_separator,
897
                int error,
898
                const char *format,
899
0
                va_list ap) {
900
901
0
        static const char nl = '\n';
902
903
0
        while (format && *n + 1 < iovec_len) {
904
0
                va_list aq;
905
0
                char *m;
906
0
                int r;
907
908
                /* We need to copy the va_list structure,
909
                 * since vasprintf() leaves it afterwards at
910
                 * an undefined location */
911
912
0
                errno = ERRNO_VALUE(error);
913
914
0
                va_copy(aq, ap);
915
0
                r = vasprintf(&m, format, aq);
916
0
                va_end(aq);
917
0
                if (r < 0)
918
0
                        return -EINVAL;
919
920
                /* Now, jump enough ahead, so that we point to
921
                 * the next format string */
922
0
                VA_FORMAT_ADVANCE(format, ap);
923
924
0
                iovec[(*n)++] = IOVEC_MAKE_STRING(m);
925
0
                if (newline_separator)
926
0
                        iovec[(*n)++] = IOVEC_MAKE((char *)&nl, 1);
927
928
0
                format = va_arg(ap, char *);
929
0
        }
930
0
        return 0;
931
0
}
932
933
int log_struct_internal(
934
                int level,
935
                int error,
936
                const char *file,
937
                int line,
938
                const char *func,
939
7.66k
                const char *format, ...) {
940
941
7.66k
        char buf[LINE_MAX];
942
7.66k
        bool found = false;
943
7.66k
        PROTECT_ERRNO;
944
7.66k
        va_list ap;
945
946
7.66k
        if (_likely_(LOG_PRI(level) > log_max_level) ||
947
7.66k
            log_target == LOG_TARGET_NULL)
948
7.66k
                return -ERRNO_VALUE(error);
949
950
0
        if ((level & LOG_FACMASK) == 0)
951
0
                level |= log_facility;
952
953
0
        if (IN_SET(log_target,
954
0
                   LOG_TARGET_AUTO,
955
0
                   LOG_TARGET_JOURNAL_OR_KMSG,
956
0
                   LOG_TARGET_JOURNAL)) {
957
958
0
                if (open_when_needed)
959
0
                        log_open_journal();
960
961
0
                if (journal_fd >= 0) {
962
0
                        char header[LINE_MAX];
963
0
                        struct iovec iovec[17];
964
0
                        size_t n = 0;
965
0
                        int r;
966
0
                        bool fallback = false;
967
968
                        /* If the journal is available do structured logging.
969
                         * Do not report the errno if it is synthetic. */
970
0
                        log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
971
0
                        iovec[n++] = IOVEC_MAKE_STRING(header);
972
973
0
                        va_start(ap, format);
974
0
                        r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
975
0
                        if (r < 0)
976
0
                                fallback = true;
977
0
                        else {
978
0
                                const struct msghdr msghdr = {
979
0
                                        .msg_iov = iovec,
980
0
                                        .msg_iovlen = n,
981
0
                                };
982
983
0
                                (void) sendmsg(journal_fd, &msghdr, MSG_NOSIGNAL);
984
0
                        }
985
986
0
                        va_end(ap);
987
0
                        for (size_t i = 1; i < n; i += 2)
988
0
                                free(iovec[i].iov_base);
989
990
0
                        if (!fallback) {
991
0
                                if (open_when_needed)
992
0
                                        log_close();
993
994
0
                                return -ERRNO_VALUE(error);
995
0
                        }
996
0
                }
997
0
        }
998
999
        /* Fallback if journal logging is not available or didn't work. */
1000
1001
0
        va_start(ap, format);
1002
0
        while (format) {
1003
0
                va_list aq;
1004
1005
0
                errno = ERRNO_VALUE(error);
1006
1007
0
                va_copy(aq, ap);
1008
0
                (void) vsnprintf(buf, sizeof buf, format, aq);
1009
0
                va_end(aq);
1010
1011
0
                if (startswith(buf, "MESSAGE=")) {
1012
0
                        found = true;
1013
0
                        break;
1014
0
                }
1015
1016
0
                VA_FORMAT_ADVANCE(format, ap);
1017
1018
0
                format = va_arg(ap, char *);
1019
0
        }
1020
0
        va_end(ap);
1021
1022
0
        if (!found) {
1023
0
                if (open_when_needed)
1024
0
                        log_close();
1025
1026
0
                return -ERRNO_VALUE(error);
1027
0
        }
1028
1029
0
        return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
1030
0
}
1031
1032
int log_struct_iovec_internal(
1033
                int level,
1034
                int error,
1035
                const char *file,
1036
                int line,
1037
                const char *func,
1038
                const struct iovec input_iovec[],
1039
0
                size_t n_input_iovec) {
1040
1041
0
        PROTECT_ERRNO;
1042
1043
0
        if (_likely_(LOG_PRI(level) > log_max_level) ||
1044
0
            log_target == LOG_TARGET_NULL)
1045
0
                return -ERRNO_VALUE(error);
1046
1047
0
        if ((level & LOG_FACMASK) == 0)
1048
0
                level |= log_facility;
1049
1050
0
        if (IN_SET(log_target, LOG_TARGET_AUTO,
1051
0
                               LOG_TARGET_JOURNAL_OR_KMSG,
1052
0
                               LOG_TARGET_JOURNAL) &&
1053
0
            journal_fd >= 0) {
1054
1055
0
                char header[LINE_MAX];
1056
0
                log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
1057
1058
0
                struct iovec iovec[1 + n_input_iovec*2];
1059
0
                iovec[0] = IOVEC_MAKE_STRING(header);
1060
0
                for (size_t i = 0; i < n_input_iovec; i++) {
1061
0
                        iovec[1+i*2] = input_iovec[i];
1062
0
                        iovec[1+i*2+1] = IOVEC_MAKE_STRING("\n");
1063
0
                }
1064
1065
0
                const struct msghdr msghdr = {
1066
0
                        .msg_iov = iovec,
1067
0
                        .msg_iovlen = 1 + n_input_iovec*2,
1068
0
                };
1069
1070
0
                if (sendmsg(journal_fd, &msghdr, MSG_NOSIGNAL) >= 0)
1071
0
                        return -ERRNO_VALUE(error);
1072
0
        }
1073
1074
0
        for (size_t i = 0; i < n_input_iovec; i++)
1075
0
                if (memory_startswith(input_iovec[i].iov_base, input_iovec[i].iov_len, "MESSAGE=")) {
1076
0
                        char *m;
1077
1078
0
                        m = strndupa_safe((char*) input_iovec[i].iov_base + STRLEN("MESSAGE="),
1079
0
                                          input_iovec[i].iov_len - STRLEN("MESSAGE="));
1080
1081
0
                        return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, m);
1082
0
                }
1083
1084
        /* Couldn't find MESSAGE=. */
1085
0
        return -ERRNO_VALUE(error);
1086
0
}
1087
1088
0
int log_set_target_from_string(const char *e) {
1089
0
        LogTarget t;
1090
1091
0
        t = log_target_from_string(e);
1092
0
        if (t < 0)
1093
0
                return t;
1094
1095
0
        log_set_target(t);
1096
0
        return 0;
1097
0
}
1098
1099
0
int log_set_max_level_from_string(const char *e) {
1100
0
        int t;
1101
1102
0
        t = log_level_from_string(e);
1103
0
        if (t < 0)
1104
0
                return t;
1105
1106
0
        log_set_max_level(t);
1107
0
        return 0;
1108
0
}
1109
1110
0
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
1111
1112
        /*
1113
         * The systemd.log_xyz= settings are parsed by all tools, and
1114
         * so is "debug".
1115
         *
1116
         * However, "quiet" is only parsed by PID 1, and only turns of
1117
         * status output to /dev/console, but does not alter the log
1118
         * level.
1119
         */
1120
1121
0
        if (streq(key, "debug") && !value)
1122
0
                log_set_max_level(LOG_DEBUG);
1123
1124
0
        else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1125
1126
0
                if (proc_cmdline_value_missing(key, value))
1127
0
                        return 0;
1128
1129
0
                if (log_set_target_from_string(value) < 0)
1130
0
                        log_warning("Failed to parse log target '%s'. Ignoring.", value);
1131
1132
0
        } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1133
1134
0
                if (proc_cmdline_value_missing(key, value))
1135
0
                        return 0;
1136
1137
0
                if (log_set_max_level_from_string(value) < 0)
1138
0
                        log_warning("Failed to parse log level '%s'. Ignoring.", value);
1139
1140
0
        } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
1141
1142
0
                if (log_show_color_from_string(value ?: "1") < 0)
1143
0
                        log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1144
1145
0
        } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
1146
1147
0
                if (log_show_location_from_string(value ?: "1") < 0)
1148
0
                        log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1149
1150
0
        } else if (proc_cmdline_key_streq(key, "systemd.log_tid")) {
1151
1152
0
                if (log_show_tid_from_string(value ?: "1") < 0)
1153
0
                        log_warning("Failed to parse log tid setting '%s'. Ignoring.", value);
1154
1155
0
        } else if (proc_cmdline_key_streq(key, "systemd.log_time")) {
1156
1157
0
                if (log_show_time_from_string(value ?: "1") < 0)
1158
0
                        log_warning("Failed to parse log time setting '%s'. Ignoring.", value);
1159
1160
0
        }
1161
1162
0
        return 0;
1163
0
}
1164
1165
4.60k
static bool should_parse_proc_cmdline(void) {
1166
4.60k
        const char *e;
1167
4.60k
        pid_t p;
1168
1169
        /* PID1 always reads the kernel command line. */
1170
4.60k
        if (getpid_cached() == 1)
1171
0
                return true;
1172
1173
        /* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
1174
         * or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
1175
4.60k
        e = getenv("SYSTEMD_EXEC_PID");
1176
4.60k
        if (!e)
1177
4.60k
                return false;
1178
1179
0
        if (streq(e, "*"))
1180
                /* For testing. */
1181
0
                return true;
1182
1183
0
        if (parse_pid(e, &p) < 0) {
1184
                /* We know that systemd sets the variable correctly. Something else must have set it. */
1185
0
                log_debug("Failed to parse \"$SYSTEMD_EXEC_PID=%s\". Ignoring.", e);
1186
0
                return false;
1187
0
        }
1188
1189
0
        return getpid_cached() == p;
1190
0
}
1191
1192
4.60k
void log_parse_environment_variables(void) {
1193
4.60k
        const char *e;
1194
1195
4.60k
        e = getenv("SYSTEMD_LOG_TARGET");
1196
4.60k
        if (e && log_set_target_from_string(e) < 0)
1197
4.60k
                log_warning("Failed to parse log target '%s'. Ignoring.", e);
1198
1199
4.60k
        e = getenv("SYSTEMD_LOG_LEVEL");
1200
4.60k
        if (e && log_set_max_level_from_string(e) < 0)
1201
4.60k
                log_warning("Failed to parse log level '%s'. Ignoring.", e);
1202
1203
4.60k
        e = getenv("SYSTEMD_LOG_COLOR");
1204
4.60k
        if (e && log_show_color_from_string(e) < 0)
1205
4.60k
                log_warning("Failed to parse log color '%s'. Ignoring.", e);
1206
1207
4.60k
        e = getenv("SYSTEMD_LOG_LOCATION");
1208
4.60k
        if (e && log_show_location_from_string(e) < 0)
1209
4.60k
                log_warning("Failed to parse log location '%s'. Ignoring.", e);
1210
1211
4.60k
        e = getenv("SYSTEMD_LOG_TIME");
1212
4.60k
        if (e && log_show_time_from_string(e) < 0)
1213
4.60k
                log_warning("Failed to parse log time '%s'. Ignoring.", e);
1214
1215
4.60k
        e = getenv("SYSTEMD_LOG_TID");
1216
4.60k
        if (e && log_show_tid_from_string(e) < 0)
1217
4.60k
                log_warning("Failed to parse log tid '%s'. Ignoring.", e);
1218
4.60k
}
1219
1220
4.60k
void log_parse_environment(void) {
1221
        /* Do not call from library code. */
1222
1223
4.60k
        if (should_parse_proc_cmdline())
1224
0
                (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
1225
1226
4.60k
        log_parse_environment_variables();
1227
4.60k
}
1228
1229
0
LogTarget log_get_target(void) {
1230
0
        return log_target;
1231
0
}
1232
1233
20.9M
int log_get_max_level(void) {
1234
20.9M
        return log_max_level;
1235
20.9M
}
1236
1237
0
void log_show_color(bool b) {
1238
0
        show_color = b;
1239
0
}
1240
1241
0
bool log_get_show_color(void) {
1242
0
        return show_color > 0; /* Defaults to false. */
1243
0
}
1244
1245
0
void log_show_location(bool b) {
1246
0
        show_location = b;
1247
0
}
1248
1249
0
bool log_get_show_location(void) {
1250
0
        return show_location;
1251
0
}
1252
1253
0
void log_show_time(bool b) {
1254
0
        show_time = b;
1255
0
}
1256
1257
0
bool log_get_show_time(void) {
1258
0
        return show_time;
1259
0
}
1260
1261
0
void log_show_tid(bool b) {
1262
0
        show_tid = b;
1263
0
}
1264
1265
0
bool log_get_show_tid(void) {
1266
0
        return show_tid;
1267
0
}
1268
1269
0
int log_show_color_from_string(const char *e) {
1270
0
        int t;
1271
1272
0
        t = parse_boolean(e);
1273
0
        if (t < 0)
1274
0
                return t;
1275
1276
0
        log_show_color(t);
1277
0
        return 0;
1278
0
}
1279
1280
0
int log_show_location_from_string(const char *e) {
1281
0
        int t;
1282
1283
0
        t = parse_boolean(e);
1284
0
        if (t < 0)
1285
0
                return t;
1286
1287
0
        log_show_location(t);
1288
0
        return 0;
1289
0
}
1290
1291
0
int log_show_time_from_string(const char *e) {
1292
0
        int t;
1293
1294
0
        t = parse_boolean(e);
1295
0
        if (t < 0)
1296
0
                return t;
1297
1298
0
        log_show_time(t);
1299
0
        return 0;
1300
0
}
1301
1302
0
int log_show_tid_from_string(const char *e) {
1303
0
        int t;
1304
1305
0
        t = parse_boolean(e);
1306
0
        if (t < 0)
1307
0
                return t;
1308
1309
0
        log_show_tid(t);
1310
0
        return 0;
1311
0
}
1312
1313
0
bool log_on_console(void) {
1314
0
        if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1315
0
                               LOG_TARGET_CONSOLE_PREFIXED))
1316
0
                return true;
1317
1318
0
        return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1319
0
}
1320
1321
static const char *const log_target_table[_LOG_TARGET_MAX] = {
1322
        [LOG_TARGET_CONSOLE]          = "console",
1323
        [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
1324
        [LOG_TARGET_KMSG]             = "kmsg",
1325
        [LOG_TARGET_JOURNAL]          = "journal",
1326
        [LOG_TARGET_JOURNAL_OR_KMSG]  = "journal-or-kmsg",
1327
        [LOG_TARGET_SYSLOG]           = "syslog",
1328
        [LOG_TARGET_SYSLOG_OR_KMSG]   = "syslog-or-kmsg",
1329
        [LOG_TARGET_AUTO]             = "auto",
1330
        [LOG_TARGET_NULL]             = "null",
1331
};
1332
1333
DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
1334
1335
0
void log_received_signal(int level, const struct signalfd_siginfo *si) {
1336
0
        assert(si);
1337
1338
0
        if (pid_is_valid(si->ssi_pid)) {
1339
0
                _cleanup_free_ char *p = NULL;
1340
1341
0
                (void) get_process_comm(si->ssi_pid, &p);
1342
1343
0
                log_full(level,
1344
0
                         "Received SIG%s from PID %"PRIu32" (%s).",
1345
0
                         signal_to_string(si->ssi_signo),
1346
0
                         si->ssi_pid, strna(p));
1347
0
        } else
1348
0
                log_full(level,
1349
0
                         "Received SIG%s.",
1350
0
                         signal_to_string(si->ssi_signo));
1351
0
}
1352
1353
0
void set_log_syntax_callback(log_syntax_callback_t cb, void *userdata) {
1354
0
        assert(!log_syntax_callback || !cb);
1355
0
        assert(!log_syntax_callback_userdata || !userdata);
1356
1357
0
        log_syntax_callback = cb;
1358
0
        log_syntax_callback_userdata = userdata;
1359
0
}
1360
1361
int log_syntax_internal(
1362
                const char *unit,
1363
                int level,
1364
                const char *config_file,
1365
                unsigned config_line,
1366
                int error,
1367
                const char *file,
1368
                int line,
1369
                const char *func,
1370
0
                const char *format, ...) {
1371
1372
0
        if (log_syntax_callback)
1373
0
                log_syntax_callback(unit, level, log_syntax_callback_userdata);
1374
1375
0
        PROTECT_ERRNO;
1376
0
        char buffer[LINE_MAX];
1377
0
        va_list ap;
1378
0
        const char *unit_fmt = NULL;
1379
1380
0
        if (_likely_(LOG_PRI(level) > log_max_level) ||
1381
0
            log_target == LOG_TARGET_NULL)
1382
0
                return -ERRNO_VALUE(error);
1383
1384
0
        errno = ERRNO_VALUE(error);
1385
1386
0
        va_start(ap, format);
1387
0
        (void) vsnprintf(buffer, sizeof buffer, format, ap);
1388
0
        va_end(ap);
1389
1390
0
        if (unit)
1391
0
                unit_fmt = getpid_cached() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1392
1393
0
        if (config_file) {
1394
0
                if (config_line > 0)
1395
0
                        return log_struct_internal(
1396
0
                                        level,
1397
0
                                        error,
1398
0
                                        file, line, func,
1399
0
                                        "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1400
0
                                        "CONFIG_FILE=%s", config_file,
1401
0
                                        "CONFIG_LINE=%u", config_line,
1402
0
                                        LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
1403
0
                                        unit_fmt, unit,
1404
0
                                        NULL);
1405
0
                else
1406
0
                        return log_struct_internal(
1407
0
                                        level,
1408
0
                                        error,
1409
0
                                        file, line, func,
1410
0
                                        "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1411
0
                                        "CONFIG_FILE=%s", config_file,
1412
0
                                        LOG_MESSAGE("%s: %s", config_file, buffer),
1413
0
                                        unit_fmt, unit,
1414
0
                                        NULL);
1415
0
        } else if (unit)
1416
0
                return log_struct_internal(
1417
0
                                level,
1418
0
                                error,
1419
0
                                file, line, func,
1420
0
                                "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1421
0
                                LOG_MESSAGE("%s: %s", unit, buffer),
1422
0
                                unit_fmt, unit,
1423
0
                                NULL);
1424
0
        else
1425
0
                return log_struct_internal(
1426
0
                                level,
1427
0
                                error,
1428
0
                                file, line, func,
1429
0
                                "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
1430
0
                                LOG_MESSAGE("%s", buffer),
1431
0
                                NULL);
1432
0
}
1433
1434
int log_syntax_invalid_utf8_internal(
1435
                const char *unit,
1436
                int level,
1437
                const char *config_file,
1438
                unsigned config_line,
1439
                const char *file,
1440
                int line,
1441
                const char *func,
1442
0
                const char *rvalue) {
1443
1444
0
        _cleanup_free_ char *p = NULL;
1445
1446
0
        if (rvalue)
1447
0
                p = utf8_escape_invalid(rvalue);
1448
1449
0
        return log_syntax_internal(unit, level, config_file, config_line,
1450
0
                                   SYNTHETIC_ERRNO(EINVAL), file, line, func,
1451
0
                                   "String is not UTF-8 clean, ignoring assignment: %s", strna(p));
1452
0
}
1453
1454
0
void log_set_upgrade_syslog_to_journal(bool b) {
1455
0
        upgrade_syslog_to_journal = b;
1456
1457
        /* Make the change effective immediately */
1458
0
        if (b) {
1459
0
                if (log_target == LOG_TARGET_SYSLOG)
1460
0
                        log_target = LOG_TARGET_JOURNAL;
1461
0
                else if (log_target == LOG_TARGET_SYSLOG_OR_KMSG)
1462
0
                        log_target = LOG_TARGET_JOURNAL_OR_KMSG;
1463
0
        }
1464
0
}
1465
1466
0
void log_set_always_reopen_console(bool b) {
1467
0
        always_reopen_console = b;
1468
0
}
1469
1470
0
void log_set_open_when_needed(bool b) {
1471
0
        open_when_needed = b;
1472
0
}
1473
1474
0
void log_set_prohibit_ipc(bool b) {
1475
0
        prohibit_ipc = b;
1476
0
}
1477
1478
0
int log_emergency_level(void) {
1479
        /* Returns the log level to use for log_emergency() logging. We use LOG_EMERG only when we are PID 1, as only
1480
         * then the system of the whole system is obviously affected. */
1481
1482
0
        return getpid_cached() == 1 ? LOG_EMERG : LOG_ERR;
1483
0
}
1484
1485
0
int log_dup_console(void) {
1486
0
        int copy;
1487
1488
        /* Duplicate the fd we use for fd logging if it's < 3 and use the copy from now on. This call is useful
1489
         * whenever we want to continue logging through the original fd, but want to rearrange stderr. */
1490
1491
0
        if (console_fd >= 3)
1492
0
                return 0;
1493
1494
0
        copy = fcntl(console_fd, F_DUPFD_CLOEXEC, 3);
1495
0
        if (copy < 0)
1496
0
                return -errno;
1497
1498
0
        console_fd = copy;
1499
0
        return 0;
1500
0
}
1501
1502
0
void log_setup(void) {
1503
0
        log_set_target(LOG_TARGET_AUTO);
1504
0
        log_parse_environment();
1505
0
        (void) log_open();
1506
0
        if (log_on_console() && show_color < 0)
1507
0
                log_show_color(true);
1508
0
}