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