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