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