]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/log.c
process-util: add getpid_cached() as a caching wrapper for getpid()
[thirdparty/systemd.git] / src / basic / log.c
CommitLineData
a7334b09
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 14 Lesser General Public License for more details.
a7334b09 15
5430f7f2 16 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
c9b97d2a 20#include <errno.h>
16801e90 21#include <fcntl.h>
11c3a366
TA
22#include <inttypes.h>
23#include <limits.h>
07630cea
LP
24#include <stdarg.h>
25#include <stddef.h>
26#include <stdio.h>
11c3a366
TA
27#include <string.h>
28#include <sys/signalfd.h>
16801e90 29#include <sys/socket.h>
11c3a366
TA
30#include <sys/time.h>
31#include <sys/uio.h>
16801e90 32#include <sys/un.h>
11c3a366 33#include <time.h>
07630cea 34#include <unistd.h>
5899f3b7 35
158350e8 36#include "sd-messages.h"
07630cea 37
b5efdb8a 38#include "alloc-util.h"
3ffd4af2 39#include "fd-util.h"
f97b34a6 40#include "format-util.h"
afc5dbf3 41#include "io-util.h"
3ffd4af2 42#include "log.h"
07630cea
LP
43#include "macro.h"
44#include "missing.h"
4e731273
LP
45#include "parse-util.h"
46#include "proc-cmdline.h"
0b452006 47#include "process-util.h"
24882e06 48#include "signal-util.h"
07630cea 49#include "socket-util.h"
15a5e950 50#include "stdio-util.h"
8b43440b 51#include "string-table.h"
07630cea 52#include "string-util.h"
7ccbd1ae 53#include "syslog-util.h"
07630cea 54#include "terminal-util.h"
93cc7779 55#include "time-util.h"
07630cea 56#include "util.h"
5899f3b7 57
bb99a35a
LP
58#define SNDBUF_SIZE (8*1024*1024)
59
16801e90 60static LogTarget log_target = LOG_TARGET_CONSOLE;
ff524019
ZJS
61static int log_max_level[] = {LOG_INFO, LOG_INFO};
62assert_cc(ELEMENTSOF(log_max_level) == _LOG_REALM_MAX);
3eff4208 63static int log_facility = LOG_DAEMON;
16801e90 64
843d2643 65static int console_fd = STDERR_FILENO;
16801e90
LP
66static int syslog_fd = -1;
67static int kmsg_fd = -1;
5ba081b0 68static int journal_fd = -1;
16801e90 69
c31e1495
LP
70static bool syslog_is_stream = false;
71
bbe63281
LP
72static bool show_color = false;
73static bool show_location = false;
74
c1dc6153 75static bool upgrade_syslog_to_journal = false;
48a601fe 76static bool always_reopen_console = false;
c1dc6153 77
35b8ca3a 78/* Akin to glibc's __abort_msg; which is private and we hence cannot
185986c6
LP
79 * use here. */
80static char *log_abort_msg = NULL;
81
843d2643
LP
82void log_close_console(void) {
83
84 if (console_fd < 0)
85 return;
16801e90 86
c8513d54
LP
87 if (getpid() == 1) {
88 if (console_fd >= 3)
03e334a1 89 safe_close(console_fd);
c8513d54 90
843d2643 91 console_fd = -1;
16801e90
LP
92 }
93}
94
843d2643 95static int log_open_console(void) {
16801e90 96
843d2643 97 if (console_fd >= 0)
16801e90 98 return 0;
843d2643 99
48a601fe 100 if (always_reopen_console) {
5ba081b0 101 console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
cd15c418 102 if (console_fd < 0)
843d2643 103 return console_fd;
843d2643
LP
104 } else
105 console_fd = STDERR_FILENO;
106
107 return 0;
108}
109
110void log_close_kmsg(void) {
03e334a1 111 kmsg_fd = safe_close(kmsg_fd);
843d2643
LP
112}
113
114static int log_open_kmsg(void) {
16801e90
LP
115
116 if (kmsg_fd >= 0)
117 return 0;
118
674f8283 119 kmsg_fd = open("/dev/kmsg", O_WRONLY|O_NOCTTY|O_CLOEXEC);
cd15c418 120 if (kmsg_fd < 0)
16801e90 121 return -errno;
0dae83f9 122
16801e90
LP
123 return 0;
124}
125
126void log_close_syslog(void) {
03e334a1 127 syslog_fd = safe_close(syslog_fd);
16801e90
LP
128}
129
c31e1495 130static int create_log_socket(int type) {
8b18fdc1 131 struct timeval tv;
95066a90 132 int fd;
c31e1495 133
8b18fdc1 134 fd = socket(AF_UNIX, type|SOCK_CLOEXEC, 0);
5ba081b0 135 if (fd < 0)
c31e1495
LP
136 return -errno;
137
0474ef7b 138 (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
bb99a35a 139
8b18fdc1
LP
140 /* We need a blocking fd here since we'd otherwise lose
141 messages way too early. However, let's not hang forever in the
142 unlikely case of a deadlock. */
4d89874a
ZJS
143 if (getpid() == 1)
144 timeval_store(&tv, 10 * USEC_PER_MSEC);
145 else
146 timeval_store(&tv, 10 * USEC_PER_SEC);
086891e5 147 (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
8b18fdc1 148
c31e1495
LP
149 return fd;
150}
151
843d2643 152static int log_open_syslog(void) {
95066a90
LP
153
154 static const union sockaddr_union sa = {
b92bea5d
ZJS
155 .un.sun_family = AF_UNIX,
156 .un.sun_path = "/dev/log",
157 };
16801e90 158
95066a90
LP
159 int r;
160
16801e90
LP
161 if (syslog_fd >= 0)
162 return 0;
163
5ba081b0
LP
164 syslog_fd = create_log_socket(SOCK_DGRAM);
165 if (syslog_fd < 0) {
166 r = syslog_fd;
843d2643 167 goto fail;
16801e90
LP
168 }
169
fc2fffe7 170 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
03e334a1 171 safe_close(syslog_fd);
c31e1495
LP
172
173 /* Some legacy syslog systems still use stream
174 * sockets. They really shouldn't. But what can we
175 * do... */
5ba081b0
LP
176 syslog_fd = create_log_socket(SOCK_STREAM);
177 if (syslog_fd < 0) {
178 r = syslog_fd;
c31e1495
LP
179 goto fail;
180 }
181
fc2fffe7 182 if (connect(syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
c31e1495
LP
183 r = -errno;
184 goto fail;
185 }
186
187 syslog_is_stream = true;
188 } else
189 syslog_is_stream = false;
190
16801e90 191 return 0;
843d2643
LP
192
193fail:
194 log_close_syslog();
843d2643
LP
195 return r;
196}
197
5ba081b0 198void log_close_journal(void) {
03e334a1 199 journal_fd = safe_close(journal_fd);
5ba081b0
LP
200}
201
202static int log_open_journal(void) {
95066a90
LP
203
204 static const union sockaddr_union sa = {
b92bea5d
ZJS
205 .un.sun_family = AF_UNIX,
206 .un.sun_path = "/run/systemd/journal/socket",
207 };
95066a90 208
5ba081b0
LP
209 int r;
210
211 if (journal_fd >= 0)
212 return 0;
213
214 journal_fd = create_log_socket(SOCK_DGRAM);
215 if (journal_fd < 0) {
216 r = journal_fd;
217 goto fail;
218 }
219
fc2fffe7 220 if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
5ba081b0
LP
221 r = -errno;
222 goto fail;
223 }
224
5ba081b0
LP
225 return 0;
226
227fail:
228 log_close_journal();
5ba081b0
LP
229 return r;
230}
231
843d2643
LP
232int log_open(void) {
233 int r;
234
e3e42fc2
ZJS
235 /* Do not call from library code. */
236
843d2643
LP
237 /* If we don't use the console we close it here, to not get
238 * killed by SAK. If we don't use syslog we close it here so
239 * that we are not confused by somebody deleting the socket in
240 * the fs. If we don't use /dev/kmsg we still keep it open,
241 * because there is no reason to close it. */
242
9fae33d2 243 if (log_target == LOG_TARGET_NULL) {
5ba081b0 244 log_close_journal();
9fae33d2
LP
245 log_close_syslog();
246 log_close_console();
247 return 0;
248 }
249
5b5688af 250 if (!IN_SET(log_target, LOG_TARGET_AUTO, LOG_TARGET_SAFE) ||
bb7df0da 251 getpid() == 1 ||
f41c094c 252 isatty(STDERR_FILENO) <= 0) {
bb7df0da 253
5b5688af
ZJS
254 if (IN_SET(log_target, LOG_TARGET_AUTO,
255 LOG_TARGET_JOURNAL_OR_KMSG,
256 LOG_TARGET_JOURNAL)) {
5ba081b0
LP
257 r = log_open_journal();
258 if (r >= 0) {
259 log_close_syslog();
bb7df0da
LP
260 log_close_console();
261 return r;
262 }
5ba081b0
LP
263 }
264
5b5688af
ZJS
265 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
266 LOG_TARGET_SYSLOG)) {
5ba081b0
LP
267 r = log_open_syslog();
268 if (r >= 0) {
269 log_close_journal();
270 log_close_console();
271 return r;
272 }
273 }
274
5b5688af
ZJS
275 if (IN_SET(log_target, LOG_TARGET_AUTO,
276 LOG_TARGET_SAFE,
277 LOG_TARGET_JOURNAL_OR_KMSG,
278 LOG_TARGET_SYSLOG_OR_KMSG,
279 LOG_TARGET_KMSG)) {
5ba081b0
LP
280 r = log_open_kmsg();
281 if (r >= 0) {
282 log_close_journal();
bb7df0da
LP
283 log_close_syslog();
284 log_close_console();
285 return r;
286 }
5ba081b0 287 }
bb7df0da 288 }
843d2643 289
5ba081b0 290 log_close_journal();
843d2643 291 log_close_syslog();
dcdf86bb 292
843d2643 293 return log_open_console();
16801e90
LP
294}
295
296void log_set_target(LogTarget target) {
297 assert(target >= 0);
298 assert(target < _LOG_TARGET_MAX);
299
c1dc6153
LP
300 if (upgrade_syslog_to_journal) {
301 if (target == LOG_TARGET_SYSLOG)
302 target = LOG_TARGET_JOURNAL;
303 else if (target == LOG_TARGET_SYSLOG_OR_KMSG)
304 target = LOG_TARGET_JOURNAL_OR_KMSG;
305 }
306
16801e90
LP
307 log_target = target;
308}
309
871e5809 310void log_close(void) {
e3e42fc2
ZJS
311 /* Do not call from library code. */
312
5ba081b0 313 log_close_journal();
871e5809 314 log_close_syslog();
5ba081b0
LP
315 log_close_kmsg();
316 log_close_console();
871e5809
LP
317}
318
4d8a7798 319void log_forget_fds(void) {
e3e42fc2
ZJS
320 /* Do not call from library code. */
321
5ba081b0 322 console_fd = kmsg_fd = syslog_fd = journal_fd = -1;
4d8a7798
MS
323}
324
ff524019 325void log_set_max_level_realm(LogRealm realm, int level) {
16801e90 326 assert((level & LOG_PRIMASK) == level);
ff524019 327 assert(realm < ELEMENTSOF(log_max_level));
16801e90 328
ff524019 329 log_max_level[realm] = level;
16801e90
LP
330}
331
3eff4208
LP
332void log_set_facility(int facility) {
333 log_facility = facility;
334}
335
843d2643 336static int write_to_console(
20c03b7b 337 int level,
086891e5 338 int error,
95066a90 339 const char *file,
20c03b7b
LP
340 int line,
341 const char *func,
342 const char *buffer) {
5899f3b7 343
79c95440 344 char location[256], prefix[1 + DECIMAL_STR_MAX(int) + 2];
aca83a53 345 struct iovec iovec[6] = {};
843d2643
LP
346 unsigned n = 0;
347 bool highlight;
5899f3b7 348
843d2643
LP
349 if (console_fd < 0)
350 return 0;
351
aca83a53 352 if (log_target == LOG_TARGET_CONSOLE_PREFIXED) {
0474ef7b 353 xsprintf(prefix, "<%i>", level);
aca83a53
LP
354 IOVEC_SET_STRING(iovec[n++], prefix);
355 }
356
bbe63281 357 highlight = LOG_PRI(level) <= LOG_ERR && show_color;
843d2643 358
674f8283 359 if (show_location) {
79c95440 360 snprintf(location, sizeof(location), "(%s:%i) ", file, line);
bbe63281 361 IOVEC_SET_STRING(iovec[n++], location);
674f8283
LP
362 }
363
843d2643 364 if (highlight)
1fc464f6 365 IOVEC_SET_STRING(iovec[n++], ANSI_HIGHLIGHT_RED);
843d2643
LP
366 IOVEC_SET_STRING(iovec[n++], buffer);
367 if (highlight)
1fc464f6 368 IOVEC_SET_STRING(iovec[n++], ANSI_NORMAL);
843d2643
LP
369 IOVEC_SET_STRING(iovec[n++], "\n");
370
0e6eaa2d
LP
371 if (writev(console_fd, iovec, n) < 0) {
372
373 if (errno == EIO && getpid() == 1) {
374
375 /* If somebody tried to kick us from our
376 * console tty (via vhangup() or suchlike),
377 * try to reconnect */
378
379 log_close_console();
380 log_open_console();
381
382 if (console_fd < 0)
383 return 0;
384
385 if (writev(console_fd, iovec, n) < 0)
386 return -errno;
387 } else
388 return -errno;
389 }
5899f3b7 390
843d2643 391 return 1;
16801e90 392}
5899f3b7 393
16801e90 394static int write_to_syslog(
086891e5
LP
395 int level,
396 int error,
95066a90 397 const char *file,
086891e5
LP
398 int line,
399 const char *func,
086891e5 400 const char *buffer) {
16801e90 401
5ffa8c81
ZJS
402 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
403 header_time[64],
404 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
b92bea5d
ZJS
405 struct iovec iovec[5] = {};
406 struct msghdr msghdr = {
407 .msg_iov = iovec,
408 .msg_iovlen = ELEMENTSOF(iovec),
409 };
16801e90
LP
410 time_t t;
411 struct tm *tm;
412
413 if (syslog_fd < 0)
843d2643 414 return 0;
16801e90 415
5ffa8c81 416 xsprintf(header_priority, "<%i>", level);
16801e90
LP
417
418 t = (time_t) (now(CLOCK_REALTIME) / USEC_PER_SEC);
fdf9f9bb
ZJS
419 tm = localtime(&t);
420 if (!tm)
16801e90
LP
421 return -EINVAL;
422
423 if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0)
424 return -EINVAL;
425
5ffa8c81 426 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
16801e90 427
16801e90
LP
428 IOVEC_SET_STRING(iovec[0], header_priority);
429 IOVEC_SET_STRING(iovec[1], header_time);
5b6319dc 430 IOVEC_SET_STRING(iovec[2], program_invocation_short_name);
16801e90
LP
431 IOVEC_SET_STRING(iovec[3], header_pid);
432 IOVEC_SET_STRING(iovec[4], buffer);
433
c899f8c6 434 /* When using syslog via SOCK_STREAM separate the messages by NUL chars */
c31e1495
LP
435 if (syslog_is_stream)
436 iovec[4].iov_len++;
437
c31e1495
LP
438 for (;;) {
439 ssize_t n;
440
8f7f7a1b
MS
441 n = sendmsg(syslog_fd, &msghdr, MSG_NOSIGNAL);
442 if (n < 0)
c31e1495
LP
443 return -errno;
444
445 if (!syslog_is_stream ||
446 (size_t) n >= IOVEC_TOTAL_SIZE(iovec, ELEMENTSOF(iovec)))
447 break;
448
449 IOVEC_INCREMENT(iovec, ELEMENTSOF(iovec), n);
450 }
16801e90 451
843d2643 452 return 1;
16801e90
LP
453}
454
455static int write_to_kmsg(
086891e5
LP
456 int level,
457 int error,
bcf5c276 458 const char *file,
086891e5
LP
459 int line,
460 const char *func,
086891e5 461 const char *buffer) {
16801e90 462
5ffa8c81
ZJS
463 char header_priority[2 + DECIMAL_STR_MAX(int) + 1],
464 header_pid[4 + DECIMAL_STR_MAX(pid_t) + 1];
b92bea5d 465 struct iovec iovec[5] = {};
16801e90
LP
466
467 if (kmsg_fd < 0)
843d2643 468 return 0;
16801e90 469
5ffa8c81
ZJS
470 xsprintf(header_priority, "<%i>", level);
471 xsprintf(header_pid, "["PID_FMT"]: ", getpid());
16801e90 472
16801e90 473 IOVEC_SET_STRING(iovec[0], header_priority);
5b6319dc 474 IOVEC_SET_STRING(iovec[1], program_invocation_short_name);
16801e90
LP
475 IOVEC_SET_STRING(iovec[2], header_pid);
476 IOVEC_SET_STRING(iovec[3], buffer);
843d2643 477 IOVEC_SET_STRING(iovec[4], "\n");
16801e90
LP
478
479 if (writev(kmsg_fd, iovec, ELEMENTSOF(iovec)) < 0)
480 return -errno;
481
843d2643 482 return 1;
16801e90
LP
483}
484
086891e5
LP
485static int log_do_header(
486 char *header,
487 size_t size,
488 int level,
489 int error,
490 const char *file, int line, const char *func,
4b58153d
LP
491 const char *object_field, const char *object,
492 const char *extra_field, const char *extra) {
086891e5 493
41a79f10 494 snprintf(header, size,
5ba081b0 495 "PRIORITY=%i\n"
3eff4208 496 "SYSLOG_FACILITY=%i\n"
086891e5 497 "%s%s%s"
e429981b 498 "%s%.*i%s"
086891e5
LP
499 "%s%s%s"
500 "%s%.*i%s"
501 "%s%s%s"
4b58153d 502 "%s%s%s"
41a79f10 503 "SYSLOG_IDENTIFIER=%s\n",
5ba081b0 504 LOG_PRI(level),
3eff4208 505 LOG_FAC(level),
086891e5
LP
506 isempty(file) ? "" : "CODE_FILE=",
507 isempty(file) ? "" : file,
508 isempty(file) ? "" : "\n",
e429981b
ZJS
509 line ? "CODE_LINE=" : "",
510 line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
511 line ? "\n" : "",
b457b33d 512 isempty(func) ? "" : "CODE_FUNC=",
086891e5
LP
513 isempty(func) ? "" : func,
514 isempty(func) ? "" : "\n",
515 error ? "ERRNO=" : "",
516 error ? 1 : 0, error,
517 error ? "\n" : "",
518 isempty(object) ? "" : object_field,
519 isempty(object) ? "" : object,
520 isempty(object) ? "" : "\n",
4b58153d
LP
521 isempty(extra) ? "" : extra_field,
522 isempty(extra) ? "" : extra,
523 isempty(extra) ? "" : "\n",
d29b05a4 524 program_invocation_short_name);
086891e5 525
41a79f10
ZJS
526 return 0;
527}
5ba081b0 528
41a79f10 529static int write_to_journal(
086891e5
LP
530 int level,
531 int error,
bcf5c276 532 const char *file,
086891e5
LP
533 int line,
534 const char *func,
535 const char *object_field,
536 const char *object,
4b58153d
LP
537 const char *extra_field,
538 const char *extra,
086891e5 539 const char *buffer) {
41a79f10
ZJS
540
541 char header[LINE_MAX];
b92bea5d
ZJS
542 struct iovec iovec[4] = {};
543 struct msghdr mh = {};
41a79f10
ZJS
544
545 if (journal_fd < 0)
546 return 0;
547
4b58153d 548 log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object, extra_field, extra);
5ba081b0 549
5ba081b0 550 IOVEC_SET_STRING(iovec[0], header);
41a79f10
ZJS
551 IOVEC_SET_STRING(iovec[1], "MESSAGE=");
552 IOVEC_SET_STRING(iovec[2], buffer);
553 IOVEC_SET_STRING(iovec[3], "\n");
5ba081b0 554
5ba081b0
LP
555 mh.msg_iov = iovec;
556 mh.msg_iovlen = ELEMENTSOF(iovec);
557
558 if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
559 return -errno;
560
561 return 1;
562}
563
93484b47 564int log_dispatch_internal(
086891e5
LP
565 int level,
566 int error,
95066a90 567 const char *file,
086891e5
LP
568 int line,
569 const char *func,
570 const char *object_field,
571 const char *object,
4b58153d
LP
572 const char *extra,
573 const char *extra_field,
086891e5 574 char *buffer) {
843d2643 575
bf371116 576 assert(buffer);
843d2643 577
0474ef7b
LP
578 if (error < 0)
579 error = -error;
580
9fae33d2 581 if (log_target == LOG_TARGET_NULL)
bf371116 582 return -error;
9fae33d2 583
29db5834 584 /* Patch in LOG_DAEMON facility if necessary */
7d76f312 585 if ((level & LOG_FACMASK) == 0)
3eff4208 586 level = log_facility | LOG_PRI(level);
29db5834 587
9726b29e
LP
588 do {
589 char *e;
9499b235 590 int k = 0;
843d2643 591
9726b29e 592 buffer += strspn(buffer, NEWLINE);
843d2643 593
9726b29e
LP
594 if (buffer[0] == 0)
595 break;
843d2643 596
9726b29e
LP
597 if ((e = strpbrk(buffer, NEWLINE)))
598 *(e++) = 0;
843d2643 599
5b5688af
ZJS
600 if (IN_SET(log_target, LOG_TARGET_AUTO,
601 LOG_TARGET_JOURNAL_OR_KMSG,
602 LOG_TARGET_JOURNAL)) {
5ba081b0 603
4b58153d 604 k = write_to_journal(level, error, file, line, func, object_field, object, extra_field, extra, buffer);
4e7bc3f3
LP
605 if (k < 0) {
606 if (k != -EAGAIN)
5ba081b0
LP
607 log_close_journal();
608 log_open_kmsg();
bf371116 609 }
5ba081b0
LP
610 }
611
5b5688af
ZJS
612 if (IN_SET(log_target, LOG_TARGET_SYSLOG_OR_KMSG,
613 LOG_TARGET_SYSLOG)) {
9726b29e 614
4b58153d 615 k = write_to_syslog(level, error, file, line, func, buffer);
4e7bc3f3
LP
616 if (k < 0) {
617 if (k != -EAGAIN)
8f7f7a1b 618 log_close_syslog();
9726b29e 619 log_open_kmsg();
bf371116 620 }
9726b29e
LP
621 }
622
9499b235 623 if (k <= 0 &&
5b5688af
ZJS
624 IN_SET(log_target, LOG_TARGET_AUTO,
625 LOG_TARGET_SAFE,
626 LOG_TARGET_SYSLOG_OR_KMSG,
627 LOG_TARGET_JOURNAL_OR_KMSG,
628 LOG_TARGET_KMSG)) {
9726b29e 629
4b58153d 630 k = write_to_kmsg(level, error, file, line, func, buffer);
4e7bc3f3
LP
631 if (k < 0) {
632 log_close_kmsg();
9726b29e 633 log_open_console();
bf371116 634 }
9726b29e
LP
635 }
636
bf371116 637 if (k <= 0)
4b58153d 638 (void) write_to_console(level, error, file, line, func, buffer);
9726b29e
LP
639
640 buffer = e;
641 } while (buffer);
642
bf371116 643 return -error;
843d2643
LP
644}
645
2149e37c 646int log_dump_internal(
ff524019
ZJS
647 int level,
648 int error,
649 const char *file,
650 int line,
651 const char *func,
652 char *buffer) {
2149e37c 653
ff524019 654 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
5c0aa72a 655 PROTECT_ERRNO;
2149e37c
LP
656
657 /* This modifies the buffer... */
658
bf371116
LP
659 if (error < 0)
660 error = -error;
661
ff524019 662 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
bf371116 663 return -error;
2149e37c 664
93484b47 665 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
2149e37c
LP
666}
667
ff524019 668int log_internalv_realm(
086891e5
LP
669 int level,
670 int error,
bcf5c276 671 const char *file,
086891e5
LP
672 int line,
673 const char *func,
674 const char *format,
675 va_list ap) {
16801e90 676
ff524019 677 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
addab137 678 char buffer[LINE_MAX];
ff524019 679 PROTECT_ERRNO;
16801e90 680
bf371116
LP
681 if (error < 0)
682 error = -error;
683
ff524019 684 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
bf371116 685 return -error;
16801e90 686
086891e5
LP
687 /* Make sure that %m maps to the specified error */
688 if (error != 0)
bf371116 689 errno = error;
086891e5 690
843d2643 691 vsnprintf(buffer, sizeof(buffer), format, ap);
843d2643 692
93484b47 693 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buffer);
185986c6 694}
16801e90 695
ff524019 696int log_internal_realm(
086891e5
LP
697 int level,
698 int error,
bcf5c276 699 const char *file,
086891e5
LP
700 int line,
701 const char *func,
702 const char *format, ...) {
17a94911 703
17a94911 704 va_list ap;
bf371116 705 int r;
17a94911
LP
706
707 va_start(ap, format);
ff524019 708 r = log_internalv_realm(level, error, file, line, func, format, ap);
17a94911
LP
709 va_end(ap);
710
711 return r;
712}
713
79008bdd 714int log_object_internalv(
086891e5
LP
715 int level,
716 int error,
bcf5c276 717 const char *file,
086891e5
LP
718 int line,
719 const char *func,
720 const char *object_field,
721 const char *object,
4b58153d
LP
722 const char *extra_field,
723 const char *extra,
086891e5
LP
724 const char *format,
725 va_list ap) {
fdf9f9bb 726
5c0aa72a 727 PROTECT_ERRNO;
f2341e0a 728 char *buffer, *b;
fdf9f9bb 729
bf371116
LP
730 if (error < 0)
731 error = -error;
732
ff524019 733 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
bf371116 734 return -error;
fdf9f9bb 735
086891e5
LP
736 /* Make sure that %m maps to the specified error */
737 if (error != 0)
bf371116 738 errno = error;
086891e5 739
f2341e0a
LP
740 /* Prepend the object name before the message */
741 if (object) {
742 size_t n;
743
744 n = strlen(object);
1741b25c 745 buffer = newa(char, n + 2 + LINE_MAX);
f2341e0a 746 b = stpcpy(stpcpy(buffer, object), ": ");
1741b25c
EV
747 } else
748 b = buffer = newa(char, LINE_MAX);
f2341e0a 749
1741b25c 750 vsnprintf(b, LINE_MAX, format, ap);
fdf9f9bb 751
93484b47
ZJS
752 return log_dispatch_internal(level, error, file, line, func,
753 object_field, object, extra_field, extra, buffer);
fdf9f9bb
ZJS
754}
755
79008bdd 756int log_object_internal(
086891e5
LP
757 int level,
758 int error,
bcf5c276 759 const char *file,
086891e5
LP
760 int line,
761 const char *func,
762 const char *object_field,
763 const char *object,
4b58153d
LP
764 const char *extra_field,
765 const char *extra,
086891e5 766 const char *format, ...) {
fdf9f9bb 767
fdf9f9bb 768 va_list ap;
bf371116 769 int r;
fdf9f9bb
ZJS
770
771 va_start(ap, format);
4b58153d 772 r = log_object_internalv(level, error, file, line, func, object_field, object, extra_field, extra, format, ap);
fdf9f9bb
ZJS
773 va_end(ap);
774
775 return r;
776}
777
086891e5
LP
778static void log_assert(
779 int level,
780 const char *text,
781 const char *file,
782 int line,
783 const char *func,
784 const char *format) {
785
addab137 786 static char buffer[LINE_MAX];
ff524019 787 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
185986c6 788
ff524019 789 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
50f72bca
ZJS
790 return;
791
bcfce235 792 DISABLE_WARNING_FORMAT_NONLITERAL;
e68eedbb 793 snprintf(buffer, sizeof buffer, format, text, file, line, func);
bcfce235 794 REENABLE_WARNING;
185986c6 795
185986c6
LP
796 log_abort_msg = buffer;
797
93484b47 798 log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
5899f3b7 799}
34f0e866 800
ff524019
ZJS
801noreturn void log_assert_failed_realm(
802 LogRealm realm,
803 const char *text,
804 const char *file,
805 int line,
806 const char *func) {
807 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
808 "Assertion '%s' failed at %s:%u, function %s(). Aborting.");
80514f9c 809 abort();
b7f33638
MS
810}
811
ff524019
ZJS
812noreturn void log_assert_failed_unreachable_realm(
813 LogRealm realm,
814 const char *text,
815 const char *file,
816 int line,
817 const char *func) {
818 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
819 "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
80514f9c
LP
820 abort();
821}
822
ff524019
ZJS
823void log_assert_failed_return_realm(
824 LogRealm realm,
825 const char *text,
826 const char *file,
827 int line,
828 const char *func) {
e5ca092c 829 PROTECT_ERRNO;
ff524019
ZJS
830 log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_DEBUG), text, file, line, func,
831 "Assertion '%s' failed at %s:%u, function %s(). Ignoring.");
b7f33638
MS
832}
833
ff524019
ZJS
834int log_oom_internal(LogRealm realm, const char *file, int line, const char *func) {
835 log_internal_realm(LOG_REALM_PLUS_LEVEL(realm, LOG_ERR),
836 ENOMEM, file, line, func, "Out of memory.");
6dc1e7e0
MS
837 return -ENOMEM;
838}
839
8a03c9ef
ZJS
840int log_format_iovec(
841 struct iovec *iovec,
842 unsigned iovec_len,
843 unsigned *n,
844 bool newline_separator,
845 int error,
846 const char *format,
847 va_list ap) {
848
849 static const char nl = '\n';
850
851 while (format && *n + 1 < iovec_len) {
852 va_list aq;
853 char *m;
854 int r;
855
856 /* We need to copy the va_list structure,
857 * since vasprintf() leaves it afterwards at
858 * an undefined location */
859
860 if (error != 0)
861 errno = error;
862
863 va_copy(aq, ap);
864 r = vasprintf(&m, format, aq);
865 va_end(aq);
866 if (r < 0)
867 return -EINVAL;
868
869 /* Now, jump enough ahead, so that we point to
870 * the next format string */
871 VA_FORMAT_ADVANCE(format, ap);
872
873 IOVEC_SET_STRING(iovec[(*n)++], m);
874
875 if (newline_separator) {
876 iovec[*n].iov_base = (char*) &nl;
877 iovec[*n].iov_len = 1;
878 (*n)++;
879 }
880
881 format = va_arg(ap, char *);
882 }
883 return 0;
884}
885
877d54e9
LP
886int log_struct_internal(
887 int level,
086891e5 888 int error,
877d54e9
LP
889 const char *file,
890 int line,
891 const char *func,
892 const char *format, ...) {
893
bf371116
LP
894 char buf[LINE_MAX];
895 bool found = false;
ff524019 896 LogRealm realm = LOG_REALM_REMOVE_LEVEL(level);
5c0aa72a 897 PROTECT_ERRNO;
877d54e9 898 va_list ap;
bf371116
LP
899
900 if (error < 0)
901 error = -error;
877d54e9 902
ff524019 903 if (_likely_(LOG_PRI(level) > log_max_level[realm]))
bf371116 904 return -error;
877d54e9
LP
905
906 if (log_target == LOG_TARGET_NULL)
bf371116 907 return -error;
877d54e9
LP
908
909 if ((level & LOG_FACMASK) == 0)
910 level = log_facility | LOG_PRI(level);
911
5b5688af
ZJS
912 if (IN_SET(log_target, LOG_TARGET_AUTO,
913 LOG_TARGET_JOURNAL_OR_KMSG,
914 LOG_TARGET_JOURNAL) &&
877d54e9 915 journal_fd >= 0) {
877d54e9 916 char header[LINE_MAX];
b92bea5d 917 struct iovec iovec[17] = {};
877d54e9 918 unsigned n = 0, i;
8a03c9ef 919 int r;
543295ad
ZJS
920 struct msghdr mh = {
921 .msg_iov = iovec,
922 };
bf371116 923 bool fallback = false;
877d54e9
LP
924
925 /* If the journal is available do structured logging */
4b58153d 926 log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL, NULL, NULL);
877d54e9
LP
927 IOVEC_SET_STRING(iovec[n++], header);
928
929 va_start(ap, format);
8a03c9ef
ZJS
930 r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap);
931 if (r < 0)
932 fallback = true;
933 else {
934 mh.msg_iovlen = n;
935 (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL);
877d54e9 936 }
877d54e9 937
e98055de 938 va_end(ap);
877d54e9
LP
939 for (i = 1; i < n; i += 2)
940 free(iovec[i].iov_base);
941
bf371116
LP
942 if (!fallback)
943 return -error;
944 }
877d54e9 945
bf371116 946 /* Fallback if journal logging is not available or didn't work. */
6357ac66 947
bf371116
LP
948 va_start(ap, format);
949 while (format) {
950 va_list aq;
877d54e9 951
bf371116
LP
952 if (error != 0)
953 errno = error;
877d54e9 954
bf371116
LP
955 va_copy(aq, ap);
956 vsnprintf(buf, sizeof(buf), format, aq);
957 va_end(aq);
963ddb91 958
bf371116
LP
959 if (startswith(buf, "MESSAGE=")) {
960 found = true;
961 break;
877d54e9 962 }
877d54e9 963
bf371116
LP
964 VA_FORMAT_ADVANCE(format, ap);
965
966 format = va_arg(ap, char *);
877d54e9 967 }
bf371116 968 va_end(ap);
877d54e9 969
bf371116
LP
970 if (!found)
971 return -error;
972
93484b47 973 return log_dispatch_internal(level, error, file, line, func, NULL, NULL, NULL, NULL, buf + 8);
877d54e9
LP
974}
975
34f0e866
LP
976int log_set_target_from_string(const char *e) {
977 LogTarget t;
978
5ba081b0
LP
979 t = log_target_from_string(e);
980 if (t < 0)
34f0e866
LP
981 return -EINVAL;
982
983 log_set_target(t);
984 return 0;
985}
986
ff524019 987int log_set_max_level_from_string_realm(LogRealm realm, const char *e) {
34f0e866
LP
988 int t;
989
5ba081b0
LP
990 t = log_level_from_string(e);
991 if (t < 0)
737af734 992 return -EINVAL;
34f0e866 993
ff524019 994 log_set_max_level_realm(realm, t);
34f0e866
LP
995 return 0;
996}
997
96287a49 998static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
1de1c9c3
LP
999
1000 /*
1001 * The systemd.log_xyz= settings are parsed by all tools, and
1002 * so is "debug".
1003 *
5e07a79e
LP
1004 * However, "quiet" is only parsed by PID 1, and only turns of
1005 * status output to /dev/console, but does not alter the log
1006 * level.
1de1c9c3
LP
1007 */
1008
1009 if (streq(key, "debug") && !value)
1010 log_set_max_level(LOG_DEBUG);
1011
1d84ad94
LP
1012 else if (proc_cmdline_key_streq(key, "systemd.log_target")) {
1013
1014 if (proc_cmdline_value_missing(key, value))
1015 return 0;
1de1c9c3
LP
1016
1017 if (log_set_target_from_string(value) < 0)
1018 log_warning("Failed to parse log target '%s'. Ignoring.", value);
1019
1d84ad94
LP
1020 } else if (proc_cmdline_key_streq(key, "systemd.log_level")) {
1021
1022 if (proc_cmdline_value_missing(key, value))
1023 return 0;
1de1c9c3
LP
1024
1025 if (log_set_max_level_from_string(value) < 0)
1026 log_warning("Failed to parse log level '%s'. Ignoring.", value);
1027
1d84ad94 1028 } else if (proc_cmdline_key_streq(key, "systemd.log_color")) {
1de1c9c3 1029
1d84ad94 1030 if (log_show_color_from_string(value ?: "1") < 0)
1de1c9c3
LP
1031 log_warning("Failed to parse log color setting '%s'. Ignoring.", value);
1032
1d84ad94 1033 } else if (proc_cmdline_key_streq(key, "systemd.log_location")) {
1de1c9c3 1034
1d84ad94 1035 if (log_show_location_from_string(value ?: "1") < 0)
1de1c9c3
LP
1036 log_warning("Failed to parse log location setting '%s'. Ignoring.", value);
1037 }
1038
1039 return 0;
1040}
1041
ff524019 1042void log_parse_environment_realm(LogRealm realm) {
e3e42fc2
ZJS
1043 /* Do not call from library code. */
1044
34f0e866 1045 const char *e;
b8d0ffc2 1046
ee46e555 1047 if (get_ctty_devnr(0, NULL) < 0)
1d84ad94
LP
1048 /* Only try to read the command line in daemons. We assume that anything that has a controlling tty is
1049 user stuff. */
1050 (void) proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_STRIP_RD_PREFIX);
34f0e866 1051
a99e002c 1052 e = getenv("SYSTEMD_LOG_TARGET");
88fae6e0 1053 if (e && log_set_target_from_string(e) < 0)
f0ea29ea 1054 log_warning("Failed to parse log target '%s'. Ignoring.", e);
34f0e866 1055
a99e002c 1056 e = getenv("SYSTEMD_LOG_LEVEL");
ff524019 1057 if (e && log_set_max_level_from_string_realm(realm, e) < 0)
f0ea29ea 1058 log_warning("Failed to parse log level '%s'. Ignoring.", e);
bbe63281 1059
a99e002c 1060 e = getenv("SYSTEMD_LOG_COLOR");
88fae6e0 1061 if (e && log_show_color_from_string(e) < 0)
f0ea29ea 1062 log_warning("Failed to parse bool '%s'. Ignoring.", e);
bbe63281 1063
a99e002c 1064 e = getenv("SYSTEMD_LOG_LOCATION");
88fae6e0 1065 if (e && log_show_location_from_string(e) < 0)
f0ea29ea 1066 log_warning("Failed to parse bool '%s'. Ignoring.", e);
34f0e866
LP
1067}
1068
1adf1049
LP
1069LogTarget log_get_target(void) {
1070 return log_target;
1071}
1072
ff524019
ZJS
1073int log_get_max_level_realm(LogRealm realm) {
1074 return log_max_level[realm];
1adf1049
LP
1075}
1076
bbe63281
LP
1077void log_show_color(bool b) {
1078 show_color = b;
1079}
1080
b1e90ec5
ZJS
1081bool log_get_show_color(void) {
1082 return show_color;
1083}
1084
bbe63281
LP
1085void log_show_location(bool b) {
1086 show_location = b;
1087}
1088
b1e90ec5
ZJS
1089bool log_get_show_location(void) {
1090 return show_location;
1091}
1092
bbe63281
LP
1093int log_show_color_from_string(const char *e) {
1094 int t;
1095
5ba081b0
LP
1096 t = parse_boolean(e);
1097 if (t < 0)
1098 return t;
bbe63281
LP
1099
1100 log_show_color(t);
1101 return 0;
1102}
1103
1104int log_show_location_from_string(const char *e) {
1105 int t;
1106
5ba081b0
LP
1107 t = parse_boolean(e);
1108 if (t < 0)
1109 return t;
bbe63281
LP
1110
1111 log_show_location(t);
1112 return 0;
1113}
1114
81270860 1115bool log_on_console(void) {
5b5688af
ZJS
1116 if (IN_SET(log_target, LOG_TARGET_CONSOLE,
1117 LOG_TARGET_CONSOLE_PREFIXED))
81270860
LP
1118 return true;
1119
1120 return syslog_fd < 0 && kmsg_fd < 0 && journal_fd < 0;
1121}
1122
2c5859af 1123static const char *const log_target_table[_LOG_TARGET_MAX] = {
34f0e866 1124 [LOG_TARGET_CONSOLE] = "console",
aca83a53 1125 [LOG_TARGET_CONSOLE_PREFIXED] = "console-prefixed",
34f0e866 1126 [LOG_TARGET_KMSG] = "kmsg",
5ba081b0
LP
1127 [LOG_TARGET_JOURNAL] = "journal",
1128 [LOG_TARGET_JOURNAL_OR_KMSG] = "journal-or-kmsg",
1129 [LOG_TARGET_SYSLOG] = "syslog",
843d2643 1130 [LOG_TARGET_SYSLOG_OR_KMSG] = "syslog-or-kmsg",
5ba081b0 1131 [LOG_TARGET_AUTO] = "auto",
a6903061 1132 [LOG_TARGET_SAFE] = "safe",
5ba081b0 1133 [LOG_TARGET_NULL] = "null"
34f0e866
LP
1134};
1135
1136DEFINE_STRING_TABLE_LOOKUP(log_target, LogTarget);
4daf54a8
ZJS
1137
1138void log_received_signal(int level, const struct signalfd_siginfo *si) {
1139 if (si->ssi_pid > 0) {
1140 _cleanup_free_ char *p = NULL;
1141
1142 get_process_comm(si->ssi_pid, &p);
1143
1144 log_full(level,
1fa2f38f 1145 "Received SIG%s from PID %"PRIu32" (%s).",
4daf54a8
ZJS
1146 signal_to_string(si->ssi_signo),
1147 si->ssi_pid, strna(p));
1148 } else
1149 log_full(level,
1150 "Received SIG%s.",
1151 signal_to_string(si->ssi_signo));
1152
1153}
c1dc6153
LP
1154
1155void log_set_upgrade_syslog_to_journal(bool b) {
1156 upgrade_syslog_to_journal = b;
1157}
158350e8
LP
1158
1159int log_syntax_internal(
1160 const char *unit,
1161 int level,
1162 const char *config_file,
1163 unsigned config_line,
1164 int error,
1165 const char *file,
1166 int line,
1167 const char *func,
1168 const char *format, ...) {
1169
1170 PROTECT_ERRNO;
1171 char buffer[LINE_MAX];
158350e8 1172 va_list ap;
c2dec702 1173 const char *unit_fmt = NULL;
158350e8
LP
1174
1175 if (error < 0)
1176 error = -error;
1177
ff524019 1178 if (_likely_(LOG_PRI(level) > log_max_level[LOG_REALM_SYSTEMD]))
158350e8
LP
1179 return -error;
1180
1181 if (log_target == LOG_TARGET_NULL)
1182 return -error;
1183
1184 if (error != 0)
1185 errno = error;
1186
1187 va_start(ap, format);
1188 vsnprintf(buffer, sizeof(buffer), format, ap);
1189 va_end(ap);
1190
1191 if (unit)
c2dec702
ZJS
1192 unit_fmt = getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s";
1193
1194 return log_struct_internal(
ff524019
ZJS
1195 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
1196 error,
c2dec702 1197 file, line, func,
2b044526 1198 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
c2dec702
ZJS
1199 "CONFIG_FILE=%s", config_file,
1200 "CONFIG_LINE=%u", config_line,
e697dfef 1201 LOG_MESSAGE("%s:%u: %s", config_file, config_line, buffer),
c2dec702
ZJS
1202 unit_fmt, unit,
1203 NULL);
158350e8 1204}
48a601fe
LP
1205
1206void log_set_always_reopen_console(bool b) {
1207 always_reopen_console = b;
1208}