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