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