LCOV - code coverage report
Current view: top level - basic - log.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 191 511 37.4 %
Date: 2015-07-29 18:47:03 Functions: 23 50 46.0 %

          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             : }

Generated by: LCOV version 1.11