LCOV - code coverage report
Current view: top level - common - logging.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 136 332 41.0 %
Date: 2015-11-05 17:10:59 Functions: 15 30 50.0 %

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

Generated by: LCOV version 1.11