Blame src/logging.c

Packit fc043f
/* logging.c - Useful logging functions
Packit fc043f
 * Copyright (C) 1998-2001, 2003-2006, 2009-2010,
Packit fc043f
 *               2017  Free Software Foundation, Inc.
Packit fc043f
 * Copyright (C) 1998-1999, 2001-2006, 2008-2017  Werner Koch
Packit fc043f
 *
Packit fc043f
 * This file is part of Libgpg-error.
Packit fc043f
 *
Packit fc043f
 * Libgpg-error is free software; you can redistribute it and/or
Packit fc043f
 * modify it under the terms of the GNU Lesser General Public License
Packit fc043f
 * as published by the Free Software Foundation; either version 2.1 of
Packit fc043f
 * the License, or (at your option) any later version.
Packit fc043f
 *
Packit fc043f
 * Libgpg-error is distributed in the hope that it will be useful, but
Packit fc043f
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit fc043f
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit fc043f
 * Lesser General Public License for more details.
Packit fc043f
 *
Packit fc043f
 * You should have received a copy of the GNU Lesser General Public
Packit fc043f
 * License along with this program; if not, see <https://www.gnu.org/licenses/>.
Packit fc043f
 * SPDX-License-Identifier: LGPL-2.1+
Packit fc043f
 *
Packit fc043f
 * This file was originally a part of GnuPG.
Packit fc043f
 */
Packit fc043f
Packit fc043f
#include <config.h>
Packit fc043f
Packit fc043f
#include <stdlib.h>
Packit fc043f
#include <stdio.h>
Packit fc043f
#include <string.h>
Packit fc043f
#include <stdarg.h>
Packit fc043f
#include <stddef.h>
Packit fc043f
#include <errno.h>
Packit fc043f
#include <time.h>
Packit fc043f
#include <sys/types.h>
Packit fc043f
#include <sys/stat.h>
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
# ifdef HAVE_WINSOCK2_H
Packit fc043f
#  include <winsock2.h>
Packit fc043f
# endif
Packit fc043f
# include <windows.h>
Packit fc043f
#else /*!HAVE_W32_SYSTEM*/
Packit fc043f
# include <sys/socket.h>
Packit fc043f
# include <sys/un.h>
Packit fc043f
# include <netinet/in.h>
Packit fc043f
# include <arpa/inet.h>
Packit fc043f
#endif /*!HAVE_W32_SYSTEM*/
Packit fc043f
#include <unistd.h>
Packit fc043f
#include <fcntl.h>
Packit fc043f
#include <assert.h>
Packit fc043f
/* #include <execinfo.h> */
Packit fc043f
Packit fc043f
#define _GPGRT_NEED_AFLOCAL 1
Packit fc043f
#include "gpgrt-int.h"
Packit fc043f
Packit fc043f
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
# ifndef S_IRWXG
Packit fc043f
#  define S_IRGRP S_IRUSR
Packit fc043f
#  define S_IWGRP S_IWUSR
Packit fc043f
# endif
Packit fc043f
# ifndef S_IRWXO
Packit fc043f
#  define S_IROTH S_IRUSR
Packit fc043f
#  define S_IWOTH S_IWUSR
Packit fc043f
# endif
Packit fc043f
#endif
Packit fc043f
Packit fc043f
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
# define isatty(a)  (0)
Packit fc043f
#endif
Packit fc043f
Packit fc043f
#undef WITH_IPV6
Packit fc043f
#if defined (AF_INET6) && defined(PF_INET) \
Packit fc043f
    && defined (INET6_ADDRSTRLEN) && defined(HAVE_INET_PTON)
Packit fc043f
# define WITH_IPV6 1
Packit fc043f
#endif
Packit fc043f
Packit fc043f
#ifndef EAFNOSUPPORT
Packit fc043f
# define EAFNOSUPPORT EINVAL
Packit fc043f
#endif
Packit fc043f
#ifndef INADDR_NONE  /* Slowaris is missing that.  */
Packit fc043f
#define INADDR_NONE  ((unsigned long)(-1))
Packit fc043f
#endif /*INADDR_NONE*/
Packit fc043f
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
#define sock_close(a)  closesocket(a)
Packit fc043f
#else
Packit fc043f
#define sock_close(a)  close(a)
Packit fc043f
#endif
Packit fc043f
Packit fc043f
Packit fc043f
static estream_t logstream;
Packit fc043f
static int log_socket = -1;
Packit fc043f
static char prefix_buffer[80];
Packit fc043f
static int with_time;
Packit fc043f
static int with_prefix;
Packit fc043f
static int with_pid;
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
static int no_registry;
Packit fc043f
#endif
Packit fc043f
static int (*get_pid_suffix_cb)(unsigned long *r_value);
Packit fc043f
static const char * (*socket_dir_cb)(void);
Packit fc043f
static int running_detached;
Packit fc043f
static int force_prefixes;
Packit fc043f
Packit fc043f
static int missing_lf;
Packit fc043f
static int errorcount;
Packit fc043f
Packit fc043f
Packit fc043f
/* Get the error count as maintained by the log fucntions.  With CLEAR
Packit fc043f
 * set reset the counter.  */
Packit fc043f
int
Packit fc043f
_gpgrt_get_errorcount (int clear)
Packit fc043f
{
Packit fc043f
  int n = errorcount;
Packit fc043f
  if (clear)
Packit fc043f
    errorcount = 0;
Packit fc043f
  return n;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Increment the error count as maintainer by the log functions.  */
Packit fc043f
void
Packit fc043f
_gpgrt_inc_errorcount (void)
Packit fc043f
{
Packit fc043f
   errorcount++;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* The following 3 functions are used by _gpgrt_fopencookie to write logs
Packit fc043f
   to a socket.  */
Packit fc043f
struct fun_cookie_s
Packit fc043f
{
Packit fc043f
  int fd;
Packit fc043f
  int quiet;
Packit fc043f
  int want_socket;
Packit fc043f
  int is_socket;
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
  int use_writefile;
Packit fc043f
#endif
Packit fc043f
  char name[1];
Packit fc043f
};
Packit fc043f
Packit fc043f
Packit fc043f
/* Write NBYTES of BUFFER to file descriptor FD. */
Packit fc043f
static int
Packit fc043f
writen (int fd, const void *buffer, size_t nbytes, int is_socket)
Packit fc043f
{
Packit fc043f
  const char *buf = buffer;
Packit fc043f
  size_t nleft = nbytes;
Packit fc043f
  int nwritten;
Packit fc043f
#ifndef HAVE_W32_SYSTEM
Packit fc043f
  (void)is_socket; /* Not required.  */
Packit fc043f
#endif
Packit fc043f
Packit fc043f
  while (nleft > 0)
Packit fc043f
    {
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
      if (is_socket)
Packit fc043f
        nwritten = send (fd, buf, nleft, 0);
Packit fc043f
      else
Packit fc043f
#endif
Packit fc043f
        nwritten = write (fd, buf, nleft);
Packit fc043f
Packit fc043f
      if (nwritten < 0 && errno == EINTR)
Packit fc043f
        continue;
Packit fc043f
      if (nwritten < 0)
Packit fc043f
        return -1;
Packit fc043f
      nleft -= nwritten;
Packit fc043f
      buf = buf + nwritten;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  return 0;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Returns true if STR represents a valid port number in decimal
Packit fc043f
   notation and no garbage is following.  */
Packit fc043f
static int
Packit fc043f
parse_portno (const char *str, unsigned short *r_port)
Packit fc043f
{
Packit fc043f
  unsigned int value;
Packit fc043f
Packit fc043f
  for (value=0; *str && (*str >= '0' && *str <= '9'); str++)
Packit fc043f
    {
Packit fc043f
      value = value * 10 + (*str - '0');
Packit fc043f
      if (value > 65535)
Packit fc043f
        return 0;
Packit fc043f
    }
Packit fc043f
  if (*str || !value)
Packit fc043f
    return 0;
Packit fc043f
Packit fc043f
  *r_port = value;
Packit fc043f
  return 1;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
static gpgrt_ssize_t
Packit fc043f
fun_writer (void *cookie_arg, const void *buffer, size_t size)
Packit fc043f
{
Packit fc043f
  struct fun_cookie_s *cookie = cookie_arg;
Packit fc043f
Packit fc043f
  /* FIXME: Use only estream with a callback for socket writing.  This
Packit fc043f
     avoids the ugly mix of fd and estream code.  */
Packit fc043f
Packit fc043f
  /* Note that we always try to reconnect to the socket but print
Packit fc043f
     error messages only the first time an error occurred.  If
Packit fc043f
     RUNNING_DETACHED is set we don't fall back to stderr and even do
Packit fc043f
     not print any error messages.  This is needed because detached
Packit fc043f
     processes often close stderr and by writing to file descriptor 2
Packit fc043f
     we might send the log message to a file not intended for logging
Packit fc043f
     (e.g. a pipe or network connection). */
Packit fc043f
  if (cookie->want_socket && cookie->fd == -1)
Packit fc043f
    {
Packit fc043f
#ifdef WITH_IPV6
Packit fc043f
      struct sockaddr_in6 srvr_addr_in6;
Packit fc043f
#endif
Packit fc043f
      struct sockaddr_in srvr_addr_in;
Packit fc043f
#ifndef HAVE_W32_SYSTEM
Packit fc043f
      struct sockaddr_un srvr_addr_un;
Packit fc043f
#endif
Packit fc043f
      const char *name_for_err = "";
Packit fc043f
      size_t addrlen;
Packit fc043f
      struct sockaddr *srvr_addr = NULL;
Packit fc043f
      unsigned short port = 0;
Packit fc043f
      int af = AF_LOCAL;
Packit fc043f
      int pf = PF_LOCAL;
Packit fc043f
      const char *name = cookie->name;
Packit fc043f
Packit fc043f
      /* Not yet open or meanwhile closed due to an error. */
Packit fc043f
      cookie->is_socket = 0;
Packit fc043f
Packit fc043f
      /* Check whether this is a TCP socket or a local socket.  */
Packit fc043f
      if (!strncmp (name, "tcp://", 6) && name[6])
Packit fc043f
        {
Packit fc043f
          name += 6;
Packit fc043f
          af = AF_INET;
Packit fc043f
          pf = PF_INET;
Packit fc043f
        }
Packit fc043f
#ifndef HAVE_W32_SYSTEM
Packit fc043f
      else if (!strncmp (name, "socket://", 9))
Packit fc043f
        name += 9;
Packit fc043f
#endif
Packit fc043f
Packit fc043f
      if (af == AF_LOCAL)
Packit fc043f
        {
Packit fc043f
          addrlen = 0;
Packit fc043f
#ifndef HAVE_W32_SYSTEM
Packit fc043f
          memset (&srvr_addr, 0, sizeof srvr_addr);
Packit fc043f
          srvr_addr_un.sun_family = af;
Packit fc043f
          if (!*name && (name = socket_dir_cb ()) && *name)
Packit fc043f
            {
Packit fc043f
              if (strlen (name) + 7 < sizeof (srvr_addr_un.sun_path)-1)
Packit fc043f
                {
Packit fc043f
                  strncpy (srvr_addr_un.sun_path,
Packit fc043f
                           name, sizeof (srvr_addr_un.sun_path)-1);
Packit fc043f
                  strcat (srvr_addr_un.sun_path, "/S.log");
Packit fc043f
                  srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0;
Packit fc043f
                  srvr_addr = (struct sockaddr *)&srvr_addr_un;
Packit fc043f
                  addrlen = SUN_LEN (&srvr_addr_un);
Packit fc043f
                  name_for_err = srvr_addr_un.sun_path;
Packit fc043f
                }
Packit fc043f
            }
Packit fc043f
          else
Packit fc043f
            {
Packit fc043f
              if (*name && strlen (name) < sizeof (srvr_addr_un.sun_path)-1)
Packit fc043f
                {
Packit fc043f
                  strncpy (srvr_addr_un.sun_path,
Packit fc043f
                           name, sizeof (srvr_addr_un.sun_path)-1);
Packit fc043f
                  srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0;
Packit fc043f
                  srvr_addr = (struct sockaddr *)&srvr_addr_un;
Packit fc043f
                  addrlen = SUN_LEN (&srvr_addr_un);
Packit fc043f
                }
Packit fc043f
            }
Packit fc043f
#endif /*!HAVE_W32SYSTEM*/
Packit fc043f
        }
Packit fc043f
      else
Packit fc043f
        {
Packit fc043f
          char *addrstr, *p;
Packit fc043f
#ifdef HAVE_INET_PTON
Packit fc043f
          void *addrbuf = NULL;
Packit fc043f
#endif /*HAVE_INET_PTON*/
Packit fc043f
Packit fc043f
          addrstr = _gpgrt_malloc (strlen (name) + 1);
Packit fc043f
          if (!addrstr)
Packit fc043f
            addrlen = 0; /* This indicates an error.  */
Packit fc043f
          else if (*name == '[')
Packit fc043f
            {
Packit fc043f
              /* Check for IPv6 literal address.  */
Packit fc043f
              strcpy (addrstr, name+1);
Packit fc043f
              p = strchr (addrstr, ']');
Packit fc043f
              if (!p || p[1] != ':' || !parse_portno (p+2, &port))
Packit fc043f
                {
Packit fc043f
                  _gpg_err_set_errno (EINVAL);
Packit fc043f
                  addrlen = 0;
Packit fc043f
                }
Packit fc043f
              else
Packit fc043f
                {
Packit fc043f
                  *p = 0;
Packit fc043f
#ifdef WITH_IPV6
Packit fc043f
                  af = AF_INET6;
Packit fc043f
                  pf = PF_INET6;
Packit fc043f
                  memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
Packit fc043f
                  srvr_addr_in6.sin6_family = af;
Packit fc043f
                  srvr_addr_in6.sin6_port = htons (port);
Packit fc043f
#ifdef HAVE_INET_PTON
Packit fc043f
                  addrbuf = &srvr_addr_in6.sin6_addr;
Packit fc043f
#endif /*HAVE_INET_PTON*/
Packit fc043f
                  srvr_addr = (struct sockaddr *)&srvr_addr_in6;
Packit fc043f
                  addrlen = sizeof srvr_addr_in6;
Packit fc043f
#else
Packit fc043f
                  _gpg_err_set_errno (EAFNOSUPPORT);
Packit fc043f
                  addrlen = 0;
Packit fc043f
#endif
Packit fc043f
                }
Packit fc043f
            }
Packit fc043f
          else
Packit fc043f
            {
Packit fc043f
              /* Check for IPv4 literal address.  */
Packit fc043f
              strcpy (addrstr, name);
Packit fc043f
              p = strchr (addrstr, ':');
Packit fc043f
              if (!p || !parse_portno (p+1, &port))
Packit fc043f
                {
Packit fc043f
                  _gpg_err_set_errno (EINVAL);
Packit fc043f
                  addrlen = 0;
Packit fc043f
                }
Packit fc043f
              else
Packit fc043f
                {
Packit fc043f
                  *p = 0;
Packit fc043f
                  memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
Packit fc043f
                  srvr_addr_in.sin_family = af;
Packit fc043f
                  srvr_addr_in.sin_port = htons (port);
Packit fc043f
#ifdef HAVE_INET_PTON
Packit fc043f
                  addrbuf = &srvr_addr_in.sin_addr;
Packit fc043f
#endif /*HAVE_INET_PTON*/
Packit fc043f
                  srvr_addr = (struct sockaddr *)&srvr_addr_in;
Packit fc043f
                  addrlen = sizeof srvr_addr_in;
Packit fc043f
                }
Packit fc043f
            }
Packit fc043f
Packit fc043f
          if (addrlen)
Packit fc043f
            {
Packit fc043f
#ifdef HAVE_INET_PTON
Packit fc043f
              if (inet_pton (af, addrstr, addrbuf) != 1)
Packit fc043f
                addrlen = 0;
Packit fc043f
#else /*!HAVE_INET_PTON*/
Packit fc043f
              /* We need to use the old function.  If we are here v6
Packit fc043f
                 support isn't enabled anyway and thus we can do fine
Packit fc043f
                 without.  Note that Windows has a compatible inet_pton
Packit fc043f
                 function named inetPton, but only since Vista.  */
Packit fc043f
              srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr);
Packit fc043f
              if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE)
Packit fc043f
                addrlen = 0;
Packit fc043f
#endif /*!HAVE_INET_PTON*/
Packit fc043f
            }
Packit fc043f
Packit fc043f
          _gpgrt_free (addrstr);
Packit fc043f
        }
Packit fc043f
Packit fc043f
      cookie->fd = addrlen? socket (pf, SOCK_STREAM, 0) : -1;
Packit fc043f
      if (cookie->fd == -1)
Packit fc043f
        {
Packit fc043f
          if (!cookie->quiet && !running_detached
Packit fc043f
              && isatty (_gpgrt_fileno (es_stderr)))
Packit fc043f
            _gpgrt_fprintf (es_stderr,
Packit fc043f
                            "failed to create socket for logging: %s\n",
Packit fc043f
                            strerror (errno));
Packit fc043f
        }
Packit fc043f
      else
Packit fc043f
        {
Packit fc043f
          if (connect (cookie->fd, srvr_addr, addrlen) == -1)
Packit fc043f
            {
Packit fc043f
              if (!cookie->quiet && !running_detached
Packit fc043f
                  && isatty (_gpgrt_fileno (es_stderr)))
Packit fc043f
                _gpgrt_fprintf (es_stderr, "can't connect to '%s%s': %s\n",
Packit fc043f
                                cookie->name, name_for_err, strerror(errno));
Packit fc043f
              sock_close (cookie->fd);
Packit fc043f
              cookie->fd = -1;
Packit fc043f
            }
Packit fc043f
        }
Packit fc043f
Packit fc043f
      if (cookie->fd == -1)
Packit fc043f
        {
Packit fc043f
          if (!running_detached)
Packit fc043f
            {
Packit fc043f
              /* Due to all the problems with apps not running
Packit fc043f
                 detached but being called with stderr closed or used
Packit fc043f
                 for a different purposes, it does not make sense to
Packit fc043f
                 switch to stderr.  We therefore disable it. */
Packit fc043f
              if (!cookie->quiet)
Packit fc043f
                {
Packit fc043f
                  /* fputs ("switching logging to stderr\n", stderr);*/
Packit fc043f
                  cookie->quiet = 1;
Packit fc043f
                }
Packit fc043f
              cookie->fd = -1; /*fileno (stderr);*/
Packit fc043f
            }
Packit fc043f
        }
Packit fc043f
      else /* Connection has been established. */
Packit fc043f
        {
Packit fc043f
          cookie->quiet = 0;
Packit fc043f
          cookie->is_socket = 1;
Packit fc043f
        }
Packit fc043f
    }
Packit fc043f
Packit fc043f
  log_socket = cookie->fd;
Packit fc043f
  if (cookie->fd != -1)
Packit fc043f
    {
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
      if (cookie->use_writefile)
Packit fc043f
        {
Packit fc043f
          DWORD nwritten;
Packit fc043f
Packit fc043f
          WriteFile ((HANDLE)cookie->fd, buffer, size, &nwritten, NULL);
Packit fc043f
          return (gpgrt_ssize_t)size; /* Okay.  */
Packit fc043f
        }
Packit fc043f
#endif
Packit fc043f
      if (!writen (cookie->fd, buffer, size, cookie->is_socket))
Packit fc043f
        return (gpgrt_ssize_t)size; /* Okay. */
Packit fc043f
    }
Packit fc043f
Packit fc043f
  if (!running_detached && cookie->fd != -1
Packit fc043f
      && isatty (_gpgrt_fileno (es_stderr)))
Packit fc043f
    {
Packit fc043f
      if (*cookie->name)
Packit fc043f
        _gpgrt_fprintf (es_stderr, "error writing to '%s': %s\n",
Packit fc043f
                        cookie->name, strerror(errno));
Packit fc043f
      else
Packit fc043f
        _gpgrt_fprintf (es_stderr, "error writing to file descriptor %d: %s\n",
Packit fc043f
                        cookie->fd, strerror(errno));
Packit fc043f
    }
Packit fc043f
  if (cookie->is_socket && cookie->fd != -1)
Packit fc043f
    {
Packit fc043f
      sock_close (cookie->fd);
Packit fc043f
      cookie->fd = -1;
Packit fc043f
      log_socket = -1;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  return (gpgrt_ssize_t)size;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
static int
Packit fc043f
fun_closer (void *cookie_arg)
Packit fc043f
{
Packit fc043f
  struct fun_cookie_s *cookie = cookie_arg;
Packit fc043f
Packit fc043f
  if (cookie->fd != -1 && cookie->fd != 2)
Packit fc043f
    sock_close (cookie->fd);
Packit fc043f
  _gpgrt_free (cookie);
Packit fc043f
  log_socket = -1;
Packit fc043f
  return 0;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Common function to either set the logging to a file or a file
Packit fc043f
   descriptor. */
Packit fc043f
static void
Packit fc043f
set_file_fd (const char *name, int fd)
Packit fc043f
{
Packit fc043f
  estream_t fp;
Packit fc043f
  int want_socket;
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
  int use_writefile = 0;
Packit fc043f
#endif
Packit fc043f
  struct fun_cookie_s *cookie;
Packit fc043f
Packit fc043f
  /* Close an open log stream.  */
Packit fc043f
  if (logstream)
Packit fc043f
    {
Packit fc043f
      if (logstream != es_stderr)
Packit fc043f
        _gpgrt_fclose (logstream);
Packit fc043f
      logstream = NULL;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  /* Figure out what kind of logging we want.  */
Packit fc043f
  if (name && !strcmp (name, "-"))
Packit fc043f
    {
Packit fc043f
      name = NULL;
Packit fc043f
      fd = _gpgrt_fileno (es_stderr);
Packit fc043f
    }
Packit fc043f
Packit fc043f
  want_socket = 0;
Packit fc043f
  if (name && !strncmp (name, "tcp://", 6) && name[6])
Packit fc043f
    want_socket = 1;
Packit fc043f
#ifndef HAVE_W32_SYSTEM
Packit fc043f
  else if (name && !strncmp (name, "socket://", 9))
Packit fc043f
    want_socket = 2;
Packit fc043f
#endif /*HAVE_W32_SYSTEM*/
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
  else if (name && !strcmp (name, "GPG2:"))
Packit fc043f
    {
Packit fc043f
      HANDLE hd;
Packit fc043f
Packit fc043f
      ActivateDevice (L"Drivers\\"GNUPG_NAME"_Log", 0);
Packit fc043f
      /* Ignore a filename and write the debug output to the GPG2:
Packit fc043f
         device.  */
Packit fc043f
      hd = CreateFile (L"GPG2:", GENERIC_WRITE,
Packit fc043f
                       FILE_SHARE_READ | FILE_SHARE_WRITE,
Packit fc043f
                       NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
Packit fc043f
      fd = (hd == INVALID_HANDLE_VALUE)? -1 : (int)hd;
Packit fc043f
      name = NULL;
Packit fc043f
      force_prefixes = 1;
Packit fc043f
      use_writefile = 1;
Packit fc043f
    }
Packit fc043f
#endif /*HAVE_W32CE_SYSTEM*/
Packit fc043f
Packit fc043f
  /* Setup a new stream.  */
Packit fc043f
Packit fc043f
  cookie = _gpgrt_malloc (sizeof *cookie + (name? strlen (name):0));
Packit fc043f
  if (!cookie)
Packit fc043f
    return; /* oops */
Packit fc043f
  strcpy (cookie->name, name? name:"");
Packit fc043f
  cookie->quiet = 0;
Packit fc043f
  cookie->is_socket = 0;
Packit fc043f
  cookie->want_socket = want_socket;
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
  cookie->use_writefile = use_writefile;
Packit fc043f
#endif
Packit fc043f
  if (!name)
Packit fc043f
    cookie->fd = fd;
Packit fc043f
  else if (want_socket)
Packit fc043f
    cookie->fd = -1;
Packit fc043f
  else
Packit fc043f
    {
Packit fc043f
      do
Packit fc043f
        cookie->fd = open (name, O_WRONLY|O_APPEND|O_CREAT,
Packit fc043f
                           (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH));
Packit fc043f
      while (cookie->fd == -1 && errno == EINTR);
Packit fc043f
    }
Packit fc043f
  log_socket = cookie->fd;
Packit fc043f
Packit fc043f
  {
Packit fc043f
    es_cookie_io_functions_t io = { NULL };
Packit fc043f
    io.func_write = fun_writer;
Packit fc043f
    io.func_close = fun_closer;
Packit fc043f
Packit fc043f
    fp = _gpgrt_fopencookie (cookie, "w", io);
Packit fc043f
  }
Packit fc043f
Packit fc043f
  /* On error default to a stderr based estream.  */
Packit fc043f
  if (!fp)
Packit fc043f
    fp = es_stderr;
Packit fc043f
Packit fc043f
  _gpgrt_setvbuf (fp, NULL, _IOLBF, 0);
Packit fc043f
Packit fc043f
  logstream = fp;
Packit fc043f
Packit fc043f
  /* We always need to print the prefix and the pid for socket mode,
Packit fc043f
     so that the server reading the socket can do something
Packit fc043f
     meaningful. */
Packit fc043f
  force_prefixes = want_socket;
Packit fc043f
Packit fc043f
  missing_lf = 0;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Set the file to write log to.  The special names NULL and "-" may
Packit fc043f
 * be used to select stderr and names formatted like
Packit fc043f
 * "socket:///home/foo/mylogs" may be used to write the logging to the
Packit fc043f
 * socket "/home/foo/mylogs".  If the connection to the socket fails
Packit fc043f
 * or a write error is detected, the function writes to stderr and
Packit fc043f
 * tries the next time again to connect the socket.  Calling this
Packit fc043f
 * function with (NULL, NULL, -1) sets the default sink.
Packit fc043f
 * Warning: This function is not thread-safe.
Packit fc043f
 */
Packit fc043f
void
Packit fc043f
_gpgrt_log_set_sink (const char *name, estream_t stream, int fd)
Packit fc043f
{
Packit fc043f
  if (name && !stream && fd == -1)
Packit fc043f
    set_file_fd (name, -1);
Packit fc043f
  else if (!name && !stream && fd != -1)
Packit fc043f
    {
Packit fc043f
      if (!_gpgrt_fd_valid_p (fd))
Packit fc043f
        _gpgrt_log_fatal ("gpgrt_log_set_sink: fd is invalid: %s\n",
Packit fc043f
                     strerror (errno));
Packit fc043f
      set_file_fd (NULL, fd);
Packit fc043f
    }
Packit fc043f
  else if (!name && stream && fd == -1)
Packit fc043f
    {
Packit fc043f
      _gpgrt_log_fatal ("gpgrt_log_set_sink: stream arg not yet supported\n");
Packit fc043f
    }
Packit fc043f
  else /* default */
Packit fc043f
    set_file_fd ("-", -1);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Set a function to retrieve the directory name of a socket if
Packit fc043f
 * only "socket://" has been given to log_set_file.
Packit fc043f
 * Warning: This function is not thread-safe.  */
Packit fc043f
void
Packit fc043f
_gpgrt_log_set_socket_dir_cb (const char *(*fnc)(void))
Packit fc043f
{
Packit fc043f
  socket_dir_cb = fnc;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Warning: This function is not thread-safe.  */
Packit fc043f
void
Packit fc043f
_gpgrt_log_set_pid_suffix_cb (int (*cb)(unsigned long *r_value))
Packit fc043f
{
Packit fc043f
  get_pid_suffix_cb = cb;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Warning: Changing TEXT is not thread-safe.  Changing only flags
Packit fc043f
 * might be thread-safe.  */
Packit fc043f
void
Packit fc043f
_gpgrt_log_set_prefix (const char *text, unsigned int flags)
Packit fc043f
{
Packit fc043f
  if (text)
Packit fc043f
    {
Packit fc043f
      strncpy (prefix_buffer, text, sizeof (prefix_buffer)-1);
Packit fc043f
      prefix_buffer[sizeof (prefix_buffer)-1] = 0;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  with_prefix = (flags & GPGRT_LOG_WITH_PREFIX);
Packit fc043f
  with_time = (flags & GPGRT_LOG_WITH_TIME);
Packit fc043f
  with_pid  = (flags & GPGRT_LOG_WITH_PID);
Packit fc043f
  running_detached = (flags & GPGRT_LOG_RUN_DETACHED);
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
  no_registry = (flags & GPGRT_LOG_NO_REGISTRY);
Packit fc043f
#endif
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
const char *
Packit fc043f
_gpgrt_log_get_prefix (unsigned int *flags)
Packit fc043f
{
Packit fc043f
  if (flags)
Packit fc043f
    {
Packit fc043f
      *flags = 0;
Packit fc043f
      if (with_prefix)
Packit fc043f
        *flags |= GPGRT_LOG_WITH_PREFIX;
Packit fc043f
      if (with_time)
Packit fc043f
        *flags |= GPGRT_LOG_WITH_TIME;
Packit fc043f
      if (with_pid)
Packit fc043f
        *flags |= GPGRT_LOG_WITH_PID;
Packit fc043f
      if (running_detached)
Packit fc043f
        *flags |= GPGRT_LOG_RUN_DETACHED;
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
      if (no_registry)
Packit fc043f
        *flags |= GPGRT_LOG_NO_REGISTRY;
Packit fc043f
#endif
Packit fc043f
    }
Packit fc043f
  return prefix_buffer;
Packit fc043f
}
Packit fc043f
Packit fc043f
/* This function returns true if the file descriptor FD is in use for
Packit fc043f
 * logging.  This is preferable over a test using log_get_fd in that
Packit fc043f
 * it allows the logging code to use more then one file descriptor.  */
Packit fc043f
int
Packit fc043f
_gpgrt_log_test_fd (int fd)
Packit fc043f
{
Packit fc043f
  if (logstream)
Packit fc043f
    {
Packit fc043f
      int tmp = _gpgrt_fileno (logstream);
Packit fc043f
      if ( tmp != -1 && tmp == fd)
Packit fc043f
        return 1;
Packit fc043f
    }
Packit fc043f
  if (log_socket != -1 && log_socket == fd)
Packit fc043f
    return 1;
Packit fc043f
  return 0;
Packit fc043f
}
Packit fc043f
Packit fc043f
int
Packit fc043f
_gpgrt_log_get_fd ()
Packit fc043f
{
Packit fc043f
  return logstream? _gpgrt_fileno (logstream) : -1;
Packit fc043f
}
Packit fc043f
Packit fc043f
estream_t
Packit fc043f
_gpgrt_log_get_stream ()
Packit fc043f
{
Packit fc043f
  if (!logstream)
Packit fc043f
    {
Packit fc043f
      /* Make sure a log stream has been set.  */
Packit fc043f
      _gpgrt_log_set_sink (NULL, NULL, -1);
Packit fc043f
      assert (logstream);
Packit fc043f
    }
Packit fc043f
  return logstream;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Note: LOGSTREAM is expected to be locked.  */
Packit fc043f
static int
Packit fc043f
print_prefix (int level, int leading_backspace)
Packit fc043f
{
Packit fc043f
  int rc;
Packit fc043f
  int length = 0;
Packit fc043f
Packit fc043f
  if (level != GPGRT_LOGLVL_CONT)
Packit fc043f
    { /* Note this does not work for multiple line logging as we would
Packit fc043f
       * need to print to a buffer first */
Packit fc043f
      if (with_time && !force_prefixes)
Packit fc043f
        {
Packit fc043f
          struct tm *tp;
Packit fc043f
          time_t atime = time (NULL);
Packit fc043f
Packit fc043f
          tp = localtime (&atime);
Packit fc043f
          rc = _gpgrt_fprintf_unlocked (logstream,
Packit fc043f
                                        "%04d-%02d-%02d %02d:%02d:%02d ",
Packit fc043f
                               1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
Packit fc043f
                               tp->tm_hour, tp->tm_min, tp->tm_sec );
Packit fc043f
          if (rc > 0)
Packit fc043f
            length += rc;
Packit fc043f
        }
Packit fc043f
      if (with_prefix || force_prefixes)
Packit fc043f
        {
Packit fc043f
          _gpgrt_fputs_unlocked (prefix_buffer, logstream);
Packit fc043f
          length += strlen (prefix_buffer);
Packit fc043f
        }
Packit fc043f
      if (with_pid || force_prefixes)
Packit fc043f
        {
Packit fc043f
          unsigned long pidsuf;
Packit fc043f
          int pidfmt;
Packit fc043f
Packit fc043f
          if (get_pid_suffix_cb && (pidfmt=get_pid_suffix_cb (&pidsuf)))
Packit fc043f
            rc = _gpgrt_fprintf_unlocked (logstream,
Packit fc043f
                                          pidfmt == 1? "[%u.%lu]":"[%u.%lx]",
Packit fc043f
                                          (unsigned int)getpid (), pidsuf);
Packit fc043f
          else
Packit fc043f
            rc = _gpgrt_fprintf_unlocked (logstream, "[%u]",
Packit fc043f
                                          (unsigned int)getpid ());
Packit fc043f
          if (rc > 0)
Packit fc043f
            length += rc;
Packit fc043f
        }
Packit fc043f
      if ((!with_time && (with_prefix || with_pid)) || force_prefixes)
Packit fc043f
        {
Packit fc043f
          _gpgrt_putc_unlocked (':', logstream);
Packit fc043f
          length++;
Packit fc043f
        }
Packit fc043f
      /* A leading backspace suppresses the extra space so that we can
Packit fc043f
         correctly output, programname, filename and linenumber. */
Packit fc043f
      if (!leading_backspace
Packit fc043f
          && (with_time || with_prefix || with_pid || force_prefixes))
Packit fc043f
        {
Packit fc043f
          _gpgrt_putc_unlocked (' ', logstream);
Packit fc043f
          length++;
Packit fc043f
        }
Packit fc043f
    }
Packit fc043f
Packit fc043f
  switch (level)
Packit fc043f
    {
Packit fc043f
    case GPGRT_LOGLVL_BEGIN: break;
Packit fc043f
    case GPGRT_LOGLVL_CONT: break;
Packit fc043f
    case GPGRT_LOGLVL_INFO: break;
Packit fc043f
    case GPGRT_LOGLVL_WARN: break;
Packit fc043f
    case GPGRT_LOGLVL_ERROR: break;
Packit fc043f
    case GPGRT_LOGLVL_FATAL:
Packit fc043f
      _gpgrt_fputs_unlocked ("Fatal: ", logstream);
Packit fc043f
      length += 7;
Packit fc043f
      break;
Packit fc043f
    case GPGRT_LOGLVL_BUG:
Packit fc043f
      _gpgrt_fputs_unlocked ("Ohhhh jeeee: ", logstream);
Packit fc043f
      length += 13;
Packit fc043f
      break;
Packit fc043f
    case GPGRT_LOGLVL_DEBUG:
Packit fc043f
      _gpgrt_fputs_unlocked ("DBG: ", logstream);
Packit fc043f
      length += 5;
Packit fc043f
      break;
Packit fc043f
    default:
Packit fc043f
      rc = _gpgrt_fprintf_unlocked (logstream,
Packit fc043f
                                    "[Unknown log level %d]: ", level);
Packit fc043f
      if (rc > 0)
Packit fc043f
        length += rc;
Packit fc043f
      break;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  return length;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Internal worker function.  Exported so that we can use it in
Packit fc043f
 * visibility.c.  Returs the number of characters printed or 0 if the
Packit fc043f
 * line ends in a LF. */
Packit fc043f
int
Packit fc043f
_gpgrt_logv_internal (int level, int ignore_arg_ptr, const char *extrastring,
Packit fc043f
                      const char *prefmt, const char *fmt, va_list arg_ptr)
Packit fc043f
{
Packit fc043f
  int leading_backspace = (fmt && *fmt == '\b');
Packit fc043f
  int length;
Packit fc043f
  int rc;
Packit fc043f
Packit fc043f
  if (!logstream)
Packit fc043f
    {
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
      char *tmp;
Packit fc043f
Packit fc043f
      tmp = (no_registry
Packit fc043f
             ? NULL
Packit fc043f
             : _gpgrt_w32_reg_query_string (NULL, "Software\\\\GNU\\\\GnuPG",
Packit fc043f
                                            "DefaultLogFile"));
Packit fc043f
      _gpgrt_log_set_sink (tmp && *tmp? tmp : NULL, NULL, -1);
Packit fc043f
      _gpgrt_free (tmp);
Packit fc043f
#else
Packit fc043f
      /* Make sure a log stream has been set.  */
Packit fc043f
      _gpgrt_log_set_sink (NULL, NULL, -1);
Packit fc043f
#endif
Packit fc043f
      assert (logstream);
Packit fc043f
    }
Packit fc043f
Packit fc043f
  _gpgrt_flockfile (logstream);
Packit fc043f
  if (missing_lf && level != GPGRT_LOGLVL_CONT)
Packit fc043f
    _gpgrt_putc_unlocked ('\n', logstream );
Packit fc043f
  missing_lf = 0;
Packit fc043f
Packit fc043f
  length = print_prefix (level, leading_backspace);
Packit fc043f
  if (leading_backspace)
Packit fc043f
    fmt++;
Packit fc043f
Packit fc043f
  if (fmt)
Packit fc043f
    {
Packit fc043f
      if (prefmt)
Packit fc043f
        {
Packit fc043f
          _gpgrt_fputs_unlocked (prefmt, logstream);
Packit fc043f
          length += strlen (prefmt);
Packit fc043f
        }
Packit fc043f
Packit fc043f
      if (ignore_arg_ptr)
Packit fc043f
        { /* This is used by log_string and comes with the extra
Packit fc043f
           * feature that after a LF the next line is indent at the
Packit fc043f
           * length of the prefix.  Note that we do not yet include
Packit fc043f
           * the length of the timestamp and pid in the indent
Packit fc043f
           * computation.  */
Packit fc043f
          const char *p, *pend;
Packit fc043f
Packit fc043f
          for (p = fmt; (pend = strchr (p, '\n')); p = pend+1)
Packit fc043f
            {
Packit fc043f
              rc = _gpgrt_fprintf_unlocked (logstream, "%*s%.*s",
Packit fc043f
                                 (int)((p != fmt
Packit fc043f
                                        && (with_prefix || force_prefixes))
Packit fc043f
                                       ?strlen (prefix_buffer)+2:0), "",
Packit fc043f
                                 (int)(pend - p)+1, p);
Packit fc043f
              if (rc > 0)
Packit fc043f
                length += rc;
Packit fc043f
            }
Packit fc043f
          _gpgrt_fputs_unlocked (p, logstream);
Packit fc043f
          length += strlen (p);
Packit fc043f
        }
Packit fc043f
      else
Packit fc043f
        {
Packit fc043f
          rc = _gpgrt_vfprintf_unlocked (logstream, fmt, arg_ptr);
Packit fc043f
          if (rc > 0)
Packit fc043f
            length += rc;
Packit fc043f
        }
Packit fc043f
Packit fc043f
      if (*fmt && fmt[strlen(fmt)-1] != '\n')
Packit fc043f
        missing_lf = 1;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  /* If we have an EXTRASTRING print it now while we still hold the
Packit fc043f
   * lock on the logstream.  */
Packit fc043f
  if (extrastring)
Packit fc043f
    {
Packit fc043f
      int c;
Packit fc043f
Packit fc043f
      if (missing_lf)
Packit fc043f
        {
Packit fc043f
          _gpgrt_putc_unlocked ('\n', logstream);
Packit fc043f
          missing_lf = 0;
Packit fc043f
          length = 0;
Packit fc043f
        }
Packit fc043f
      length += print_prefix (level, leading_backspace);
Packit fc043f
      _gpgrt_fputs_unlocked (">> ", logstream);
Packit fc043f
      length += 3;
Packit fc043f
      missing_lf = 1;
Packit fc043f
      while ((c = *extrastring++))
Packit fc043f
        {
Packit fc043f
          missing_lf = 1;
Packit fc043f
          if (c == '\\')
Packit fc043f
            {
Packit fc043f
              _gpgrt_fputs_unlocked ("\\\\", logstream);
Packit fc043f
              length += 2;
Packit fc043f
            }
Packit fc043f
          else if (c == '\r')
Packit fc043f
            {
Packit fc043f
              _gpgrt_fputs_unlocked ("\\r", logstream);
Packit fc043f
              length += 2;
Packit fc043f
            }
Packit fc043f
          else if (c == '\n')
Packit fc043f
            {
Packit fc043f
              _gpgrt_fputs_unlocked ("\\n\n", logstream);
Packit fc043f
              length = 0;
Packit fc043f
              if (*extrastring)
Packit fc043f
                {
Packit fc043f
                  length += print_prefix (level, leading_backspace);
Packit fc043f
                  _gpgrt_fputs_unlocked (">> ", logstream);
Packit fc043f
                  length += 3;
Packit fc043f
                }
Packit fc043f
              else
Packit fc043f
                missing_lf = 0;
Packit fc043f
            }
Packit fc043f
          else
Packit fc043f
            {
Packit fc043f
              _gpgrt_putc_unlocked (c, logstream);
Packit fc043f
              length++;
Packit fc043f
            }
Packit fc043f
        }
Packit fc043f
      if (missing_lf)
Packit fc043f
        {
Packit fc043f
          _gpgrt_putc_unlocked ('\n', logstream);
Packit fc043f
          length = 0;
Packit fc043f
          missing_lf = 0;
Packit fc043f
        }
Packit fc043f
    }
Packit fc043f
Packit fc043f
  if (level == GPGRT_LOGLVL_FATAL)
Packit fc043f
    {
Packit fc043f
      if (missing_lf)
Packit fc043f
        _gpgrt_putc_unlocked ('\n', logstream);
Packit fc043f
      _gpgrt_funlockfile (logstream);
Packit fc043f
      exit (2);
Packit fc043f
    }
Packit fc043f
  else if (level == GPGRT_LOGLVL_BUG)
Packit fc043f
    {
Packit fc043f
      if (missing_lf)
Packit fc043f
        _gpgrt_putc_unlocked ('\n', logstream );
Packit fc043f
      _gpgrt_funlockfile (logstream);
Packit fc043f
      /* Using backtrace requires a configure test and to pass
Packit fc043f
       * -rdynamic to gcc.  Thus we do not enable it now.  */
Packit fc043f
      /* { */
Packit fc043f
      /*   void *btbuf[20]; */
Packit fc043f
      /*   int btidx, btlen; */
Packit fc043f
      /*   char **btstr; */
Packit fc043f
Packit fc043f
      /*   btlen = backtrace (btbuf, DIM (btbuf)); */
Packit fc043f
      /*   btstr = backtrace_symbols (btbuf, btlen); */
Packit fc043f
      /*   if (btstr) */
Packit fc043f
      /*     for (btidx=0; btidx < btlen; btidx++) */
Packit fc043f
      /*       log_debug ("[%d] %s\n", btidx, btstr[btidx]); */
Packit fc043f
      /* } */
Packit fc043f
      abort ();
Packit fc043f
    }
Packit fc043f
  else
Packit fc043f
    _gpgrt_funlockfile (logstream);
Packit fc043f
Packit fc043f
  /* Bumb the error counter for log_error.  */
Packit fc043f
  if (level == GPGRT_LOGLVL_ERROR)
Packit fc043f
    {
Packit fc043f
      /* Protect against counter overflow.  */
Packit fc043f
      if (errorcount < 30000)
Packit fc043f
        errorcount++;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  return length;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_log (int level, const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr ;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt) ;
Packit fc043f
  _gpgrt_logv_internal (level, 0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_logv (int level, const char *fmt, va_list arg_ptr)
Packit fc043f
{
Packit fc043f
  _gpgrt_logv_internal (level, 0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Same as log_logv but PREFIX is printed immediately before FMT.
Packit fc043f
 * Note that PREFIX is an additional string and independent of the
Packit fc043f
 * prefix set by gpgrt_log_set_prefix.  */
Packit fc043f
void
Packit fc043f
_gpgrt_logv_prefix (int level, const char *prefix,
Packit fc043f
                    const char *fmt, va_list arg_ptr)
Packit fc043f
{
Packit fc043f
  _gpgrt_logv_internal (level, 0, NULL, prefix, fmt, arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
static void
Packit fc043f
do_log_ignore_arg (int level, const char *str, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
  va_start (arg_ptr, str);
Packit fc043f
  _gpgrt_logv_internal (level, 1, NULL, NULL, str, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Log STRING at LEVEL but indent from the second line on by the
Packit fc043f
 * length of the prefix.  */
Packit fc043f
void
Packit fc043f
_gpgrt_log_string (int level, const char *string)
Packit fc043f
{
Packit fc043f
  /* We need a dummy arg_ptr, but there is no portable way to create
Packit fc043f
   * one.  So we call the _gpgrt_logv_internal function through a
Packit fc043f
   * variadic wrapper. */
Packit fc043f
  do_log_ignore_arg (level, string);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_log_info (const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr ;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt);
Packit fc043f
  _gpgrt_logv_internal (GPGRT_LOGLVL_INFO, 0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_log_error (const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr ;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt);
Packit fc043f
  _gpgrt_logv_internal (GPGRT_LOGLVL_ERROR, 0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_log_fatal (const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr ;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt);
Packit fc043f
  _gpgrt_logv_internal (GPGRT_LOGLVL_FATAL, 0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
  abort (); /* Never called; just to make the compiler happy.  */
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_log_bug (const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr ;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt);
Packit fc043f
  _gpgrt_logv_internal (GPGRT_LOGLVL_BUG, 0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
  abort (); /* Never called; just to make the compiler happy.  */
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_log_debug (const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt);
Packit fc043f
  _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* The same as log_debug but at the end of the output STRING is
Packit fc043f
 * printed with LFs expanded to include the prefix and a final --end--
Packit fc043f
 * marker.  */
Packit fc043f
void
Packit fc043f
_gpgrt_log_debug_string (const char *string, const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt);
Packit fc043f
  _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, string, NULL, fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_log_printf (const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt);
Packit fc043f
  _gpgrt_logv_internal (fmt ? GPGRT_LOGLVL_CONT : GPGRT_LOGLVL_BEGIN,
Packit fc043f
                        0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Flush the log - this is useful to make sure that the trailing
Packit fc043f
   linefeed has been printed.  */
Packit fc043f
void
Packit fc043f
_gpgrt_log_flush (void)
Packit fc043f
{
Packit fc043f
  do_log_ignore_arg (GPGRT_LOGLVL_CONT, NULL);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Print a hexdump of (BUFFER,LENGTH).  With FMT passed as NULL print
Packit fc043f
 * just the raw dump (in this case ARG_PTR is not used), with FMT
Packit fc043f
 * being an empty string, print a trailing linefeed, otherwise print
Packit fc043f
 * an entire debug line with the expanded FMT followed by a possible
Packit fc043f
 * wrapped hexdump and a final LF.  */
Packit fc043f
void
Packit fc043f
_gpgrt_logv_printhex (const void *buffer, size_t length,
Packit fc043f
                      const char *fmt, va_list arg_ptr)
Packit fc043f
{
Packit fc043f
  int wrap = 0;
Packit fc043f
  int cnt = 0;
Packit fc043f
  const unsigned char *p;
Packit fc043f
Packit fc043f
  /* FIXME: This printing is not yet protected by _gpgrt_flockfile.  */
Packit fc043f
  if (fmt && *fmt)
Packit fc043f
    {
Packit fc043f
      _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, NULL, NULL, fmt, arg_ptr);
Packit fc043f
      wrap = 1;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  if (length)
Packit fc043f
    {
Packit fc043f
      if (wrap)
Packit fc043f
        _gpgrt_log_printf (" ");
Packit fc043f
Packit fc043f
      for (p = buffer; length--; p++)
Packit fc043f
        {
Packit fc043f
          _gpgrt_log_printf ("%02x", *p);
Packit fc043f
          if (wrap && ++cnt == 32 && length)
Packit fc043f
            {
Packit fc043f
              cnt = 0;
Packit fc043f
              /* (we indicate continuations with a backslash) */
Packit fc043f
              _gpgrt_log_printf (" \\\n");
Packit fc043f
              _gpgrt_log_debug ("%s", "");
Packit fc043f
              if (fmt && *fmt)
Packit fc043f
                _gpgrt_log_printf (" ");
Packit fc043f
            }
Packit fc043f
        }
Packit fc043f
    }
Packit fc043f
Packit fc043f
  if (fmt)
Packit fc043f
    _gpgrt_log_printf ("\n");
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Print a hexdump of (BUFFER,LENGTH).  With FMT passed as NULL print
Packit fc043f
 * just the raw dump, with FMT being an empty string, print a trailing
Packit fc043f
 * linefeed, otherwise print an entire debug line with the expanded
Packit fc043f
 * FMT followed by the hexdump and a final LF.  */
Packit fc043f
void
Packit fc043f
_gpgrt_log_printhex (const void *buffer, size_t length,
Packit fc043f
                     const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
Packit fc043f
  if (fmt)
Packit fc043f
    {
Packit fc043f
      va_start (arg_ptr, fmt);
Packit fc043f
      _gpgrt_logv_printhex (buffer, length, fmt, arg_ptr);
Packit fc043f
      va_end (arg_ptr);
Packit fc043f
    }
Packit fc043f
  else
Packit fc043f
    {
Packit fc043f
      /* va_list is not necessary a pointer and thus we can't use NULL
Packit fc043f
       * because that would conflict with platforms using a straight
Packit fc043f
       * struct for it (e.g. arm64).  We use a dummy variable instead;
Packit fc043f
       * the static is a simple way zero it out so to not get
Packit fc043f
       * complains about uninitialized use.  */
Packit fc043f
      static va_list dummy_argptr;
Packit fc043f
Packit fc043f
      _gpgrt_logv_printhex (buffer, length, NULL, dummy_argptr);
Packit fc043f
    }
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Print a microsecond timestamp followed by FMT.  */
Packit fc043f
void
Packit fc043f
_gpgrt_logv_clock (const char *fmt, va_list arg_ptr)
Packit fc043f
{
Packit fc043f
#if ENABLE_LOG_CLOCK
Packit fc043f
  static unsigned long long initial;
Packit fc043f
  struct timespec tv;
Packit fc043f
  unsigned long long now;
Packit fc043f
  char clockbuf[50];
Packit fc043f
Packit fc043f
  if (clock_gettime (CLOCK_REALTIME, &tv))
Packit fc043f
    {
Packit fc043f
      _gpgrt_log_debug ("error getting the realtime clock value\n");
Packit fc043f
      return;
Packit fc043f
    }
Packit fc043f
  now = tv.tv_sec * 1000000000ull;
Packit fc043f
  now += tv.tv_nsec;
Packit fc043f
Packit fc043f
  if (!initial)
Packit fc043f
    initial = now;
Packit fc043f
Packit fc043f
  snprintf (clockbuf, sizeof clockbuf, "[%6llu] ", (now - initial)/1000);
Packit fc043f
  _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG, 0, NULL, clockbuf, fmt, arg_ptr);
Packit fc043f
Packit fc043f
#else /*!ENABLE_LOG_CLOCK*/
Packit fc043f
Packit fc043f
  /* You may need to link with -ltr to use the above code.  */
Packit fc043f
Packit fc043f
  _gpgrt_logv_internal (GPGRT_LOGLVL_DEBUG,
Packit fc043f
                        0, NULL, "[no clock] ", fmt, arg_ptr);
Packit fc043f
Packit fc043f
#endif  /*!ENABLE_LOG_CLOCK*/
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Print a microsecond timestamp followed by FMT.  */
Packit fc043f
void
Packit fc043f
_gpgrt_log_clock (const char *fmt, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, fmt);
Packit fc043f
  _gpgrt_logv_clock (fmt, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt__log_assert (const char *expr, const char *file,
Packit fc043f
                   int line, const char *func)
Packit fc043f
{
Packit fc043f
#ifdef GPGRT_HAVE_MACRO_FUNCTION
Packit fc043f
  _gpgrt_log (GPGRT_LOGLVL_BUG, "Assertion \"%s\" in %s failed (%s:%d)\n",
Packit fc043f
              expr, func, file, line);
Packit fc043f
#else /*!GPGRT_HAVE_MACRO_FUNCTION*/
Packit fc043f
  _gpgrt_log (GPGRT_LOGLVL_BUG, "Assertion \"%s\" failed (%s:%d)\n",
Packit fc043f
           expr, file, line);
Packit fc043f
#endif /*!GPGRT_HAVE_MACRO_FUNCTION*/
Packit fc043f
  abort (); /* Never called; just to make the compiler happy.  */
Packit fc043f
}