Commit eab50bfd authored by Daniel Kahn Gillmor's avatar Daniel Kahn Gillmor

New upstream version 2.1.18

parents 881d5a5d f8289b1d
......@@ -15,9 +15,9 @@ copyrightable year that would otherwise be listed individually.
List of Copyright holders
=========================
Copyright (C) 1997-2016 Werner Koch
Copyright (C) 1994-2016 Free Software Foundation, Inc.
Copyright (C) 2003-2013,2015-2016 g10 Code GmbH
Copyright (C) 1997-2017 Werner Koch
Copyright (C) 1994-2017 Free Software Foundation, Inc.
Copyright (C) 2003-2013,2015-2017 g10 Code GmbH
Copyright (C) 2002 Klarälvdalens Datakonsult AB
Copyright (C) 1995-1997, 2000-2007 Ulrich Drepper <drepper@gnu.ai.mit.edu>
Copyright (C) 1994 X Consortium
......@@ -204,6 +204,10 @@ Yann E. MORIN <yann.morin.1998@free.fr>
Arnaud Fontaine <arnaud.fontaine at ssi.gouv.fr>
2016-10-17:580484F4.8040806@ssi.gouv.fr:
Phil Pennock <phil.pennock@spodhuis.org>
Phil Pennock <phil@pennock-tech.com>
2017-01-19:20170119061225.GA26207@breadbox.private.spodhuis.org:
Other authors
=============
......@@ -244,8 +248,8 @@ COPYING.CC0) which basically puts them into the public domain.
=========
Copyright 1998-2016 Free Software Foundation, Inc.
Copyright 1997-2016 Werner Koch
Copyright 1998-2017 Free Software Foundation, Inc.
Copyright 1997-2017 Werner Koch
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
......
This diff is collapsed.
......@@ -20,7 +20,7 @@
ACLOCAL_AMFLAGS = -I m4
DISTCHECK_CONFIGURE_FLAGS = --enable-symcryptrun --enable-g13 \
--enable-gpg2-is-gpg
--enable-gpg2-is-gpg --enable-gpgtar --enable-wks-tools --disable-ntbtls
GITLOG_TO_CHANGELOG=gitlog-to-changelog
......
This diff is collapsed.
......@@ -2,8 +2,8 @@
=========================
Version 2.1
Copyright 1997-2016 Werner Koch
Copyright 1998-2016 Free Software Foundation, Inc.
Copyright 1997-2017 Werner Koch
Copyright 1998-2017 Free Software Foundation, Inc.
* INTRODUCTION
......
......@@ -532,7 +532,7 @@ int agent_card_learn (ctrl_t ctrl,
void (*sinfo_cb)(void*, const char *,
size_t, const char *),
void *sinfo_cb_arg);
int agent_card_serialno (ctrl_t ctrl, char **r_serialno);
int agent_card_serialno (ctrl_t ctrl, char **r_serialno, const char *demand);
int agent_card_pksign (ctrl_t ctrl,
const char *keyid,
int (*getpin_cb)(void *, const char *, char*, size_t),
......
......@@ -679,16 +679,22 @@ get_serialno_cb (void *opaque, const char *line)
/* Return the serial number of the card or an appropriate error. The
serial number is returned as a hexstring. */
int
agent_card_serialno (ctrl_t ctrl, char **r_serialno)
agent_card_serialno (ctrl_t ctrl, char **r_serialno, const char *demand)
{
int rc;
char *serialno = NULL;
char line[ASSUAN_LINELENGTH];
rc = start_scd (ctrl);
if (rc)
return rc;
rc = assuan_transact (ctrl->scd_local->ctx, "SERIALNO",
if (!demand)
strcpy (line, "SERIALNO");
else
snprintf (line, DIM(line), "SERIALNO --demand=%s", demand);
rc = assuan_transact (ctrl->scd_local->ctx, line,
NULL, NULL, NULL, NULL,
get_serialno_cb, &serialno);
if (rc)
......
/* command-ssh.c - gpg-agent's ssh-agent emulation layer
/* command-ssh.c - gpg-agent's implementation of the ssh-agent protocol.
* Copyright (C) 2004-2006, 2009, 2012 Free Software Foundation, Inc.
* Copyright (C) 2004-2006, 2009, 2012-2014 Werner Koch
*
......@@ -2408,7 +2408,7 @@ card_key_available (ctrl_t ctrl, gcry_sexp_t *r_pk, char **cardsn)
if ( gpg_err_code (err) == GPG_ERR_CARD_REMOVED )
{
/* Ask for the serial number to reset the card. */
err = agent_card_serialno (ctrl, &serialno);
err = agent_card_serialno (ctrl, &serialno, NULL);
if (err)
{
if (opt.verbose)
......@@ -3216,7 +3216,7 @@ ssh_identities_remove_all (void)
err = 0;
/* FIXME: shall we remove _all_ cache entries or only those
registered through the ssh emulation? */
registered through the ssh-agent protocol? */
return err;
}
......
......@@ -58,7 +58,7 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
for (;;)
{
rc = agent_card_serialno (ctrl, &serialno);
rc = agent_card_serialno (ctrl, &serialno, want_sn);
if (!rc)
{
log_debug ("detected card with S/N %s\n", serialno);
......@@ -72,11 +72,17 @@ ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
return 0; /* yes, we have the correct card */
}
}
else if (gpg_err_code (rc) == GPG_ERR_ENODEV)
{
log_debug ("no device present\n");
rc = 0;
no_card = 1;
}
else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
{
log_debug ("no card present\n");
rc = 0;
no_card = 1;
no_card = 2;
}
else
{
......
......@@ -303,8 +303,10 @@ static int putty_support;
#endif /*HAVE_W32_SYSTEM*/
/* The list of open file descriptors at startup. Note that this list
has been allocated using the standard malloc. */
* has been allocated using the standard malloc. */
#ifndef HAVE_W32_SYSTEM
static int *startup_fd_list;
#endif
/* The signal mask at startup and a flag telling whether it is valid. */
#ifdef HAVE_SIGPROCMASK
......@@ -344,7 +346,7 @@ static char *redir_socket_name_extra;
static char *socket_name_browser;
static char *redir_socket_name_browser;
/* Name of the communication socket used for ssh-agent-emulation. */
/* Name of the communication socket used for ssh-agent protocol. */
static char *socket_name_ssh;
static char *redir_socket_name_ssh;
......@@ -949,8 +951,10 @@ main (int argc, char **argv )
/* Before we do anything else we save the list of currently open
file descriptors and the signal mask. This info is required to
do the exec call properly. */
do the exec call properly. We don't need it on Windows. */
#ifndef HAVE_W32_SYSTEM
startup_fd_list = get_all_open_fds ();
#endif /*!HAVE_W32_SYSTEM*/
#ifdef HAVE_SIGPROCMASK
if (!sigprocmask (SIG_UNBLOCK, NULL, &startup_signal_mask))
startup_signal_mask_valid = 1;
......@@ -1759,11 +1763,19 @@ agent_libgcrypt_progress_cb (void *data, const char *what, int printchar,
/* Libgcrypt < 1.8 does not know about nPth and thus when it reads
* from /dev/random this will block the process. To mitigate this
* problem we take a short nap when Libgcrypt tells us that it needs
* problem we yield the thread when Libgcrypt tells us that it needs
* more entropy. This way other threads have chance to run. */
#if GCRYPT_VERSION_NUMBER < 0x010800 /* 1.8.0 */
if (what && !strcmp (what, "need_entropy"))
npth_usleep (100000); /* 100ms */
{
#if GPGRT_VERSION_NUMBER < 0x011900 /* 1.25 */
/* In older gpg-error versions gpgrt_yield is buggy for use with
* nPth and thus we need to resort to a sleep call. */
npth_usleep (1000); /* 1ms */
#else
gpgrt_yield ();
#endif
}
#endif
}
......
......@@ -330,7 +330,7 @@ agent_handle_learn (ctrl_t ctrl, int send, void *assuan_context, int force)
cparm.ctrl = ctrl;
/* Check whether a card is present and get the serial number */
rc = agent_card_serialno (ctrl, &serialno);
rc = agent_card_serialno (ctrl, &serialno, NULL);
if (rc)
goto leave;
......
#! /bin/sh
# autogen.sh
# Copyright (C) 2003, 2014 g10 Code GmbH
# Copyright (C) 2003, 2014, 2017 g10 Code GmbH
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
......@@ -15,7 +15,7 @@
# configure it for the respective package. It is maintained as part of
# GnuPG and source copied by other packages.
#
# Version: 2014-06-06
# Version: 2017-01-17
configure_ac="configure.ac"
......@@ -80,7 +80,17 @@ if [ -n "${AUTOGEN_SH_SILENT}" ]; then
SILENT=" --silent"
fi
if test x"$1" = x"--help"; then
echo "usage: ./autogen.sh [--silent] [--force] [--build-TYPE] [ARGS]"
echo "usage: ./autogen.sh [OPTIONS] [ARGS]"
echo " Options:"
echo " --silent Silent operation"
echo " --force Pass --force to autoconf"
echo " --find-version Helper for configure.ac"
echo " --build-TYPE Configure to cross build for TYPE"
echo " --print-host Print only the host triplet"
echo " --print-build Print only the build platform triplet"
echo ""
echo " ARGS are passed to configure in --build-TYPE mode."
echo " Configuration for this script is expected in autogen.rc"
exit 0
fi
if test x"$1" = x"--silent"; then
......@@ -200,6 +210,11 @@ if [ "$myhost" = "find-version" ]; then
minor="$3"
micro="$4"
if [ -z "$package" -o -z "$major" -o -z "$minor" ]; then
echo "usage: ./autogen.sh --find-version PACKAGE MAJOR MINOR [MICRO]" >&2
exit 1
fi
case "$version_parts" in
2)
matchstr1="$package-$major.[0-9]*"
......@@ -217,15 +232,17 @@ if [ "$myhost" = "find-version" ]; then
if [ -e .git ]; then
ingit=yes
tmp=$(git describe --match "${matchstr1}" --long 2>/dev/null)
tmp=$(echo "$tmp" | sed s/^"$package"//)
if [ -n "$tmp" ]; then
tmp=$(echo "$tmp"|awk -F- '$3!=0 && $3 !~ /^beta/ {print"-beta"$3}')
tmp=$(echo "$tmp" | sed s/^"$package"// \
| awk -F- '$3!=0 && $3 !~ /^beta/ {print"-beta"$3}')
else
tmp=$(git describe --match "${matchstr2}" --long 2>/dev/null \
| awk -F- '$4!=0{print"-beta"$4}')
fi
[ -n "$tmp" ] && beta=yes
rev=$(git rev-parse --short HEAD | tr -d '\n\r')
rvd=$((0x$(echo ${rev} | head -c 4)))
rvd=$((0x$(echo ${rev} | dd bs=1 count=4 2>/dev/null)))
else
ingit=no
beta=yes
......@@ -417,13 +434,16 @@ fi
# Check the git setup.
if [ -d .git ]; then
CP="cp -a"
[ -z "${SILENT}" ] && CP="$CP -v"
CP="cp -p"
# If we have a GNU cp we can add -v
if cp --version >/dev/null 2>/dev/null; then
[ -z "${SILENT}" ] && CP="$CP -v"
fi
if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then
[ -z "${SILENT}" ] && cat <<EOF
*** Activating trailing whitespace git pre-commit hook. ***
For more information see this thread:
http://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084.html
https://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084.html
To deactivate this pre-commit hook again move .git/hooks/pre-commit
and .git/hooks/pre-commit.sample out of the way.
EOF
......
......@@ -179,6 +179,7 @@ sub parse_amend_file($)
my $amend_file;
my $append_dot = 0;
my $tear_off = 0;
my $firstline;
GetOptions
(
help => sub { usage 0 },
......@@ -338,7 +339,9 @@ sub parse_amend_file($)
# Prefix each non-empty line with a TAB.
@line = map { length $_ ? "\t$_" : '' } @line;
print "\n", join ("\n", @line), "\n";
$firstline = shift @line;
print "\n", $firstline, "\n", "\t+ commit $sha\n";
print join ("\n", @line), "\n";
}
SKIPCOMMIT:
......
/* [argparse.c wk 17.06.97] Argument Parser for option handling
* Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
* Copyright (C) 1997-2001, 2006-2008, 2013-2016 Werner Koch
* Copyright (C) 1997-2001, 2006-2008, 2013-2017 Werner Koch
*
* This file is part of GnuPG.
*
......@@ -71,7 +71,7 @@
#else /* Used by GnuPG */
# define ARGPARSE_GPL_VERSION 3
# define ARGPARSE_CRIGHT_STR "Copyright (C) 2016 Free Software Foundation, Inc."
# define ARGPARSE_CRIGHT_STR "Copyright (C) 2017 Free Software Foundation, Inc."
#endif /*GNUPG_MAJOR_VERSION*/
......@@ -898,7 +898,9 @@ find_long_option( ARGPARSE_ARGS *arg,
int j;
for(j=i+1; opts[j].short_opt; j++ ) {
if( opts[j].long_opt
&& !strncmp( opts[j].long_opt, keyword, n ) )
&& !strncmp( opts[j].long_opt, keyword, n )
&& !(opts[j].short_opt == opts[i].short_opt
&& opts[j].flags == opts[i].flags ) )
return -2; /* abbreviation is ambiguous */
}
return i;
......
......@@ -128,11 +128,14 @@ close_all_fds (int first, int *except)
/* Returns an array with all currently open file descriptors. The end
of the array is marked by -1. The caller needs to release this
array using the *standard free* and not with xfree. This allow the
use of this function right at startup even before libgcrypt has
been initialized. Returns NULL on error and sets ERRNO
accordingly. */
* of the array is marked by -1. The caller needs to release this
* array using the *standard free* and not with xfree. This allow the
* use of this function right at startup even before libgcrypt has
* been initialized. Returns NULL on error and sets ERRNO
* accordingly. Note that fstat prints a warning to DebugView for all
* invalid fds which is a bit annoying. We actually do not need this
* function in real code (close_all_fds is a dummy anyway) but we keep
* it for use by t-exechelp.c. */
int *
get_all_open_fds (void)
{
......
......@@ -232,36 +232,38 @@ copy_buffer_do_copy (struct copy_buffer *c, estream_t source, estream_t sink)
if (c->nread == 0)
{
c->writep = c->buffer;
err = es_read (source, c->buffer, sizeof c->buffer, &c->nread);
if (err)
if (es_read (source, c->buffer, sizeof c->buffer, &c->nread))
{
if (errno == EAGAIN)
err = my_error_from_syserror ();
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
return 0; /* We will just retry next time. */
return my_error_from_syserror ();
return err;
}
assert (c->nread <= sizeof c->buffer);
log_assert (c->nread <= sizeof c->buffer);
}
if (c->nread == 0)
return 0; /* Done copying. */
nwritten = 0;
err = sink? es_write (sink, c->writep, c->nread, &nwritten) : 0;
if (sink && es_write (sink, c->writep, c->nread, &nwritten))
err = my_error_from_syserror ();
else
err = 0;
assert (nwritten <= c->nread);
log_assert (nwritten <= c->nread);
c->writep += nwritten;
c->nread -= nwritten;
assert (c->writep - c->buffer <= sizeof c->buffer);
log_assert (c->writep - c->buffer <= sizeof c->buffer);
if (err)
{
if (errno == EAGAIN)
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
return 0; /* We will just retry next time. */
return my_error_from_syserror ();
return err;
}
if (sink && es_fflush (sink) && errno != EAGAIN)
......@@ -275,16 +277,24 @@ copy_buffer_do_copy (struct copy_buffer *c, estream_t source, estream_t sink)
static gpg_error_t
copy_buffer_flush (struct copy_buffer *c, estream_t sink)
{
gpg_error_t err;
gpg_error_t err = 0;
size_t nwritten = 0;
while (c->nread > 0)
{
err = copy_buffer_do_copy (c, NULL, sink);
if (err)
return err;
}
if (es_write (sink, c->writep, c->nread, &nwritten))
err = my_error_from_syserror ();
log_assert (nwritten <= c->nread);
c->writep += nwritten;
c->nread -= nwritten;
log_assert (c->writep - c->buffer <= sizeof c->buffer);
if (err)
return err;
if (es_fflush (sink))
err = my_error_from_syserror ();
return 0;
return err;
}
......@@ -444,6 +454,8 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
if (es_feof (input))
{
err = copy_buffer_flush (cpbuf_in, fds[0].stream);
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
continue; /* Retry next time. */
if (err)
{
log_error ("error feeding data to '%s': %s\n",
......@@ -470,6 +482,8 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
if (es_feof (inextra))
{
err = copy_buffer_flush (cpbuf_extra, fds[3].stream);
if (gpg_err_code (err) == GPG_ERR_EAGAIN)
continue; /* Retry next time. */
if (err)
{
log_error ("error feeding data to '%s': %s\n",
......@@ -606,9 +620,11 @@ gnupg_exec_tool (const char *pgmname, const char *argv[],
if (len)
{
err = es_read (output, *result, len, &nread);
if (err)
goto leave;
if (es_read (output, *result, len, &nread))
{
err = my_error_from_syserror ();
goto leave;
}
if (nread != len)
log_fatal ("%s: short read from memstream\n", __func__);
}
......
......@@ -133,7 +133,7 @@ gnupg_set_time (time_t newtime, int freeze)
else if (freeze)
{
timemode = FROZEN;
timewarp = current;
timewarp = newtime == (time_t)-1 ? current : newtime;
}
else if (newtime > current)
{
......
......@@ -665,31 +665,10 @@ log_get_stream ()
return logstream;
}
static void
do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
print_prefix (int level, int leading_backspace)
{
if (!logstream)
{
#ifdef HAVE_W32_SYSTEM
char *tmp;
tmp = (no_registry
? NULL
: read_w32_registry_string (NULL, GNUPG_REGISTRY_DIR,
"DefaultLogFile"));
log_set_file (tmp && *tmp? tmp : NULL);
xfree (tmp);
#else
log_set_file (NULL); /* Make sure a log stream has been set. */
#endif
assert (logstream);
}
es_flockfile (logstream);
if (missing_lf && level != GPGRT_LOG_CONT)
es_putc_unlocked ('\n', logstream );
missing_lf = 0;
if (level != GPGRT_LOG_CONT)
{ /* Note this does not work for multiple line logging as we would
* need to print to a buffer first */
......@@ -720,11 +699,9 @@ do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
es_putc_unlocked (':', logstream);
/* A leading backspace suppresses the extra space so that we can
correctly output, programname, filename and linenumber. */
if (fmt && *fmt == '\b')
fmt++;
else
if (with_time || with_prefix || with_pid || force_prefixes)
es_putc_unlocked (' ', logstream);
if (!leading_backspace
&& (with_time || with_prefix || with_pid || force_prefixes))
es_putc_unlocked (' ', logstream);
}
switch (level)
......@@ -741,6 +718,40 @@ do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
es_fprintf_unlocked (logstream,"[Unknown log level %d]: ", level);
break;
}
}
static void
do_logv (int level, int ignore_arg_ptr, const char *extrastring,
const char *fmt, va_list arg_ptr)
{
int leading_backspace = (fmt && *fmt == '\b');
if (!logstream)
{
#ifdef HAVE_W32_SYSTEM
char *tmp;
tmp = (no_registry
? NULL
: read_w32_registry_string (NULL, GNUPG_REGISTRY_DIR,
"DefaultLogFile"));
log_set_file (tmp && *tmp? tmp : NULL);
xfree (tmp);
#else
log_set_file (NULL); /* Make sure a log stream has been set. */
#endif
assert (logstream);
}
es_flockfile (logstream);
if (missing_lf && level != GPGRT_LOG_CONT)
es_putc_unlocked ('\n', logstream );
missing_lf = 0;
print_prefix (level, leading_backspace);
if (leading_backspace)
fmt++;
if (fmt)
{
......@@ -766,6 +777,48 @@ do_logv (int level, int ignore_arg_ptr, const char *fmt, va_list arg_ptr)
missing_lf = 1;
}
/* If we have an EXTRASTRING print it now while we still hold the
* lock on the logstream. */
if (extrastring)
{
int c;
if (missing_lf)
{
es_putc_unlocked ('\n', logstream);
missing_lf = 0;
}
print_prefix (level, leading_backspace);
es_fputs_unlocked (">> ", logstream);
missing_lf = 1;
while ((c = *extrastring++))
{
missing_lf = 1;
if (c == '\\')
es_fputs_unlocked ("\\\\", logstream);
else if (c == '\r')
es_fputs_unlocked ("\\r", logstream);
else if (c == '\n')
{
es_fputs_unlocked ("\\n\n", logstream);
if (*extrastring)
{
print_prefix (level, leading_backspace);
es_fputs_unlocked (">> ", logstream);
}
else
missing_lf = 0;
}
else
es_putc_unlocked (c, logstream);
}
if (missing_lf)
{
es_putc_unlocked ('\n', logstream);
missing_lf = 0;
}
}
if (level == GPGRT_LOG_FATAL)
{
if (missing_lf)
......@@ -804,7 +857,7 @@ log_log (int level, const char *fmt, ...)
va_list arg_ptr ;
va_start (arg_ptr, fmt) ;
do_logv (level, 0, fmt, arg_ptr);
do_logv (level, 0, NULL, fmt, arg_ptr);
va_end (arg_ptr);
}
......@@ -812,7 +865,7 @@ log_log (int level, const char *fmt, ...)
void
log_logv (int level, const char *fmt, va_list arg_ptr)
{
do_logv (level, 0, fmt, arg_ptr);
do_logv (level, 0, NULL, fmt, arg_ptr);
}
......@@ -821,7 +874,7 @@ do_log_ignore_arg (int level, const char *str, ...)
{
va_list arg_ptr;
va_start (arg_ptr, str);
do_logv (level, 1, str, arg_ptr);
do_logv (level, 1, NULL, str, arg_ptr);
va_end (arg_ptr);
}
......@@ -843,7 +896,7 @@ log_info (const char *fmt, ...)
va_list arg_ptr ;
va_start (arg_ptr, fmt);
do_logv (GPGRT_LOG_INFO, 0, fmt, arg_ptr);
do_logv (GPGRT_LOG_INFO, 0, NULL, fmt, arg_ptr);
va_end (arg_ptr);
}
......@@ -854,7 +907,7 @@ log_error (const char *fmt, ...)
va_list arg_ptr ;
va_start (arg_ptr, fmt);
do_logv (GPGRT_LOG_ERROR, 0, fmt, arg_ptr);
do_logv (GPGRT_LOG_ERROR, 0, NULL, fmt, arg_ptr);
va_end (arg_ptr);
/* Protect against counter overflow. */
if (errorcount < 30000)
......@@ -868,7 +921,7 @@ log_fatal (const char *fmt, ...)
va_list arg_ptr ;
va_start (arg_ptr, fmt);
do_logv (GPGRT_LOG_FATAL, 0, fmt, arg_ptr);
do_logv (GPGRT_LOG_FATAL, 0, NULL, fmt, arg_ptr);
va_end (arg_ptr);
abort (); /* Never called; just to make the compiler happy. */
}
......@@ -880,7 +933,7 @@ log_bug (const char *fmt, ...)
va_list arg_ptr ;
va_start (arg_ptr, fmt);
do_logv (GPGRT_LOG_BUG, 0, fmt, arg_ptr);
do_logv (GPGRT_LOG_BUG, 0, NULL, fmt, arg_ptr);
va_end (arg_ptr);
abort (); /* Never called; just to make the compiler happy. */
}
......@@ -892,7 +945,21 @@ log_debug (const char *fmt, ...)
va_list arg_ptr ;
va_start (arg_ptr, fmt);
do_logv (GPGRT_LOG_DEBUG, 0, fmt, arg_ptr);
do_logv (GPGRT_LOG_DEBUG, 0, NULL, fmt, arg_ptr);
va_end (arg_ptr);
}
/* The same as log_debug but at the end of the output STRING is