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