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