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