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