LCOV - code coverage report
Current view: top level - common - logging.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 148 355 41.7 %
Date: 2016-09-12 12:29:17 Functions: 17 32 53.1 %

          Line data    Source code
       1             : /* logging.c - Useful logging functions
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
       3             :  *               2009, 2010 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify it
       8             :  * under the terms of either
       9             :  *
      10             :  *   - the GNU Lesser General Public License as published by the Free
      11             :  *     Software Foundation; either version 3 of the License, or (at
      12             :  *     your option) any later version.
      13             :  *
      14             :  * or
      15             :  *
      16             :  *   - the GNU General Public License as published by the Free
      17             :  *     Software Foundation; either version 2 of the License, or (at
      18             :  *     your option) any later version.
      19             :  *
      20             :  * or both in parallel, as here.
      21             :  *
      22             :  * GnuPG is distributed in the hope that it will be useful, but
      23             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      24             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      25             :  * General Public License for more details.
      26             :  *
      27             :  * You should have received a copies of the GNU General Public License
      28             :  * and the GNU Lesser General Public License along with this program;
      29             :  * if not, see <http://www.gnu.org/licenses/>.
      30             :  */
      31             : 
      32             : 
      33             : #include <config.h>
      34             : #include <stdlib.h>
      35             : #include <stdio.h>
      36             : #include <string.h>
      37             : #include <stdarg.h>
      38             : #include <stddef.h>
      39             : #include <errno.h>
      40             : #include <time.h>
      41             : #include <sys/types.h>
      42             : #include <sys/stat.h>
      43             : #ifdef HAVE_W32_SYSTEM
      44             : # ifdef HAVE_WINSOCK2_H
      45             : #  include <winsock2.h>
      46             : # endif
      47             : # include <windows.h>
      48             : #else /*!HAVE_W32_SYSTEM*/
      49             : # include <sys/socket.h>
      50             : # include <sys/un.h>
      51             : # include <netinet/in.h>
      52             : # include <arpa/inet.h>
      53             : #endif /*!HAVE_W32_SYSTEM*/
      54             : #include <unistd.h>
      55             : #include <fcntl.h>
      56             : #include <assert.h>
      57             : /* #include <execinfo.h> */
      58             : 
      59             : #define GNUPG_COMMON_NEED_AFLOCAL 1
      60             : #include "util.h"
      61             : #include "i18n.h"
      62             : #include "common-defs.h"
      63             : #include "logging.h"
      64             : 
      65             : #ifdef HAVE_W32_SYSTEM
      66             : # define S_IRGRP S_IRUSR
      67             : # define S_IROTH S_IRUSR
      68             : # define S_IWGRP S_IWUSR
      69             : # define S_IWOTH S_IWUSR
      70             : #endif
      71             : 
      72             : 
      73             : #ifdef HAVE_W32CE_SYSTEM
      74             : # define isatty(a)  (0)
      75             : #endif
      76             : 
      77             : #undef WITH_IPV6
      78             : #if defined (AF_INET6) && defined(PF_INET) \
      79             :     && defined (INET6_ADDRSTRLEN) && defined(HAVE_INET_PTON)
      80             : # define WITH_IPV6 1
      81             : #endif
      82             : 
      83             : #ifndef EAFNOSUPPORT
      84             : # define EAFNOSUPPORT EINVAL
      85             : #endif
      86             : #ifndef INADDR_NONE  /* Slowaris is missing that.  */
      87             : #define INADDR_NONE  ((unsigned long)(-1))
      88             : #endif /*INADDR_NONE*/
      89             : 
      90             : #ifdef HAVE_W32_SYSTEM
      91             : #define sock_close(a)  closesocket(a)
      92             : #else
      93             : #define sock_close(a)  close(a)
      94             : #endif
      95             : 
      96             : 
      97             : static estream_t logstream;
      98             : static int log_socket = -1;
      99             : static char prefix_buffer[80];
     100             : static int with_time;
     101             : static int with_prefix;
     102             : static int with_pid;
     103             : #ifdef HAVE_W32_SYSTEM
     104             : static int no_registry;
     105             : #endif
     106             : static int (*get_pid_suffix_cb)(unsigned long *r_value);
     107             : static const char * (*socket_dir_cb)(void);
     108             : static int running_detached;
     109             : static int force_prefixes;
     110             : 
     111             : static int missing_lf;
     112             : static int errorcount;
     113             : 
     114             : 
     115             : int
     116        7607 : log_get_errorcount (int clear)
     117             : {
     118        7607 :     int n = errorcount;
     119        7607 :     if( clear )
     120           0 :         errorcount = 0;
     121        7607 :     return n;
     122             : }
     123             : 
     124             : void
     125           6 : log_inc_errorcount (void)
     126             : {
     127           6 :    errorcount++;
     128           6 : }
     129             : 
     130             : 
     131             : /* The following 3 functions are used by es_fopencookie to write logs
     132             :    to a socket.  */
     133             : struct fun_cookie_s
     134             : {
     135             :   int fd;
     136             :   int quiet;
     137             :   int want_socket;
     138             :   int is_socket;
     139             : #ifdef HAVE_W32CE_SYSTEM
     140             :   int use_writefile;
     141             : #endif
     142             :   char name[1];
     143             : };
     144             : 
     145             : 
     146             : /* Write NBYTES of BUFFER to file descriptor FD. */
     147             : static int
     148        8769 : writen (int fd, const void *buffer, size_t nbytes, int is_socket)
     149             : {
     150        8769 :   const char *buf = buffer;
     151        8769 :   size_t nleft = nbytes;
     152             :   int nwritten;
     153             : #ifndef HAVE_W32_SYSTEM
     154             :   (void)is_socket; /* Not required.  */
     155             : #endif
     156             : 
     157       23384 :   while (nleft > 0)
     158             :     {
     159             : #ifdef HAVE_W32_SYSTEM
     160             :       if (is_socket)
     161             :         nwritten = send (fd, buf, nleft, 0);
     162             :       else
     163             : #endif
     164        5846 :         nwritten = write (fd, buf, nleft);
     165             : 
     166        5846 :       if (nwritten < 0 && errno == EINTR)
     167           0 :         continue;
     168        5846 :       if (nwritten < 0)
     169           0 :         return -1;
     170        5846 :       nleft -= nwritten;
     171        5846 :       buf = buf + nwritten;
     172             :     }
     173             : 
     174        8769 :   return 0;
     175             : }
     176             : 
     177             : 
     178             : /* Returns true if STR represents a valid port number in decimal
     179             :    notation and no garbage is following.  */
     180             : static int
     181           0 : parse_portno (const char *str, unsigned short *r_port)
     182             : {
     183             :   unsigned int value;
     184             : 
     185           0 :   for (value=0; *str && (*str >= '0' && *str <= '9'); str++)
     186             :     {
     187           0 :       value = value * 10 + (*str - '0');
     188           0 :       if (value > 65535)
     189           0 :         return 0;
     190             :     }
     191           0 :   if (*str || !value)
     192           0 :     return 0;
     193             : 
     194           0 :   *r_port = value;
     195           0 :   return 1;
     196             : }
     197             : 
     198             : 
     199             : static gpgrt_ssize_t
     200        8769 : fun_writer (void *cookie_arg, const void *buffer, size_t size)
     201             : {
     202        8769 :   struct fun_cookie_s *cookie = cookie_arg;
     203             : 
     204             :   /* FIXME: Use only estream with a callback for socket writing.  This
     205             :      avoids the ugly mix of fd and estream code.  */
     206             : 
     207             :   /* Note that we always try to reconnect to the socket but print
     208             :      error messages only the first time an error occurred.  If
     209             :      RUNNING_DETACHED is set we don't fall back to stderr and even do
     210             :      not print any error messages.  This is needed because detached
     211             :      processes often close stderr and by writing to file descriptor 2
     212             :      we might send the log message to a file not intended for logging
     213             :      (e.g. a pipe or network connection). */
     214        8769 :   if (cookie->want_socket && cookie->fd == -1)
     215             :     {
     216             : #ifdef WITH_IPV6
     217             :       struct sockaddr_in6 srvr_addr_in6;
     218             : #endif
     219             :       struct sockaddr_in srvr_addr_in;
     220             : #ifndef HAVE_W32_SYSTEM
     221             :       struct sockaddr_un srvr_addr_un;
     222             : #endif
     223           0 :       const char *name_for_err = "";
     224             :       size_t addrlen;
     225           0 :       struct sockaddr *srvr_addr = NULL;
     226           0 :       unsigned short port = 0;
     227           0 :       int af = AF_LOCAL;
     228           0 :       int pf = PF_LOCAL;
     229           0 :       const char *name = cookie->name;
     230             : 
     231             :       /* Not yet open or meanwhile closed due to an error. */
     232           0 :       cookie->is_socket = 0;
     233             : 
     234             :       /* Check whether this is a TCP socket or a local socket.  */
     235           0 :       if (!strncmp (name, "tcp://", 6) && name[6])
     236             :         {
     237           0 :           name += 6;
     238           0 :           af = AF_INET;
     239           0 :           pf = PF_INET;
     240             :         }
     241             : #ifndef HAVE_W32_SYSTEM
     242           0 :       else if (!strncmp (name, "socket://", 9))
     243           0 :         name += 9;
     244             : #endif
     245             : 
     246           0 :       if (af == AF_LOCAL)
     247             :         {
     248           0 :           addrlen = 0;
     249             : #ifndef HAVE_W32_SYSTEM
     250           0 :           memset (&srvr_addr, 0, sizeof srvr_addr);
     251           0 :           srvr_addr_un.sun_family = af;
     252           0 :           if (!*name && (name = socket_dir_cb ()) && *name)
     253             :             {
     254           0 :               if (strlen (name) + 7 < sizeof (srvr_addr_un.sun_path)-1)
     255             :                 {
     256           0 :                   strncpy (srvr_addr_un.sun_path,
     257             :                            name, sizeof (srvr_addr_un.sun_path)-1);
     258           0 :                   strcat (srvr_addr_un.sun_path, "/S.log");
     259           0 :                   srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0;
     260           0 :                   srvr_addr = (struct sockaddr *)&srvr_addr_un;
     261           0 :                   addrlen = SUN_LEN (&srvr_addr_un);
     262           0 :                   name_for_err = srvr_addr_un.sun_path;
     263             :                 }
     264             :             }
     265             :           else
     266             :             {
     267           0 :               if (*name && strlen (name) < sizeof (srvr_addr_un.sun_path)-1)
     268             :                 {
     269           0 :                   strncpy (srvr_addr_un.sun_path,
     270             :                            name, sizeof (srvr_addr_un.sun_path)-1);
     271           0 :                   srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0;
     272           0 :                   srvr_addr = (struct sockaddr *)&srvr_addr_un;
     273           0 :                   addrlen = SUN_LEN (&srvr_addr_un);
     274             :                 }
     275             :             }
     276             : #endif /*!HAVE_W32SYSTEM*/
     277             :         }
     278             :       else
     279             :         {
     280             :           char *addrstr, *p;
     281             : #ifdef HAVE_INET_PTON
     282           0 :           void *addrbuf = NULL;
     283             : #endif /*HAVE_INET_PTON*/
     284             : 
     285           0 :           addrstr = xtrymalloc (strlen (name) + 1);
     286           0 :           if (!addrstr)
     287           0 :             addrlen = 0; /* This indicates an error.  */
     288           0 :           else if (*name == '[')
     289             :             {
     290             :               /* Check for IPv6 literal address.  */
     291           0 :               strcpy (addrstr, name+1);
     292           0 :               p = strchr (addrstr, ']');
     293           0 :               if (!p || p[1] != ':' || !parse_portno (p+2, &port))
     294             :                 {
     295           0 :                   gpg_err_set_errno (EINVAL);
     296           0 :                   addrlen = 0;
     297             :                 }
     298             :               else
     299             :                 {
     300           0 :                   *p = 0;
     301             : #ifdef WITH_IPV6
     302           0 :                   af = AF_INET6;
     303           0 :                   pf = PF_INET6;
     304           0 :                   memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
     305           0 :                   srvr_addr_in6.sin6_family = af;
     306           0 :                   srvr_addr_in6.sin6_port = htons (port);
     307             : #ifdef HAVE_INET_PTON
     308           0 :                   addrbuf = &srvr_addr_in6.sin6_addr;
     309             : #endif /*HAVE_INET_PTON*/
     310           0 :                   srvr_addr = (struct sockaddr *)&srvr_addr_in6;
     311           0 :                   addrlen = sizeof srvr_addr_in6;
     312             : #else
     313             :                   gpg_err_set_errno (EAFNOSUPPORT);
     314             :                   addrlen = 0;
     315             : #endif
     316             :                 }
     317             :             }
     318             :           else
     319             :             {
     320             :               /* Check for IPv4 literal address.  */
     321           0 :               strcpy (addrstr, name);
     322           0 :               p = strchr (addrstr, ':');
     323           0 :               if (!p || !parse_portno (p+1, &port))
     324             :                 {
     325           0 :                   gpg_err_set_errno (EINVAL);
     326           0 :                   addrlen = 0;
     327             :                 }
     328             :               else
     329             :                 {
     330           0 :                   *p = 0;
     331           0 :                   memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
     332           0 :                   srvr_addr_in.sin_family = af;
     333           0 :                   srvr_addr_in.sin_port = htons (port);
     334             : #ifdef HAVE_INET_PTON
     335           0 :                   addrbuf = &srvr_addr_in.sin_addr;
     336             : #endif /*HAVE_INET_PTON*/
     337           0 :                   srvr_addr = (struct sockaddr *)&srvr_addr_in;
     338           0 :                   addrlen = sizeof srvr_addr_in;
     339             :                 }
     340             :             }
     341             : 
     342           0 :           if (addrlen)
     343             :             {
     344             : #ifdef HAVE_INET_PTON
     345           0 :               if (inet_pton (af, addrstr, addrbuf) != 1)
     346           0 :                 addrlen = 0;
     347             : #else /*!HAVE_INET_PTON*/
     348             :               /* We need to use the old function.  If we are here v6
     349             :                  support isn't enabled anyway and thus we can do fine
     350             :                  without.  Note that Windows has a compatible inet_pton
     351             :                  function named inetPton, but only since Vista.  */
     352             :               srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr);
     353             :               if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE)
     354             :                 addrlen = 0;
     355             : #endif /*!HAVE_INET_PTON*/
     356             :             }
     357             : 
     358           0 :           xfree (addrstr);
     359             :         }
     360             : 
     361           0 :       cookie->fd = addrlen? socket (pf, SOCK_STREAM, 0) : -1;
     362           0 :       if (cookie->fd == -1)
     363             :         {
     364           0 :           if (!cookie->quiet && !running_detached
     365           0 :               && isatty (es_fileno (es_stderr)))
     366           0 :             es_fprintf (es_stderr, "failed to create socket for logging: %s\n",
     367           0 :                         strerror(errno));
     368             :         }
     369             :       else
     370             :         {
     371           0 :           if (connect (cookie->fd, srvr_addr, addrlen) == -1)
     372             :             {
     373           0 :               if (!cookie->quiet && !running_detached
     374           0 :                   && isatty (es_fileno (es_stderr)))
     375           0 :                 es_fprintf (es_stderr, "can't connect to '%s%s': %s\n",
     376           0 :                             cookie->name, name_for_err, strerror(errno));
     377           0 :               sock_close (cookie->fd);
     378           0 :               cookie->fd = -1;
     379             :             }
     380             :         }
     381             : 
     382           0 :       if (cookie->fd == -1)
     383             :         {
     384           0 :           if (!running_detached)
     385             :             {
     386             :               /* Due to all the problems with apps not running
     387             :                  detached but being called with stderr closed or used
     388             :                  for a different purposes, it does not make sense to
     389             :                  switch to stderr.  We therefore disable it. */
     390           0 :               if (!cookie->quiet)
     391             :                 {
     392             :                   /* fputs ("switching logging to stderr\n", stderr);*/
     393           0 :                   cookie->quiet = 1;
     394             :                 }
     395           0 :               cookie->fd = -1; /*fileno (stderr);*/
     396             :             }
     397             :         }
     398             :       else /* Connection has been established. */
     399             :         {
     400           0 :           cookie->quiet = 0;
     401           0 :           cookie->is_socket = 1;
     402             :         }
     403             :     }
     404             : 
     405        8769 :   log_socket = cookie->fd;
     406        8769 :   if (cookie->fd != -1)
     407             :     {
     408             : #ifdef HAVE_W32CE_SYSTEM
     409             :       if (cookie->use_writefile)
     410             :         {
     411             :           DWORD nwritten;
     412             : 
     413             :           WriteFile ((HANDLE)cookie->fd, buffer, size, &nwritten, NULL);
     414             :           return (gpgrt_ssize_t)size; /* Okay.  */
     415             :         }
     416             : #endif
     417        8769 :       if (!writen (cookie->fd, buffer, size, cookie->is_socket))
     418        8769 :         return (gpgrt_ssize_t)size; /* Okay. */
     419             :     }
     420             : 
     421           0 :   if (!running_detached && cookie->fd != -1
     422           0 :       && isatty (es_fileno (es_stderr)))
     423             :     {
     424           0 :       if (*cookie->name)
     425           0 :         es_fprintf (es_stderr, "error writing to '%s': %s\n",
     426           0 :                     cookie->name, strerror(errno));
     427             :       else
     428           0 :         es_fprintf (es_stderr, "error writing to file descriptor %d: %s\n",
     429           0 :                     cookie->fd, strerror(errno));
     430             :     }
     431           0 :   if (cookie->is_socket && cookie->fd != -1)
     432             :     {
     433           0 :       sock_close (cookie->fd);
     434           0 :       cookie->fd = -1;
     435           0 :       log_socket = -1;
     436             :     }
     437             : 
     438           0 :   return (gpgrt_ssize_t)size;
     439             : }
     440             : 
     441             : 
     442             : static int
     443           0 : fun_closer (void *cookie_arg)
     444             : {
     445           0 :   struct fun_cookie_s *cookie = cookie_arg;
     446             : 
     447           0 :   if (cookie->fd != -1 && cookie->fd != 2)
     448           0 :     sock_close (cookie->fd);
     449           0 :   xfree (cookie);
     450           0 :   log_socket = -1;
     451           0 :   return 0;
     452             : }
     453             : 
     454             : 
     455             : /* Common function to either set the logging to a file or a file
     456             :    descriptor. */
     457             : static void
     458         978 : set_file_fd (const char *name, int fd)
     459             : {
     460             :   estream_t fp;
     461             :   int want_socket;
     462             : #ifdef HAVE_W32CE_SYSTEM
     463             :   int use_writefile = 0;
     464             : #endif
     465             :   struct fun_cookie_s *cookie;
     466             : 
     467             :   /* Close an open log stream.  */
     468         978 :   if (logstream)
     469             :     {
     470           0 :       es_fclose (logstream);
     471           0 :       logstream = NULL;
     472             :     }
     473             : 
     474             :   /* Figure out what kind of logging we want.  */
     475         978 :   if (name && !strcmp (name, "-"))
     476             :     {
     477         978 :       name = NULL;
     478         978 :       fd = es_fileno (es_stderr);
     479             :     }
     480             : 
     481         978 :   want_socket = 0;
     482         978 :   if (name && !strncmp (name, "tcp://", 6) && name[6])
     483           0 :     want_socket = 1;
     484             : #ifndef HAVE_W32_SYSTEM
     485         978 :   else if (name && !strncmp (name, "socket://", 9))
     486           0 :     want_socket = 2;
     487             : #endif /*HAVE_W32_SYSTEM*/
     488             : #ifdef HAVE_W32CE_SYSTEM
     489             :   else if (name && !strcmp (name, "GPG2:"))
     490             :     {
     491             :       HANDLE hd;
     492             : 
     493             :       ActivateDevice (L"Drivers\\"GNUPG_NAME"_Log", 0);
     494             :       /* Ignore a filename and write the debug output to the GPG2:
     495             :          device.  */
     496             :       hd = CreateFile (L"GPG2:", GENERIC_WRITE,
     497             :                        FILE_SHARE_READ | FILE_SHARE_WRITE,
     498             :                        NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     499             :       fd = (hd == INVALID_HANDLE_VALUE)? -1 : (int)hd;
     500             :       name = NULL;
     501             :       force_prefixes = 1;
     502             :       use_writefile = 1;
     503             :     }
     504             : #endif /*HAVE_W32CE_SYSTEM*/
     505             : 
     506             :   /* Setup a new stream.  */
     507             : 
     508             :   /* The xmalloc below is justified because we can expect that this
     509             :      function is called only during initialization and there is no
     510             :      easy way out of this error condition.  */
     511         978 :   cookie = xmalloc (sizeof *cookie + (name? strlen (name):0));
     512         978 :   strcpy (cookie->name, name? name:"");
     513         978 :   cookie->quiet = 0;
     514         978 :   cookie->is_socket = 0;
     515         978 :   cookie->want_socket = want_socket;
     516             : #ifdef HAVE_W32CE_SYSTEM
     517             :   cookie->use_writefile = use_writefile;
     518             : #endif
     519         978 :   if (!name)
     520         978 :     cookie->fd = fd;
     521           0 :   else if (want_socket)
     522           0 :     cookie->fd = -1;
     523             :   else
     524             :     {
     525             :       do
     526           0 :         cookie->fd = open (name, O_WRONLY|O_APPEND|O_CREAT,
     527             :                            (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH));
     528           0 :       while (cookie->fd == -1 && errno == EINTR);
     529             :     }
     530         978 :   log_socket = cookie->fd;
     531             : 
     532             :   {
     533         978 :     es_cookie_io_functions_t io = { NULL };
     534         978 :     io.func_write = fun_writer;
     535         978 :     io.func_close = fun_closer;
     536             : 
     537         978 :     fp = es_fopencookie (cookie, "w", io);
     538             :   }
     539             : 
     540             :   /* On error default to a stderr based estream.  */
     541         978 :   if (!fp)
     542           0 :     fp = es_stderr;
     543             : 
     544         978 :   es_setvbuf (fp, NULL, _IOLBF, 0);
     545             : 
     546         978 :   logstream = fp;
     547             : 
     548             :   /* We always need to print the prefix and the pid for socket mode,
     549             :      so that the server reading the socket can do something
     550             :      meaningful. */
     551         978 :   force_prefixes = want_socket;
     552             : 
     553         978 :   missing_lf = 0;
     554         978 : }
     555             : 
     556             : 
     557             : /* Set the file to write log to.  The special names NULL and "-" may
     558             :    be used to select stderr and names formatted like
     559             :    "socket:///home/foo/mylogs" may be used to write the logging to the
     560             :    socket "/home/foo/mylogs".  If the connection to the socket fails
     561             :    or a write error is detected, the function writes to stderr and
     562             :    tries the next time again to connect the socket.
     563             :   */
     564             : void
     565         978 : log_set_file (const char *name)
     566             : {
     567         978 :   set_file_fd (name? name: "-", -1);
     568         978 : }
     569             : 
     570             : void
     571           0 : log_set_fd (int fd)
     572             : {
     573           0 :   set_file_fd (NULL, fd);
     574           0 : }
     575             : 
     576             : 
     577             : /* Set a function to retrieve the directory name of a socket if
     578             :  * only "socket://" has been given to log_set_file.  */
     579             : void
     580        2340 : log_set_socket_dir_cb (const char *(*fnc)(void))
     581             : {
     582        2340 :   socket_dir_cb = fnc;
     583        2340 : }
     584             : 
     585             : 
     586             : void
     587           0 : log_set_pid_suffix_cb (int (*cb)(unsigned long *r_value))
     588             : {
     589           0 :   get_pid_suffix_cb = cb;
     590           0 : }
     591             : 
     592             : 
     593             : void
     594        2386 : log_set_prefix (const char *text, unsigned int flags)
     595             : {
     596        2386 :   if (text)
     597             :     {
     598        2341 :       strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
     599        2341 :       prefix_buffer[sizeof (prefix_buffer)-1] = 0;
     600             :     }
     601             : 
     602        2386 :   with_prefix = (flags & GPGRT_LOG_WITH_PREFIX);
     603        2386 :   with_time = (flags & GPGRT_LOG_WITH_TIME);
     604        2386 :   with_pid  = (flags & GPGRT_LOG_WITH_PID);
     605        2386 :   running_detached = (flags & GPGRT_LOG_RUN_DETACHED);
     606             : #ifdef HAVE_W32_SYSTEM
     607             :   no_registry = (flags & GPGRT_LOG_NO_REGISTRY);
     608             : #endif
     609        2386 : }
     610             : 
     611             : 
     612             : const char *
     613          45 : log_get_prefix (unsigned int *flags)
     614             : {
     615          45 :   if (flags)
     616             :     {
     617          45 :       *flags = 0;
     618          45 :       if (with_prefix)
     619          45 :         *flags |= GPGRT_LOG_WITH_PREFIX;
     620          45 :       if (with_time)
     621           0 :         *flags |= GPGRT_LOG_WITH_TIME;
     622          45 :       if (with_pid)
     623          45 :         *flags |= GPGRT_LOG_WITH_PID;
     624          45 :       if (running_detached)
     625           0 :         *flags |= GPGRT_LOG_RUN_DETACHED;
     626             : #ifdef HAVE_W32_SYSTEM
     627             :       if (no_registry)
     628             :         *flags |= GPGRT_LOG_NO_REGISTRY;
     629             : #endif
     630             :     }
     631          45 :   return prefix_buffer;
     632             : }
     633             : 
     634             : /* This function returns true if the file descriptor FD is in use for
     635             :    logging.  This is preferable over a test using log_get_fd in that
     636             :    it allows the logging code to use more then one file descriptor.  */
     637             : int
     638         135 : log_test_fd (int fd)
     639             : {
     640         135 :   if (logstream)
     641             :     {
     642         135 :       int tmp = es_fileno (logstream);
     643         135 :       if ( tmp != -1 && tmp == fd)
     644           0 :         return 1;
     645             :     }
     646         135 :   if (log_socket != -1 && log_socket == fd)
     647          45 :     return 1;
     648          90 :   return 0;
     649             : }
     650             : 
     651             : int
     652           0 : log_get_fd ()
     653             : {
     654           0 :   return logstream? es_fileno(logstream) : -1;
     655             : }
     656             : 
     657             : estream_t
     658         495 : log_get_stream ()
     659             : {
     660         495 :   if (!logstream)
     661             :     {
     662           0 :       log_set_file (NULL); /* Make sure a log stream has been set.  */
     663           0 :       assert (logstream);
     664             :     }
     665         495 :   return logstream;
     666             : }
     667             : 
     668             : static void
     669        3403 : do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
     670             : {
     671        3403 :   if (!logstream)
     672             :     {
     673             : #ifdef HAVE_W32_SYSTEM
     674             :       char *tmp;
     675             : 
     676             :       tmp = (no_registry
     677             :              ? NULL
     678             :              : read_w32_registry_string (NULL, GNUPG_REGISTRY_DIR,
     679             :                                          "DefaultLogFile"));
     680             :       log_set_file (tmp && *tmp? tmp : NULL);
     681             :       xfree (tmp);
     682             : #else
     683         978 :       log_set_file (NULL); /* Make sure a log stream has been set.  */
     684             : #endif
     685         978 :       assert (logstream);
     686             :     }
     687             : 
     688        3403 :   es_flockfile (logstream);
     689        3403 :   if (missing_lf && level != GPGRT_LOG_CONT)
     690           0 :     es_putc_unlocked ('\n', logstream );
     691        3403 :   missing_lf = 0;
     692             : 
     693        3403 :   if (level != GPGRT_LOG_CONT)
     694             :     { /* Note this does not work for multiple line logging as we would
     695             :        * need to print to a buffer first */
     696        2643 :       if (with_time && !force_prefixes)
     697             :         {
     698             :           struct tm *tp;
     699           0 :           time_t atime = time (NULL);
     700             : 
     701           0 :           tp = localtime (&atime);
     702           0 :           es_fprintf_unlocked (logstream, "%04d-%02d-%02d %02d:%02d:%02d ",
     703           0 :                                1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
     704             :                                tp->tm_hour, tp->tm_min, tp->tm_sec );
     705             :         }
     706        2643 :       if (with_prefix || force_prefixes)
     707        2642 :         es_fputs_unlocked (prefix_buffer, logstream);
     708        2643 :       if (with_pid || force_prefixes)
     709             :         {
     710             :           unsigned long pidsuf;
     711             :           int pidfmt;
     712             : 
     713         121 :           if (get_pid_suffix_cb && (pidfmt=get_pid_suffix_cb (&pidsuf)))
     714           0 :             es_fprintf_unlocked (logstream, pidfmt == 1? "[%u.%lu]":"[%u.%lx]",
     715           0 :                                  (unsigned int)getpid (), pidsuf);
     716             :           else
     717         121 :             es_fprintf_unlocked (logstream, "[%u]", (unsigned int)getpid ());
     718             :         }
     719        2643 :       if ((!with_time && (with_prefix || with_pid)) || force_prefixes)
     720        2642 :         es_putc_unlocked (':', logstream);
     721             :       /* A leading backspace suppresses the extra space so that we can
     722             :          correctly output, programname, filename and linenumber. */
     723        2643 :       if (fmt && *fmt == '\b')
     724           0 :         fmt++;
     725             :       else
     726        2643 :         if (with_time || with_prefix || with_pid || force_prefixes)
     727        2642 :           es_putc_unlocked (' ', logstream);
     728             :     }
     729             : 
     730        3403 :   switch (level)
     731             :     {
     732           0 :     case GPGRT_LOG_BEGIN: break;
     733         760 :     case GPGRT_LOG_CONT: break;
     734        2586 :     case GPGRT_LOG_INFO: break;
     735           0 :     case GPGRT_LOG_WARN: break;
     736          57 :     case GPGRT_LOG_ERROR: break;
     737           0 :     case GPGRT_LOG_FATAL: es_fputs_unlocked ("Fatal: ",logstream ); break;
     738           0 :     case GPGRT_LOG_BUG:   es_fputs_unlocked ("Ohhhh jeeee: ", logstream); break;
     739           0 :     case GPGRT_LOG_DEBUG: es_fputs_unlocked ("DBG: ", logstream ); break;
     740             :     default:
     741           0 :       es_fprintf_unlocked (logstream,"[Unknown log level %d]: ", level);
     742           0 :       break;
     743             :     }
     744             : 
     745        3403 :   if (fmt)
     746             :     {
     747        3403 :       if (ignore_arg_ptr)
     748             :         { /* This is used by log_string and comes with the extra
     749             :            * feature that after a LF the next line is indent at the
     750             :            * length of the prefix.  Note that we do not yet include
     751             :            * the length of the timestamp and pid in the indent
     752             :            * computation.  */
     753             :           const char *p, *pend;
     754             : 
     755          15 :           for (p = fmt; (pend = strchr (p, '\n')); p = pend+1)
     756          18 :             es_fprintf_unlocked (logstream, "%*s%.*s",
     757             :                                  (int)((p != fmt
     758           7 :                                         && (with_prefix || force_prefixes))
     759           7 :                                        ?strlen (prefix_buffer)+2:0), "",
     760          11 :                                  (int)(pend - p)+1, p);
     761           4 :           es_fputs_unlocked (p, logstream);
     762             :         }
     763             :       else
     764        3399 :         es_vfprintf_unlocked (logstream, fmt, arg_ptr);
     765        3403 :       if (*fmt && fmt[strlen(fmt)-1] != '\n')
     766         496 :         missing_lf = 1;
     767             :     }
     768             : 
     769        3403 :   if (level == GPGRT_LOG_FATAL)
     770             :     {
     771           0 :       if (missing_lf)
     772           0 :         es_putc_unlocked ('\n', logstream);
     773           0 :       es_funlockfile (logstream);
     774           0 :       exit (2);
     775             :     }
     776        3403 :   else if (level == GPGRT_LOG_BUG)
     777             :     {
     778           0 :       if (missing_lf)
     779           0 :         es_putc_unlocked ('\n', logstream );
     780           0 :       es_funlockfile (logstream);
     781             :       /* Using backtrace requires a configure test and to pass
     782             :        * -rdynamic to gcc.  Thus we do not enable it now.  */
     783             :       /* { */
     784             :       /*   void *btbuf[20]; */
     785             :       /*   int btidx, btlen; */
     786             :       /*   char **btstr; */
     787             : 
     788             :       /*   btlen = backtrace (btbuf, DIM (btbuf)); */
     789             :       /*   btstr = backtrace_symbols (btbuf, btlen); */
     790             :       /*   if (btstr) */
     791             :       /*     for (btidx=0; btidx < btlen; btidx++) */
     792             :       /*       log_debug ("[%d] %s\n", btidx, btstr[btidx]); */
     793             :       /* } */
     794           0 :       abort ();
     795             :     }
     796             :   else
     797        3403 :     es_funlockfile (logstream);
     798        3403 : }
     799             : 
     800             : 
     801             : void
     802           0 : log_log (int level, const char *fmt, ...)
     803             : {
     804             :   va_list arg_ptr ;
     805             : 
     806           0 :   va_start (arg_ptr, fmt) ;
     807           0 :   do_logv (level, 0, fmt, arg_ptr);
     808           0 :   va_end (arg_ptr);
     809           0 : }
     810             : 
     811             : 
     812             : void
     813           0 : log_logv (int level, const char *fmt, va_list arg_ptr)
     814             : {
     815           0 :   do_logv (level, 0, fmt, arg_ptr);
     816           0 : }
     817             : 
     818             : 
     819             : static void
     820           4 : do_log_ignore_arg (int level, const char *str, ...)
     821             : {
     822             :   va_list arg_ptr;
     823           4 :   va_start (arg_ptr, str);
     824           4 :   do_logv (level, 1, str, arg_ptr);
     825           4 :   va_end (arg_ptr);
     826           4 : }
     827             : 
     828             : 
     829             : /* Log STRING at LEVEL but indent from the second line on by the
     830             :  * length of the prefix.  */
     831             : void
     832           4 : log_string (int level, const char *string)
     833             : {
     834             :   /* We need a dummy arg_ptr, but there is no portable way to create
     835             :    * one.  So we call the do_logv function through a variadic wrapper. */
     836           4 :   do_log_ignore_arg (level, string);
     837           4 : }
     838             : 
     839             : 
     840             : void
     841        2582 : log_info (const char *fmt, ...)
     842             : {
     843             :   va_list arg_ptr ;
     844             : 
     845        2582 :   va_start (arg_ptr, fmt);
     846        2582 :   do_logv (GPGRT_LOG_INFO, 0, fmt, arg_ptr);
     847        2582 :   va_end (arg_ptr);
     848        2582 : }
     849             : 
     850             : 
     851             : void
     852          57 : log_error (const char *fmt, ...)
     853             : {
     854             :   va_list arg_ptr ;
     855             : 
     856          57 :   va_start (arg_ptr, fmt);
     857          57 :   do_logv (GPGRT_LOG_ERROR, 0, fmt, arg_ptr);
     858          57 :   va_end (arg_ptr);
     859             :   /* Protect against counter overflow.  */
     860          57 :   if (errorcount < 30000)
     861          57 :     errorcount++;
     862          57 : }
     863             : 
     864             : 
     865             : void
     866           0 : log_fatal (const char *fmt, ...)
     867             : {
     868             :   va_list arg_ptr ;
     869             : 
     870           0 :   va_start (arg_ptr, fmt);
     871           0 :   do_logv (GPGRT_LOG_FATAL, 0, fmt, arg_ptr);
     872           0 :   va_end (arg_ptr);
     873           0 :   abort (); /* Never called; just to make the compiler happy.  */
     874             : }
     875             : 
     876             : 
     877             : void
     878           0 : log_bug (const char *fmt, ...)
     879             : {
     880             :   va_list arg_ptr ;
     881             : 
     882           0 :   va_start (arg_ptr, fmt);
     883           0 :   do_logv (GPGRT_LOG_BUG, 0, fmt, arg_ptr);
     884           0 :   va_end (arg_ptr);
     885           0 :   abort (); /* Never called; just to make the compiler happy.  */
     886             : }
     887             : 
     888             : 
     889             : void
     890           0 : log_debug (const char *fmt, ...)
     891             : {
     892             :   va_list arg_ptr ;
     893             : 
     894           0 :   va_start (arg_ptr, fmt);
     895           0 :   do_logv (GPGRT_LOG_DEBUG, 0, fmt, arg_ptr);
     896           0 :   va_end (arg_ptr);
     897           0 : }
     898             : 
     899             : 
     900             : void
     901         760 : log_printf (const char *fmt, ...)
     902             : {
     903             :   va_list arg_ptr;
     904             : 
     905         760 :   va_start (arg_ptr, fmt);
     906         760 :   do_logv (fmt ? GPGRT_LOG_CONT : GPGRT_LOG_BEGIN, 0, fmt, arg_ptr);
     907         760 :   va_end (arg_ptr);
     908         760 : }
     909             : 
     910             : 
     911             : /* Flush the log - this is useful to make sure that the trailing
     912             :    linefeed has been printed.  */
     913             : void
     914           0 : log_flush (void)
     915             : {
     916           0 :   do_log_ignore_arg (GPGRT_LOG_CONT, NULL);
     917           0 : }
     918             : 
     919             : 
     920             : /* Print a hexdump of BUFFER.  With TEXT of NULL print just the raw
     921             :    dump, with TEXT just an empty string, print a trailing linefeed,
     922             :    otherwise print an entire debug line. */
     923             : void
     924           0 : log_printhex (const char *text, const void *buffer, size_t length)
     925             : {
     926           0 :   if (text && *text)
     927           0 :     log_debug ("%s ", text);
     928           0 :   if (length)
     929             :     {
     930           0 :       const unsigned char *p = buffer;
     931           0 :       log_printf ("%02X", *p);
     932           0 :       for (length--, p++; length--; p++)
     933           0 :         log_printf (" %02X", *p);
     934             :     }
     935           0 :   if (text)
     936           0 :     log_printf ("\n");
     937           0 : }
     938             : 
     939             : 
     940             : /*
     941             : void
     942             : log_printcanon () {}
     943             : is found in sexputils.c
     944             : */
     945             : 
     946             : /*
     947             : void
     948             : log_printsexp () {}
     949             : is found in sexputils.c
     950             : */
     951             : 
     952             : 
     953             : void
     954           0 : log_clock (const char *string)
     955             : {
     956             : #if 0
     957             :   static unsigned long long initial;
     958             :   struct timespec tv;
     959             :   unsigned long long now;
     960             : 
     961             :   if (clock_gettime (CLOCK_REALTIME, &tv))
     962             :     {
     963             :       log_debug ("error getting the realtime clock value\n");
     964             :       return;
     965             :     }
     966             :   now = tv.tv_sec * 1000000000ull;
     967             :   now += tv.tv_nsec;
     968             : 
     969             :   if (!initial)
     970             :     initial = now;
     971             : 
     972             :   log_debug ("[%6llu] %s", (now - initial)/1000, string);
     973             : #else
     974             :   /* You need to link with -ltr to enable the above code.  */
     975           0 :   log_debug ("[not enabled in the source] %s", string);
     976             : #endif
     977           0 : }
     978             : 
     979             : 
     980             : #ifdef GPGRT_HAVE_MACRO_FUNCTION
     981             : void
     982           0 : bug_at( const char *file, int line, const char *func )
     983             : {
     984           0 :   log_log (GPGRT_LOG_BUG, "... this is a bug (%s:%d:%s)\n", file, line, func);
     985           0 :   abort (); /* Never called; just to make the compiler happy.  */
     986             : }
     987             : #else /*!GPGRT_HAVE_MACRO_FUNCTION*/
     988             : void
     989             : bug_at( const char *file, int line )
     990             : {
     991             :   log_log (GPGRT_LOG_BUG, "you found a bug ... (%s:%d)\n", file, line);
     992             :   abort (); /* Never called; just to make the compiler happy.  */
     993             : }
     994             : #endif /*!GPGRT_HAVE_MACRO_FUNCTION*/
     995             : 
     996             : 
     997             : #ifdef GPGRT_HAVE_MACRO_FUNCTION
     998             : void
     999           0 : _log_assert (const char *expr, const char *file, int line, const char *func)
    1000             : {
    1001           0 :   log_log (GPGRT_LOG_BUG, "Assertion \"%s\" in %s failed (%s:%d)\n",
    1002             :            expr, func, file, line);
    1003           0 :   abort (); /* Never called; just to make the compiler happy.  */
    1004             : }
    1005             : #else /*!GPGRT_HAVE_MACRO_FUNCTION*/
    1006             : void
    1007             : _log_assert (const char *expr, const char *file, int line)
    1008             : {
    1009             :   log_log (GPGRT_LOG_BUG, "Assertion \"%s\" failed (%s:%d)\n",
    1010             :            file, line, func);
    1011             :   abort (); /* Never called; just to make the compiler happy.  */
    1012             : }
    1013             : #endif /*!GPGRT_HAVE_MACRO_FUNCTION*/

Generated by: LCOV version 1.11