diff --git a/ChangeLog b/ChangeLog
index 8c0a2fe79..e765ef892 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,1313 +1,1319 @@
+2010-12-14  Werner Koch  <wk@g10code.com>
+
+	* configure.ac (BUILD_WITH_GPG, BUILD_WITH_GPGSM)
+	(BUILD_WITH_AGENT, BUILD_WITH_SCDAEMON, BUILD_WITH_DIRMNGR)
+	(BUILD_WITH_G13): New defines.
+
 2010-11-23  Werner Koch  <wk@g10code.com>
 
 	* am/cmacros.am (extra_bin_ldflags): New.  For W32CE set the stack
 	size to 256k.
 
 2010-11-17  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (ENABLE_CARD_SUPPORT): Define. 
 
 2010-10-27  Werner Koch  <wk@g10code.com>
 
 	* acinclude.m4 (GNUPG_TIME_T_UNSIGNED): New.
 	* configure.ac (AC_HEADER_TIME): Include before checking time_t.
 	(GNUPG_TIME_T_UNSIGNED): Add.
 
 2010-10-26  Werner Koch  <wk@g10code.com>
 
 	Release 2.1.0beta1.
 
 2010-10-18  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (install-data-hook): Add W32 specific hook.
 
 2010-10-08  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Add option --enable-dirmngr-auto-start.
 	(USE_DIRMNGR_AUTO_START): New ac_define.
 	* autogen.sh <--build-w32ce>: Use new option.
 
 2010-10-06  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Make --enable-standard-socket the default.
 
 2010-10-04  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (GNUPG_CHECK_FAQPROG): Remove.
 
 2010-08-19  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (AH_BOTTOM): Define GPG_ERR_ENABLE_ERRNO_MACROS.
 
 2010-08-09  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (inet_pton): Check for it.
 
 2010-08-05  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (AH_BOTTOM): Remove HTTP_USE_ESTREAM.
 
 2010-08-02  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Require libksba 1.1.0 due to the use of
 	ksba_reader_set_release_notify.
 
 2010-07-30  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (GNUPG_PTH_PATH) [W32]: Require version 2.0.3.
 
 2010-07-25  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (USE_LDAPWRAPPER): AC_DEFINE and AM_CONDITIONAL it.
 
 2010-06-09  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (GNUPG_DIRMNGR_LDAP_PGM): Add option
 	--with-dirmngr-ldap-pgm.
 
 	* am/cmacros.am (-DGNUPG_LOCALSTATEDIR): New.
 	(GNUPG_DEFAULT_DIRMNGR_LDAP): New.
 
 2010-06-08  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Add build support for dirmngr.
 	(try_ldap): Rename to try_ks_ldap.
 	(GNUPG_CHECK_LDAP): Also test if dirmngr is to be build.
 
 	* Makefile.am (SUBDIRS): Add dirmngr.
 
 2010-06-07  Werner Koch  <wk@g10code.com>
 
 	* dirmngr/: New.
 
 	* configure.ac: Add option --enable-gpgtar.
 
 2010-05-31  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (AC_CHECK_FUNCS): Check for lstat.
 
 2010-04-30  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Add option --enable-standard-socket.
 	(USE_STANDARD_SOCKET): ac_define it.
 
 2010-04-14  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (keyserver) [W32CE]: Do not build for now.
 
 	* configure.ac (use_zip): New.
 	(--disable-zip): New option.
 	(HAVE_ZIP): New.
 	* autogen.sh <build-w32ce>: Disable ZIP.
 
 2010-04-07  Werner Koch  <wk@g10code.com>
 
 	* autogen.sh: Take a .gnupg-autogen.rc file in account.
 
 	* gl/mkdtemp.c (getpid) [W32CE]: New macro.
 
 2010-03-24  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (AH_BOTTOM): Use /gnupg as the default homedir on
 	dosish systems which don't support drive letters (e.g. W32CE).
 
 	* am/cmacros.am (extra_sys_libs): New.
 
 2010-03-23  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (W32SOCKLIBS): Change value for W32CE.
 
 2010-03-12  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (AC_INIT): Prepare for using git.
 
 2010-03-10  Werner Koch  <wk@g10code.com>
 
 	* jnlib/: Move all code to common/.
 	* Makefile.am (SUBDIRS): Remove jnlib.
 	* configure.ac (AC_CONFIG_FILES): Remove jnlib/Makefile.
 
 	* configure.ac (AM_PATH_LIBASSUAN): Remove double test.
 	* acinclude.m4 (GNUPG_CHECK_ENDIAN): Remove bogus warning.
 
 2010-03-09  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Add option --disable-ccid-driver.
 	(AH_BOTTOM): Define GPG_ERR_ENABLE_GETTEXT_MACROS.
 
 2010-02-26  Werner Koch  <wk@g10code.com>
 
 	* gl/mkdtemp.c (__set_errno) [W32CE]: Use gpg_err_set_errno.
 	* gl/setenv.c (__set_errno) [W32CE]: Ditto.
 	* gl/unsetenv.c (__set_errno) [W32CE]: Ditto.
 
 	* configure.ac (HAVE_W32CE_SYSTEM): New ac_define and
 	am_conditional.
 	(signal.h, getenv): Check for them.
 
 	* autogen.sh: New option --build-w32ce.  Remove obsolete option
 	--without-included-gettext.
 
 2009-12-08  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (USE_DNS_CERT): Support ADNS.
 
 2009-12-07  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Check for ADNS before checking for the BIND
 	resolver.
 	(USE_ADNS): Fallback macro for PKA and CERT lookups.
 
 2009-10-20  Marcus Brinkmann  <marcus@g10code.com>
 
 	* configure.ac: Check for fusermount and encfs.
 
 2009-10-16  Marcus Brinkmann  <marcus@g10code.com>
 
 	* configure.ac: Check for libassuan instead of libassuan-pth.
 
 2009-10-12  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Use -O3 because newer gcc versions require that
 	for uninitialized variable warnings.
 
 2009-09-23  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (HAVE_ASSUAN_SET_IO_MONITOR): Remove test.
 	(_ASSUAN_ONLY_GPG_ERRORS): Remove.
 
 2009-09-23  Marcus Brinkmann  <marcus@g10code.de>
 
 	* configure.ac (NEED_LIBASSUAN_API, NEED_LIBASSUAN_VERSION):
 	Update to new API (2, 1.1.0).
 
 2009-09-21  Werner Koch  <wk@g10code.com>
 
 	Start a new development branch in the SVN trunk.  The stable one
 	is now known in the SVN as branches/GNUPG-STABLE-2-0.
 
 2009-09-04  Werner Koch  <wk@g10code.com>
 
 	Release 2.0.13.
 
 2009-06-29  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Take care of --without-adns.  Suggested by
 	Arfrever Frehtes Taifersar Arahesis.
 
 2009-06-17  Werner Koch  <wk@g10code.com>
 
 	Release 2.0.12.
 
 2009-06-05  David Shaw  <dshaw@jabberwocky.com>
 
 	* configure.ac: Remove Camellia restriction.
 
 2009-04-01  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Test for fsync.
 
 2009-03-18  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Test for getrlimit.
 
 2009-03-03  Werner Koch  <wk@g10code.com>
 
 	Release 2.0.11.
 
 2009-01-12  Werner Koch  <wk@g10code.com>
 
 	Release 2.0.10.
 
 2008-12-09  Werner Koch  <wk@g10code.com>
 
 	Release 2.0.10rc1.
 
 2008-10-17  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Use more warning options with modern GCCs.
 
 2008-09-29  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Require libgcrypt 1.4.
 
 2008-08-27  David Shaw  <dshaw@jabberwocky.com>
 
 	* configure.ac: Use printf for the most portable SVN version
 	detection.
 
 	* configure.ac: Darwin's /bin/sh has a builtin echo that doesn't
 	understand '-n'.  Use tr to trim the carriage return instead.
 
 2008-04-23  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Call gl_HEADER_SYS_SOCKET and gl_TYPE_SOCKLEN_T.
 
 2008-04-07  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (ADNSLIBS): Test for adns.
 	(GPGKEYS_KDNS): New.
 
 2008-04-01  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Require curl 7.10 (Oct 1 2002) or later as we use
 	curl_version_info().
 	(AC_INIT): Fix quoting.
 
 2008-03-27  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dist_doc_DATA): New. Install README.
 
 2008-03-26  Werner Koch  <wk@g10code.com>
 
 	Release 2.0.9.
 
 2008-02-19  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Remove --with-pkits-tests.
 
 2008-02-15  Werner Koch  <wk@g10code.com>
 
 	* gl/allocsa.h, gl/m4/allocsa.m4: Replace HAVE_LONG_LONG by
 	HAVE_LONG_LONG_INT.
 
 2008-02-15  gettextize  <bug-gnu-gettext@gnu.org>
 
 	* configure.ac (AM_GNU_GETTEXT_VERSION): Bump to 0.17.
 
 2007-12-20  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.8.
 
 2007-12-17  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Add treatment for HAVE_LDAP_START_TLS_SA.
 
 2007-12-14  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.8rc1.
 
 2007-12-12  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (USE_CAMELLIA): Define by new option --enable-camellia.
 
 2007-12-03  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Add test gt_LC_MESSAGES..
 
 2007-10-01  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Require assuan 1.0.4.
 
 2007-09-14  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (GNUPG_LIBASSUAN_VERSION): New.
 
 2007-09-10  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.7.
 
 2007-08-27  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Remove remaining support for internal regex.
 	Define DISABLE_REGEX automake conditional.  Add option
 	--with-regex.
 	* autogen.sh [--build-w32]: Remove --disable-regex.  Use --with-regex.
 
 2007-08-16  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.6.
 
 2007-08-08  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Use AC_CANONICAL_HOST and not AC_CANONICAL_TARGET.
 
 2007-07-09  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (AM_ICONV): Check for it even when building without
 	NLS.
 
 2007-07-05  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.5.
 
 	* configure.ac: Require libassuan 1.0.2.
 
 2007-07-05  Marcus Brinkmann  <marcus@g10code.de>
 
 	* configure.ac: Invoke AM_LANGINFO_CODESET.
 
 2007-07-04  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (AUTOMAKE_OPTIONS): Add no-dist-gzip.
 
 	Switched entire package to GPLv3+.
 
 	* configure.ac: Require libksba 1.0.2.
 
 	* COPYING:  Updated to GPLv3.
 	* COPYING.LIB: New as jnlib/ uses this license.
 
 	* gl/: Switched to GPLv3+.
 
 	* intl/ Removed.
 	* configure.ac (AM_GNU_GETTEXT): Add external flag.
 	(AM_ICONV): New.
 
 2007-07-03  Werner Koch  <wk@g10code.com>
 
 	* configure.ac [W32]: Use ws2_32 instead of wsock32.
 
 2007-06-25  Werner Koch  <wk@g10code.com>
 
 	* gl/mkdtemp.c (gen_tempname) [MKDIR_TAKES_ONE_ARG]: Avoid
 	compiler warning by using the proper config macro.
 
 2007-06-15  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Call AM_PO_SUBDIRS.
 	(W32SOCKLIBS): New.
 
 	* autogen.sh: Use = and not == in test to be POSIXly correct.
 	<build-w32>: Disable use of regex.
 
 2007-06-14  Werner Koch  <wk@g10code.com>
 
 	* configure.ac [AH_BOTTOM]: Remove the hardwired names of modules.
 
 2007-06-12  Werner Koch  <wk@g10code.com>
 
 	* configure.ac [AH_BOTTOM]: Define HTTP_NO_WSASTARTUP.
 
 2007-06-11  Werner Koch  <wk@g10code.com>
 
 	* am/cmacros.am (libcommonstd, libcommonpth, libcommonstd_ldadd)
 	(libcommonpth_ldadd): Add macros.
 
 2007-06-06  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Add a few notices message so make browsing of the
 	log file easier.
 	(CC_FOR_BUILD): New.
 
 2007-05-30  Werner Koch  <wk@g10code.com>
 
 	* configure.ac [W32]: Do not create a symlink to w32-pth.h.
 	Require the installation of the w32pth package.
 
 2007-05-29  Werner Koch  <wk@g10code.com>
 
 	* gl/: Updated to a newer version.
 
 2007-05-24  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Use -Wpointer-arith is possible.
 
 2007-05-15  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Renamed the estream macros. Remove -Wformat-nonliteral.
 
 	* configure.ac: Call ESTREAM_INIT and define the memory
 	allocators for estream_asprintf.
 	(gl_MODULES): Remove vasprintf.
 
 2007-05-09  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.4.
 
 2007-05-07  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Require libgcrypt 1.2.2 to avoid compiler warnings.
 
 2007-05-07  gettextize  <bug-gnu-gettext@gnu.org>
 
 	* configure.ac (AM_GNU_GETTEXT_VERSION): Bump to 0.16.1.
 
 2007-05-07  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Bail out if no C-89 compiler has been found.
 
 2007-05-04  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Add --enable-mailto
 
 	* configure.ac: Require automake 1.10
 	(AC_CONFIG_FILES): Rename gpgkeys_ to gpg2keys_.
 	(AM_PROG_CC_C_O): New.
 
 2007-03-08  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.3.
 
 	* autogen.sh: Add option --force.
 
 2007-01-31  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.2.
 
 2006-11-30  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Save original LIBS when testing for dlopen.
 
 2006-11-28  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.1.
 
 2006-11-23  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.1rc1.
 
 2006-11-21  Werner Koch  <wk@g10code.com>
 
 	* configure.ac [AH_BOTTOM]: Disable PTH soft mapping.
 	(AC_CHECK_SIZEOF): Check for time_t.
 	(BUILD_INCLUDED_LIBINTL): Remove AM_PO_SUBDIRS as it is not
 	required for C.
 
 2006-11-15  Werner Koch  <wk@g10code.com>
 
 	* autogen.sh: Add convenience option --build-amd64.
 
 2006-11-14  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (HAVE_ASSUAN_SET_IO_MONITOR): Test for it.
 
 2006-11-11  Werner Koch  <wk@g10code.com>
 
 	Released 2.0.0.
 
 2006-11-06  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.95.
 
 2006-11-03  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Test for pty.h.  From Gentoo.
 
 2006-10-24  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.94.
 
 2006-10-20  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (stowinstall): Add convenience target.
 
 2006-10-18  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: svn revison magic fixes for old bashs.  Suggested
 	by Alain Guibert.
 
 2006-10-18  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.93.
 
 2006-10-17  Werner Koch  <wk@g10code.com>
 
 	* autogen.sh <--build-w32>: Test also for a host "mingw32".
 
 	* configure.ac: Removed W32LIBS. Use NETLIBS instead.
 
 2006-10-11  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.92.
 
 	* configure.ac: Require libassuan 0.9.3.
 
 2006-10-09  Werner Koch  <wk@g10code.com>
 
 	* acinclude.m4: Moved pth check to m4/gnupg-pth.m4.
 
 2006-10-06  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Also check for libassuan's pth version.
 
 2006-10-04  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.91.
 
 	* configure.ac: Require libassuan 0.9.1 which fixes a problem with
 	gpgsm.
 
 2006-09-27  Werner Koch  <wk@g10code.com>
 
 	* gl/strsep.h, gl/strsep.c, gl/m4/strsep.m4: Removed.
 	* gl/strpbrk.h, gl/strpbrk.c, gl/m4/strpbrk.m4: Removed.
 	* gl/Makefile.am: Removed module strsep and strpbrk.
 	* configure.ac: Check for strsep in the context of jnlib.  Remove
 	check from gl_MODULES. Moved check for timegm into the jnlib context.
 
 2006-09-27  Marcus Brinkmann  <marcus@g10code.de>
 
 	* Makefile.am: Fix cut & paste error.
 
 2006-09-25  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.90.
 
 2006-09-22  Werner Koch  <wk@g10code.com>
 
 	* AUTHORS: Add information about used licenses.
 
 2006-09-20  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dist-hook): Removed distfiles cruft.
 	(SUBDIRS): Added include
 
 2006-09-18  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.23.
 
 	* configure.ac (--enable-agent-only): Donot build tools and doc
 	(--disable-tools,--disable-doc): New.
 	* Makefile.am (SUBDIRS): Allow to conditional build tools and doc.
 
 2006-09-14  Werner Koch  <wk@g10code.com>
 
  	Replaced all call gpg_error_from_errno(errno) by
 	gpg_error_from_syserror().
 
 	* configure.ac: Build gpg by default.
 	(GNUPG_SYS_SO_PEERCRED): Removed.
 
 2006-09-13  Werner Koch  <wk@g10code.com>
 
 	* autogen.sh: Better detection of the cross compiler kit.
 
 2006-09-06  Marcus Brinkmann  <marcus@g10code.de>
 
 	* configure.ac: New automake conditional RUN_GPG_TESTS.
 
 2006-09-06  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Define _ASSUAN_ONLY_GPG_ERRORS.  Require Assuan
 	0.9 and libgpg-error 1.4.
 
 2006-08-31  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Require libksba 1.0 and added API check for it.
 	(GPG_ERR_LOCKED): Removed DECL check as we require 1.2 anyway.
 	(have_libusb): New to give a feedback about CCID support
 
 2006-08-21  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Removed docbook tests.
 	(AC_CONFIG_FILES): Added gpgkeys_test and gpgkeys_mailto.
 
 	* Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Enable gpg.
 
 2006-08-17  Werner Koch  <wk@g10code.com>
 
 	* THANKS: Merged with the 1.4 one.
 
 2006-08-16  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Removed test for capabilities and mlock.
 
 2006-08-15  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (keyserver): Enable building of keyserver helpers.
 
 	* configure.ac: Merged with the current configure from 1.4.5.
 	Require libgpg-error 1.2 and libksba 0.9.16.
 
 2006-07-29  Marcus Brinkmann  <marcus@g10code.de>
 
 	* README: Spelling fixes.
 
 2006-07-27  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.22.
 
 	* configure.ac: Call AB_INIT.
 
 2006-07-03  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Test for ksba_dn_teststr.
 
 2006-06-30  Werner Koch  <wk@g10code.com>
 
 	* keyserver/: New.  Taken from 1.4.4
 	* Makefile.am (SUBDIRS): Include keyserver/.
 	* configure.ac: Include keyserver/.
 	(FAKE_CURL, GPGKEYS_CURL): New.
 
 2006-06-20  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.21.
 
 2006-06-08  Marcus Brinkmann  <marcus@g10code.de>
 
 	* configure.ac (PTH_LIBS): Add --all to pth-config invocation.
 
 2006-05-24  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: New option --disable-optimization taked from 1.4.3.
 
 2006-05-23  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (ZLIBS): New for zlib link commands. Add bzip2
 	support.
 
 2006-05-22  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (EXEEXT): New.
 
 2006-04-18  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (PK_UID_CACHE_SIZE): New.
 
 2006-04-07  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Use new method to include the SVN revison.  Now it
 	is the actual global revision number.
 
 2005-12-20  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.20.
 
 2005-11-28  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Append the revision to the version string.
 
 2005-11-13  Werner Koch  <wk@g10code.com>
 
 	* am/cmacros.am (-DGNUPG_SYSCONFDIR): Define it.
 
 2005-11-11  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (NEED_KSBA_VERSION: Require 0.9.13.
 
 2005-09-12  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.19.
 
 2005-08-01  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.18.
 
 	* configure.ac: Require libksba 0.9.12 to match new features in gpgsm.
 
 2005-06-20  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.17.
 
 2005-06-02  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (HAVE_PTH): Define as alias for USE_GNU_PTH.  It is
 	used by common/estream.c.
 
 2005-06-01  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (gl_INIT): Add gnulib stuff.
 	(fseeko, ftello, ttyname, isascii): Replaced the AC_REPLACE_FUNCS
 	by a simple check.
 	(putc_unlocked): Removed check.  Not used.
 	(strsep, mkdtemp, asprintf): Replaced checks by gnulib checks.
 	(xsize): Added will probably come handy soon.
 	(CFLAGS): Use -Wformat-security instead of
 	-Wformat-nonliteral. Add --Wno-format-y2k.
 	* gl/, gl/m4/: New.
 
 2005-05-15  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Remove option --disable-threads; require the use
 	of GNU Pth.
 
 2005-04-27  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Removed OpenSC detection and options.
 	* acinclude.m4: Ditto.
 
 2005-04-21  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.16.
 
 	* configure.ac: Do not build gpg by default.
 
 2005-04-20  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Test whether GPG_ERR_LOCKED is declared and
 	provide a replacement if not.
 
 2005-04-15  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Require libksba 0.9.11.
 
 2005-04-15  Marcus Brinkmann  <marcus@g10code.de>
 
 	* configure.ac: Check for /usr/bin/shred and define SHRED.
 
 	* configure.ac: Add --enable-symcryptrun, disabled by default.
 	Define automake variable BUILD_SYMCRYPTRUN.
 	Check for openpty -lutil, define LIBUTIL_LIBS.
 
 2005-03-03  Werner Koch  <wk@g10code.com>
 
 	* acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Accidently used
 	--ldflags instead of --cflags. Reported by Kazu Yamamoto.
 
 2005-02-03  Werner Koch  <wk@g10code.com>
 
 	* AUTHORS: Copied from 1.4 and edited to refelct the changes in
 	1.9.
 
 2005-01-17  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Make --without-included-regex work as expected.
 	Fixed FTP location info for some libraries.
 
 2005-01-13  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.15.
 
 	* acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Link a simple test
 	program to see whether the installation is sane.
 
 2005-01-07  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Require gpg-error 1.0.
 
 2005-01-04  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Remove hack not to build gpg2 for W32.
 	* autogen.sh <build-w32>: Pass option --disable-gpg instead.
 
 2004-12-22  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.14.
 
 2004-12-20  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Add PATHSEP_C and PATHSEP_S. For W32 let all
 	directories default to c:/gnupg.  Require libassuan 0.6.9.
 
 2004-12-18  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (AH_BOTTOM): Define EXEEXT_S.
 
 	* autogen.sh: Updated --build-w32 feature.
 
 2004-12-15  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (SUBDIRS) [W32]: Do not build in tests/.
 
 	* acinclude.m4: Add proper macro name quoting for use with
 	automake 1.9.
 
 	* configure.ac: Add replacement check for ttyname.
 	Removed support for a included zlib.
 
 2004-12-06  Werner Koch  <wk@g10code.com>
 
 	* configure.ac (have_w32_system): New.  Disable Pth checks for W32.
 	Link jnlib/w32-pth.h to pth.h.
 
 2004-12-03  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.13.
 
 2004-11-26  Werner Koch  <wk@g10code.com>
 
 	* configure.ac: Replace strsep.  Replaced use of "target" by
 	"host".
 
 2004-10-22  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.12.
 
 	* Makefile.am (AUTOMAKE_OPTIONS): Set option to create bzip2 tarball.
 
 2004-10-01  Werner Koch  <wk@g10code.com>
 
 	Released 1.9.11.
 
 2004-09-30  Werner Koch  <wk@g10code.com>
 
 	* README: Minor updates.
 
 2004-09-30  gettextize  <bug-gnu-gettext@gnu.org>
 
 	* configure.ac (AM_GNU_GETTEXT_VERSION): Bump to 0.14.1.
 
 2004-08-16  Werner Koch  <wk@g10code.de>
 
 	* configure.ac: Build Makefile for tests/pkits.  New option
 	--with-pkits-tests.
 
 2004-08-05  Werner Koch  <wk@g10code.de>
 
 	* configure.ac: Changed tests for libusb to also suuport the
 	stable version 0.1.x.
 
 2004-07-22  Werner Koch  <wk@g10code.de>
 
 	Released 1.9.10.
 
 	* configure.ac: Define AM conditional HAVE_OPENSC.
 
 2004-07-21  Werner Koch  <wk@g10code.de>
 
 	* configure.ac: Don't set DIE to no after it might has been set to
 	yes.
 
 2004-07-20  Werner Koch  <wk@g10code.de>
 
 	* Makefile.am (sm): Build kbx only if gpgsm is to be build.
 
 2004-07-20  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: New option --enable-agent-only.
 
 2004-06-08  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.9.
 
 2004-06-06  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Require libksba 0.9.7.
 
 2004-04-29  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.8.
 
 2004-04-20  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Remove the fopencookie test.  We don't need the
 	dummy function because we conditionally use fopencookie,
 	fpencookie or a replacement at place.
 
 2004-04-02  Thomas Schwinge  <schwinge@nic-nac-project.de>
 
 	* autogen.sh: Added ACLOCAL_FLAGS.
 
 2004-04-06  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.7.
 
 	* configure.ac: Require libgcrypt 1.1.94.
 	Introduce PACKAGE_GT and set it to gnupg2.
 
 2004-03-23  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Define SAFE_VERSION_DASH and SAFE_VERSION_DOT.
 
 2004-03-09  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (NEED_GPG_ERROR_VERSION): Set to 0.7.
 
 2004-03-06  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.6.
 
 	* configure.ac: Check the Libgcrypt API.
 
 2004-02-25  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: New option --disable-threads to inhibit
 	unintentional builds without Pth.
 
 2004-02-21  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.5.
 
 2004-02-20  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Fixed URLs in the notice messages.
 
 2004-02-18  Werner Koch  <wk@gnupg.org>
 
 	* acinclude.m4: Removed macros to detect gpg-error, libgcrypt,
 	libassuan and ksba as they are now distributed in m4/.
 
 2004-02-13  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Require libksba 0.9.4 and libgcrypt 1.1.92.
 
 2004-02-12  Werner Koch  <wk@gnupg.org>
 
 	* autogen.sh: Removed cruft from debugging.
 
 	* am/cmacros.am: New.
 
 2004-02-11  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Removed the need for g10defs.h.  Reworked the
 	--with-foo-pgm stuff.
 
 	* autogen.sh (check_version): Removed bashism and simplified.
 	* acinclude.m4 (AM_PATH_OPENSC): Kludge to avoid error output for
 	a bad opensc-config.
 
 2004-01-30  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.4.
 
 	* configure.ac: Require libksba 0.9.3 due to another bug fix there.
 
 2004-01-29  Werner Koch  <wk@gnupg.org>
 
 	* README: Updated.
 
 	* configure.ac: Require libksba 0.9.2 due to bug fixes.
 
 2004-01-24  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Now requires libassuan 0.6.3.
 
 2003-12-23  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.3.
 
 	* README-alpha: Removed.
 	* configure.ac, Makefile.am: Add the tests and tools directories.
 
 2003-12-19  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Now require libgcrypt 1.1.91 to help testing the
 	latest libgcrypt changes.  Requires libksab 0.9.1.
 
 2003-12-17  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Requires now libassuan 0.6.2.
 	(CFLAGS): Add --Wformat-noliteral in gcc mode.
 
 2003-12-16  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Check for funopen and fopencookie as part of the
 	jnlib checks.
 
 2003-12-09  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Add a min_automake_version.
 	* README.CVS: New.
 	* autogen.sh: Revamped except for the --build-w32 hack.
 	* Makefile.am: Add README.CVS
 
 2003-11-17  Werner Koch  <wk@gnupg.org>
 
 	Release 1.9.2.
 
 	* configure.ac: Requires now libassuan 0.6.1.
 
 2003-10-31  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (NEED_KSBA_VERSION): Set to 0.9.0 due the changed
 	time interface.
 
 2003-10-21  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (PRINTABLE_OS_NAME): Remove special case for The
 	Hurd; Robert Millan reported that the uname test is now
 	sufficient.
 
 2003-10-01  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (AH_BOTTOM): Define GNUPG_MAJOR_VERSION.
 
 2003-09-23  Werner Koch  <wk@gnupg.org>
 
 	Merged most of David Shaw's changes in 1.3 since 2003-06-03.
 
 	* configure.ac: Drop all TIGER/192 support.
 	(uint64_t): Check for UINT64_C to go along with uint64_t.
 	(getaddrinfo): Check for it.
 	(sigset_t): Check for sigset_t and struct sigaction.  This is for
 	Forte c89 on Solaris which seems to define only the function call
 	half of the two pairs by default.
 	(W32LIBS): Include wsock32 in W32LIBS.  This is different from
 	NETLIBS so we don't need to force other platforms to pull in the
 	netlibs when they aren't actually needed.
 
 2003-09-06  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.1.
 
 	* configure.ac: Require newer versions of some libraries.
 
 2003-09-02  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (HAVE_LIBUSB): Added a simple test for libusb.
 
 2003-08-19  Marcus Brinkmann  <marcus@g10code.de>
 
 	* configure.ac (AM_PATH_GPG_ERROR): Add missing comma in
 	invocation.
 
 2003-08-06  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Check for libgpg-error.  Print infos about missing
 	libraries more nicely.
 	* acinclude.m4 (AM_PATH_GPG_ERROR): Added.
 
 2003-08-05  Werner Koch  <wk@gnupg.org>
 
 	Released 1.9.0.
 
 	* configure.ac (GNUPG_DEFAULT_HONMEDIR): Changed back to ~/.gnupg.
 
 2003-07-31  Werner Koch  <wk@gnupg.org>
 
 	* Makefile.am (DISTCLEANFILES): Add g10defs.h
 
 2003-06-18  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (GNUPG_DEFAULT_HOMEDIR): Changed temporary to
 	.gnupg2 to avoid accidential use with production keys.
 
 2003-06-11  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Merged all stuff from current 1.3 version in.
 	* acinclude.m4: Merged required macros from current 1.2 version in.
 
 2003-06-04  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac, Makefile.am: Enable building of gpg.
 
 2003-04-29  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Build a limited version of scdaemon if libopensc
 	is not available.
 
 	* configure.ac (ALL_LINUGAS): Removed.
 
 	* Makefile.am (ACLOCAL_AMFLAGS): New.
 	* configure.ac (AM_GNU_GETTEXT_VERSION): New.  Set to 0.11.5.
 
 2003-04-29  gettextize  <bug-gnu-gettext@gnu.org>
 
 	* Makefile.am (SUBDIRS): Add m4.
 	(ACLOCAL_AMFLAGS): New variable.
 	(EXTRA_DIST): Add scripts/config.rpath.
 	* configure.ac (AC_CONFIG_FILES): Add m4/Makefile.
 
 2003-04-29  Werner Koch  <wk@gnupg.org>
 
 	* assuan/ : Removed.  We now use libassuan.
 	* Makefile.am (SUBDIRS): Removed assuan
 
 	* configure.ac: Check for libassuan.
 
 2003-01-09  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (GNUPG_PROTECT_TOOL): New option --with-protect-tool.
 	(NEED_KSBA_VERSION): Does now require 0.4.6.
 
 	* README: Noted where to find gpg-protect-tool.
 
 2002-10-31  Neal H. Walfield  <neal@g10code.de>
 
 	* configure.ac: Check for flockfile and funlockfile.  Check for
 	isascii and putc_unlocked replacing them if not found.
 
 	* configure.ac (PTH_LIBS): If pth is found, add the output of
 	`$PTH_CONFIG --ldflags`, not just `$PTH_CONFIG --libs`.
 
 2002-10-19  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Bumped version number to 1.9.0-cvs.
 
         NewPG (Aegypten project) to GnuPG merge.
 
 2002-09-20  Werner Koch  <wk@gnupg.org>
 
 	Released 0.9.2.
 
 2002-09-05  Neal H. Walfield  <neal@g10code.de>
 
 	* configure.ac: Check for makeinfo.
 
 2002-09-03  Neal H. Walfield  <neal@g10code.de>
 
 	* autogen.sh (have_version): New function.  Generalize and
 	simplify logic for finding and determining the versions of GNU
 	programs.  Use it.
 
 2002-08-23  Werner Koch  <wk@gnupg.org>
 
 	Released 0.9.1.
 
 	* acinclude.m4 (AM_PATH_LIBGCRYPT): Updated from Libgcrypt.
 	(AM_PATH_OPENSC): Strip non-digits from the micro version.
 
 2002-08-21  Werner Koch  <wk@gnupg.org>
 
 	Released 0.9.0.
 
 	* configure.ac: Changed the default homedir to .gnupg.
 	* README-alpha: Removed.
 
 2002-08-19  Werner Koch  <wk@gnupg.org>
 
 	* acinclude.m4: Removed -lpcsclite from KSBA_LIBS; copy+paste bug.
 
 2002-08-13  Werner Koch  <wk@gnupg.org>
 
 	* acinclude.m4 (AM_PATH_OPENSC, AM_PATH_KSBA): New.
 	* configure.ac: Use them.
 
 2002-08-10  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.10.
 
 	* configure.ac (NEED_LIBKSBA_VERSION): Require 0.4.4. Add support
 	for gettext.
 
 2002-07-22  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Check for ftello and provide a replacement.
 
 2002-07-01  Werner Koch  <wk@gnupg.org>
 
         Released 0.3.9.
 
 	* README: Short note on how to export in pkcs-12 format.
 
 2002-06-29  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Define --with options to set the default location
 	of the agent, scdaemon, pinentry and dirmngr.
 
 2002-06-27  Werner Koch  <wk@gnupg.org>
 
 	* README: Short blurb on how to import a PKCS-12 file.
 
 	* configure.ac (AH_BOTTOM): New to define some constants.
 
 2002-06-25  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.8.
 
 	* configure.ac (NEED_LIBGCRYPT_VERSION): Set to 1.1.8.
 
 2002-06-12  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (NEED_LIBKSBA_VERSION): We need 0.4.3 now.
 
 2002-06-04  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.7.
 
 2002-05-21  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: We now require libgcrypt 1.1.7 and libksba 0.4.2.
 
 2002-05-14  Werner Koch  <wk@gnupg.org>
 
 	* doc/: New
 	* configure.ac, Makefile.am:  Added doc/.
 
 2002-05-03  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.6.
 
 2002-04-25  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Check for setlocale.
 
 2002-04-24  Marcus Brinkmann  <marcus@g10code.de>
 
 	* configure.ac: Check for locale.h.
 
 2002-04-15  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.5.
 
 	* NEWS: Started to describe release notes.
 
 	* configure.ac (NEED_LIBKSBA_VERSION, NEED_LIBGCRYPT_VERSION): Defined
 
 2002-04-01  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.4.
 
 2002-03-18  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.3.
 
 2002-03-08  Werner Koch  <wk@gnupg.org>
 
 	* README: Add some explanation on how to specify a user ID.
 
 2002-03-06  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.2.
 
 2002-03-04  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.1.
 
 	* README: Explained some options and files.
 
 2002-02-14  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Fixed status messages related to presence of Pth.
 
 2002-02-13  Werner Koch  <wk@gnupg.org>
 
 	* acinclude.m4 (GNUPG_SYS_SO_PEERCRED): New.
 	* configure.ac: use it.
 
 2002-02-12  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Check for PTH.  Provide replacement fucntions for
 	apsrintf and fopencookie.
 
 	* acinclude.m4 (GNUPG_PTH_VERSION_CHECK): New.
 
 2002-02-07  Werner Koch  <wk@gnupg.org>
 
 	Released 0.3.0.
 
 	* configure.ac: Require libgcrypt 1.1.6.
 
 2002-02-01  Marcus Brinkmann  <marcus@g10code.de>
 
 	* configure.ac (KSBA_CONFIG): Remove superfluous x in front of
 	variable.
 
 2002-01-26  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac: Add options to disable the build of some programs
 	and print a configure status at the end.
 	* acinclude.m4 (GNUPG_BUILD_PROGRAM): New.
 
 	* scd/ : New.  Added to Makefile and configure.
 	* configure.ac: Check for libopensc
 	* Makefile.am: Build scd only when libopensc is available
 
 2002-01-23  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (mkdtemp): See whether we have to provide a
 	replacement.
 
 2001-12-18  Werner Koch  <wk@gnupg.org>
 
 	Released 0.0.0.
 
 2001-12-17  Werner Koch  <wk@gnupg.org>
 
 	* acinclude.m4: Add AM_PATH_LIBGCRYPT macro.
 	* configure.ac: and use it here. Figure out the location of libksba
 
 2001-12-15  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (missing_dir): Bail out if asprintf and fopencookie
 	are not available.
 
 2001-12-04  Werner Koch  <wk@gnupg.org>
 
 	* configure.ac (HAVE_JNLIB_LOGGING): always define it.
 
 
  Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007.
 	   2010 Free Software Foundation, Inc.
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
  modifications, as long as this notice is preserved.
 
  This file is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 
diff --git a/NEWS b/NEWS
index afd9053c2..2cdf854bf 100644
--- a/NEWS
+++ b/NEWS
@@ -1,797 +1,799 @@
 Noteworthy changes in version 2.1.0beta2 (unreleased)
 -----------------------------------------------------
 
  * TMPDIR is now also honored when creating a socket using
    --no-standard-socket and with symcryptrun's temp files.
 
  * Fixed a bug where SCdaemon sends a signal to Gpg-agent running in
    non-daemon mode.
 
  * Print "AES128" instead of "AES".  This change introduces a little
    incompatibility for tools using "gpg --list-config".  We hope that
    these tools are written robust enough to accept this new algorithm
    name as well.
 
+ * Fixed CRL loading under W32 (bug#1010).
+
 
 Noteworthy changes in version 2.1.0beta1 (2010-10-26)
 -----------------------------------------------------
 
  * Encrypted OpenPGP messages with trailing data (e.g. other OpenPGP
    packets) are now correctly parsed.
 
  * The GPGSM --audit-log feature is now more complete.
 
  * The G13 tool for disk encryption key management has been added.
 
  * The default for --include-cert is now to include all certificates
    in the chain except for the root certificate.
 
  * Numerical values may now be used as an alternative to the
    debug-level keywords.
 
  * Support DNS lookups for SRV, PKA and CERT on W32.
 
  * New GPGSM option --ignore-cert-extension.
 
  * New and changed passphrases are now created with an iteration count
    requiring about 100ms of CPU work.
 
  * Support for Windows CE.
 
  * If the agent's --use-standard-socket option is active, all tools
    try to start and daemonize the agent on the fly.  In the past this
    was only supported on W32; on non-W32 systems the new configure
    option --disable-standard-socket may now be used to disable this
    new default.
 
  * Dirmngr is now a part of this package.  Dirmngr is now also
    expected to run as a system service and the configuration
    directories are changed to the GnuPG name space.
 
  * Given sufficient permissions Dirmngr is started automagically.
 
  * Fixed output of "gpgconf --check-options".
 
  * GPG does not anymore use secring.gpg but delegates all secret key
    operations to gpg-agent.  The import command moves secret keys to
    the agent.
 
  * The OpenPGP import command is now able to merge secret keys.
 
  * Removed GPG options:
     --export-options: export-secret-subkey-passwd
     --simple-sk-checksum
 
  * New GPG options:
     --try-secret-key
 
 
 Noteworthy changes in version 2.0.13 (2009-09-04)
 -------------------------------------------------
 
  * GPG now generates 2048 bit RSA keys by default.  The default hash
    algorithm preferences has changed to prefer SHA-256 over SHA-1.
    2048 bit DSA keys are now generated to use a 256 bit hash algorithm
 
  * The envvars XMODIFIERS, GTK_IM_MODULE and QT_IM_MODULE are now
    passed to the Pinentry to make SCIM work.
 
  * The GPGSM command --gen-key features a --batch mode and implements
    all features of gpgsm-gencert.sh in standard mode.
 
  * New option --re-import for GPGSM's IMPORT server command.
 
  * Enhanced writing of existing keys to OpenPGP v2 cards.
 
  * Add hack to the internal CCID driver to allow the use of some
    Omnikey based card readers with 2048 bit keys.
 
  * GPG now repeatly asks the user to insert the requested OpenPGP
    card.  This can be disabled with --limit-card-insert-tries=1.
 
  * Minor bug fixes.
 
 
 Noteworthy changes in version 2.0.12 (2009-06-17)
 -------------------------------------------------
 
  * GPGSM now always lists ephemeral certificates if specified by
    fingerprint or keygrip.
 
  * New command "KEYINFO" for GPG_AGENT.  GPGSM now also returns
    information about smartcards.
 
  * Made sure not to leak file descriptors if running gpg-agent with a
    command.  Restore the signal mask to solve a problem in Mono.
 
  * Changed order of the confirmation questions for root certificates
    and store negative answers in trustlist.txt.
 
  * Better synchronization of concurrent smartcard sessions.
 
  * Support 2048 bit OpenPGP cards.
 
  * Support Telesec Netkey 3 cards.
 
  * The gpg-protect-tool now uses gpg-agent via libassuan.  Under
    Windows the Pinentry will now be put into the foreground.
 
  * Changed code to avoid a possible Mac OS X system freeze.
 
 
 Noteworthy changes in version 2.0.11 (2009-03-03)
 -------------------------------------------------
 
  * Fixed a problem in SCDAEMON which caused unexpected card resets.
 
  * SCDAEMON is now aware of the Geldkarte.
 
  * The SCDAEMON option --allow-admin is now used by default.
 
  * GPGCONF now restarts SCdaemon if necessary.
 
  * The default cipher algorithm in GPGSM is now again 3DES.  This is
    due to interoperability problems with Outlook 2003 which still
    can't cope with AES.
 
 
 Noteworthy changes in version 2.0.10 (2009-01-12)
 -------------------------------------------------
 
  * [gpg] New keyserver helper gpg2keys_kdns as generic DNS CERT
    lookup.  Run with --help for a short description.  Requires the
    ADNS library.
 
  * [gpg] New mechanisms "local" and "nodefault" for --auto-key-locate.
    Fixed a few problems with this option.
 
  * [gpg] New command --locate-keys.
 
  * [gpg] New options --with-sig-list and --with-sig-check.
 
  * [gpg] The option "-sat" is no longer an alias for --clearsign.
 
  * [gpg] The option --fixed-list-mode is now implicitly used and obsolete.
 
  * [gpg] New control statement %ask-passphrase for the unattended key
    generation.
 
  * [gpg] The algorithm to compute the SIG_ID status has been changed.
 
  * [gpgsm] Now uses AES by default.
 
  * [gpgsm] Made --output option work with --export-secret-key-p12.
 
  * [gpg-agent] Terminate process if the own listening socket is not
    anymore served by ourself.
 
  * [scdaemon] Made it more robust on W32.
 
  * [gpg-connect-agent] Accept commands given as command line arguments.
 
  * [w32] Initialized the socket subsystem for all keyserver helpers.
 
  * [w32] The sysconf directory has been moved from a subdirectory of
    the installation directory to %CSIDL_COMMON_APPDATA%/GNU/etc/gnupg.
 
  * [w32] The gnupg2.nls directory is not anymore used.  The standard
    locale directory is now used.  
 
  * [w32] Fixed a race condition between gpg and gpgsm in the use of
    temporary file names.
 
  * The gpg-preset-passphrase mechanism works again.  An arbitrary
    string may now be used for a custom cache ID.
 
  * Admin PINs are cached again (bug in 2.0.9).
 
  * Support for version 2 OpenPGP cards.
 
  * Libgcrypt 1.4 is now required.
 
 
 Noteworthy changes in version 2.0.9 (2008-03-26)
 ------------------------------------------------
 
  * Gpgsm always tries to locate missing certificates from a running
    Dirmngr's cache.
 
  * Tweaks for Windows.
 
  * The Admin PIN for OpenPGP cards may now be entered with the pinpad.
 
  * Improved certificate chain construction.
 
  * Extended the PKITS framework.
 
  * Fixed a bug in the ambigious name detection.
 
  * Fixed possible memory corruption while importing OpenPGP keys (bug
    introduced with 2.0.8). [CVE-2008-1530]
 
  * Minor bug fixes.
 
 
 Noteworthy changes in version 2.0.8 (2007-12-20)
 ------------------------------------------------
 
  * Enhanced gpg-connect-agent with a small scripting language.
 
  * New option --list-config for gpgconf.
 
  * Fixed a crash in gpgconf.
 
  * Gpg-agent now supports the passphrase quality bar of the latest
    Pinentry.
 
  * The envvars XAUTHORITY and PINENTRY_USER_DATA are now passed to the
    Pinentry.
 
  * Fixed the auto creation of the key stub for smartcards.  
 
  * Fixed a rare bug in decryption using the OpenPGP card.
 
  * Creating DSA2 keys is now possible.
 
  * New option --extra-digest-algo for gpgsm to allow verification of
    broken signatures.
 
  * Allow encryption with legacy Elgamal sign+encrypt keys with option
    --rfc2440.
 
  * Windows is now a supported platform.
 
  * Made sure that under Windows the file permissions of the socket are
    taken into account.  This required a change of our socket emulation
    code and changed the IPC protocol under Windows.
 
 
 Noteworthy changes in version 2.0.7 (2007-09-10)
 ------------------------------------------------
 
  * Fixed encryption problem if duplicate certificates are in the
    keybox.
 
  * Made it work on Windows Vista.  Note that the entire Windows port
    is still considered Beta.
 
  * Add new options min-passphrase-nonalpha, check-passphrase-pattern,
    enforce-passphrase-constraints and max-passphrase-days to
    gpg-agent.
 
  * Add command --check-components to gpgconf.  Gpgconf now uses the
    installed versions of the programs and does not anymore search via
    PATH for them.
 
 
 Noteworthy changes in version 2.0.6 (2007-08-16)
 ------------------------------------------------
 
  * GPGSM does now grok --default-key.
 
  * GPGCONF is now aware of --default-key and --encrypt-to. 
 
  * GPGSM does again correctly print the serial number as well the the
    various keyids.  This was broken since 2.0.4.
 
  * New option --validation-model and support for the chain-model.
 
  * Improved Windows support.
 
  
 Noteworthy changes in version 2.0.5 (2007-07-05)
 ------------------------------------------------
 
  * Switched license to GPLv3.
 
  * Basic support for Windows.  Run "./autogen.sh --build-w32" to build
    it.  As usual the mingw cross compiling toolchain is required.
 
  * Fixed bug when using the --p12-charset without --armor.
 
  * The command --gen-key may now be used instead of the
    gpgsm-gencert.sh script.
 
  * Changed key generation to reveal less information about the
    machine.  Bug fixes for gpg2's card key generation.
 
 
 Noteworthy changes in version 2.0.4 (2007-05-09)
 ------------------------------------------------
 
  * The server mode key listing commands are now also working for
    systems without the funopen/fopencookie API.
 
  * PKCS#12 import now tries several encodings in case the passphrase
    was not utf-8 encoded.  New option --p12-charset for gpgsm.
 
  * Improved the libgcrypt logging support in all modules.
 
 
 Noteworthy changes in version 2.0.3 (2007-03-08)
 ------------------------------------------------
 
  * By default, do not allow processing multiple plaintexts in a single
    stream.  Many programs that called GnuPG were assuming that GnuPG
    did not permit this, and were thus not using the plaintext boundary
    status tags that GnuPG provides.  This change makes GnuPG reject
    such messages by default which makes those programs safe again.
    --allow-multiple-messages returns to the old behavior. [CVE-2007-1263].
 
  * New --verify-option show-primary-uid-only. 
 
  * gpgconf may now reads a global configuration file to select which
    options are changeable by a frontend.  The new applygnupgdefaults
    tool may be used by an admin to set default options for all users.
 
  * The PIN pad of the Cherry XX44 keyboard is now supported.  The
    DINSIG and the NKS applications are now also aware of PIN pads.
 
 
 Noteworthy changes in version 2.0.2 (2007-01-31)
 ------------------------------------------------
 
  * Fixed a serious and exploitable bug in processing encrypted
    packages. [CVE-2006-6235].
 
  * Added --passphrase-repeat to set the number of times GPG will
    prompt for a new passphrase to be repeated.  This is useful to help
    memorize a new passphrase.  The default is 1 repetition.
 
  * Using a PIN pad does now also work for the signing key.
 
  * A warning is displayed by gpg-agent if a new passphrase is too
    short.  New option --min-passphrase-len defaults to 8.
 
  * The status code BEGIN_SIGNING now shows the used hash algorithms.
 
 
 Noteworthy changes in version 2.0.1 (2006-11-28)
 ------------------------------------------------
 
  * Experimental support for the PIN pads of the SPR 532 and the Kaan
    Advanced card readers.  Add "disable-keypad" scdaemon.conf if you
    don't want it.  Does currently only work for the OpenPGP card and
    its authentication and decrypt keys.
 
  * Fixed build problems on some some platforms and crashes on amd64.
 
  * Fixed a buffer overflow in gpg2. [bug#728,CVE-2006-6169]
 
 
 Noteworthy changes in version 2.0.0 (2006-11-11)
 ------------------------------------------------
 
  * First stable version of a GnuPG integrating OpenPGP and S/MIME.
 
 
 Noteworthy changes in version 1.9.95 (2006-11-06)
 -------------------------------------------------
 
  * Minor bug fixes.
 
 
 Noteworthy changes in version 1.9.94 (2006-10-24)
 -------------------------------------------------
 
  * Keys for gpgsm may now be specified using a keygrip.  A keygrip is
    indicated by a prefixing it with an ampersand.
 
  * gpgconf now supports switching the CMS cipher algo (e.g. to AES).
 
  * New command --gpgconf-test for all major tools. This may be used to
    check whether the configuration file is sane.
 
 
 Noteworthy changes in version 1.9.93 (2006-10-18)
 -------------------------------------------------
 
  * In --with-validation mode gpgsm will now also ask whether a root
    certificate should be trusted.
 
  * Link to Pth only if really necessary.
 
  * Fixed a pubring corruption bug in gpg2 occurring when importing
    signatures or keys with insane lengths.
 
  * Fixed v3 keyID calculation bug in gpg2.
 
  * More tweaks for certificates without extensions.
 
 
 Noteworthy changes in version 1.9.92 (2006-10-11)
 -------------------------------------------------
 
  * Bug fixes.
 
 
 Noteworthy changes in version 1.9.91 (2006-10-04)
 -------------------------------------------------
 
  * New "relax" flag for trustlist.txt to allow root CA certificates
    without BasicContraints.
 
  * [gpg2] Removed the -k PGP 2 compatibility hack.  -k is now an
    alias for --list-keys.
 
  * [gpg2] Print a warning if "-sat" is used instead of "--clearsign".
 
 
 Noteworthy changes in version 1.9.90 (2006-09-25)
 -------------------------------------------------
 
  * Made readline work for gpg.
 
  * Cleanups und minor bug fixes.
 
  * Included translations from gnupg 1.4.5.
 
 
 Noteworthy changes in version 1.9.23 (2006-09-18)
 -------------------------------------------------
 
  * Regular man pages for most tools are now build directly from the
    Texinfo source.
 
  * The gpg code from 1.4.5 has been fully merged into this release.
    The configure option --enable-gpg is still required to build this
    gpg part.  For production use of OpenPGP the gpg version 1.4.5 is
    still recommended.  Note, that gpg will be installed under the name
    gpg2 to allow coexisting with an 1.4.x gpg.
 
  * API change in gpg-agent's pkdecrypt command.  Thus an older gpgsm
    may not be used with the current gpg-agent.
 
  * The scdaemon will now call a script on reader status changes.
 
  * gpgsm now allows file descriptor passing for "INPUT", "OUTPUT" and
    "MESSAGE".
 
  * The gpgsm server may now output a key listing to the output file
    handle. This needs to be enabled using "OPTION list-to-output=1".
 
  * The --output option of gpgsm has now an effect on list-keys.
 
  * New gpgsm commands --dump-chain and list-chain.
 
  * gpg-connect-agent has new options to utilize descriptor passing.
 
  * A global trustlist may now be used.  See doc/examples/trustlist.txt.
 
  * When creating a new pubring.kbx keybox common certificates are
    imported.
 
 
 Noteworthy changes in version 1.9.22 (2006-07-27)
 -------------------------------------------------
 
  * Enhanced pkcs#12 support to allow import from simple keyBags.
 
  * Exporting to pkcs#12 now create bag attributes so that Mozilla is
    able to import the files.
 
  * Fixed uploading of certain keys to the smart card.
 
 
 Noteworthy changes in version 1.9.21 (2006-06-20)
 -------------------------------------------------
 
  * New command APDU for scdaemon to allow using it for general card
    access.  Might be used through gpg-connect-agent by using the SCD
    prefix command.
 
  * Support for the CardMan 4040 PCMCIA reader (Linux 2.6.15 required).
 
  * Scdaemon does not anymore reset cards at the end of a connection. 
 
  * Kludge to allow use of Bundesnetzagentur issued X.509 certificates.
 
  * Added --hash=xxx option to scdaemon's PKSIGN command.
 
  * Pkcs#12 files are now created with a MAC.  This is for better
    interoperability.
 
  * Collected bug fixes and minor other changes.
 
 
 Noteworthy changes in version 1.9.20 (2005-12-20)
 -------------------------------------------------
 
  * Importing pkcs#12 files created be recent versions of Mozilla works
    again.
 
  * Basic support for qualified signatures.
 
  * New debug tool gpgparsemail. 
 
 
 Noteworthy changes in version 1.9.19 (2005-09-12)
 -------------------------------------------------
 
  * The Belgian eID card is now supported for signatures and ssh.
    Other pkcs#15 cards should work as well.
 
  * Fixed bug in --export-secret-key-p12 so that certificates are again
    included.
 
 
 Noteworthy changes in version 1.9.18 (2005-08-01)
 -------------------------------------------------
 
  * [gpgsm] Now allows for more than one email address as well as URIs
    and dnsNames in certificate request generation.  A keygrip may be
    given to create a request from an existing key.
 
  * A couple of minor bug fixes.
 
 
 Noteworthy changes in version 1.9.17 (2005-06-20)
 -------------------------------------------------
 
  * gpg-connect-agent has now features to handle Assuan INQUIRE
    commands.
 
  * Internal changes for OpenPGP cards. New Assuan command WRITEKEY.
 
  * GNU Pth is now a hard requirement.
 
  * [scdaemon] Support for OpenSC has been removed.  Instead a new and
    straightforward pkcs#15 modules has been written.  As of now it
    does allows only signing using TCOS cards but we are going to
    enhance it to match all the old capabilities.
 
  * [gpg-agent] New option --write-env-file and Assuan command
    UPDATESTARTUPTTY.
 
  * [gpg-agent] New option --default-cache-ttl-ssh to set the TTL for
    SSH passphrase caching independent from the other passphrases.
 
 
 Noteworthy changes in version 1.9.16 (2005-04-21)
 -------------------------------------------------
 
  * gpg-agent does now support the ssh-agent protocol and thus allows
    to use the pinentry as well as the OpenPGP smartcard with ssh.
 
  * New tool gpg-connect-agent as a general client for the gpg-agent.
 
  * New tool symcryptrun as a wrapper for certain encryption tools.
 
  * The gpg tool is not anymore build by default because those gpg
    versions available in the gnupg 1.4 series are far more matured.
 
 
 Noteworthy changes in version 1.9.15 (2005-01-13)
 -------------------------------------------------
 
  * Fixed passphrase caching bug.
 
  * Better support for CCID readers; the reader from Cherry RS 6700 USB
    does now work.
 
 
 Noteworthy changes in version 1.9.14 (2004-12-22)
 -------------------------------------------------
 
  * [gpg-agent] New option --use-standard-socket to allow the use of a
    fixed socket.  gpgsm falls back to this socket if GPG_AGENT_INFO
    has not been set.
 
  * Ported to MS Windows with some functional limitations.
 
  * New tool gpg-preset-passphrase.
 
 
 Noteworthy changes in version 1.9.13 (2004-12-03)
 -------------------------------------------------
 
  * [gpgsm] New option --prefer-system-dirmngr.
 
  * Minor cleanups and debugging aids.
 
 
 Noteworthy changes in version 1.9.12 (2004-10-22)
 -------------------------------------------------
 
  * [scdaemon] Partly rewrote the PC/SC code.
 
  * Removed the sc-investigate tool.  It is now in a separate package
    available at ftp://ftp.g10code.com/g10code/gscutils/ .
 
  * [gpg-agent] Fixed logging problem.
 
 
 Noteworthy changes in version 1.9.11 (2004-10-01)
 -------------------------------------------------
 
  * When using --import along with --with-validation, the imported
    certificates are validated and only imported if they are fully
    valid.
 
  * [gpg-agent] New option --max-cache-ttl.
 
  * [gpg-agent] When used without --daemon or --server, gpg-agent now
    check whether a agent is already running and usable.
 
  * Fixed some i18n problems.
 
 
 Noteworthy changes in version 1.9.10 (2004-07-22)
 -------------------------------------------------
 
  * Fixed a serious bug in the checking of trusted root certificates.
 
  * New configure option --enable-agent-pnly allows to build and
    install just the agent.
 
  * Fixed a problem with the log file handling.
 
 
 Noteworthy changes in version 1.9.9 (2004-06-08)
 ------------------------------------------------
 
  * [gpg-agent] The new option --allow-mark-trusted is now required to
    allow gpg-agent to add a key to the trustlist.txt after user
    confirmation.
 
  * Creating PKCS#10 requests does now honor the key usage.
 
 
 Noteworthy changes in version 1.9.8 (2004-04-29)
 ------------------------------------------------
 
  * [scdaemon] Overhauled the internal CCID driver.
 
  * [scdaemon] Status files named ~/.gnupg/reader_<n>.status are now
    written when using the internal CCID driver.
 
  * [gpgsm] New commands --dump-{,secret,external}-keys to show a very
    detailed view of the certificates.
 
  * The keybox gets now compressed after 3 hours and ephemeral
    stored certificates are deleted after about a day.
 
  * [gpg] Usability fixes for --card-edit.  Note, that this has already
    been ported back to gnupg-1.3
 
 
 Noteworthy changes in version 1.9.7 (2004-04-06)
 ------------------------------------------------
 
  * Instrumented the modules for gpgconf.
 
  * Added support for DINSIG card applications.
 
  * Include the smimeCapabilities attribute with signed messages.
 
  * Now uses the gettext domain "gnupg2" to avoid conflicts with gnupg
    versions < 1.9.
 
 
 Noteworthy changes in version 1.9.6 (2004-03-06)
 ------------------------------------------------
 
  * Code cleanups and bug fixes.
 
 
 Noteworthy changes in version 1.9.5 (2004-02-21)
 ------------------------------------------------
 
  * gpg-protect-tool gets now installed into libexec as it ought to be.
    Cleaned up the build system to better comply with the coding
    standards.
 
  * [gpgsm] The --import command is now able to autodetect pkcs#12
    files and import secret and private keys from this file format.
    A new command --export-secret-key-p12 is provided to allow
    exporting of secret keys in PKCS\#12 format.
 
  * [gpgsm] The pinentry will now present a description of the key for
    whom the passphrase is requested.
 
  * [gpgsm] New option --with-validation to check the validity of key
    while listing it.
 
  * New option --debug-level={none,basic,advanced,expert,guru} to map
    the debug flags to sensitive levels on a per program base.
 
 
 Noteworthy changes in version 1.9.4 (2004-01-30)
 ------------------------------------------------
 
  * Added support for the Telesec NKS 2.0 card application.
 
  * Added simple tool addgnupghome to create .gnupg directories from
    /etc/skel/.gnupg.
 
  * Various minor bug fixes and cleanups; mainly gpgsm and gpg-agent
    related.
 
 
 Noteworthy changes in version 1.9.3 (2003-12-23)
 ------------------------------------------------
 
  * New gpgsm options --{enable,disable}-ocsp to validate keys using
    OCSP. This option requires a not yet released DirMngr version.
    Default is disabled.
 
  * The --log-file option may now be used to print logs to a socket.
    Prefix the socket name with "socket://" to enable this.  This does
    not work on all systems and falls back to stderr if there is a
    problem with the socket.
 
  * The options --encrypt-to and --no-encrypt-to now work the same in
    gpgsm as in gpg.  Note, they are also used in server mode.
 
  * Duplicated recipients are now silently removed in gpgsm.
 
 
 Noteworthy changes in version 1.9.2 (2003-11-17)
 ------------------------------------------------
 
  * On card key generation is no longer done using the --gen-key
    command but from the menu provided by the new --card-edit command.
 
  * PINs are now properly cached and there are only 2 PINs visible.
    The 3rd PIN (CHV2) is internally syncronized with the regular PIN.
 
  * All kind of other internal stuff.
 
 
 Noteworthy changes in version 1.9.1 (2003-09-06)
 ------------------------------------------------
 
  * Support for OpenSC is back. scdaemon supports a --disable-opensc to
    disable OpenSC use at runtime, so that PC/SC or ct-API can still be
    used directly.
 
  * Rudimentary support for the SCR335 smartcard reader using an
    internal driver.  Requires current libusb from CVS.
 
  * Bug fixes.
 
 
 Noteworthy changes in version 1.9.0 (2003-08-05)
 ------------------------------------------------
 
       ====== PLEASE SEE README-alpha =======
 
  * gpg has been renamed to gpg2 and gpgv to gpgv2.  This is a
    temporary change to allow co-existing with stable gpg versions.
 
  * ~/.gnupg/gpg.conf-1.9.0 is fist tried as config file before the
    usual gpg.conf.
 
  * Removed the -k, -kv and -kvv commands.  -k is now an alias to
    --list-keys.  New command -K as alias for --list-secret-keys.
 
  * Removed --run-as-shm-coprocess feature.
 
  * gpg does now also use libgcrypt, libgpg-error is required.
 
  * New gpgsm commands --call-dirmngr and --call-protect-tool.
 
  * Changing a passphrase is now possible using "gpgsm --passwd"
 
  * The content-type attribute is now recognized and created.
 
  * The agent does now reread certain options on receiving a HUP.
 
  * The pinentry is now forked for each request so that clients with
    different environments are supported.  When running in daemon mode
    and --keep-display is not used the DISPLAY variable is ignored.
 
  * Merged stuff from the newpg branch and started this new
    development branch.
 
 
  Copyright 2002, 2003, 2004, 2005, 2006, 2007,
            2008, 2009  Free Software Foundation, Inc.
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
  modifications, as long as this notice is preserved.
 
  This file is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/configure.ac b/configure.ac
index 1fa73e05a..b6ed4b34c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,1685 +1,1710 @@
 # configure.ac - for GnuPG 2.1
 # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 #               2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 # 
 # This file is part of GnuPG.
 # 
 # GnuPG is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 3 of the License, or
 # (at your option) any later version.
 # 
 # GnuPG is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 # Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.61)
 min_automake_version="1.10"
 
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
 m4_define([my_version], [2.1.0])
 m4_define([my_issvn], [yes])
 
 m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \
           | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)]))
 m4_define([git_revision], m4_esyscmd([git branch -v 2>/dev/null \
           | awk '/^\* / {printf "%s",$3}']))
 AC_INIT([gnupg], 
         [my_version[]m4_if(my_issvn,[yes],
         [m4_if(git_revision,[],[-svn[]svn_revision],[-git[]git_revision])])],
         [http://bugs.gnupg.org])
 # Set development_version to yes if the minor number is odd or you
 # feel that the default check for a development version is not
 # sufficient.
 development_version=no
 
 NEED_GPG_ERROR_VERSION=1.8
 
 NEED_LIBGCRYPT_API=1
 NEED_LIBGCRYPT_VERSION=1.4.0
 
 NEED_LIBASSUAN_API=2
 NEED_LIBASSUAN_VERSION=2.0.0
 
 NEED_KSBA_API=1
 NEED_KSBA_VERSION=1.1.0
 
 
 PACKAGE=$PACKAGE_NAME
 PACKAGE_GT=${PACKAGE_NAME}2
 VERSION=$PACKAGE_VERSION
 
 AC_CONFIG_AUX_DIR(scripts)
 AC_CONFIG_SRCDIR(sm/gpgsm.c)
 AM_CONFIG_HEADER(config.h)
 AM_INIT_AUTOMAKE($PACKAGE, $VERSION)
 AC_CANONICAL_HOST
 AB_INIT
 
 AC_GNU_SOURCE
 
 # Some status variables.
 have_gpg_error=no
 have_libgcrypt=no 
 have_libassuan=no
 have_ksba=no
 have_pth=no
 have_libusb=no
 have_adns=no
 
 use_zip=yes
 use_bzip2=yes
 use_exec=yes
 disable_keyserver_path=no
 use_ccid_driver=yes
 use_standard_socket=yes
 dirmngr_auto_start=no
 
 try_ks_ldap=no
 
 GNUPG_BUILD_PROGRAM(gpg, yes)
 GNUPG_BUILD_PROGRAM(gpgsm, yes)
 GNUPG_BUILD_PROGRAM(agent, yes)
 GNUPG_BUILD_PROGRAM(scdaemon, yes)
 GNUPG_BUILD_PROGRAM(g13, yes)
 GNUPG_BUILD_PROGRAM(dirmngr, yes)
 GNUPG_BUILD_PROGRAM(tools, yes)
 GNUPG_BUILD_PROGRAM(doc, yes)
 GNUPG_BUILD_PROGRAM(symcryptrun, no)
 GNUPG_BUILD_PROGRAM(gpgtar, no)
 
 AC_SUBST(PACKAGE)
 AC_SUBST(PACKAGE_GT)
 AC_SUBST(VERSION)
 AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
 AC_DEFINE_UNQUOTED(PACKAGE_GT, "$PACKAGE_GT",
                                 [Name of this package for gettext])
 AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
 AC_DEFINE_UNQUOTED(PACKAGE_BUGREPORT, "$PACKAGE_BUGREPORT",
                                         [Bug report address])
 AC_DEFINE_UNQUOTED(NEED_LIBGCRYPT_VERSION, "$NEED_LIBGCRYPT_VERSION",
                                        [Required version of Libgcrypt])
 AC_DEFINE_UNQUOTED(NEED_KSBA_VERSION, "$NEED_KSBA_VERSION",
                                        [Required version of Libksba])
 
 
 
 # The default is to use the modules from this package and the few
 # other packages in a standard place; i.e where this package gets
 # installed.  With these options it is possible to override these
 # ${prefix} depended values with fixed paths, which can't be replaced
 # at make time.  See also am/cmacros.am and the defaults in AH_BOTTOM.
 AC_ARG_WITH(agent-pgm,
     [  --with-agent-pgm=PATH  Use PATH as the default for the agent)],
           GNUPG_AGENT_PGM="$withval", GNUPG_AGENT_PGM="" )
 AC_SUBST(GNUPG_AGENT_PGM)
 AM_CONDITIONAL(GNUPG_AGENT_PGM, test -n "$GNUPG_AGENT_PGM")
 show_gnupg_agent_pgm="(default)"
 test -n "$GNUPG_AGENT_PGM" && show_gnupg_agent_pgm="$GNUPG_AGENT_PGM"
 
 AC_ARG_WITH(pinentry-pgm,
     [  --with-pinentry-pgm=PATH  Use PATH as the default for the pinentry)],
           GNUPG_PINENTRY_PGM="$withval", GNUPG_PINENTRY_PGM="" )
 AC_SUBST(GNUPG_PINENTRY_PGM)
 AM_CONDITIONAL(GNUPG_PINENTRY_PGM, test -n "$GNUPG_PINENTRY_PGM")
 show_gnupg_pinentry_pgm="(default)"
 test -n "$GNUPG_PINENTRY_PGM" && show_gnupg_pinentry_pgm="$GNUPG_PINENTRY_PGM"
 
 
 AC_ARG_WITH(scdaemon-pgm,
     [  --with-scdaemon-pgm=PATH  Use PATH as the default for the scdaemon)],
           GNUPG_SCDAEMON_PGM="$withval", GNUPG_SCDAEMON_PGM="" )
 AC_SUBST(GNUPG_SCDAEMON_PGM)
 AM_CONDITIONAL(GNUPG_SCDAEMON_PGM, test -n "$GNUPG_SCDAEMON_PGM")
 show_gnupg_scdaemon_pgm="(default)"
 test -n "$GNUPG_SCDAEMON_PGM" && show_gnupg_scdaemon_pgm="$GNUPG_SCDAEMON_PGM"
 
 
 AC_ARG_WITH(dirmngr-pgm,
     [  --with-dirmngr-pgm=PATH  Use PATH as the default for the dirmngr)],
           GNUPG_DIRMNGR_PGM="$withval", GNUPG_DIRMNGR_PGM="" )
 AC_SUBST(GNUPG_DIRMNGR_PGM)
 AM_CONDITIONAL(GNUPG_DIRMNGR_PGM, test -n "$GNUPG_DIRMNGR_PGM")
 show_gnupg_dirmngr_pgm="(default)"
 test -n "$GNUPG_DIRMNGR_PGM" && show_gnupg_dirmngr_pgm="$GNUPG_DIRMNGR_PGM"
 
 AC_ARG_WITH(protect-tool-pgm,
     [  --with-protect-tool-pgm=PATH  Use PATH as the default for the protect-tool)],
           GNUPG_PROTECT_TOOL_PGM="$withval", GNUPG_PROTECT_TOOL_PGM="" )
 AC_SUBST(GNUPG_PROTECT_TOOL_PGM)
 AM_CONDITIONAL(GNUPG_PROTECT_TOOL_PGM, test -n "$GNUPG_PROTECT_TOOL_PGM")
 show_gnupg_protect_tool_pgm="(default)"
 test -n "$GNUPG_PROTECT_TOOL_PGM" \
       && show_gnupg_protect_tool_pgm="$GNUPG_PROTECT_TOOL_PGM"
 
 AC_ARG_WITH(dirmngr-ldap-pgm,
     [  --with-dirmngr-ldap-pgm=PATH  Use PATH as the default for the dirmnge ldap wrapper)],
           GNUPG_DIRMNGR_LDAP_PGM="$withval", GNUPG_DIRMNGR_LDAP_PGM="" )
 AC_SUBST(GNUPG_DIRMNGR_LDAP_PGM)
 AM_CONDITIONAL(GNUPG_DIRMNGR_LDAP_PGM, test -n "$GNUPG_DIRMNGR_LDAP_PGM")
 show_gnupg_dirmngr_ldap_pgm="(default)"
 test -n "$GNUPG_DIRMNGR_LDAP_PGM" \
       && show_gnupg_dirmngr_ldap_pgm="$GNUPG_DIRMNGR_LDAP_PGM"
 
 
 # Some folks want to use only the agent from this packet.  Make it
 # easier for them by providing the configure option
 # --enable-only-agent.
 AC_ARG_ENABLE(agent-only,
     AC_HELP_STRING([--enable-agent-only],[build only the gpg-agent]),
     build_agent_only=$enableval)
 
 # SELinux support includes tracking of sensitive files to avoid
 # leaking their contents through processing these files by gpg itself
 AC_MSG_CHECKING([whether SELinux support is requested])
 AC_ARG_ENABLE(selinux-support,
               AC_HELP_STRING([--enable-selinux-support],
                              [enable SELinux support]),
               selinux_support=$enableval, selinux_support=no)
 AC_MSG_RESULT($selinux_support)
 
 # Allow disabling of zip support.
 # This is in general not a good idea because according to rfc4880 OpenPGP
 # implementations SHOULD support ZLIB.
 AC_MSG_CHECKING([whether to enable the ZIP and ZLIB compression algorithm])
 AC_ARG_ENABLE(zip,
    AC_HELP_STRING([--disable-zip],
                   [disable the ZIP and ZLIB compression algorithm]),
    use_zip=$enableval)
 AC_MSG_RESULT($use_zip)
 
 # Allow disabling of bzib2 support.
 # It is defined only after we confirm the library is available later
 AC_MSG_CHECKING([whether to enable the BZIP2 compression algorithm])
 AC_ARG_ENABLE(bzip2,
    AC_HELP_STRING([--disable-bzip2],[disable the BZIP2 compression algorithm]),
    use_bzip2=$enableval)
 AC_MSG_RESULT($use_bzip2)
 
 # Configure option to allow or disallow execution of external
 # programs, like a photo viewer.
 AC_MSG_CHECKING([whether to enable external program execution])
 AC_ARG_ENABLE(exec,
     AC_HELP_STRING([--disable-exec],[disable all external program execution]),
     use_exec=$enableval)
 AC_MSG_RESULT($use_exec)
 if test "$use_exec" = no ; then
     AC_DEFINE(NO_EXEC,1,[Define to disable all external program execution])
 fi
 
 if test "$use_exec" = yes ; then
   AC_MSG_CHECKING([whether to enable photo ID viewing])
   AC_ARG_ENABLE(photo-viewers,
       [  --disable-photo-viewers disable photo ID viewers],
       [if test "$enableval" = no ; then
          AC_DEFINE(DISABLE_PHOTO_VIEWER,1,[define to disable photo viewing])
       fi],enableval=yes)
   gnupg_cv_enable_photo_viewers=$enableval
   AC_MSG_RESULT($enableval)
 
   if test "$gnupg_cv_enable_photo_viewers" = yes ; then
     AC_MSG_CHECKING([whether to use a fixed photo ID viewer])
     AC_ARG_WITH(photo-viewer,
         [  --with-photo-viewer=FIXED_VIEWER  set a fixed photo ID viewer],
         [if test "$withval" = yes ; then
            withval=no
         elif test "$withval" != no ; then
            AC_DEFINE_UNQUOTED(FIXED_PHOTO_VIEWER,"$withval",
   	                    [if set, restrict photo-viewer to this])
         fi],withval=no)
     AC_MSG_RESULT($withval)
   fi
 
   AC_MSG_CHECKING([whether to enable external keyserver helpers])
   AC_ARG_ENABLE(keyserver-helpers,
       [  --disable-keyserver-helpers  disable all external keyserver support],
       [if test "$enableval" = no ; then
          AC_DEFINE(DISABLE_KEYSERVER_HELPERS,1,
                   [define to disable keyserver helpers])
       fi],enableval=yes)
   gnupg_cv_enable_keyserver_helpers=$enableval
   AC_MSG_RESULT($enableval)
 
   if test "$gnupg_cv_enable_keyserver_helpers" = yes ; then
     # LDAP is defined only after we confirm the library is available later
     AC_MSG_CHECKING([whether LDAP keyserver support is requested])
     AC_ARG_ENABLE(ldap,
       AC_HELP_STRING([--disable-ldap],[disable LDAP keyserver interface only]),
       try_ks_ldap=$enableval, try_ks_ldap=yes)
     AC_MSG_RESULT($try_ks_ldap)
 
     AC_MSG_CHECKING([whether HKP keyserver support is requested])
     AC_ARG_ENABLE(hkp,
       AC_HELP_STRING([--disable-hkp],[disable HKP keyserver interface only]),
       try_hkp=$enableval, try_hkp=yes)
     AC_MSG_RESULT($try_hkp)
 
     AC_MSG_CHECKING([whether finger key fetching support is requested])
     AC_ARG_ENABLE(finger,
       AC_HELP_STRING([--disable-finger],
         [disable finger key fetching interface only]),
       try_finger=$enableval, try_finger=yes)
     AC_MSG_RESULT($try_finger)
 
     AC_MSG_CHECKING([whether generic object key fetching support is requested])
     AC_ARG_ENABLE(generic,
       AC_HELP_STRING([--disable-generic],
         [disable generic object key fetching interface only]),
       try_generic=$enableval, try_generic=yes)
     AC_MSG_RESULT($try_generic)
 
     AC_MSG_CHECKING([whether email keyserver support is requested])
     AC_ARG_ENABLE(mailto,
       AC_HELP_STRING([--enable-mailto],
 	[enable email keyserver interface only]),
       try_mailto=$enableval, try_mailto=no)
     AC_MSG_RESULT($try_mailto)
   fi
 
   AC_MSG_CHECKING([whether keyserver exec-path is enabled])
   AC_ARG_ENABLE(keyserver-path,
       AC_HELP_STRING([--disable-keyserver-path],
         [disable the exec-path option for keyserver helpers]),
       [if test "$enableval" = no ; then
          disable_keyserver_path=yes
       fi],enableval=yes)
   AC_MSG_RESULT($enableval)
 fi
 
 
 #
 # Check for the key/uid cache size.  This can't be zero, but can be
 # pretty small on embedded systems.  This is used for the gpg part.
 #
 AC_MSG_CHECKING([for the size of the key and uid cache])
 AC_ARG_ENABLE(key-cache,
         AC_HELP_STRING([--enable-key-cache=SIZE],
                        [Set key cache to SIZE (default 4096)]),,enableval=4096)
 if test "$enableval" = "no"; then
    enableval=5
 elif test "$enableval" = "yes" || test "$enableval" = ""; then
    enableval=4096
 fi
 changequote(,)dnl
 key_cache_size=`echo "$enableval" | sed 's/[A-Za-z]//g'`
 changequote([,])dnl
 if test "$enableval" != "$key_cache_size" || test "$key_cache_size" -lt 5; then
    AC_MSG_ERROR([invalid key-cache size])
 fi
 AC_MSG_RESULT($key_cache_size)
 AC_DEFINE_UNQUOTED(PK_UID_CACHE_SIZE,$key_cache_size,
                   [Size of the key and UID caches])
 
 
 
 #
 # Check whether we want to use Linux capabilities
 #
 AC_MSG_CHECKING([whether use of capabilities is requested])
 AC_ARG_WITH(capabilities,
     [  --with-capabilities     use linux capabilities [default=no]],
 [use_capabilities="$withval"],[use_capabilities=no])
 AC_MSG_RESULT($use_capabilities)
 
 
 #
 # Allow disabling of internal CCID support.
 # It is defined only after we confirm the library is available later
 #
 AC_MSG_CHECKING([whether to enable the internal CCID driver])
 AC_ARG_ENABLE(ccid-driver,
               AC_HELP_STRING([--disable-ccid-driver],
                              [disable the internal CCID driver]),
               use_ccid_driver=$enableval)
 AC_MSG_RESULT($use_ccid_driver)
 
 # 
 # Dirmngr is nowadays a system service and thus it usually does no
 # make sense to start it as needed.  However on some systems this is
 # possible; this option enable the feature.
 #
 AC_MSG_CHECKING([whether to auto start dirmngr])
 AC_ARG_ENABLE(dirmngr-auto-start,
               AC_HELP_STRING([--enable-dirmngr-auto-start],
                              [enable auto starting of the dirmngr]),
               dirmngr_auto_start=$enableval)
 AC_MSG_RESULT($dirmngr_auto_start)
 if test "$dirmngr_auto_start" = yes ; then
     AC_DEFINE(USE_DIRMNGR_AUTO_START,1,
               [Define to enable auto starting of the dirmngr])
 fi
 
 
 #
 # To avoid double inclusion of config.h which might happen at some
 # places, we add the usual double inclusion protection at the top of
 # config.h.
 #
 AH_TOP([
 #ifndef GNUPG_CONFIG_H_INCLUDED
 #define GNUPG_CONFIG_H_INCLUDED
 ])
 
 #
 # Stuff which goes at the bottom of config.h.
 #
 AH_BOTTOM([
 /* This is the major version number of GnuPG so that
    source included files can test for this.  Note, that
    we use 2 here even for GnuPG 1.9.x. */
 #define GNUPG_MAJOR_VERSION 2
 
 /* Now to separate file name parts.
    Please note that the string version must not contain more
    than one character because the code assumes strlen()==1 */
 #ifdef HAVE_DOSISH_SYSTEM
 #define DIRSEP_C '\\'
 #define DIRSEP_S "\\"
 #define EXTSEP_C '.'
 #define EXTSEP_S "."
 #define PATHSEP_C ';'
 #define PATHSEP_S ";"
 #define EXEEXT_S ".exe"
 #else
 #define DIRSEP_C '/'
 #define DIRSEP_S "/"
 #define EXTSEP_C '.'
 #define EXTSEP_S "."
 #define PATHSEP_C ':'
 #define PATHSEP_S ":"
 #define EXEEXT_S ""
 #endif
 
 /* This is the same as VERSION, but should be overridden if the
    platform cannot handle things like dots '.' in filenames. Set
    SAFE_VERSION_DOT and SAFE_VERSION_DASH to whatever SAFE_VERSION
    uses for dots and dashes. */
 #define SAFE_VERSION VERSION
 #define SAFE_VERSION_DOT  '.'
 #define SAFE_VERSION_DASH '-'
 
 /* Some global constants. */
 #ifdef HAVE_DOSISH_SYSTEM
 # ifdef HAVE_DRIVE_LETTERS
 #  define GNUPG_DEFAULT_HOMEDIR "c:/gnupg"
 # else
 #  define GNUPG_DEFAULT_HOMEDIR "/gnupg"
 # endif
 #elif defined(__VMS)
 #define GNUPG_DEFAULT_HOMEDIR "/SYS$LOGIN/gnupg" 
 #else
 #define GNUPG_DEFAULT_HOMEDIR "~/.gnupg"
 #endif 
 #define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d"
 
 /* For some systems (DOS currently), we hardcode the path here.  For
    POSIX systems the values are constructed by the Makefiles, so that
    the values may be overridden by the make invocations; this is to
    comply with the GNU coding standards.  Note that these values are
    only defaults.  */
 #ifdef HAVE_DOSISH_SYSTEM
 # ifdef HAVE_DRIVE_LETTERS
 #  define GNUPG_BINDIR      "c:\\gnupg"
 #  define GNUPG_LIBEXECDIR  "c:\\gnupg"
 #  define GNUPG_LIBDIR      "c:\\gnupg"
 #  define GNUPG_DATADIR     "c:\\gnupg"
 #  define GNUPG_SYSCONFDIR  "c:\\gnupg"
 # else
 #  define GNUPG_BINDIR      "\\gnupg"
 #  define GNUPG_LIBEXECDIR  "\\gnupg"
 #  define GNUPG_LIBDIR      "\\gnupg"
 #  define GNUPG_DATADIR     "\\gnupg"
 #  define GNUPG_SYSCONFDIR  "\\gnupg"
 # endif
 #endif
 
 /* Derive some other constants. */
 #if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID))
 #define EXEC_TEMPFILE_ONLY
 #endif
 
 
 /* We didn't define endianness above, so get it from OS macros.  This
    is intended for making fat binary builds on OS X. */
 #if !defined(BIG_ENDIAN_HOST) && !defined(LITTLE_ENDIAN_HOST)
 #if defined(__BIG_ENDIAN__)
 #define BIG_ENDIAN_HOST 1
 #elif defined(__LITTLE_ENDIAN__)
 #define LITTLE_ENDIAN_HOST 1
 #else
 #error "No endianness found"
 #endif
 #endif
 
 
 /* Hack used for W32: ldap.m4 also tests for the ASCII version of
    ldap_start_tls_s because that is the actual symbol used in the
    library.  winldap.h redefines it to our commonly used value,
    thus we define our usual macro here.  */
 #ifdef HAVE_LDAP_START_TLS_SA
 # ifndef HAVE_LDAP_START_TLS_S
 #  define HAVE_LDAP_START_TLS_S 1
 # endif
 #endif
 
 
 /* Tell libgcrypt not to use its own libgpg-error implementation. */
 #define USE_LIBGPG_ERROR 1
 
 /* We use jnlib, so tell other modules about it.  */
 #define HAVE_JNLIB_LOGGING 1
 
 /* Our HTTP code is used in estream mode.  */
 #define HTTP_USE_ESTREAM 1
 
 /* Under W32 we do an explicit socket initialization, thus we need to
    avoid the on-demand initialization which would also install an atexit
    handler.  */
 #define HTTP_NO_WSASTARTUP
 
 /* We always include support for the OpenPGP card.  */
 #define ENABLE_CARD_SUPPORT 1
 
 /* We explicitly need to disable PTH's soft mapping as Debian
    currently enables it by default for no reason. */
 #define PTH_SYSCALL_SOFT 0
 
 /* We want to use the libgcrypt provided memory allocation for
    asprintf.  */
 #define _ESTREAM_PRINTF_MALLOC        gcry_malloc
 #define _ESTREAM_PRINTF_FREE          gcry_free
 #define _ESTREAM_PRINTF_EXTRA_INCLUDE "../common/util.h"
 
 /* Under Windows we use the gettext code from libgpg-error.  */
 #define GPG_ERR_ENABLE_GETTEXT_MACROS
 
 /* Under WindowsCE we use the strerror replacement from libgpg-error.  */
 #define GPG_ERR_ENABLE_ERRNO_MACROS
 
 #endif /*GNUPG_CONFIG_H_INCLUDED*/
 ])
 
 
 AM_MAINTAINER_MODE
 
 # Checks for programs.
 AC_MSG_NOTICE([checking for programs])
 AC_PROG_MAKE_SET
 AM_SANITY_CHECK
 missing_dir=`cd $ac_aux_dir && pwd`
 AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
 AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
 AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
 AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
 AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
 AC_PROG_AWK
 AC_PROG_CC
 AC_PROG_CPP
 AM_PROG_CC_C_O
 if test "x$ac_cv_prog_cc_c89" = "xno" ; then
   AC_MSG_ERROR([[No C-89 compiler found]])
 fi
 AC_PROG_INSTALL
 AC_PROG_LN_S
 AC_PROG_RANLIB
 AC_CHECK_TOOL(AR, ar, :)
 AC_PATH_PROG(PERL,"perl")
 AC_CHECK_TOOL(WINDRES, windres, :)
 AC_ISC_POSIX
 gl_EARLY
 AC_SYS_LARGEFILE
 GNUPG_CHECK_USTAR
 
 # We need to compile and run a program on the build machine.  A
 # comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in
 # the AC archive is broken for autoconf 2.57.  Given that there is no
 # newer version of that macro, we assume that it is also broken for
 # autoconf 2.61 and thus we use a simple but usually sufficient
 # approach.
 AC_MSG_CHECKING(for cc for build)
 if test "$cross_compiling" = "yes"; then
   CC_FOR_BUILD="${CC_FOR_BUILD-cc}"
 else
   CC_FOR_BUILD="${CC_FOR_BUILD-$CC}"
 fi
 AC_MSG_RESULT($CC_FOR_BUILD)
 AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler])
 
 
 
 try_gettext=yes
 have_dosish_system=no
 have_w32_system=no
 have_w32ce_system=no
 use_simple_gettext=no
 use_ldapwrapper=yes
 mmap_needed=yes
 case "${host}" in
     *-mingw32*)
         # special stuff for Windoze NT
         ac_cv_have_dev_random=no
         AC_DEFINE(USE_ONLY_8DOT3,1,
                   [Set this to limit filenames to the 8.3 format])
         AC_DEFINE(USE_SIMPLE_GETTEXT,1,
                   [Because the Unix gettext has too much overhead on
                    MingW32 systems and these systems lack Posix functions,
                    we use a simplified version of gettext])
         disable_keyserver_path=yes
         have_dosish_system=yes
         have_w32_system=yes
         use_ldapwrapper=no  # Fixme: Do this only for CE.
         case "${host}" in 
           *-mingw32ce*)
             have_w32ce_system=yes
             ;;
           *)
             AC_DEFINE(HAVE_DRIVE_LETTERS,1,
                       [Defined if the OS supports drive letters.])
             ;;
         esac
         try_gettext="no"
 	use_simple_gettext=yes
 	mmap_needed=no
         ;;
     i?86-emx-os2 | i?86-*-os2*emx )
         # OS/2 with the EMX environment
         ac_cv_have_dev_random=no
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         have_dosish_system=yes
         try_gettext="no"
         ;;
 
     i?86-*-msdosdjgpp*)
         # DOS with the DJGPP environment
         ac_cv_have_dev_random=no
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         have_dosish_system=yes
         try_gettext="no"
         ;;
 
     *-*-freebsd*)
        # FreeBSD
        CPPFLAGS="$CPPFLAGS -I/usr/local/include"
        LDFLAGS="$LDFLAGS -L/usr/local/lib"
        ;;
 
     *-*-hpux*)
         if test -z "$GCC" ; then
             CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE"
         fi
         ;;
     *-dec-osf4*)
         if test -z "$GCC" ; then
             # Suppress all warnings
             # to get rid of the unsigned/signed char mismatch warnings.
             CFLAGS="$CFLAGS -w"
         fi
         ;;
     *-dec-osf5*)
         if test -z "$GCC" ; then
             # Use the newer compiler `-msg_disable ptrmismatch1' to
             # get rid of the unsigned/signed char mismatch warnings.
             # Using this may hide other pointer mismatch warnings, but
 	    # it at least lets other warning classes through
             CFLAGS="$CFLAGS -msg_disable ptrmismatch1"
         fi
         ;;
     m68k-atari-mint)
         ;;
     *)
        ;;
 esac
 
 if test "$have_dosish_system" = yes; then
    AC_DEFINE(HAVE_DOSISH_SYSTEM,1,
              [Defined if we run on some of the PCDOS like systems 
               (DOS, Windoze. OS/2) with special properties like
               no file modes, case insensitive file names and preferred
               use of backslashes as directory name separators.])
 fi
 AM_CONDITIONAL(HAVE_DOSISH_SYSTEM, test "$have_dosish_system" = yes)
 
 AM_CONDITIONAL(USE_SIMPLE_GETTEXT, test x"$use_simple_gettext" = xyes)
 
 if test "$have_w32_system" = yes; then
    AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system])
    if test "$have_w32ce_system" = yes; then
       AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE])
    fi
 fi
 AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
 AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes)
 
 if test "$use_ldapwrapper" = yes; then
    AC_DEFINE(USE_LDAPWRAPPER,1, [Build dirmngr with LDAP wrapper process])
 fi
 AM_CONDITIONAL(USE_LDAPWRAPPER, test "$use_ldapwrapper" = yes)
 
 if test "$disable_keyserver_path" = yes; then
     AC_DEFINE(DISABLE_KEYSERVER_PATH,1,
               [Defined to disable exec-path for keyserver helpers])
 fi
 
 #
 # Allows enabling the use of a standard socket by default This is
 # gpg-agent's option --[no-]use-standard-socket.  For Windows we force
 # the use of this.
 #
 AC_MSG_CHECKING([whether to use a standard socket by default])
 AC_ARG_ENABLE(standard-socket,
               AC_HELP_STRING([--disable-standard-socket],
                              [don't use a standard socket by default]),
               use_standard_socket=$enableval)
 tmp=""
 if test "$use_standard_socket" != yes; then
   if test "$have_w32_system" = yes; then
     use_standard_socket=yes
     tmp=" (forced)"
   fi
 fi
 AC_MSG_RESULT($use_standard_socket$tmp)
 if test "$use_standard_socket" = yes; then
   AC_DEFINE(USE_STANDARD_SOCKET,1,
             [Use the standard socket for the agent by default])
 fi
 
 
 # (These need to go after AC_PROG_CC so that $EXEEXT is defined)
 AC_DEFINE_UNQUOTED(EXEEXT,"$EXEEXT",[The executable file extension, if any])
 
 if test x"$try_hkp" = xyes ; then
   AC_SUBST(GPGKEYS_HKP,"gpg2keys_hkp$EXEEXT")
 fi
 
 if test x"$try_finger" = xyes ; then
   AC_SUBST(GPGKEYS_FINGER,"gpg2keys_finger$EXEEXT")
 fi
 
 
 
 #
 # Checks for libraries.
 #
 AC_MSG_NOTICE([checking for libraries])
 
 
 #
 # libgpg-error is a library with error codes shared between GnuPG
 # related projects.
 #
 AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
                   have_gpg_error=yes,have_gpg_error=no)
 
 
 #
 # Libgcrypt is our generic crypto library
 #
 AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION",
         have_libgcrypt=yes,have_libgcrypt=no)
 
 
 #
 # libassuan is used for IPC
 #
 AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION",
                   have_libassuan=yes,have_libassuan=no)
 if test "$have_libassuan" = "yes"; then
   AC_DEFINE_UNQUOTED(GNUPG_LIBASSUAN_VERSION, "$libassuan_version",
                      [version of the libassuan library])
 fi
 
 
 
 #
 # libksba is our X.509 support library
 #
 AM_PATH_KSBA("$NEED_KSBA_API:$NEED_KSBA_VERSION",have_ksba=yes,have_ksba=no)
 
 
 #
 # libusb allows us to use the integrated CCID smartcard reader driver.
 #
 # FiXME: Use GNUPG_CHECK_LIBUSB and modify to use separate AC_SUBSTs.
 if test "$use_ccid_driver" = yes ; then
   AC_CHECK_LIB(usb, usb_bulk_write,
                 [ LIBUSB_LIBS="$LIBUSB_LIBS -lusb"
                   AC_DEFINE(HAVE_LIBUSB,1,
                            [defined if libusb is available])
                   have_libusb=yes
                ])
   AC_CHECK_FUNCS(usb_create_match)
 fi
 AC_SUBST(LIBUSB_LIBS)
 
 #
 # Check wether it is necessary to link against libdl.
 #
 gnupg_dlopen_save_libs="$LIBS"
 LIBS=""
 AC_SEARCH_LIBS(dlopen, c dl,,,)
 DL_LIBS=$LIBS
 AC_SUBST(DL_LIBS)
 LIBS="$gnupg_dlopen_save_libs"
 
 # Checks for g13
 
 AC_PATH_PROG(ENCFS, encfs, /usr/bin/encfs)
 AC_DEFINE_UNQUOTED(ENCFS,
 	"${ENCFS}", [defines the filename of the encfs program])
 
 AC_PATH_PROG(FUSERMOUNT, fusermount, /usr/bin/fusermount)
 AC_DEFINE_UNQUOTED(FUSERMOUNT,
 	"${FUSERMOUNT}", [defines the filename of the fusermount program])
 
 
 # Checks for dirmngr
 
 
 #
 # Checks for symcryptrun:
 #
 
 # libutil has openpty() and login_tty().
 AC_CHECK_LIB(util, openpty,
               [ LIBUTIL_LIBS="$LIBUTIL_LIBS -lutil"
                 AC_DEFINE(HAVE_LIBUTIL,1,
                          [defined if libutil is available])
              ])
 AC_SUBST(LIBUTIL_LIBS)
 
 # shred is used to clean temporary plain text files.
 AC_PATH_PROG(SHRED, shred, /usr/bin/shred)
 AC_DEFINE_UNQUOTED(SHRED,
 	"${SHRED}", [defines the filename of the shred program])
 
 
 #
 # Check whether the GNU Pth library is available
 # Note, that we include a Pth emulation for W32.
 #
 if test "$have_w32_system" = yes; then
   GNUPG_PATH_PTH([2.0.4])
 else
   GNUPG_PATH_PTH
 fi
 if test "$have_pth" = "yes"; then
   AC_DEFINE(USE_GNU_PTH, 1,
               [Defined if the GNU Portable Thread Library should be used])
 else
   AC_MSG_WARN([[
 ***
 *** To support concurrent access to the gpg-agent and the SCdaemon
 *** we need the support of the GNU Portable Threads Library.
 *** Download it from ftp://ftp.gnu.org/gnu/pth/
 *** On a Debian GNU/Linux system you might want to try 
 ***   apt-get install libpth-dev
 ***]])
 fi
 
 
 AC_MSG_NOTICE([checking for networking options])
 
 #
 # Must check for network library requirements before doing link tests
 # for ldap, for example. If ldap libs are static (or dynamic and without
 # ELF runtime link paths), then link will fail and LDAP support won't
 # be detected.
 #
 AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname,
 	[NETLIBS="-lnsl $NETLIBS"]))
 AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt,
 	[NETLIBS="-lsocket $NETLIBS"]))
 
 
 #
 # Check for ADNS.
 #
 _cppflags="${CPPFLAGS}"
 _ldflags="${LDFLAGS}"
 AC_ARG_WITH(adns,
             AC_HELP_STRING([--with-adns=DIR],
                            [look for the adns library in DIR]),
             [if test -d "$withval"; then
                CPPFLAGS="${CPPFLAGS} -I$withval/include"
                LDFLAGS="${LDFLAGS} -L$withval/lib"
              fi])
 if test "$with_adns" != "no"; then
   AC_CHECK_HEADERS(adns.h,
                 AC_CHECK_LIB(adns, adns_init,
                              [have_adns=yes],
                              [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}]),
                 [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}])
 fi
 if test "$have_adns" = "yes"; then
   ADNSLIBS="-ladns" 
 fi
 AC_SUBST(ADNSLIBS)
 # Newer adns versions feature a free function to be used under W32.
 AC_CHECK_FUNCS(adns_free)
 
 
 
 #
 # Now try for the resolver functions so we can use DNS for SRV, PA and CERT.
 #
 if test x"$try_hkp" = xyes || test x"$try_http" = xyes ; then
   AC_ARG_ENABLE(dns-srv,
      AC_HELP_STRING([--disable-dns-srv],
                     [disable the use of DNS SRV in HKP and HTTP]),
                 use_dns_srv=$enableval,use_dns_srv=yes)
 fi
 
 AC_ARG_ENABLE(dns-pka,
    AC_HELP_STRING([--disable-dns-pka],
 	[disable the use of PKA records in DNS]),
    use_dns_pka=$enableval,use_dns_pka=yes)
 
 AC_ARG_ENABLE(dns-cert,
    AC_HELP_STRING([--disable-dns-cert],
 	[disable the use of CERT records in DNS]),
    use_dns_cert=$enableval,use_dns_cert=yes)
 
 if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes \
    || test x"$use_dns_cert" = xyes; then
   _dns_save_libs=$LIBS
   LIBS=""
   # the double underscore thing is a glibc-ism?
   AC_SEARCH_LIBS(res_query,resolv bind,,
                  AC_SEARCH_LIBS(__res_query,resolv bind,,have_resolver=no))
   AC_SEARCH_LIBS(dn_expand,resolv bind,,
                  AC_SEARCH_LIBS(__dn_expand,resolv bind,,have_resolver=no))
   AC_SEARCH_LIBS(dn_skipname,resolv bind,,
                  AC_SEARCH_LIBS(__dn_skipname,resolv bind,,have_resolver=no))
 
   if test x"$have_resolver" != xno ; then
 
     # Make sure that the BIND 4 resolver interface is workable before
     # enabling any code that calls it.  At some point I'll rewrite the
     # code to use the BIND 8 resolver API.
     # We might also want to use adns instead.  Problem with ADNS is that
     # it does not support v6.
 
     AC_MSG_CHECKING([whether the resolver is usable])
     AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <resolv.h>],
 [[unsigned char answer[PACKETSZ];
   res_query("foo.bar",C_IN,T_A,answer,PACKETSZ);
   dn_skipname(0,0); 
   dn_expand(0,0,0,0,0);
 ]])],have_resolver=yes,have_resolver=no)
     AC_MSG_RESULT($have_resolver)
 
     # This is Apple-specific and somewhat bizarre as they changed the
     # define in bind 8 for some reason.
 
     if test x"$have_resolver" != xyes ; then
        AC_MSG_CHECKING(
              [whether I can make the resolver usable with BIND_8_COMPAT])
        AC_LINK_IFELSE([AC_LANG_PROGRAM([#define BIND_8_COMPAT
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
 #include <resolv.h>],
 [[unsigned char answer[PACKETSZ];
   res_query("foo.bar",C_IN,T_A,answer,PACKETSZ);
   dn_skipname(0,0); dn_expand(0,0,0,0,0);
 ]])],[have_resolver=yes ; need_compat=yes])
        AC_MSG_RESULT($have_resolver)
     fi
   fi
 
   if test x"$have_resolver" = xyes ; then
      DNSLIBS=$LIBS
 
      if test x"$use_dns_srv" = xyes ; then
         AC_DEFINE(USE_DNS_SRV,1,[define to use DNS SRV])
      fi
 
      if test x"$use_dns_pka" = xyes ; then
         AC_DEFINE(USE_DNS_PKA,1,[define to use our experimental DNS PKA])
      fi
 
      if test x"$use_dns_cert" = xyes ; then
         AC_DEFINE(USE_DNS_CERT,1,[define to use DNS CERT])
      fi
 
      if test x"$need_compat" = xyes ; then
         AC_DEFINE(BIND_8_COMPAT,1,[an Apple OSXism])
      fi
   else
      # If we have no resolver library but ADNS (e.g. under W32) enable the
      # code parts which can be used with ADNS.
      if test x"$have_adns" = xyes ; then
         DNSLIBS="$ADNSLIBS"
         AC_DEFINE(USE_ADNS,1,[Use ADNS as resolver library.])
 
         if test x"$use_dns_srv" = xyes ; then
            AC_DEFINE(USE_DNS_SRV,1)
         fi
 
         if test x"$use_dns_pka" = xyes ; then
            AC_DEFINE(USE_DNS_PKA,1)
         fi
 
         if test x"$use_dns_cert" = xyes ; then
            AC_DEFINE(USE_DNS_CERT,1,[define to use DNS CERT])
         fi
      else
         use_dns_srv=no
         use_dns_pka=no
         use_dns_cert=no
      fi
   fi
 
   LIBS=$_dns_save_libs
 fi
 
 AC_SUBST(DNSLIBS)
 
 AM_CONDITIONAL(USE_DNS_SRV, test x"$use_dns_srv" = xyes)
 
 
 #
 # Check for LDAP
 #
 if test "$try_ks_ldap" = yes || test "$build_dirmngr" = "yes" ; then
    GNUPG_CHECK_LDAP($NETLIBS)
 fi
 
 #
 # Check for curl.  We fake the curl API if libcurl isn't installed.
 # We require 7.10 or later as we use curl_version_info().
 #
 LIBCURL_CHECK_CONFIG([yes],[7.10],,[fake_curl=yes])
 AM_CONDITIONAL(FAKE_CURL,test x"$fake_curl" = xyes)
 
 # Generic, for us, means curl
 
 if test x"$try_generic" = xyes ; then
    AC_SUBST(GPGKEYS_CURL,"gpg2keys_curl$EXEEXT")
 fi
 
 #
 # Check for sendmail
 #
 # This isn't necessarily sendmail itself, but anything that gives a
 # sendmail-ish interface to the outside world.  That includes Exim,
 # Postfix, etc.  Basically, anything that can handle "sendmail -t".
 if test "$try_mailto" = yes ; then
   AC_ARG_WITH(mailprog,
       AC_HELP_STRING([--with-mailprog=NAME],
                      [use "NAME -t" for mail transport]),
              ,with_mailprog=yes)
 
   if test x"$with_mailprog" = xyes ; then
     AC_PATH_PROG(SENDMAIL,sendmail,,$PATH:/usr/sbin:/usr/libexec:/usr/lib)
     if test "$ac_cv_path_SENDMAIL" ; then
       GPGKEYS_MAILTO="gpg2keys_mailto"
     fi
   elif test x"$with_mailprog" != xno ; then
     AC_MSG_CHECKING([for a mail transport program])
     AC_SUBST(SENDMAIL,$with_mailprog)
     AC_MSG_RESULT($with_mailprog)
     GPGKEYS_MAILTO="gpg2keys_mailto"
   fi
 fi
 
 AC_SUBST(GPGKEYS_MAILTO)
 
 #
 # Construct a printable name of the OS
 #
 case "${host}" in
     *-mingw32ce*)
         PRINTABLE_OS_NAME="W32CE"
         ;;
     *-mingw32*)
         PRINTABLE_OS_NAME="MingW32"
         ;;
     *-*-cygwin*)
         PRINTABLE_OS_NAME="Cygwin"
         ;;
     i?86-emx-os2 | i?86-*-os2*emx )
         PRINTABLE_OS_NAME="OS/2"
         ;;
     i?86-*-msdosdjgpp*)
         PRINTABLE_OS_NAME="MSDOS/DJGPP"
         try_dynload=no
         ;;
     *-linux*)
         PRINTABLE_OS_NAME="GNU/Linux"
         ;;
     *)
         PRINTABLE_OS_NAME=`uname -s || echo "Unknown"`
         ;;
 esac
 AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME",
                    [A human readable text with the name of the OS])
 
 
 #
 # Checking for iconv
 #
 AM_ICONV
 
 
 #
 # Check for gettext
 #
 # This is "GNU gnupg" - The project-id script from gettext
 #                       needs this string
 #
 AC_MSG_NOTICE([checking for gettext])
 AM_PO_SUBDIRS
 AM_GNU_GETTEXT_VERSION([0.17])
 if test "$try_gettext" = yes; then
   AM_GNU_GETTEXT([external],[need-ngettext])
 
   # gettext requires some extra checks.  These really should be part of
   # the basic AM_GNU_GETTEXT macro.  TODO: move other gettext-specific
   # function checks to here.
 
   AC_CHECK_FUNCS(strchr)
 else
   USE_NLS=no
   USE_INCLUDED_LIBINTL=no
   BUILD_INCLUDED_LIBINTL=no
   POSUB=po
   AC_SUBST(USE_NLS)
   AC_SUBST(USE_INCLUDED_LIBINTL)
   AC_SUBST(BUILD_INCLUDED_LIBINTL)
   AC_SUBST(POSUB)
 fi
 
 # We use HAVE_LANGINFO_CODESET in a couple of places.
 AM_LANGINFO_CODESET
 
 # Checks required for our use locales
 gt_LC_MESSAGES
 
 
 #
 # SELinux support
 #
 if test "$selinux_support" = yes ; then
   AC_DEFINE(ENABLE_SELINUX_HACKS,1,[Define to enable SELinux support])
 fi
 
 
 #
 # Checks for header files.
 #
 AC_MSG_NOTICE([checking for header files])
 AC_HEADER_STDC
 AC_CHECK_HEADERS([string.h unistd.h langinfo.h termio.h locale.h getopt.h \
                   pty.h pwd.h inttypes.h signal.h])
 AC_HEADER_TIME
 
 
 #
 # Checks for typedefs, structures, and compiler characteristics.
 #
 AC_MSG_NOTICE([checking for system characteristics])
 AC_C_CONST
 AC_C_INLINE
 AC_C_VOLATILE
 AC_TYPE_SIZE_T
 AC_TYPE_MODE_T
 AC_TYPE_SIGNAL
 AC_DECL_SYS_SIGLIST
 
 gl_HEADER_SYS_SOCKET
 gl_TYPE_SOCKLEN_T
 
 AC_ARG_ENABLE(endian-check,
               AC_HELP_STRING([--disable-endian-check],
 	      [disable the endian check and trust the OS provided macros]),
 	      endiancheck=$enableval,endiancheck=yes)
 
 if test x"$endiancheck" = xyes ; then
   GNUPG_CHECK_ENDIAN
 fi
 
 # fixme: we should get rid of the byte type
 GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF)
 GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF)
 GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF)
 GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF)
 GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF)
 
 AC_CHECK_SIZEOF(unsigned short)
 AC_CHECK_SIZEOF(unsigned int)
 AC_CHECK_SIZEOF(unsigned long)
 AC_CHECK_SIZEOF(unsigned long long)
 AC_HEADER_TIME
 AC_CHECK_SIZEOF(time_t,,[[
 #include <stdio.h>
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
 #else
 # if HAVE_SYS_TIME_H
 #  include <sys/time.h>
 # else
 #  include <time.h>
 # endif
 #endif
 ]])
 GNUPG_TIME_T_UNSIGNED
 
 
 # Ensure that we have UINT64_C before we bother to check for uint64_t
 # Fixme: really needed in gnupg?  I think it is only useful in libcgrypt.
 AC_CACHE_CHECK([for UINT64_C],[gnupg_cv_uint64_c_works],
    AC_COMPILE_IFELSE(AC_LANG_PROGRAM([#include <inttypes.h>
        uint64_t foo=UINT64_C(42);]),
      gnupg_cv_uint64_c_works=yes,gnupg_cv_uint64_c_works=no))
 if test "$gnupg_cv_uint64_c_works" = "yes" ; then
    AC_CHECK_SIZEOF(uint64_t)
 fi
 
 if test "$ac_cv_sizeof_unsigned_short" = "0" \
    || test "$ac_cv_sizeof_unsigned_int" = "0" \
    || test "$ac_cv_sizeof_unsigned_long" = "0"; then
     AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]);
 fi
 
 
 #
 # Checks for library functions.
 #
 AC_MSG_NOTICE([checking for library functions])
 AC_CHECK_DECLS(getpagesize)
 AC_FUNC_FSEEKO
 AC_FUNC_VPRINTF
 AC_FUNC_FORK
 AC_CHECK_FUNCS([strerror strlwr tcgetattr mmap canonicalize_file_name])
 AC_CHECK_FUNCS([strcasecmp strncasecmp ctermid times gmtime_r strtoull])
 AC_CHECK_FUNCS([unsetenv fcntl ftruncate canonicalize_file_name])
 AC_CHECK_FUNCS([gettimeofday getrusage getrlimit setrlimit clock_gettime])
 AC_CHECK_FUNCS([atexit raise getpagesize strftime nl_langinfo setlocale])
 AC_CHECK_FUNCS([waitpid wait4 sigaction sigprocmask pipe getaddrinfo])
 AC_CHECK_FUNCS([ttyname rand ftello fsync stat lstat])
 
 AC_CHECK_TYPES([struct sigaction, sigset_t],,,[#include <signal.h>])
 
 # Dirmngr requires mmap on Unix systems.
 if test $ac_cv_func_mmap != yes -a $mmap_needed = yes; then
   AC_MSG_ERROR([[Sorry, the current implemenation requires mmap.]])
 fi
 
 #
 # These are needed by the jnlib parts in common.
 # Note:  We already checked pwd.h.
 AC_CHECK_HEADERS([signal.h])
 AC_CHECK_FUNCS([memicmp stpcpy strsep strlwr strtoul memmove stricmp strtol \
                 memrchr isascii timegm getrusage setrlimit stat setlocale   \
                 flockfile funlockfile fopencookie funopen getpwnam getpwuid \
                 getenv inet_pton])
 # end jnlib checks.
 
 
 
 #
 # gnulib checks
 #
 gl_SOURCE_BASE([gl])
 gl_M4_BASE([gl/m4])
 gl_MODULES([setenv mkdtemp xsize strpbrk])
 gl_INIT
 
 
 #
 # W32 specific test
 #
 GNUPG_FUNC_MKDIR_TAKES_ONE_ARG
 
 #
 # Sanity check regex.  Tests adapted from mutt.
 #
 AC_MSG_CHECKING([whether regular expression support is requested])
 AC_ARG_ENABLE(regex,
   AC_HELP_STRING([--disable-regex],
     [do not handle regular expressions in trust signatures]),
   use_regex=$enableval, use_regex=yes)
 AC_MSG_RESULT($use_regex)
 
 if test "$use_regex" = yes ; then
   _cppflags="${CPPFLAGS}"
   _ldflags="${LDFLAGS}"
   AC_ARG_WITH(regex,
      AC_HELP_STRING([--with-regex=DIR],[look for regex in DIR]),
       [
       if test -d "$withval" ; then
         CPPFLAGS="${CPPFLAGS} -I$withval/include"
         LDFLAGS="${LDFLAGS} -L$withval/lib"
       fi
       ],withval="")     
 
   # Does the system have regex functions at all?
   AC_SEARCH_LIBS([regcomp], [regex])
   AC_CHECK_FUNC(regcomp, gnupg_cv_have_regex=yes, gnupg_cv_have_regex=no)
 
   if test $gnupg_cv_have_regex = no; then
     use_regex=no
   else
     if test x"$cross_compiling" = xyes; then
       AC_MSG_WARN([cross compiling; assuming regexp libray is not broken])
     else
       AC_CACHE_CHECK([whether your system's regexp library is broken],
        [gnupg_cv_regex_broken],
        AC_TRY_RUN([
 #include <unistd.h>
 #include <regex.h>
 main() { regex_t blah ; regmatch_t p; p.rm_eo = p.rm_eo; return regcomp(&blah, "foo.*bar", REG_NOSUB) || regexec (&blah, "foobar", 0, NULL, 0); }],
        gnupg_cv_regex_broken=no, gnupg_cv_regex_broken=yes, gnupg_cv_regex_broken=yes))
 
       if test $gnupg_cv_regex_broken = yes; then
         AC_MSG_WARN([your regex is broken - disabling regex use])
         use_regex=no
       fi
     fi
   fi
   CPPFLAGS="${_cppflags}"
   LDFLAGS="${_ldflags}"
 fi
 
 if test "$use_regex" != yes ; then
   AC_DEFINE(DISABLE_REGEX,1, [Define to disable regular expression support])
 fi
 AM_CONDITIONAL(DISABLE_REGEX, test x"$use_regex" != xyes)
 
 
 
 #
 # Do we have zlib? Must do it here because Solaris failed
 # when compiling a conftest (due to the "-lz" from LIBS).
 # Note that we combine zlib and bzlib2 in ZLIBS.
 #
 if test "$use_zip" = yes ; then
   _cppflags="${CPPFLAGS}"
   _ldflags="${LDFLAGS}"
   AC_ARG_WITH(zlib,
     [  --with-zlib=DIR         use libz in DIR],[
       if test -d "$withval"; then
         CPPFLAGS="${CPPFLAGS} -I$withval/include"
         LDFLAGS="${LDFLAGS} -L$withval/lib"
       fi
     ])
   
   AC_CHECK_HEADER(zlib.h,
         AC_CHECK_LIB(z, deflateInit2_,
          ZLIBS="-lz",
          CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}),
          CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags})
          
   AC_DEFINE(HAVE_ZIP,1, [Defined if ZIP and ZLIB are supported])
 fi
 
 
 #
 # Check whether we can support bzip2
 # 
 if test "$use_bzip2" = yes ; then
   _cppflags="${CPPFLAGS}"
   _ldflags="${LDFLAGS}"
   AC_ARG_WITH(bzip2,
      AC_HELP_STRING([--with-bzip2=DIR],[look for bzip2 in DIR]),
       [
       if test -d "$withval" ; then
         CPPFLAGS="${CPPFLAGS} -I$withval/include"
         LDFLAGS="${LDFLAGS} -L$withval/lib"
       fi
       ],withval="")
 
   # Checking alongside stdio.h as an early version of bzip2 (1.0)
   # required stdio.h to be included before bzlib.h, and Solaris 9 is 
   # woefully out of date.
   if test "$withval" != no ; then
      AC_CHECK_HEADER(bzlib.h,
         AC_CHECK_LIB(bz2,BZ2_bzCompressInit,
   	  [
 	  have_bz2=yes
 	  ZLIBS="$ZLIBS -lbz2"
 	  AC_DEFINE(HAVE_BZIP2,1,
 		  [Defined if the bz2 compression library is available])
 	  ],
 	  CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}),
 	  CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags},[#include <stdio.h>])
   fi
 fi
 AM_CONDITIONAL(ENABLE_BZIP2_SUPPORT,test x"$have_bz2" = "xyes")
 AC_SUBST(ZLIBS)
 
 
 # Check for readline support
 GNUPG_CHECK_READLINE
 
 #
 # Allow users to append something to the version string without
 # flagging it as development version.  The user version parts is
 # considered everything after a dash. 
 #
 if test "$development_version" != yes; then
   changequote(,)dnl
   tmp_pat='[a-zA-Z]'
   changequote([,])dnl
   if echo "$VERSION" | sed 's/-.*//' | grep "$tmp_pat" >/dev/null ; then
     development_version=yes
   fi
 fi
 if test "$development_version" = yes; then
     AC_DEFINE(IS_DEVELOPMENT_VERSION,1,
             [Defined if this is not a regular release])
 fi
 
 AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes)
 
 GNUPG_CHECK_GNUMAKE
 
 # Add some extra libs here so that previous tests don't fail for
 # mysterious reasons - the final link step should bail out.
 # W32SOCKLIBS is also defined so that if can be used for tools not
 # requiring any network stuff but linking to code in libcommon which
 # tracks in winsock stuff (e.g. init_common_subsystems).
 if test "$have_w32_system" = yes; then
    if test "$have_w32ce_system" = yes; then
      W32SOCKLIBS="-lws2"
    else
      W32SOCKLIBS="-lws2_32"
    fi
    NETLIBS="${NETLIBS} ${W32SOCKLIBS}"
 fi
 
 AC_SUBST(NETLIBS)
 AC_SUBST(W32SOCKLIBS)
 
 #
 # Setup gcc specific options
 #
 AC_MSG_NOTICE([checking for cc features])
 if test "$GCC" = yes; then
     # Note that it is okay to use CFLAGS here because this are just
     # warning options and the user should have a chance of overriding
     # them.
     if test "$USE_MAINTAINER_MODE" = "yes"; then
         CFLAGS="$CFLAGS -O3 -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
         CFLAGS="$CFLAGS -Wformat -Wno-format-y2k -Wformat-security"
         AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers])
         _gcc_cflags_save=$CFLAGS
         CFLAGS="-Wno-missing-field-initializers"
         AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]),_gcc_wopt=yes,_gcc_wopt=no)
         AC_MSG_RESULT($_gcc_wopt)
         CFLAGS=$_gcc_cflags_save;
         if test x"$_gcc_wopt" = xyes ; then
           CFLAGS="$CFLAGS -W -Wno-sign-compare -Wno-missing-field-initializers"
         fi
         AC_MSG_CHECKING([if gcc supports -Wdeclaration-after-statement])
         _gcc_cflags_save=$CFLAGS
         CFLAGS="-Wdeclaration-after-statement"
         AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]),_gcc_wopt=yes,_gcc_wopt=no)
         AC_MSG_RESULT($_gcc_wopt)
         CFLAGS=$_gcc_cflags_save;
         if test x"$_gcc_wopt" = xyes ; then
           CFLAGS="$CFLAGS -Wdeclaration-after-statement"
         fi
     else
         CFLAGS="$CFLAGS -Wall"
     fi
 
     AC_MSG_CHECKING([if gcc supports -Wno-pointer-sign])
     _gcc_cflags_save=$CFLAGS
     CFLAGS="-Wno-pointer-sign"
     AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]),_gcc_psign=yes,_gcc_psign=no)
     AC_MSG_RESULT($_gcc_psign)
     CFLAGS=$_gcc_cflags_save;
     if test x"$_gcc_psign" = xyes ; then
        CFLAGS="$CFLAGS -Wno-pointer-sign"
     fi
 
     AC_MSG_CHECKING([if gcc supports -Wpointer-arith])
     _gcc_cflags_save=$CFLAGS
     CFLAGS="-Wpointer-arith"
     AC_COMPILE_IFELSE(AC_LANG_PROGRAM([]),_gcc_psign=yes,_gcc_psign=no)
     AC_MSG_RESULT($_gcc_psign)
     CFLAGS=$_gcc_cflags_save;
     if test x"$_gcc_psign" = xyes ; then
        CFLAGS="$CFLAGS -Wpointer-arith"
     fi
 fi
 
 
 #
 # This is handy for debugging so the compiler doesn't rearrange
 # things and eliminate variables.
 #
 AC_ARG_ENABLE(optimization,
    AC_HELP_STRING([--disable-optimization],
                   [disable compiler optimization]),
                   [if test $enableval = no ; then
                       CFLAGS=`echo $CFLAGS | sed 's/-O[[0-9]]//'`
                    fi])
 
 #
 # Prepare building of estream
 #
 estream_INIT
 
 
 #
 # Decide what to build
 #
 if test "$have_adns" = "yes"; then
   AC_SUBST(GPGKEYS_KDNS, "gpg2keys_kdns$EXEEXT")
 fi
 
 
 missing_pth=no
 if test $have_ksba = no; then
   build_gpgsm=no
   build_scdaemon=no
 fi
 
 build_agent_threaded=""
 if test "$build_agent" = "yes"; then
   if test $have_pth = no; then
      build_agent_threaded="(not multi-threaded)"
      missing_pth=yes
   fi
 fi
 
 build_scdaemon_extra=""
 if test "$build_scdaemon" = "yes"; then
   tmp=""
   if test $have_pth = no; then
      build_scdaemon_extra="not multi-threaded"
      tmp=", "
      missing_pth=yes
   fi
   if test $have_libusb = no; then
      build_scdaemon_extra="${tmp}without internal CCID driver"
      tmp=", "
   fi
   if test -n "$build_scdaemon_extra"; then
      build_scdaemon_extra="(${build_scdaemon_extra})"
   fi
 fi
 
 
 if test "$build_agent_only" = "yes" ; then
   build_gpg=no
   build_gpgsm=no
   build_scdaemon=no
   build_tools=no
   build_doc=no
 fi
 
-
+#
+# Set variables for use by th automake makefile.
+#
 AM_CONDITIONAL(BUILD_GPG,         test "$build_gpg" = "yes")
 AM_CONDITIONAL(BUILD_GPGSM,       test "$build_gpgsm" = "yes")
 AM_CONDITIONAL(BUILD_AGENT,       test "$build_agent" = "yes")
 AM_CONDITIONAL(BUILD_SCDAEMON,    test "$build_scdaemon" = "yes")
 AM_CONDITIONAL(BUILD_G13,         test "$build_g13" = "yes")
 AM_CONDITIONAL(BUILD_DIRMNGR,     test "$build_dirmngr" = "yes")
 AM_CONDITIONAL(BUILD_TOOLS,       test "$build_tools" = "yes")
 AM_CONDITIONAL(BUILD_DOC,         test "$build_doc" = "yes")
 AM_CONDITIONAL(BUILD_SYMCRYPTRUN, test "$build_symcryptrun" = "yes")
 AM_CONDITIONAL(BUILD_GPGTAR,      test "$build_gpgtar" = "yes")
 
 AM_CONDITIONAL(RUN_GPG_TESTS,
                test x$cross_compiling = xno -a "$build_gpg" = yes )
 
+# 
+# Set some defines for use gpgconf.
+#
+if test "$build_gpg" = yes ; then
+    AC_DEFINE(BUILD_WITH_GPG,1,[Defined if GPG is to be build])
+fi
+if test "$build_gpgsm" = yes ; then
+    AC_DEFINE(BUILD_WITH_GPGSM,1,[Defined if GPGSM is to be build])
+fi
+if test "$build_agent" = yes ; then
+    AC_DEFINE(BUILD_WITH_AGENT,1,[Defined if GPG-AGENT is to be build])
+fi
+if test "$build_scdaemon" = yes ; then
+    AC_DEFINE(BUILD_WITH_SCDAEMON,1,[Defined if SCDAEMON is to be build])
+fi
+if test "$build_dirmngr" = yes ; then
+    AC_DEFINE(BUILD_WITH_DIRMNGR,1,[Defined if SCDAEMON is to be build])
+fi
+if test "$build_g13" = yes ; then
+    AC_DEFINE(BUILD_WITH_G13,1,[Defined if G13 is to be build])
+fi
+
+
 
 #
 # Print errors here so that they are visible all
 # together and the user can acquire them all together.
 #
 die=no
 if test "$have_gpg_error" = "no"; then
    die=yes
    AC_MSG_NOTICE([[
 ***  
 *** You need libgpg-error to build this program.
 **  This library is for example available at
 ***   ftp://ftp.gnupg.org/gcrypt/libgpg-error
 *** (at least version $NEED_GPG_ERROR_VERSION is required.)
 ***]])
 fi
 if test "$have_libgcrypt" = "no"; then
    die=yes
    AC_MSG_NOTICE([[
 ***  
 *** You need libgcrypt to build this program.
 **  This library is for example available at
 ***   ftp://ftp.gnupg.org/gcrypt/libgcrypt/
 *** (at least version $NEED_LIBGCRYPT_VERSION using API $NEED_LIBGCRYPT_API is required.)
 ***]])
 fi
 if test "$have_libassuan" = "no"; then
    die=yes
    AC_MSG_NOTICE([[
 ***
 *** You need libassuan to build this program.
 *** This library is for example available at
 ***   ftp://ftp.gnupg.org/gcrypt/libassuan/
 *** (at least version $NEED_LIBASSUAN_VERSION (API $NEED_LIBASSUAN_API) is required).
 ***]])
 fi
 if test "$have_ksba" = "no"; then
     AC_MSG_NOTICE([[
 ***
 *** You need libksba to build this program.
 *** This library is for example available at
 ***   ftp://ftp.gnupg.org/gcrypt/libksba/
 *** (at least version $NEED_KSBA_VERSION using API $NEED_KSBA_API is required).
 ***]])
 fi
 if test "$gnupg_have_ldap" = "no"; then
     die=yes
     AC_MSG_NOTICE([[
 ***
 *** You need a LDAP library to build this program.
 *** Check out 
 ***    http://www.openldap.org 
 *** for a suitable implementation.
 ***]])
    if test "$have_w32ce_system" = yes; then
     AC_MSG_NOTICE([[
 *** Note that CeGCC might be broken, a package fixing this is:
 ***    http://files.kolab.org/local/windows-ce/ 
 ***                           source/wldap32_0.1-mingw32ce.orig.tar.gz
 ***                           binary/wldap32-ce-arm-dev_0.1-1_all.deb
 ***]])
    fi
 fi
 if test "$missing_pth" = "yes"; then
     AC_MSG_NOTICE([[
 ***
 *** It is now required to build with support for the
 *** GNU Portable Threads Library (Pth). Please install this
 *** library first.  The library is for example available at
 ***   ftp://ftp.gnu.org/gnu/pth/
 *** On a Debian GNU/Linux system you can install it using 
 ***   apt-get install libpth-dev
 *** To build GnuPG for Windows you need to use the W32PTH
 *** package; available at:
 ***   ftp://ftp.g10code.com/g10code/w32pth/
 ***]])
    die=yes
 fi
 
 if test "$die" = "yes"; then
     AC_MSG_ERROR([[
 ***
 *** Required libraries not found. Please consult the above messages
 *** and install them before running configure again.
 ***]])
 fi
 
 
 
 AC_CONFIG_FILES([ m4/Makefile 
 Makefile
 po/Makefile.in
 gl/Makefile
 include/Makefile
 common/Makefile
 kbx/Makefile
 g10/Makefile
 sm/Makefile
 agent/Makefile
 scd/Makefile
 g13/Makefile
 dirmngr/Makefile
 keyserver/Makefile
 keyserver/gpg2keys_mailto
 keyserver/gpg2keys_test
 tools/gpg-zip
 tools/Makefile
 doc/Makefile
 tests/Makefile
 tests/openpgp/Makefile
 tests/pkits/Makefile
 ])
 AC_OUTPUT
 
 
 echo "
         GnuPG v${VERSION} has been configured as follows:
         
         Platform:  $PRINTABLE_OS_NAME ($host)
 
         OpenPGP:   $build_gpg
         S/MIME:    $build_gpgsm
         Agent:     $build_agent $build_agent_threaded
         Smartcard: $build_scdaemon $build_scdaemon_extra
         G13:       $build_g13
         Dirmngr:   $build_dirmngr
         Gpgtar:    $build_gpgtar
 
         Protect tool:      $show_gnupg_protect_tool_pgm
         LDAP wrapper:      $show_gnupg_dirmngr_ldap_pgm
         Default agent:     $show_gnupg_agent_pgm
         Default pinentry:  $show_gnupg_pinentry_pgm
         Default scdaemon:  $show_gnupg_scdaemon_pgm
         Default dirmngr:   $show_gnupg_dirmngr_pgm
 
         Use standard socket: $use_standard_socket
         Dirmngr auto start:  $dirmngr_auto_start
 "
 if test x"$use_regex" != xyes ; then
 echo "
         Warning: No regular expression support available.
                  OpenPGP trust signatures won't work.
                  gpg-check-pattern will not be build.
 "
 fi
diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog
index 11fd1b7f1..2c208755d 100644
--- a/dirmngr/ChangeLog
+++ b/dirmngr/ChangeLog
@@ -1,1492 +1,1499 @@
 2010-12-14  Werner Koch  <wk@g10code.com>
 
+	* cdb.h (struct cdb) [W32]: Add field CDB_MAPPING.
+	* cdblib.c (cdb_init) [W32]: Save mapping handle.
+	(cdb_free) [W32]: Don't leak the mapping handle from cdb_init by
+	using the saved one.
+
+	* crlcache.c (crl_cache_insert): Close unused matching files.
+
 	* dirmngr.c (main) [W32CE]: Change homedir in daemon mode to /gnupg.
 
 2010-12-07  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (TIMERTICK_INTERVAL) [W32CE]: Change to 60s.
 
 2010-11-23  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dirmngr_LDFLAGS): Add extra_bin_ldflags.
 	(dirmngr_client_LDFLAGS): Ditto.
 
 2010-10-21  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (main): Changed faked system time warning
 
 2010-10-15  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (CLEANFILES): Add no-libgcrypt.c.
 
 2010-09-16  Werner Koch  <wk@g10code.com>
 
 	* validate.c (validate_cert_chain): Use GPG_ERR_MISSING_ISSUER_CERT.
 
 2010-08-13  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dirmngr_SOURCES): Add w32-ldap-help.h.
 
 	* dirmngr_ldap.c (fetch_ldap): Call ldap_unbind.
 
 	* w32-ldap-help.h: New.
 	* dirmngr_ldap.c [W32CE]: Include w32-ldap-help.h and use the
 	mapped ldap functions.
 
 2010-08-12  Werner Koch  <wk@g10code.com>
 
 	* crlcache.c (update_dir, crl_cache_insert): s/unlink/gnupg_remove/.
 
 	* dirmngr.c (dirmngr_sighup_action): New.
 
 	* server.c (cmd_killdirmngr, cmd_reloaddirmngr): New.
 	(struct server_local_s): Add field STOPME.
 	(start_command_handler): Act on STOPME.
 
 2010-08-06  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (JNLIB_NEED_AFLOCAL): Define macro.
 	(main): Use SUN_LEN macro.
 	(main) [W32]: Allow EEXIST in addition to EADDRINUSE.
 
 2010-08-05  Werner Koch  <wk@g10code.com>
 
 	* server.c (set_error, leave_cmd): New.
 	(cmd_validate, cmd_ldapserver, cmd_isvalid, cmd_checkcrl)
 	(cmd_checkocsp, cmd_lookup, cmd_listcrls, cmd_cachecert): Use
 	leave_cmd.
 	(cmd_getinfo): New.
 	(data_line_cookie_write, data_line_cookie_close): New.
 	(cmd_listcrls): Replace assuan_get_data_fp by es_fopencookie.
 
 	* misc.c (create_estream_ksba_reader, my_estream_ksba_reader_cb): New.
 	* certcache.c (load_certs_from_dir): Use create_estream_ksba_reader.
 	* crlcache.c (crl_cache_load): Ditto.
 
 2010-08-03  Werner Koch  <wk@g10code.com>
 
 	* dirmngr_ldap.c (pth_enter, pth_leave) [USE_LDAPWRAPPER]: Turn
 	into functions for use in a 'for' control stmt.
 
 2010-07-26  Werner Koch  <wk@g10code.com>
 
 	* dirmngr_ldap.c (print_ldap_entries): Remove special fwrite case
 	for W32 because that is now handles by estream.
 
 2010-07-25  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dirmngr_SOURCES) [!USE_LDAPWRAPPER]: Build
 	ldap-wrapper-ce.
 	* ldap-wrapper-ce.c: New.
 
 	* dirmngr_ldap.c (opt): Remove global variable ...
 	(my_opt_t): ... and declare a type instead.
 	(main): Define a MY_OPT variable and change all references to OPT
 	to this.
 	(set_timeout, print_ldap_entries, fetch_ldap, process_url): Pass
 	MYOPT arg.
 
 2010-07-24  Werner Koch  <wk@g10code.com>
 
 	* dirmngr_ldap.c (main): Init common subsystems.  Call
 	es_set_binary.
 
 2010-07-19  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c: Include ldap-wrapper.h.
 	(launch_reaper_thread): Move code to ...
 	* ldap-wrapper.c (ldap_wrapper_launch_thread): .. here.  Change
 	callers.
 	(ldap_wrapper_thread): Rename to ...
 	(wrapper_thread): this and make local.
 
 	* ldap.c (destroy_wrapper, print_log_line)
 	(read_log_data, ldap_wrapper_thread)
 	(ldap_wrapper_wait_connections, ldap_wrapper_release_context)
 	(ldap_wrapper_connection_cleanup, reader_callback, ldap_wrapper):
 	Factor code out to ...
 	* ldap-wrapper.c: new.
 	(ldap_wrapper): Make public.
 	(read_buffer): Copy from ldap.c.
 	* ldap-wrapper.h: New.
 	* Makefile.am (dirmngr_SOURCES): Add new files.
 
 2010-07-16  Werner Koch  <wk@g10code.com>
 
 	* http.c, http.h: Remove.
 
 	* dirmngr-err.h: New.
 	* dirmngr.h: Include dirmngr-err.h instead of gpg-error.h
 
 	* cdblib.c: Replace assignments to ERRNO by a call to
 	gpg_err_set_errno.  Include dirmngr-err.h.
 	(cdb_free) [__MINGW32CE__]: Do not use get_osfhandle.
 
 	* dirmngr.c [!HAVE_SIGNAL_H]: Don't include signal.h.
 	(USE_W32_SERVICE): New.  Use this to control the use of the W32
 	service system.
 
 2010-07-06  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (main): Print note on directory name changes.
 
 	Replace almost all uses of stdio by estream.
 
 	* b64dec.c, b64enc.c: Remove.  They are duplicated in ../common/.
 
 2010-06-28  Werner Koch  <wk@g10code.com>
 
 	* dirmngr_ldap.c (my_i18n_init): Remove.
 	(main): Call i18n_init instead of above function.
 
 	* dirmngr-client.c (my_i18n_init): Remove.
 	(main): Call i18n_init instead of above function.
 
 	* Makefile.am (dirmngr_LDADD): Add ../gl/libgnu.
 	(dirmngr_ldap_LDADD, dirmngr_client_LDADD): Ditto.
 
 2010-06-09  Werner Koch  <wk@g10code.com>
 
 	* i18n.h: Remove.
 
 	* Makefile.am (no-libgcrypt.c): New rule.
 
 	* exechelp.h: Remove.
 	* exechelp.c: Remove.
 	(dirmngr_release_process): Change callers to use the gnupg func.
 	(dirmngr_wait_process): Likewise.
 	(dirmngr_kill_process): Likewise.  This actually implements it for
 	W32.
 	* ldap.c (ldap_wrapper): s/get_dirmngr_ldap_path/gnupg_module_name/.
 	(ldap_wrapper_thread): Use gnupg_wait_process and adjust for
 	changed semantics.
 	(ldap_wrapper): Replace xcalloc by xtrycalloc.  Replace spawn
 	mechanism.
 
 	* server.c (start_command_handler): Remove assuan_set_log_stream.
 
 	* validate.c: Remove gcrypt.h and ksba.h.
 
 	* ldapserver.c: s/util.h/dirmngr.h/.
 
 	* dirmngr.c (sleep) [W32]: Remove macro.
 	(main): s/sleep/gnupg_sleep/.
 	(pid_suffix_callback): Change arg type.
 	(my_gcry_logger): Remove.
 	(fixed_gcry_pth_init): New.
 	(main): Use it.
 	(FD2INT): Remove.
 
 2010-06-08  Werner Koch  <wk@g10code.com>
 
 	* misc.h (copy_time): Remove and replace by gnupg_copy_time which
 	allows to set a null date.
 	* misc.c (dump_isotime, get_time, get_isotime, set_time)
 	(check_isotime, add_isotime): Remove and replace all calls by the
 	versions from common/gettime.c.
 
 	* crlcache.c, misc.c, misc.h: s/dirmngr_isotime_t/gnupg_isotime_t/.
 	* server.c, ldap.c: Reorder include directives.
 	* crlcache.h, misc.h: Remove all include directives.
 
 	* certcache.c (cmp_simple_canon_sexp): Remove.
 	(compare_serialno): Rewrite using cmp_simple_canon_sexp from
 	common/sexputil.c
 
 	* error.h: Remove.
 
 	* dirmngr.c: Remove transitional option "--ignore-ocsp-servic-url".
 	(opts): Use ARGPARSE macros.
 	(i18n_init): Remove.
 	(main): Use GnuPG init functions.
 
 	* dirmngr.h: Remove duplicated stuff now taken from ../common.
 
 	* get-path.c, util.h: Remove.
 
 	* Makefile.am: Adjust to GnuPG system.
 	* estream.c, estream.h, estream-printf.c, estream-printf.h: Remove.
 
 2010-06-07  Werner Koch  <wk@g10code.com>
 
 	* OAUTHORS, ONEWS, ChangeLog.1: New.
 
 	* ChangeLog, Makefile.am, b64dec.c, b64enc.c, cdb.h, cdblib.c
 	* certcache.c, certcache.h, crlcache.c, crlcache.h, crlfetch.c
 	* crlfetch.h, dirmngr-client.c, dirmngr.c, dirmngr.h
 	* dirmngr_ldap.c, error.h, estream-printf.c, estream-printf.h
 	* estream.c, estream.h, exechelp.c, exechelp.h, get-path.c, http.c
 	* http.h, i18n.h, ldap-url.c, ldap-url.h, ldap.c, ldapserver.c
 	* ldapserver.h, misc.c, misc.h, ocsp.c, ocsp.h, server.c, util.h
 	* validate.c, validate.h: Imported from the current SVN of the
 	dirmngr package (only src/).
 
 2010-03-13  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (int_and_ptr_u): New.
 	(pid_suffix_callback): Trick out compiler.
 	(start_connection_thread): Ditto.
 	(handle_connections): Ditto.
 
 2010-03-09  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (set_debug): Allow numerical values.
 
 2009-12-15  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c: Add option --ignore-cert-extension.
 	(parse_rereadable_options): Implement.
 	* dirmngr.h (opt): Add IGNORED_CERT_EXTENSIONS.
 	* validate.c (unknown_criticals): Handle ignored extensions.
 
 2009-12-08  Marcus Brinkmann  <marcus@g10code.de>
 
 	* dirmngr-client.c (start_dirmngr): Convert posix FDs to assuan fds.
 
 2009-11-25  Marcus Brinkmann  <marcus@g10code.de>
 
 	* server.c (start_command_handler): Use assuan_fd_t and
 	assuan_fdopen on fds.
 
 2009-11-05  Marcus Brinkmann  <marcus@g10code.de>
 
 	* server.c (start_command_handler): Update use of
 	assuan_init_socket_server.
 	* dirmngr-client.c (start_dirmngr): Update use of
 	assuan_pipe_connect and assuan_socket_connect.
 
 2009-11-04  Werner Koch  <wk@g10code.com>
 
 	* server.c (register_commands): Add help arg to
 	assuan_register_command.  Change all command comments to strings.
 
 2009-11-02  Marcus Brinkmann  <marcus@g10code.de>
 
 	* server.c (reset_notify): Take LINE argument, return gpg_error_t.
 
 2009-10-16  Marcus Brinkmann  <marcus@g10code.com>
 
 	* Makefile.am: (dirmngr_LDADD): Link to $(LIBASSUAN_LIBS) instead
 	of $(LIBASSUAN_PTH_LIBS).
 	* dirmngr.c: Invoke ASSUAN_SYSTEM_PTH_IMPL.
 	(main): Call assuan_set_system_hooks and assuan_sock_init.
 
 2009-09-22  Marcus Brinkmann  <marcus@g10code.de>
 
 	* dirmngr.c (main): Update to new Assuan interface.
 	* server.c (option_handler, cmd_ldapserver, cmd_isvalid)
 	(cmd_checkcrl, cmd_checkocsp, cmd_lookup, cmd_loadcrl)
 	(cmd_listcrls, cmd_cachecert, cmd_validate): Return gpg_error_t
 	instead int.
 	(register_commands): Likewise for member HANDLER.
 	(start_command_handler): Allocate context with assuan_new before
 	starting server.  Release on error.
 	* dirmngr-client.c (main): Update to new Assuan interface.
 	(start_dirmngr): Allocate context with assuan_new before
 	connecting to server.  Release on error.
 
 2009-08-12  Werner Koch  <wk@g10code.com>
 
 	* dirmngr-client.c (squid_loop_body): Flush stdout.  Suggested by
 	Philip Shin.
 
 2009-08-07  Werner Koch  <wk@g10code.com>
 
 	* crlfetch.c (my_es_read): Add explicit check for EOF.
 
 	* http.c (struct http_context_s): Turn IN_DATA and IS_HTTP_0_9 to
 	bit fields.
 	(struct cookie_s): Add CONTENT_LENGTH_VALID and CONTENT_LENGTH.
 	(parse_response): Parse the Content-Length header.
 	(cookie_read): Handle content length.
 	(http_open): Make NEED_HEADER the semi-default.
 
 	* http.h (HTTP_FLAG_IGNORE_CL): New.
 
 2009-08-04  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (ldap_wrapper_thread): Factor some code out to ...
 	(read_log_data): ... new.  Close the log fd on error.
 	(ldap_wrapper_thread): Delay cleanup until the log fd is closed.
 	(SAFE_PTH_CLOSE): New.  Use it instead of pth_close.
 
 2009-07-31  Werner Koch  <wk@g10code.com>
 
 	* server.c (cmd_loadcrl): Add option --url.
 	* dirmngr-client.c (do_loadcrl): Make use of --url.
 
 	* crlfetch.c (crl_fetch): Remove HTTP_FLAG_NO_SHUTDOWN.  Add
 	flag HTTP_FLAG_LOG_RESP with active DBG_LOOKUP.
 
 	* http.c: Require estream.  Remove P_ES macro.
 	(write_server): Remove.
 	(my_read_line): Remove.  Replace all callers by es_read_line.
 	(send_request): Use es_asprintf.  Always store the cookie.
 	(http_wait_response): Remove the need to dup the socket.  USe new
 	shutdown flag.
 	* http.h (HTTP_FLAG_NO_SHUTDOWN): Rename to HTTP_FLAG_SHUTDOWN.
 
 	* estream.c, estream.h, estream-printf.c, estream-printf.h: Update
 	from current libestream.  This is provide es_asprintf.
 
 2009-07-20  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (pid_suffix_callback): New.
 	(main): Use log_set_pid_suffix_cb.
 	(start_connection_thread): Put the fd into the tls.
 
 	* ldap.c (ldap_wrapper_thread): Print ldap worker stati.
 	(ldap_wrapper_release_context): Print a debug info.
 	(end_cert_fetch_ldap): Release the reader.  Might fix bug#999.
 
 2009-06-17  Werner Koch  <wk@g10code.com>
 
 	* util.h: Remove unused dotlock.h.
 
 2009-05-26  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (ldap_wrapper): Show reader object in diagnostics.
 	* crlcache.c (crl_cache_reload_crl): Ditto.  Change debug messages
 	to regular diagnostics.
 	* dirmngr_ldap.c (print_ldap_entries): Add extra diagnostics.
 
 2009-04-03  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.h (struct server_local_s): Move back to ...
 	* server.c (struct server_local_s): ... here.
 	(get_ldapservers_from_ctrl): New.
 	* ldapserver.h (ldapserver_iter_begin): Use it.
 
 2008-10-29  Marcus Brinkmann  <marcus@g10code.de>
 
 	* estream.c (es_getline): Add explicit cast to silence gcc -W
 	warning.
 	* crlcache.c (finish_sig_check): Likewise.
 
 	* dirmngr.c (opts): Add missing initializer to silence gcc
 	-W warning.
 	* server.c (register_commands): Likewise.
 	* dirmngr-client.c (opts): Likewise.
 	* dirmngr_ldap.c (opts): Likewise.
 
 	* dirmngr-client.c (status_cb, inq_cert, data_cb): Change return
 	type to gpg_error_t to silence gcc warning.
 
 2008-10-21  Werner Koch  <wk@g10code.com>
 
 	* certcache.c (load_certs_from_dir): Accept ".der" files.
 
 	* server.c (get_istrusted_from_client): New.
 	* validate.c (validate_cert_chain): Add new optional arg
 	R_TRUST_ANCHOR.  Adjust all callers
 	* crlcache.c (crl_cache_entry_s): Add fields USER_TRUST_REQ
 	and CHECK_TRUST_ANCHOR.
 	(release_one_cache_entry): Release CHECK_TRUST_ANCHOR.
 	(list_one_crl_entry): Print info about the new fields.
 	(open_dir, write_dir_line_crl): Support the new U-flag.
 	(crl_parse_insert): Add arg R_TRUST_ANCHOR and set it accordingly.
 	(crl_cache_insert): Store trust anchor in entry object.
 	(cache_isvalid): Ask client for trust is needed.
 
 	* crlcache.c (open_dir): Replace xcalloc by xtrycalloc.
 	(next_line_from_file): Ditt.  Add arg to return the gpg error.
 	Change all callers.
 	(update_dir): Replace sprintf and malloc by estream_asprintf.
 	(crl_cache_insert): Ditto.
 	(crl_cache_isvalid): Replace xmalloc by xtrymalloc.
 	(get_auth_key_id): Ditto.
 	(crl_cache_insert): Ditto.
 
 	* crlcache.c (start_sig_check): Remove HAVE_GCRY_MD_DEBUG test.
 	* validate.c (check_cert_sig): Ditto.  Remove workaround for bug
 	in libgcrypt 1.2.
 
 	* estream.c, estream.h, estream-printf.c, estream-printf.h: Update
 	from current libestream (svn rev 61).
 
 2008-09-30  Marcus Brinkmann  <marcus@g10code.com>
 
 	* get-path.c (get_dirmngr_ldap_path): Revert last change.
 	Instead, use dirmngr_libexecdir().
 	(find_program_at_standard_place): Don't define for now.
 
 2008-09-30  Marcus Brinkmann  <marcus@g10code.com>
 
 	* get-path.c (dirmngr_cachedir): Make COMP a pointer to const to
 	silence gcc warning.
 	(get_dirmngr_ldap_path): Look for dirmngr_ldap in the installation
 	directory.
 
 2008-08-06  Marcus Brinkmann  <marcus@g10code.com>
 
 	* dirmngr.c (main): Mark the ldapserverlist-file option as
 	read-only.
 
 2008-07-31  Werner Koch  <wk@g10code.com>
 
 	* crlcache.c (start_sig_check) [!HAVE_GCRY_MD_DEBUG]: Use
 	gcry_md_start_debug
 
 2008-06-16  Werner Koch  <wk@g10code.com>
 
 	* get-path.c (w32_commondir): New.
 	(dirmngr_sysconfdir): Use it here.
 	(dirmngr_datadir): Ditto.
 
 2008-06-12  Marcus Brinkmann  <marcus@g10code.de>
 
 	* Makefile.am (dirmngr_SOURCES): Add ldapserver.h and ldapserver.c.
 	* ldapserver.h, ldapserver.c: New files.
 	* ldap.c: Include "ldapserver.h".
 	(url_fetch_ldap): Use iterator to get session servers as well.
 	(attr_fetch_ldap, start_default_fetch_ldap): Likewise.
 	* dirmngr.c: Include "ldapserver.h".
 	(free_ldapservers_list): Removed.  Change callers to
 	ldapserver_list_free.
 	(parse_ldapserver_file): Use ldapserver_parse_one.
 	* server.c: Include "ldapserver.h".
 	(cmd_ldapserver): New command.
 	(register_commands): Add new command LDAPSERVER.
 	(reset_notify): New function.
 	(start_command_handler): Register reset notify handler.
 	Deallocate session server list.
 	(lookup_cert_by_pattern): Use iterator to get session servers as well.
 	(struct server_local_s): Move to ...
 	* dirmngr.h (struct server_local_s): ... here.  Add new member
 	ldapservers.
 
 2008-06-10  Werner Koch  <wk@g10code.com>
 
 	Support PEM encoded CRLs.  Fixes bug#927.
 
 	* crlfetch.c (struct reader_cb_context_s): New.
 	(struct file_reader_map_s): Replace FP by new context.
 	(register_file_reader, get_file_reader): Adjust accordingly.
 	(my_es_read): Detect Base64 encoded CRL and decode if needed.
 	(crl_fetch): Pass new context to the callback.
 	(crl_close_reader): Cleanup the new context.
 	* b64dec.c: New.  Taken from GnuPG.
 	* util.h (struct b64state): Add new fields STOP_SEEN and
 	INVALID_ENCODING.
 
 2008-05-26  Marcus Brinkmann  <marcus@g10code.com>
 
 	* dirmngr.c (main) [HAVE_W32_SYSTEM]: Switch to system
 	configuration on gpgconf related commands, and make all options
 	unchangeable.
 
 2008-03-25  Marcus Brinkmann  <marcus@g10code.de>
 
 	* dirmngr_ldap.c (print_ldap_entries): Add code alternative for
 	W32 console stdout (unused at this point).
 
 2008-03-21  Marcus Brinkmann  <marcus@g10code.de>
 
 	* estream.c (ESTREAM_MUTEX_DESTROY): New macro.
 	(es_create, es_destroy): Use it.
 
 2008-02-21  Werner Koch  <wk@g10code.com>
 
 	* validate.c (check_cert_sig) [HAVE_GCRY_MD_DEBUG]: Use new debug
 	function if available.
 
 	* crlcache.c (abort_sig_check): Mark unused arg.
 
 	* exechelp.c (dirmngr_release_process) [!W32]: Mark unsed arg.
 
 	* validate.c (is_root_cert): New.  Taken from GnuPG.
 	(validate_cert_chain): Use it in place of the simple DN compare.
 
 2008-02-15  Marcus Brinkmann  <marcus@g10code.de>
 
 	* dirmngr.c (main): Reinitialize assuan log stream if necessary.
 
 	* crlcache.c (update_dir) [HAVE_W32_SYSTEM]: Remove destination
 	file before rename.
 	(crl_cache_insert) [HAVE_W32_SYSTEM]: Remove destination file
 	before rename.
 
 2008-02-14  Marcus Brinkmann  <marcus@g10code.de>
 
 	* validate.c (check_cert_policy): Use ksba_free instead of xfree.
 	(validate_cert_chain): Likewise.  Free SUBJECT on error.
 	(cert_usage_p): Likewise.
 
 	* crlcache.c (finish_sig_check): Undo last change.
 	(finish_sig_check): Close md.
 	(abort_sig_check): New function.
 	(crl_parse_insert): Use abort_sig_check to clean up.
 
 	* crlcache.c (crl_cache_insert): Clean up CDB on error.
 
 2008-02-13  Marcus Brinkmann  <marcus@g10code.de>
 
 	* crlcache.c (finish_sig_check): Call gcry_md_stop_debug.
 	* exechelp.h (dirmngr_release_process): New prototype.
 	* exechelp.c (dirmngr_release_process): New function.
 	* ldap.c (ldap_wrapper_thread): Release pid.
 	(destroy_wrapper): Likewise.
 
 	* dirmngr.c (launch_reaper_thread): Destroy tattr.
 	(handle_connections): Likewise.
 
 2008-02-12  Marcus Brinkmann  <marcus@g10code.de>
 
 	* ldap.c (pth_close) [! HAVE_W32_SYSTEM]: New macro.
 	(struct wrapper_context_s): New member log_ev.
 	(destroy_wrapper): Check FDs for != -1 rather than != 0.  Use
 	pth_close instead of close.  Free CTX->log_ev.
 	(ldap_wrapper_thread): Rewritten to use pth_wait instead of
 	select.  Also use pth_read instead of read and pth_close instead
 	of close.
 	(ldap_wrapper): Initialize CTX->log_ev.
 	(reader_callback): Use pth_close instead of close.
 	* exechelp.c (create_inheritable_pipe) [HAVE_W32_SYSTEM]: Removed.
 	(dirmngr_spawn_process) [HAVE_W32_SYSTEM]: Use pth_pipe instead.
 	* dirmngr_ldap.c [HAVE_W32_SYSTEM]: Include <fcntl.h>.
 	(main) [HAVE_W32_SYSTEM]: Set mode of stdout to binary.
 
 2008-02-01  Werner Koch  <wk@g10code.com>
 
 	* ldap.c: Remove all ldap headers as they are unused.
 
 	* dirmngr_ldap.c (LDAP_DEPRECATED): New, to have OpenLDAP use the
 	old standard API.
 
 2008-01-10  Werner Koch  <wk@g10code.com>
 
 	* dirmngr-client.c: New option --local.
 	(do_lookup): Use it.
 
 	* server.c (lookup_cert_by_pattern): Implement local lookup.
 	(return_one_cert): New.
 	* certcache.c (hexsn_to_sexp): New.
 	(classify_pattern, get_certs_bypattern): New.
 
 	* misc.c (unhexify): Allow passing NULL for RESULT.
 	(cert_log_subject): Do not call ksba_free on an unused variable.
 
 2008-01-02  Marcus Brinkmann  <marcus@g10code.de>
 
 	* Makefile.am (dirmngr_LDADD, dirmngr_ldap_LDADD)
 	(dirmngr_client_LDADD): Add $(LIBICONV).  Reported by Michael
 	Nottebrock.
 
 2007-12-11  Werner Koch  <wk@g10code.com>
 
 	* server.c (option_handler): New option audit-events.
 	* dirmngr.h (struct server_control_s): Add member AUDIT_EVENTS.
 
 2007-11-26  Marcus Brinkmann  <marcus@g10code.de>
 
 	* get-path.c (dirmngr_cachedir): Create intermediate directories.
 	(default_socket_name): Use CSIDL_WINDOWS.
 
 2007-11-21  Werner Koch  <wk@g10code.com>
 
 	* server.c (lookup_cert_by_pattern): Add args SINGLE and CACHE_ONLY.
 	(cmd_lookup): Add options --single and --cache-only.
 
 2007-11-16  Werner Koch  <wk@g10code.com>
 
 	* certcache.c (load_certs_from_dir): Also log the subject DN.
 	* misc.c (cert_log_subject): New.
 
 2007-11-14  Werner Koch  <wk@g10code.com>
 
 	* dirmngr-client.c: Replace --lookup-url by --url.
 	(main): Remove extra code for --lookup-url.
 	(do_lookup): Remove LOOKUP_URL arg and use the
 	global option OPT.URL.
 
 	* server.c (has_leading_option): New.
 	(cmd_lookup): Use it.
 
 	* crlfetch.c (fetch_cert_by_url): Use GPG_ERR_INV_CERT_OBJ.
 	(fetch_cert_by_url): Use gpg_error_from_syserror.
 
 2007-11-14  Moritz  <moritz@gnu.org>  (wk)
 
 	* dirmngr-client.c: New command: --lookup-url <URL>.
 	(do_lookup): New parameter: lookup_url.  If TRUE, include "--url"
 	switch in LOOKUP transaction.
 	(enum): New entry: oLookupUrl.
 	(opts): Likewise.
 	(main): Handle oLookupUrl.  New variable: cmd_lookup_url, set
 	during option parsing, pass to do_lookup() and substitute some
 	occurences of "cmd_lookup" with "cmd_lookup OR cmd_lookup_url".
 	* crlfetch.c (fetch_cert_by_url): New function, uses
 	url_fetch_ldap() to create a reader object and libksba functions
 	to read a single cert from that reader.
 	* server.c (lookup_cert_by_url, lookup_cert_by_pattern): New
 	functions.
 	(cmd_lookup): Moved almost complete code ...
 	(lookup_cert_by_pattern): ... here.
 	(cmd_lookup): Support new optional argument: --url.  Depending on
 	the presence of that switch, call lookup_cert_by_url() or
 	lookup_cert_by_pattern().
 	(lookup_cert_by_url): Heavily stripped down version of
 	lookup_cert_by_pattern(), using fetch_cert_by_url.
 
 2007-10-24  Marcus Brinkmann  <marcus@g10code.de>
 
 	* exechelp.c (dirmngr_spawn_process): Fix child handles.
 
 2007-10-05  Marcus Brinkmann  <marcus@g10code.de>
 
 	* dirmngr.h: Include assuan.h.
 	(start_command_handler): Change type of FD to assuan_fd_t.
 	* dirmngr.c: Do not include w32-afunix.h.
         (socket_nonce): New global variable.
         (create_server_socket): Use assuan socket wrappers.  Remove W32
 	specific stuff.  Save the server nonce.
         (check_nonce): New function.
         (start_connection_thread): Call it.
         (handle_connections): Change args to assuan_fd_t.
 	* server.c (start_command_handler): Change type of FD to assuan_fd_t.
 
 2007-09-12  Marcus Brinkmann  <marcus@g10code.de>
 
 	* dirmngr.c (main): Percent escape pathnames in --gpgconf-list output.
 
 2007-08-27  Moritz Schulte  <moritz@g10code.com>
 
 	* src/Makefile.am (AM_CPPFLAGS): Define DIRMNGR_SOCKETDIR based on
 	$(localstatedir).
 	* src/get-path.c (default_socket_name): Use DIRMNGR_SOCKETDIR
 	instead of hard-coded "/var/run/dirmngr".
 
 2007-08-16  Werner Koch  <wk@g10code.com>
 
 	* get-path.c (get_dirmngr_ldap_path): Make PATHNAME const.
 
 	* dirmngr.c (my_ksba_hash_buffer): Mark unused arg.
 	(dirmngr_init_default_ctrl): Ditto.
 	(my_gcry_logger): Ditto.
 	* dirmngr-client.c (status_cb): Ditto.
 	* dirmngr_ldap.c (catch_alarm): Ditto.
 	* estream-printf.c (pr_bytes_so_far): Ditto.
 	* estream.c (es_func_fd_create): Ditto.
 	(es_func_fp_create): Ditto.
 	(es_write_hexstring): Ditto.
 	* server.c (cmd_listcrls): Ditto.
 	(cmd_cachecert): Ditto.
 	* crlcache.c (cache_isvalid): Ditto.
 	* ocsp.c (do_ocsp_request): Ditto.
 	* ldap.c (ldap_wrapper_thread): Ditto.
 	* http.c (http_register_tls_callback): Ditto.
 	(connect_server): Ditto.
 	(write_server) [!HTTP_USE_ESTREAM]: Don't build.
 
 2007-08-14  Werner Koch  <wk@g10code.com>
 
 	* get-path.c (dirmngr_cachedir) [W32]: Use CSIDL_LOCAL_APPDATA.
 
 2007-08-13  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (handle_connections): Use a timeout in the accept
 	function.  Block signals while creating a new thread.
 	(shutdown_pending): Needs to be volatile as also accessed bt the
 	service function.
 	(w32_service_control): Do not use the regular log fucntions here.
 	(handle_tick): New.
 	(main): With system_service in effect use aDaemon as default
 	command.
 	(main) [W32]: Only temporary redefine main for the sake of Emacs's
 	"C-x 4 a".
 
 	* dirmngr-client.c (main) [W32]: Initialize sockets.
 	(start_dirmngr): Use default_socket_name instead of a constant.
 	* Makefile.am (dirmngr_client_SOURCES): Add get-path.c
 
 2007-08-09  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (parse_ocsp_signer): New.
 	(parse_rereadable_options): Set opt.ocsp_signer to this.
 	* dirmngr.h (fingerprint_list_t): New.
 	* ocsp.c (ocsp_isvalid, check_signature, validate_responder_cert):
 	Allow for several default ocscp signers.
 	(ocsp_isvalid): Return GPG_ERR_NO_DATA for an unknwon status.
 
 	* dirmngr-client.c: New option --force-default-responder.
 
 	* server.c (has_option, skip_options): New.
 	(cmd_checkocsp): Add option --force-default-responder.
 	(cmd_isvalid): Ditto.  Also add option --only-ocsp.
 
 	* ocsp.c (ocsp_isvalid): New arg FORCE_DEFAULT_RESPONDER.
 
 	* dirmngr.c: New option --ocsp-max-period.
 	* ocsp.c (ocsp_isvalid): Implement it and take care that a missing
 	next_update is to be ignored.
 
 	* crlfetch.c (my_es_read): New.  Use it instead of es_read.
 
 	* estream.h, estream.c, estream-printf.c: Updated from current
 	libestream SVN.
 
 2007-08-08  Werner Koch  <wk@g10code.com>
 
 	* crlcache.c (crl_parse_insert): Hack to allow for a missing
 	nextUpdate.
 
 	* dirmngr_ldap.c (print_ldap_entries): Strip the extension from
 	the want_attr.
 
 	* exechelp.c (dirmngr_wait_process): Reworked for clear error
 	semantics.
 	* ldap.c (ldap_wrapper_thread): Adjust for new
 	dirmngr_wait_process semantics.
 
 2007-08-07  Werner Koch  <wk@g10code.com>
 
 	* get-path.c (default_socket_name) [!W32]: Fixed syntax error.
 
 	* ldap.c (X509CACERT, make_url, fetch_next_cert_ldap): Support
 	x509caCert as used by the Bundesnetzagentur.
 	(ldap_wrapper): Do not pass the prgtram name as the first
 	argument.  dirmngr_spawn_process takes care of that.
 
 2007-08-04  Marcus Brinkmann  <marcus@g10code.de>
 
 	* dirmngr.h (opt): Add member system_service.
 	* dirmngr.c (opts) [HAVE_W32_SYSTEM]: New entry for option
 	--service.
 	(DEFAULT_SOCKET_NAME): Removed.
 	(service_handle, service_status,
 	w32_service_control) [HAVE_W32_SYSTEM]: New symbols.
 	(main) [HAVE_W32_SYSTEM]: New entry point for --service.  Rename
 	old function to ...
 	(real_main) [HAVE_W32_SYSTEM]: ... this.  Use default_socket_name
 	instead of DEFAULT_SOCKET_NAME, and similar for other paths.
 	Allow colons in Windows socket path name, and implement --service
 	option.
 	* util.h (dirmngr_sysconfdir, dirmngr_libexecdir, dirmngr_datadir,
 	dirmngr_cachedir, default_socket_name): New prototypes.
 	* get-path.c (dirmngr_sysconfdir, dirmngr_libexecdir)
 	(dirmngr_datadir, dirmngr_cachedir, default_socket_name): New
 	functions.
 	(DIRSEP_C, DIRSEP_S): New macros.
 
 2007-08-03  Marcus Brinkmann  <marcus@g10code.de>
 
 	* get-path.c: Really add the file this time.
 
 2007-07-31  Marcus Brinkmann  <marcus@g10code.de>
 
 	* crlfetch.c: Include "estream.h".
 	(crl_fetch): Use es_read callback instead a file handle.
 	(crl_close_reader): Use es_fclose instead of fclose.
 	(struct file_reader_map_s): Change type of FP to estream_t.
 	(register_file_reader, crl_fetch, crl_close_reader): Likewise.
 	* ocsp.c: Include "estream.h".
 	(read_response): Change type of FP to estream_t.
 	(read_response, do_ocsp_request): Use es_* variants of I/O
 	functions.
 
 	* http.c: Include <pth.h>.
 	(http_wait_response) [HAVE_W32_SYSTEM]: Use DuplicateHandle.
 	(cookie_read): Use pth_read instead read.
 	(cookie_write): Use pth_write instead write.
 
 2007-07-30  Marcus Brinkmann  <marcus@g10code.de>
 
 	* ldap-url.c (ldap_str2charray): Fix buglet in ldap_utf8_strchr
 	invocation.
 
 2007-07-27  Marcus Brinkmann  <marcus@g10code.de>
 
 	* estream.h, estream.c: Update from recent GnuPG.
 
 	* get-path.c: New file.
 	* Makefile.am (dirmngr_SOURCES): Add get-path.c.
 	* util.h (default_homedir, get_dirmngr_ldap_path): New prototypes.
 	* dirmngr.c (main): Use default_homedir().
 	* ldap-url.h: Remove japanese white space (sorry!).
 
 2007-07-26  Marcus Brinkmann  <marcus@g10code.de>
 
 	* ldap.c (pth_yield): Remove macro.
 
 	* ldap.c (pth_yield) [HAVE_W32_SYSTEM]: Define to Sleep(0).
 
 	* dirmngr_ldap.c [HAVE_W32_SYSTEM]: Do not include <ldap.h>, but
 	<winsock2.h>, <winldap.h> and "ldap-url.h".
 	* ldap.c [HAVE_W32_SYSTEM]: Do not include <ldap.h>, but
 	<winsock2.h> and <winldap.h>.
 
 	* ldap-url.c: Do not include <ldap.h>, but <winsock2.h>,
 	<winldap.h> and "ldap-url.h".
 	(LDAP_P): New macro.
 	* ldap-url.h: New file.
 	* Makefile.am (ldap_url): Add ldap-url.h.
 
 	* Makefile.am (ldap_url): New variable.
 	(dirmngr_ldap_SOURCES): Add $(ldap_url).
 	(dirmngr_ldap_LDADD): Add $(LIBOBJS).
 	* ldap-url.c: New file, excerpted from OpenLDAP.
 	* dirmngr.c (main) [HAVE_W32_SYSTEM]: Avoid the daemonization.
 	* dirmngr_ldap.c: Include "util.h".
 	(main) [HAVE_W32_SYSTEM]: Don't set up alarm.
 	(set_timeout) [HAVE_W32_SYSTEM]: Likewise.
 	* ldap.c [HAVE_W32_SYSTEM]: Add macros for setenv and pth_yield.
 	* no-libgcrypt.h (NO_LIBGCRYPT): Define.
 	* util.h [NO_LIBGCRYPT]: Don't include <gcrypt.h>.
 
 2007-07-23  Marcus Brinkmann  <marcus@g10code.de>
 
 	* Makefile.am (dirmngr_SOURCES): Add exechelp.h and exechelp.c.
 	* exechelp.h, exechelp.c: New files.
 	* ldap.c: Don't include <sys/wait.h> but "exechelp.h".
 	(destroy_wrapper, ldap_wrapper_thread,
 	ldap_wrapper_connection_cleanup): Use dirmngr_kill_process instead
 	of kill.
 	(ldap_wrapper_thread): Use dirmngr_wait_process instead of
 	waitpid.
 	(ldap_wrapper): Use dirmngr_spawn_process.
 
 2007-07-20  Marcus Brinkmann  <marcus@g10code.de>
 
 	* certcache.c (cert_cache_lock): Do not initialize statically.
 	(init_cache_lock): New function.
 	(cert_cache_init): Call init_cache_lock.
 
 	* estream.h, estream.c, estream-printf.h, estream-printf.c: New
 	files.
 	* Makefile.am (dirmngr_SOURCES): Add estream.c, estream.h,
 	estream-printf.c, estream-printf.h.
 
 	* http.c: Update to latest version from GnuPG.
 
 	* Makefile.am (cdb_sources)
 	* cdblib.c: Port to windows (backport from tinycdb 0.76).
 
 	* crlcache.c [HAVE_W32_SYSTEM]: Don't include sys/utsname.h.
 	[MKDIR_TAKES_ONE_ARG]: Define mkdir as a macro for such systems.
 	(update_dir, crl_cache_insert) [HAVE_W32_SYSTEM]: Don't get uname.
 	* server.c (start_command_handler) [HAVE_W32_SYSTEM]: Don't log
 	peer credentials.
 
 	* dirmngr.c [HAVE_W32_SYSTEM]: Do not include sys/socket.h or
 	sys/un.h, but ../jnlib/w32-afunix.h.
 	(sleep) [HAVE_W32_SYSTEM]: New macro.
 	(main) [HAVE_W32_SYSTEM]: Don't mess with SIGPIPE.  Use W32 socket
 	API.
 	(handle_signal) [HAVE_W32_SYSTEM]: Deactivate the bunch of the
 	code.
 	(handle_connections) [HAVE_W32_SYSTEM]: don't handle signals.
 
 2006-11-29  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (my_strusage): Use macro for the bug report address
 	and the copyright line.
 	* dirmngr-client.c (my_strusage): Ditto.
 	* dirmngr_ldap.c (my_strusage): Ditto.
 
 	* Makefile.am: Do not link against LIBICONV.
 
 2006-11-19  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c: Include i18n.h.
 
 2006-11-17  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dirmngr_LDADD): Use LIBASSUAN_PTH_LIBS.
 
 2006-11-16  Werner Koch  <wk@g10code.com>
 
 	* server.c (start_command_handler): Replaced
 	assuan_init_connected_socket_server by assuan_init_socket_server_ext.
 
 	* crlcache.c (update_dir): Put a diagnostic into DIR.txt.
 	(open_dir): Detect invalid and duplicate entries.
 	(update_dir): Fixed search for second field.
 
 2006-10-23  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (main): New command --gpgconf-test.
 
 2006-09-14  Werner Koch  <wk@g10code.com>
 
 	* server.c (start_command_handler): In vebose mode print
 	information about the peer.  This may later be used to restrict
 	certain commands.
 
 2006-09-12  Werner Koch  <wk@g10code.com>
 
 	* server.c (start_command_handler): Print a more informative hello
 	line.
 	* dirmngr.c: Moved config_filename into the opt struct.
 
 2006-09-11  Werner Koch  <wk@g10code.com>
 
 	Changed everything to use Assuan with gpg-error codes.
 	* maperror.c: Removed.
 	* server.c (map_to_assuan_status): Removed.
 	* dirmngr.c (main): Set assuan error source.
 	* dirmngr-client.c (main): Ditto.
 
 2006-09-04  Werner Koch  <wk@g10code.com>
 
 	* crlfetch.c (crl_fetch): Implement HTTP redirection.
 	* ocsp.c (do_ocsp_request): Ditto.
 
 	New HTTP code version taken from gnupg svn release 4236.
 	* http.c (http_get_header): New.
 	(capitalize_header_name, store_header): New.
 	(parse_response): Store headers away.
 	(send_request): Return GPG_ERR_NOT_FOUND if connect_server failed.
 	* http.h: New flag HTTP_FLAG_NEED_HEADER.
 
 2006-09-01  Werner Koch  <wk@g10code.com>
 
 	* crlfetch.c (register_file_reader, get_file_reader): New.
 	(crl_fetch): Register the file pointer for HTTP.
 	(crl_close_reader): And release it.
 
 	* http.c, http.h: Updated from GnuPG SVN trunk.  Changed all users
 	to adopt the new API.
 	* dirmngr.h: Moved inclusion of jnlib header to ...
 	* util.h: .. here.  This is required becuase http.c includes only
 	a file util.h but makes use of log_foo. Include gcrypt.h so that
 	gcry_malloc et al are declared.
 
 2006-08-31  Werner Koch  <wk@g10code.com>
 
 	* ocsp.c (check_signature): Make use of the responder id.
 
 2006-08-30  Werner Koch  <wk@g10code.com>
 
 	* validate.c (check_cert_sig): Workaround for rimemd160.
 	(allowed_ca): Always allow trusted CAs.
 
 	* dirmngr.h (cert_ref_t): New.
 	(struct server_control_s): Add field OCSP_CERTS.
 	* server.c (start_command_handler): Release new field
 	* ocsp.c (release_ctrl_ocsp_certs): New.
 	(check_signature): Store certificates in OCSP_CERTS.
 
 	* certcache.c (find_issuing_cert): Reset error if cert was found
 	by subject.
 	(put_cert): Add new arg FPR_BUFFER.  Changed callers.
 	(cache_cert_silent): New.
 
 	* dirmngr.c (parse_rereadable_options): New options
 	--ocsp-max-clock-skew and --ocsp-current-period.
 	* ocsp.c (ocsp_isvalid): Use them here.
 
 	* ocsp.c (validate_responder_cert): New optional arg signer_cert.
 	(check_signature_core): Ditto.
 	(check_signature): Use the default signer certificate here.
 
 2006-06-27  Werner Koch  <wk@g10code.com>
 
 	* dirmngr-client.c (inq_cert): Take care of SENDCERT_SKI.
 
 2006-06-26  Werner Koch  <wk@g10code.com>
 
 	* crlcache.c (lock_db_file): Count open files when needed.
 	(find_entry): Fixed deleted case.
 
 2006-06-23  Werner Koch  <wk@g10code.com>
 
 	* misc.c (cert_log_name): New.
 
 	* certcache.c (load_certs_from_dir): Also print certificate name.
 	(find_cert_bysn): Release ISSDN.
 
 	* validate.h: New VALIDATE_MODE_CERT.
 	* server.c (cmd_validate): Use it here so that no policy checks
 	are done.  Try to validated a cached copy of the target.
 
 	* validate.c (validate_cert_chain): Implement a validation cache.
 	(check_revocations): Print more diagnostics.  Actually use the
 	loop variable and not the head of the list.
 	(validate_cert_chain): Do not check revocations of CRL issuer
 	certificates in plain CRL check mode.
 	* ocsp.c (ocsp_isvalid): Make sure it is reset for a status of
 	revoked.
 
 2006-06-22  Werner Koch  <wk@g10code.com>
 
 	* validate.c (cert_use_crl_p): New.
 	(cert_usage_p): Add a mode 6 for CRL signing.
 	(validate_cert_chain): Check that the certificate may be used for
 	CRL signing.  Print a note when not running as system daemon.
 	(validate_cert_chain): Reduce the maximum depth from 50 to 10.
 
 	* certcache.c (find_cert_bysn): Minor restructuring
 	(find_cert_bysubject): Ditto.  Use get_cert_local when called
 	without KEYID.
 	* crlcache.c (get_crlissuer_cert_bysn): Removed.
 	(get_crlissuer_cert): Removed.
 	(crl_parse_insert): Use find_cert_bysubject and find_cert_bysn
 	instead of the removed functions.
 
 2006-06-19  Werner Koch  <wk@g10code.com>
 
 	* certcache.c (compare_serialno): Silly me. Using 0 as true is
 	that hard; tsss. Fixed call cases except for the only working one
 	which are both numbers of the same length.
 
 2006-05-15  Werner Koch  <wk@g10code.com>
 
 	* crlfetch.c (crl_fetch): Use no-shutdown flag for HTTP.  This
 	seems to be required for "IBM_HTTP_Server/2.0.47.1 Apache/2.0.47
 	(Unix)".
 
 	* http.c (parse_tuple): Set flag to to indicate no value.
 	(build_rel_path): Take care of it.
 
 	* crlcache.c (crl_cache_reload_crl): Also iterate over all names
 	within a DP.
 
 2005-09-28  Marcus Brinkmann  <marcus@g10code.de>
 
 	* Makefile.am (dirmngr_LDADD): Add @LIBINTL@ and @LIBICONV@.
 	(dirmngr_ldap_LDADD): Likewise.
 	(dirmngr_client_LDADD): Likewise.
 
 2005-09-12  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c: Fixed description to match the one in gpgconf.
 
 2005-06-15  Werner Koch  <wk@g10code.com>
 
 	* server.c (cmd_lookup): Take care of NO_DATA which might get
 	returned also by start_cert_fetch().
 
 2005-04-20  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (ldap_wrapper_wait_connections): Set a shutdown flag.
 	(ldap_wrapper_thread): Handle shutdown in a special way.
 
 2005-04-19  Werner Koch  <wk@g10code.com>
 
 	* server.c (get_cert_local, get_issuing_cert_local)
 	(get_cert_local_ski): Bail out if called without a local context.
 
 2005-04-18  Werner Koch  <wk@g10code.com>
 
 	* certcache.c (find_issuing_cert): Fixed last resort method which
 	should be finding by subject and not by issuer. Try to locate it
 	also using the keyIdentifier method.  Improve error reporting.
 	(cmp_simple_canon_sexp): New.
 	(find_cert_bysubject): New.
 	(find_cert_bysn): Ask back to the caller before trying an extarnl
 	lookup.
 	* server.c (get_cert_local_ski): New.
 	* crlcache.c (crl_parse_insert): Also try to locate issuer
 	certificate using the keyIdentifier.  Improved error reporting.
 
 2005-04-14  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (start_cert_fetch_ldap): Really return ERR.
 
 2005-03-17  Werner Koch  <wk@g10code.com>
 
 	* http.c (parse_response): Changed MAXLEN and LEN to size_t to
 	match the requirement of read_line.
 	* http.h (http_context_s): Ditto for BUFFER_SIZE.
 
 2005-03-15  Werner Koch  <wk@g10code.com>
 
 	* ldap.c: Included time.h.  Reported by Bernhard Herzog.
 
 2005-03-09  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c: Add a note to the help listing check the man page for
 	other options.
 
 2005-02-01  Werner Koch  <wk@g10code.com>
 
 	* crlcache.c (crl_parse_insert): Renamed a few variables and
 	changed diagnostic strings for clarity.
 	(get_issuer_cert): Renamed to get_crlissuer_cert. Try to locate
 	the certificate from the cache using the subject name.  Use new
 	fetch function.
 	(get_crlissuer_cert_bysn): New.
 	(crl_parse_insert): Use it here.
 	* crlfetch.c (ca_cert_fetch): Changed interface.
 	(fetch_next_ksba_cert): New.
 	* ldap.c (run_ldap_wrapper): Add arg MULTI_MODE.  Changed all
 	callers.
 	(start_default_fetch_ldap): New
 	* certcache.c (get_cert_bysubject): New.
 	(clean_cache_slot, put_cert): Store the subject DN if available.
 	(MAX_EXTRA_CACHED_CERTS): Increase limit of cachable certificates
 	to 1000.
 	(find_cert_bysn): Loop until a certificate with a matching S/N has
 	been found.
 
 	* dirmngr.c (main): Add honor-http-proxy to the gpgconf list.
 
 2005-01-31  Werner Koch  <wk@g10code.com>
 
 	* ldap.c: Started to work on support for userSMIMECertificates.
 
 	* dirmngr.c (main): Make sure to always pass a server control
 	structure to the caching functions.  Reported by Neil Dunbar.
 
 2005-01-05  Werner Koch  <wk@g10code.com>
 
 	* dirmngr-client.c (read_pem_certificate): Skip trailing percent
 	escaped linefeeds.
 
 2005-01-03  Werner Koch  <wk@g10code.com>
 
 	* dirmngr-client.c (read_pem_certificate): New.
 	(read_certificate): Divert to it depending on pem option.
 	(squid_loop_body): New.
 	(main): New options --pem and --squid-mode.
 
 2004-12-17  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (launch_ripper_thread): Renamed to launch_reaper_thread.
 	(shutdown_reaper): New.  Use it for --server and --daemon.
 	* ldap.c (ldap_wrapper_wait_connections): New.
 
 2004-12-17  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dirmngr_ldap_LDADD): Adjusted for new LDAP checks.
 
 2004-12-16  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (ldap_wrapper): Peek on the output to detect empty output
 	early.
 
 2004-12-15  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (ldap_wrapper): Print a diagnostic after forking for the
 	ldap wrapper.
 	* certcache.h (find_cert_bysn): Add this prototype.
 	* crlcache.c (start_sig_check): Write CRL hash debug file.
 	(finish_sig_check): Dump the signer's certificate.
 	(crl_parse_insert): Try to get the issuing cert by authKeyId.
 	Moved certificate retrieval after item processing.
 
 2004-12-13  Werner Koch  <wk@g10code.com>
 
 	* dirmngr_ldap.c (catch_alarm, set_timeout): new.
 	(main): Install alarm handler. Add new option --only-search-timeout.
 	(print_ldap_entries, fetch_ldap): Use set_timeout ();
 	* dirmngr.h: Make LDAPTIMEOUT a simple unsigned int.  Change all
 	initializations.
 	* ldap.c (start_cert_fetch_ldap, run_ldap_wrapper): Pass timeout
 	option to the wrapper.
 	(INACTIVITY_TIMEOUT): Depend on LDAPTIMEOUT.
 	(run_ldap_wrapper): Add arg IGNORE_TIMEOUT.
 	(ldap_wrapper_thread): Check for special timeout exit code.
 
 	* dirmngr.c: Workaround a typo in gpgconf for
 	ignore-ocsp-service-url.
 
 2004-12-10  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (url_fetch_ldap): Use TMP and not a HOST which is always
 	NULL.
 	* misc.c (host_and_port_from_url): Fixed bad encoding detection.
 
 2004-12-03  Werner Koch  <wk@g10code.com>
 
 	* crlcache.c (crl_cache_load): Re-implement it.
 
 	* dirmngr-client.c: New command --load-crl
 	(do_loadcrl): New.
 
 	* dirmngr.c (parse_rereadable_options, main): Make --allow-ocsp,
 	--ocsp-responder, --ocsp-signer and --max-replies re-readable.
 
 	* ocsp.c (check_signature): try to get the cert from the cache
 	first.
 	(ocsp_isvalid): Print the next and this update times on time
 	conflict.
 
 	* certcache.c (load_certs_from_dir): Print the fingerprint for
 	trusted certificates.
 	(get_cert_byhexfpr): New.
 	* misc.c (get_fingerprint_hexstring_colon): New.
 
 2004-12-01  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dirmngr_LDADD): Don't use LDAP_LIBS.
 
 	* validate.c (validate_cert_chain): Fixed test; as written in the
 	comment we want to do this only in daemon mode.  For clarity
 	reworked by using a linked list of certificates and include root
 	and tragte certificate.
 	(check_revocations): Likewise.  Introduced a recursion sentinel.
 
 2004-11-30  Werner Koch  <wk@g10code.com>
 
 	* crlfetch.c (ca_cert_fetch, crl_fetch_default): Do not use the
 	binary prefix as this will be handled in the driver.
 
 	* dirmngr_ldap.c: New option --log-with-pid.
 	(fetch_ldap): Handle LDAP_NO_SUCH_OBJECT.
 	* ldap.c (run_ldap_wrapper, start_cert_fetch_ldap): Use new log
 	option.
 
 
 2004-11-25  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (dirmngr_ldap_CFLAGS): Added GPG_ERROR_CFLAGS.
 	Noted by Bernhard Herzog.
 
 2004-11-24  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (ldap_wrapper): Fixed default name of the ldap wrapper.
 
 	* b64enc.c (b64enc_start, b64enc_finish): Use standard strdup/free
 	to manage memory.
 
 	* dirmngr.c: New options --ignore-http-dp, --ignore-ldap-dp and
 	--ignore-ocsp-service-url.
 	* crlcache.c (crl_cache_reload_crl): Implement them.
 	* ocsp.c (ocsp_isvalid): Ditto.
 
 2004-11-23  Werner Koch  <wk@g10code.com>
 
 	* ldap.c (ldap_wrapper_thread, reader_callback, ldap_wrapper):
 	Keep a timestamp and terminate the wrapper after some time of
 	inactivity.
 
 	* dirmngr-client.c (do_lookup): New.
 	(main): New option --lookup.
 	(data_cb): New.
 	* b64enc.c: New. Taken from GnuPG 1.9.
 	* no-libgcrypt.c (gcry_strdup): Added.
 
 	* ocsp.c (ocsp_isvalid): New arg CERT and lookup the issuer
 	certificate using the standard methods.
 
 	* server.c (cmd_lookup): Truncation is now also an indication for
 	error.
 	(cmd_checkocsp): Implemented.
 
 	* dirmngr_ldap.c (fetch_ldap): Write an error marker for a
 	truncated search.
 	* ldap.c (add_server_to_servers): Reactivated.
 	(url_fetch_ldap): Call it here and try all configured servers in
 	case of a a failed lookup.
 	(fetch_next_cert_ldap): Detect the truncation error flag.
 	* misc.c (host_and_port_from_url, remove_percent_escapes): New.
 
 2004-11-22  Werner Koch  <wk@g10code.com>
 
 	* dirmngr_ldap.c (main): New option --proxy.
 	* ocsp.c (do_ocsp_request): Take care of opt.disable_http.
 	* crlfetch.c (crl_fetch): Honor the --honor-http-proxy variable.
 	(crl_fetch): Take care of  opt.disable_http and disable_ldap.
 	(crl_fetch_default, ca_cert_fetch, start_cert_fetch):
 	* ldap.c (run_ldap_wrapper): New arg PROXY.
 	(url_fetch_ldap, attr_fetch_ldap, start_cert_fetch_ldap): Pass it.
 
 	* http.c (http_open_document): Add arg PROXY.
 	(http_open): Ditto.
 	(send_request): Ditto and implement it as an override.
 
 	* ocsp.c (validate_responder_cert): Use validate_cert_chain.
 
 	* Makefile.am (AM_CPPFLAGS): Add macros for a few system
 	directories.
 	* dirmngr.h (opt): New members homedir_data, homedir_cache,
 	ldap_wrapper_program, system_daemon, honor_http_proxy, http_proxy,
 	ldap_proxy, only_ldap_proxy, disable_ldap, disable_http.
 	* dirmngr.c (main): Initialize new opt members HOMEDIR_DATA and
 	HOMEDIR_CACHE.
 	(parse_rereadable_options): New options --ldap-wrapper-program,
 	--http-wrapper-program, --disable-ldap, --disable-http,
 	--honor-http-proxy, --http-proxy, --ldap-proxy, --only-ldap-proxy.
 	(reread_configuration): New.
 
 	* ldap.c (ldap_wrapper): Use the correct name for the wrapper.
 
 	* crlcache.c (DBDIR_D): Make it depend on opt.SYSTEM_DAEMON.
 	(cleanup_cache_dir, open_dir, update_dir, make_db_file_name)
 	(crl_cache_insert, create_directory_if_needed): Use opt.HOMEDIR_CACHE
 
 	* validate.c (check_revocations): New.
 	* crlcache.c (crl_cache_isvalid): Factored most code out to
 	(cache_isvalid): .. new.
 	(crl_cache_cert_isvalid): New.
 	* server.c (cmd_checkcrl): Cleaned up by using this new function.
 	(reload_crl): Moved to ..
 	* crlcache.c (crl_cache_reload_crl): .. here and made global.
 
 	* certcache.c (cert_compute_fpr): Renamed from computer_fpr and
 	made global.
 	(find_cert_bysn): Try to lookup missing certs.
 	(cert_cache_init): Intialize using opt.HOMEDIR_DATA.
 
 
 2004-11-19  Werner Koch  <wk@g10code.com>
 
 	* dirmngr-client.c (status_cb): New.  Use it in very verbose mode.
 
 	* server.c (start_command_handler): Malloc the control structure
 	and properly release it.  Removed the primary_connection
 	hack. Cleanup running wrappers.
 	(dirmngr_status): Return an error code.
 	(dirmngr_tick): Return an error code and detect a
 	cancellation. Use wall time and not CPU time.
 	* validate.c (validate_cert_chain): Add CTRL arg and changed callers.
 	* crlcache.c (crl_cache_isvalid):
 	* crlfetch.c (ca_cert_fetch, start_cert_fetch, crl_fetch_default)
 	(crl_fetch): Ditto.
 	* ldap.c (ldap_wrapper, run_ldap_wrapper, url_fetch_ldap)
 	(attr_fetch_ldap, start_cert_fetch_ldap): Ditto.
 	(ldap_wrapper_release_context): Reset the stored CTRL.
 	(reader_callback): Periodically call dirmngr_tick.
 	(ldap_wrapper_release_context): Print an error message for read
 	errors.
 	(ldap_wrapper_connection_cleanup): New.
 
 2004-11-18  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (main): Do not cd / if not running detached.
 
 	* dirmngr-client.c: New options --cache-cert and --validate.
 	(do_cache, do_validate): New.
 	* server.c (cmd_cachecert, cmd_validate): New.
 
 	* crlcache.c (get_issuer_cert): Make use of the certificate cache.
 	(crl_parse_insert): Validate the issuer certificate.
 
 	* dirmngr.c (handle_signal): Reinitialize the certificate cache on
 	a HUP.
 	(struct opts): Add --homedir to enable the already implemented code.
 	(handle_signal): Print stats on SIGUSR1.
 
 	* certcache.c (clean_cache_slot, cert_cache_init)
 	(cert_cache_deinit): New.
 	(acquire_cache_read_lock, acquire_cache_write_lock)
 	(release_cache_lock): New.  Use them where needed.
 	(put_cert): Renamed from put_loaded_cert.
 	(cache_cert): New.
 	(cert_cache_print_stats): New.
 	(compare_serialno): Fixed.
 
 2004-11-16  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (AM_CPPFLAGS): Define DIRMNGR_SYSCONFDIR and
 	DIRMNGR_LIBEXECDIR.
 
 	* misc.c (dump_isotime, dump_string, dump_cert): New.  Taken from
 	gnupg 1.9.
 	(dump_serial): New.
 
 2004-11-15  Werner Koch  <wk@g10code.com>
 
 	* validate.c: New. Based on gnupg's certchain.c
 
 	* ldap.c (get_cert_ldap): Removed.
 	(read_buffer): New.
 	(start_cert_fetch_ldap, fetch_next_cert_ldap)
 	(end_cert_fetch_ldap): Rewritten to make use of the ldap wrapper.
 
 2004-11-12  Werner Koch  <wk@g10code.com>
 
 	* http.c (insert_escapes): Print the percent sign too.
 
 	* dirmngr-client.c (inq_cert): Ignore "SENDCERT" and
 	"SENDISSUERCERT".
 
 	* server.c (do_get_cert_local): Limit the length of a retruned
 	certificate.  Return NULL without an error if an empry value has
 	been received.
 
 	* crlfetch.c (ca_cert_fetch): Use the ksba_reader_object.
 	(setup_funopen, fun_reader, fun_closer): Removed.
 
 	* crlcache.c (get_issuer_cert): Adjust accordingly.
 
 	* ldap.c (attr_fetch_ldap_internal, attr_fetch_fun_closer)
 	(attr_fetch_fun_reader, url_fetch_ldap_internal)
 	(get_attr_from_result_ldap): Removed.
 	(destroy_wrapper, print_log_line, ldap_wrapper_thread)
 	(ldap_wrapper_release_context, reader_callback, ldap_wrapper)
 	(run_ldap_wrapper): New.
 	(url_fetch_ldap): Make use of the new ldap wrapper and return a
 	ksba reader object instead of a stdio stream.
 	(attr_fetch_ldap): Ditto.
 	(make_url, escape4url): New.
 
 2004-11-11  Werner Koch  <wk@g10code.com>
 
 	* dirmngr.c (launch_ripper_thread): New.
 	(main): Start it wheere appropriate.  Always ignore SIGPIPE.
 	(start_connection_thread): Maintain a connection count.
 	(handle_signal, handle_connections): Use it here instead of the
 	thread count.
 
 	* crlcache.c (crl_cache_insert): Changed to use ksba reader
 	object.  Changed all callers to pass this argument.
 
 2004-11-08  Werner Koch  <wk@g10code.com>
 
 	* dirmngr_ldap.c: New.
 
 	* crlcache.c (crl_cache_init): Don't return a cache object but
 	keep it module local.  We only need one.
 	(crl_cache_deinit): Don't take cache object but work on existing
 	one.
 	(get_current_cache): New.
 	(crl_cache_insert, crl_cache_list, crl_cache_load): Use the global
 	cache object and removed the cache arg.  Changed all callers.
 
 	* dirmngr-client.c: New option --ping.
 
 	* dirmngr.c (main): New option --daemon. Initialize PTH.
 	(handle_connections, start_connection_thread): New.
 	(handle_signal): New.
 	(parse_rereadable_options): New. Changed main to make use of it.
 	(set_debug): Don't bail out on invalid debug levels.
 	(main): Init the crl_chache for server and daemon mode.
 
 	* server.c (start_command_handler): New arg FD.  Changed callers.
 
 2004-11-06  Werner Koch  <wk@g10code.com>
 
 	* server.c (map_assuan_err): Factored out to ..
 	* maperror.c: .. new file.
 	* util.h: Add prototype
 
 2004-11-05  Werner Koch  <wk@g10code.com>
 
 	* no-libgcrypt.c: New, used as helper for dirmngr-client which
 	does not need libgcrypt proper but jnlib references the memory
 	functions.  Taken from gnupg 1.9.12.
 
 	* dirmngr.h: Factored i18n and xmalloc code out to ..
 	* i18n.h, util.h: .. New.
 
 	* dirmngr-client.c: New.  Some code taken from gnupg 1.9.12.
 	* Makefile.am (bin_PROGRAMS) Add dirmngr-client.
 
 2004-11-04  Werner Koch  <wk@g10code.com>
 
 	* src/server.c (get_fingerprint_from_line, cmd_checkcrl)
 	(cmd_checkocsp): New.
 	(register_commands): Register new commands.
 	(inquire_cert_and_load_crl): Factored most code out to ..
 	(reload_crl): .. new function.
 	* src/certcache.h, src/certcache.c: New.
 	* src/Makefile.am (dirmngr_SOURCES): Add new files.
 
 2004-11-04  Werner Koch  <wk@g10code.com>
 
 	Please note that earlier entries are found in the top level
 	ChangeLog.
 	[Update after merge with GnuPG: see ./ChangeLog.1]
 
 
  Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
  modifications, as long as this notice is preserved.
 
  This file is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/dirmngr/cdb.h b/dirmngr/cdb.h
index 73cc9952e..0c0d2702a 100644
--- a/dirmngr/cdb.h
+++ b/dirmngr/cdb.h
@@ -1,91 +1,94 @@
 /* $Id: cdb.h 106 2003-12-12 17:36:49Z werner $
  * public cdb include file
  *
  * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
  * Public domain.
  *
  * Taken from tinycdb-0.73. By Werner Koch <wk@gnupg.org> 2003-12-12.
  */
 
 #ifndef TINYCDB_VERSION
 #define TINYCDB_VERSION 0.73
 
 typedef unsigned int cdbi_t; /*XXX should be at least 32 bits long */
 
 /* common routines */
 cdbi_t cdb_hash(const void *buf, cdbi_t len);
 cdbi_t cdb_unpack(const unsigned char buf[4]);
 void cdb_pack(cdbi_t num, unsigned char buf[4]);
 
 struct cdb {
   int cdb_fd;			/* file descriptor */
   /* private members */
+#ifdef HAVE_W32_SYSTEM
+  void *cdb_mapping;            /* Mapping handle.  */
+#endif
   cdbi_t cdb_fsize;		/* datafile size */
   const unsigned char *cdb_mem; /* mmap'ed file memory */
   cdbi_t cdb_vpos, cdb_vlen;	/* found data */
   cdbi_t cdb_kpos, cdb_klen;    /* found key (only set if cdb_findinit
                                    was called with KEY set to NULL). */
 };
 
 #define cdb_datapos(c) ((c)->cdb_vpos)
 #define cdb_datalen(c) ((c)->cdb_vlen)
 #define cdb_keypos(c) ((c)->cdb_kpos)
 #define cdb_keylen(c) ((c)->cdb_klen)
 #define cdb_fileno(c) ((c)->cdb_fd)
 
 int cdb_init(struct cdb *cdbp, int fd);
 void cdb_free(struct cdb *cdbp);
 
 int cdb_read(const struct cdb *cdbp,
 	     void *buf, unsigned len, cdbi_t pos);
 int cdb_find(struct cdb *cdbp, const void *key, unsigned klen);
 
 struct cdb_find {
   struct cdb *cdb_cdbp;
   cdbi_t cdb_hval;
   const unsigned char *cdb_htp, *cdb_htab, *cdb_htend;
   cdbi_t cdb_httodo;
   const void *cdb_key;
   cdbi_t cdb_klen;
 };
 
 int cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
 		 const void *key, cdbi_t klen);
 int cdb_findnext(struct cdb_find *cdbfp);
 
 /* old simple interface */
 /* open file using standard routine, then: */
 int cdb_seek(int fd, const void *key, unsigned klen, cdbi_t *dlenp);
 int cdb_bread(int fd, void *buf, int len);
 
 /* cdb_make */
 
 struct cdb_make {
   int cdb_fd;			/* file descriptor */
   /* private */
   cdbi_t cdb_dpos;		/* data position so far */
   cdbi_t cdb_rcnt;		/* record count so far */
   char cdb_buf[4096];		/* write buffer */
   char *cdb_bpos;		/* current buf position */
   struct cdb_rl *cdb_rec[256];	/* list of arrays of record infos */
 };
 
 
 
 int cdb_make_start(struct cdb_make *cdbmp, int fd);
 int cdb_make_add(struct cdb_make *cdbmp,
 		 const void *key, cdbi_t klen,
 		 const void *val, cdbi_t vlen);
 int cdb_make_exists(struct cdb_make *cdbmp,
 		    const void *key, cdbi_t klen);
 int cdb_make_put(struct cdb_make *cdbmp,
 		 const void *key, cdbi_t klen,
 		 const void *val, cdbi_t vlen,
 		 int flag);
 #define CDB_PUT_ADD	0	/* add unconditionnaly, like cdb_make_add() */
 #define CDB_PUT_REPLACE	1	/* replace: do not place to index OLD record */
 #define CDB_PUT_INSERT	2	/* add only if not already exists */
 #define CDB_PUT_WARN	3	/* add unconditionally but ret. 1 if exists */
 int cdb_make_finish(struct cdb_make *cdbmp);
 
 #endif /* include guard */
diff --git a/dirmngr/cdblib.c b/dirmngr/cdblib.c
index 16d53aed8..3bfeffc11 100644
--- a/dirmngr/cdblib.c
+++ b/dirmngr/cdblib.c
@@ -1,935 +1,928 @@
 /* cdblib.c - all CDB library functions.
  *
  * This file is a part of tinycdb package by Michael Tokarev, mjt@corpit.ru.
  * Public domain.
  *
  * Taken from tinycdb-0.73 and merged into one file for easier
  * inclusion into Dirmngr.  By Werner Koch <wk@gnupg.org> 2003-12-12.
  */
 
 /* A cdb database is a single file used to map `keys' to `values',
    having records of (key,value) pairs.  File consists of 3 parts: toc
    (table of contents), data and index (hash tables).
 
    Toc has fixed length of 2048 bytes, containing 256 pointers to hash
    tables inside index sections.  Every pointer consists of position
    of a hash table in bytes from the beginning of a file, and a size
    of a hash table in entries, both are 4-bytes (32 bits) unsigned
    integers in little-endian form.  Hash table length may have zero
    length, meaning that corresponding hash table is empty.
 
    Right after toc section, data section follows without any
    alingment.  It consists of series of records, each is a key length,
    value (data) length, key and value.  Again, key and value length
    are 4-byte unsigned integers.  Each next record follows previous
    without any special alignment.
 
    After data section, index (hash tables) section follows.  It should
    be looked to in conjunction with toc section, where each of max 256
    hash tables are defined.  Index section consists of series of hash
    tables, with starting position and length defined in toc section.
    Every hash table is a sequence of records each holds two numbers:
    key's hash value and record position inside data section (bytes
    from the beginning of a file to first byte of key length starting
    data record).  If record position is zero, then this is an empty
    hash table slot, pointed to nowhere.
 
    CDB hash function is
      hv = ((hv << 5) + hv) ^ c
    for every single c byte of a key, starting with hv = 5381.
 
    Toc section indexed by (hv % 256), i.e. hash value modulo 256
    (number of entries in toc section).
 
    In order to find a record, one should: first, compute the hash
    value (hv) of a key.  Second, look to hash table number hv modulo
    256.  If it is empty, then there is no such key exists.  If it is
    not empty, then third, loop by slots inside that hash table,
    starting from slot with number hv divided by 256 modulo length of
    that table, or ((hv / 256) % htlen), searching for this hv in hash
    table.  Stop search on empty slot (if record position is zero) or
    when all slots was probed (note cyclic search, jumping from end to
    beginning of a table).  When hash value in question is found in
    hash table, look to key of corresponding record, comparing it with
    key in question.  If them of the same length and equals to each
    other, then record is found, overwise, repeat with next hash table
    slot.  Note that there may be several records with the same key.
 */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 #include <stdlib.h> 
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
 #ifdef _WIN32
 # include <windows.h>
 #else
 # include <sys/mman.h>
 # ifndef MAP_FAILED
 #  define MAP_FAILED ((void*)-1)
 # endif
 #endif
 #include <sys/stat.h>
 
 #include "dirmngr-err.h"
 #include "cdb.h"
 
 #ifndef EPROTO
 # define EPROTO EINVAL
 #endif
 #ifndef SEEK_SET
 # define SEEK_SET 0
 #endif
 
 
 struct cdb_rec {
   cdbi_t hval;
   cdbi_t rpos;
 };
   
 struct cdb_rl {
   struct cdb_rl *next;
   cdbi_t cnt;
   struct cdb_rec rec[254];
 };
 
 static int make_find(struct cdb_make *cdbmp,
 		   const void *key, cdbi_t klen, cdbi_t hval,
 		   struct cdb_rl **rlp);
 static int make_write(struct cdb_make *cdbmp,
 		    const char *ptr, cdbi_t len);
 
 
 
 /* Initializes structure given by CDBP pointer and associates it with
    the open file descriptor FD.  Allocate memory for the structure
    itself if needed and file open operation should be done by
    application.  File FD should be opened at least read-only, and
    should be seekable.  Routine returns 0 on success or negative value
    on error. */
 int
 cdb_init(struct cdb *cdbp, int fd)
 {
   struct stat st;
   unsigned char *mem;
   unsigned fsize;
 #ifdef _WIN32
   HANDLE hFile, hMapping;
 #endif
 
   /* get file size */
   if (fstat(fd, &st) < 0)
     return -1;
   /* trivial sanity check: at least toc should be here */
   if (st.st_size < 2048) {
     gpg_err_set_errno (EPROTO);
     return -1;
   }
   fsize = (unsigned)(st.st_size & 0xffffffffu);
   /* memory-map file */
 #ifdef _WIN32
 # ifdef __MINGW32CE__
   hFile = fd;
 # else
   hFile = (HANDLE) _get_osfhandle(fd);
-#endif
+# endif
   if (hFile == (HANDLE) -1)
     return -1;
   hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
   if (!hMapping)
     return -1;
   mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
   if (!mem)
     return -1;
+  cdbp->cdb_mapping = hMapping;
 #else
   mem = (unsigned char*)mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
   if (mem == MAP_FAILED)
     return -1;
 #endif /* _WIN32 */
 
   cdbp->cdb_fd = fd;
   cdbp->cdb_fsize = st.st_size;
   cdbp->cdb_mem = mem;
 
 #if 0
   /* XXX don't know well about madvise syscall -- is it legal
      to set different options for parts of one mmap() region?
      There is also posix_madvise() exist, with POSIX_MADV_RANDOM etc...
   */
 #ifdef MADV_RANDOM
   /* set madvise() parameters. Ignore errors for now if system
      doesn't support it */
   madvise(mem, 2048, MADV_WILLNEED);
   madvise(mem + 2048, cdbp->cdb_fsize - 2048, MADV_RANDOM);
 #endif
 #endif
 
   cdbp->cdb_vpos = cdbp->cdb_vlen = 0;
 
   return 0;
 }
 
 
 /* Frees the internal resources held by structure.  Note that this
    routine does not close the file. */
 void
 cdb_free(struct cdb *cdbp)
 {
   if (cdbp->cdb_mem) {
 #ifdef _WIN32
-    HANDLE hFile, hMapping;
-#endif
-#ifdef _WIN32
-#ifdef __MINGW32CE__
-    hFile = cdbp->cdb_fd;
-#else
-    hFile = (HANDLE) _get_osfhandle(cdbp->cdb_fd);
-#endif
-    hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
-    UnmapViewOfFile((void*) cdbp->cdb_mem);
-    CloseHandle(hMapping);
+    UnmapViewOfFile ((void*) cdbp->cdb_mem);
+    CloseHandle (cdbp->cdb_mapping);
+    cdbp->cdb_mapping = NULL;
 #else
     munmap((void*)cdbp->cdb_mem, cdbp->cdb_fsize);
 #endif /* _WIN32 */
     cdbp->cdb_mem = NULL;
   }
   cdbp->cdb_fsize = 0;
 }
 
 
 /* Read data from cdb file, starting at position pos of length len,
    placing result to buf.  This routine may be used to get actual
    value found by cdb_find() or other routines that returns position
    and length of a data.  Returns 0 on success or negative value on
    error. */
 int
 cdb_read(const struct cdb *cdbp, void *buf, unsigned len, cdbi_t pos)
 {
   if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
     gpg_err_set_errno (EPROTO);
     return -1;
   }
   memcpy(buf, cdbp->cdb_mem + pos, len);
   return 0;
 }
 
 
 /* Attempts to find a key given by (key,klen) parameters.  If key
    exists in database, routine returns 1 and places position and
    length of value associated with this key to internal fields inside
    cdbp structure, to be accessible by cdb_datapos() and
    cdb_datalen().  If key is not in database, routines returns 0.  On
    error, negative value is returned.  Note that using cdb_find() it
    is possible to lookup only first record with a given key. */
 int
 cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen)
 {
   const unsigned char *htp;	/* hash table pointer */
   const unsigned char *htab;	/* hash table */
   const unsigned char *htend;	/* end of hash table */
   cdbi_t httodo;		/* ht bytes left to look */
   cdbi_t pos, n;
 
   cdbi_t hval;
 
   if (klen > cdbp->cdb_fsize)	/* if key size is larger than file */
     return 0;
 
   hval = cdb_hash(key, klen);
 
   /* find (pos,n) hash table to use */
   /* first 2048 bytes (toc) are always available */
   /* (hval % 256) * 8 */
   htp = cdbp->cdb_mem + ((hval << 3) & 2047); /* index in toc (256x8) */
   n = cdb_unpack(htp + 4);	/* table size */
   if (!n)			/* empty table */
     return 0;			/* not found */
   httodo = n << 3;		/* bytes of htab to lookup */
   pos = cdb_unpack(htp);	/* htab position */
   if (n > (cdbp->cdb_fsize >> 3) /* overflow of httodo ? */
       || pos > cdbp->cdb_fsize /* htab start within file ? */
       || httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */
   {
     gpg_err_set_errno (EPROTO);
     return -1;
   }
 
   htab = cdbp->cdb_mem + pos;	/* htab pointer */
   htend = htab + httodo;	/* after end of htab */
   /* htab starting position: rest of hval modulo htsize, 8bytes per elt */
   htp = htab + (((hval >> 8) % n) << 3);
 
   for(;;) {
     pos = cdb_unpack(htp + 4);	/* record position */
     if (!pos)
       return 0;
     if (cdb_unpack(htp) == hval) {
       if (pos > cdbp->cdb_fsize - 8) { /* key+val lengths */
 	gpg_err_set_errno (EPROTO);
 	return -1;
       }
       if (cdb_unpack(cdbp->cdb_mem + pos) == klen) {
 	if (cdbp->cdb_fsize - klen < pos + 8) {
 	  gpg_err_set_errno (EPROTO);
 	  return -1;
 	}
 	if (memcmp(key, cdbp->cdb_mem + pos + 8, klen) == 0) {
 	  n = cdb_unpack(cdbp->cdb_mem + pos + 4);
 	  pos += 8 + klen;
 	  if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
 	    gpg_err_set_errno (EPROTO);
 	    return -1;
 	  }
 	  cdbp->cdb_vpos = pos;
 	  cdbp->cdb_vlen = n;
 	  return 1;
 	}
       }
     }
     httodo -= 8;
     if (!httodo)
       return 0;
     if ((htp += 8) >= htend)
       htp = htab;
   }
 
 }
 
 
 
 /* Sequential-find routines that used separate structure.  It is
    possible to have many than one record with the same key in a
    database, and these routines allows to enumerate all them.
    cdb_findinit() initializes search structure pointed to by cdbfp.
    It will return negative value on error or 0 on success.  cdb_find�
    next() attempts to find next matching key, setting value position
    and length in cdbfp structure.  It will return positive value if
    given key was found, 0 if there is no more such key(s), or negative
    value on error.  To access value position and length after
    successeful call to cdb_findnext() (when it returned positive
    result), use cdb_datapos() and cdb_datalen() macros with cdbp
    pointer.  It is error to use cdb_findnext() after it returned 0 or
    error condition.  These routines is a bit slower than
    cdb_find(). 
 
    Setting KEY to NULL will start a sequential search through the
    entire DB.
 */
 int
 cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
              const void *key, cdbi_t klen)
 {
   cdbi_t n, pos;
 
   cdbfp->cdb_cdbp = cdbp;
   cdbfp->cdb_key  = key;
   cdbfp->cdb_klen = klen;
   cdbfp->cdb_hval = key? cdb_hash(key, klen) : 0;
 
   if (key)
     {
       cdbfp->cdb_htp = cdbp->cdb_mem + ((cdbfp->cdb_hval << 3) & 2047);
       n = cdb_unpack(cdbfp->cdb_htp + 4);
       cdbfp->cdb_httodo = n << 3; /* Set to size of hash table. */
       if (!n)
         return 0; /* The hash table is empry. */
       pos = cdb_unpack(cdbfp->cdb_htp);
       if (n > (cdbp->cdb_fsize >> 3)
           || pos > cdbp->cdb_fsize
           || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
         {
           gpg_err_set_errno (EPROTO);
           return -1;
         }
 
       cdbfp->cdb_htab = cdbp->cdb_mem + pos;
       cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
       cdbfp->cdb_htp = cdbfp->cdb_htab + (((cdbfp->cdb_hval >> 8) % n) << 3);
     }
   else /* Walk over all entries. */
     {
       cdbfp->cdb_hval = 0; 
       /* Force stepping in findnext. */
       cdbfp->cdb_htp = cdbfp->cdb_htend = cdbp->cdb_mem;
     }
   return 0;
 }
 
 
 /* See cdb_findinit. */
 int 
 cdb_findnext(struct cdb_find *cdbfp)
 {
   cdbi_t pos, n;
   struct cdb *cdbp = cdbfp->cdb_cdbp;
 
   if (cdbfp->cdb_key)
     {
       while(cdbfp->cdb_httodo) {
         pos = cdb_unpack(cdbfp->cdb_htp + 4);
         if (!pos)
           return 0;
         n = cdb_unpack(cdbfp->cdb_htp) == cdbfp->cdb_hval;
         if ((cdbfp->cdb_htp += 8) >= cdbfp->cdb_htend)
           cdbfp->cdb_htp = cdbfp->cdb_htab;
         cdbfp->cdb_httodo -= 8;
         if (n) {
           if (pos > cdbp->cdb_fsize - 8) {
             gpg_err_set_errno (EPROTO);
             return -1;
           }
           if (cdb_unpack(cdbp->cdb_mem + pos) == cdbfp->cdb_klen) {
             if (cdbp->cdb_fsize - cdbfp->cdb_klen < pos + 8) {
               gpg_err_set_errno (EPROTO);
               return -1;
             }
             if (memcmp(cdbfp->cdb_key,
                        cdbp->cdb_mem + pos + 8, cdbfp->cdb_klen) == 0) {
               n = cdb_unpack(cdbp->cdb_mem + pos + 4);
               pos += 8 + cdbfp->cdb_klen;
               if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
                 gpg_err_set_errno (EPROTO);
                 return -1;
               }
               cdbp->cdb_vpos = pos;
               cdbp->cdb_vlen = n;
               return 1;
             }
           }
         }
       }
     }
   else /* Walk over all entries. */
     {
       do
         {
           while (cdbfp->cdb_htp >= cdbfp->cdb_htend)
             {
               if (cdbfp->cdb_hval > 255)
                 return 0; /* No more items. */
               
               cdbfp->cdb_htp = cdbp->cdb_mem + cdbfp->cdb_hval * 8;
               cdbfp->cdb_hval++; /* Advance for next round. */
               pos = cdb_unpack (cdbfp->cdb_htp);     /* Offset of table. */
               n   = cdb_unpack (cdbfp->cdb_htp + 4); /* Number of entries. */
               cdbfp->cdb_httodo = n * 8;             /* Size of table. */
               if (n > (cdbp->cdb_fsize / 8)
                   || pos > cdbp->cdb_fsize
                   || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
                 {
                   gpg_err_set_errno (EPROTO);
                   return -1;
                 }
               
               cdbfp->cdb_htab  = cdbp->cdb_mem + pos;
               cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
               cdbfp->cdb_htp   = cdbfp->cdb_htab;
             }
           
           pos = cdb_unpack (cdbfp->cdb_htp + 4); /* Offset of record. */
           cdbfp->cdb_htp += 8;
         } 
       while (!pos);
       if (pos > cdbp->cdb_fsize - 8)
         {
           gpg_err_set_errno (EPROTO);
           return -1;
         }
       
       cdbp->cdb_kpos = pos + 8;
       cdbp->cdb_klen = cdb_unpack(cdbp->cdb_mem + pos);
       cdbp->cdb_vpos = pos + 8 + cdbp->cdb_klen;
       cdbp->cdb_vlen = cdb_unpack(cdbp->cdb_mem + pos + 4);
       n = 8 + cdbp->cdb_klen + cdbp->cdb_vlen;
       if ( pos > cdbp->cdb_fsize || pos > cdbp->cdb_fsize - n)
         {
           gpg_err_set_errno (EPROTO);
           return -1;
         }
       return 1; /* Found. */
     }
   return 0;
 }
 
 /* Read a chunk from file, ignoring interrupts (EINTR) */
 int
 cdb_bread(int fd, void *buf, int len)
 {
   int l;
   while(len > 0) {
     do l = read(fd, buf, len);
     while(l < 0 && errno == EINTR);
     if (l <= 0) {
       if (!l)
         gpg_err_set_errno (EIO);
       return -1;
     }
     buf = (char*)buf + l;
     len -= l;
   }
   return 0;
 }
 
 /* Find a given key in cdb file, seek a file pointer to it's value and
    place data length to *dlenp. */
 int
 cdb_seek(int fd, const void *key, unsigned klen, cdbi_t *dlenp)
 {
   cdbi_t htstart;		/* hash table start position */
   cdbi_t htsize;		/* number of elements in a hash table */
   cdbi_t httodo;		/* hash table elements left to look */
   cdbi_t hti;			/* hash table index */
   cdbi_t pos;			/* position in a file */
   cdbi_t hval;			/* key's hash value */
   unsigned char rbuf[64];	/* read buffer */
   int needseek = 1;		/* if we should seek to a hash slot */
 
   hval = cdb_hash(key, klen);
   pos = (hval & 0xff) << 3; /* position in TOC */
   /* read the hash table parameters */
   if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
     return -1;
   if ((htsize = cdb_unpack(rbuf + 4)) == 0)
     return 0;
   hti = (hval >> 8) % htsize;	/* start position in hash table */
   httodo = htsize;
   htstart = cdb_unpack(rbuf);
 
   for(;;) {
     if (needseek && lseek(fd, htstart + (hti << 3), SEEK_SET) < 0)
       return -1;
     if (cdb_bread(fd, rbuf, 8) < 0)
       return -1;
     if ((pos = cdb_unpack(rbuf + 4)) == 0) /* not found */
       return 0;
 
     if (cdb_unpack(rbuf) != hval) /* hash value not matched */
       needseek = 0;
     else { /* hash value matched */
       if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
 	return -1;
       if (cdb_unpack(rbuf) == klen) { /* key length matches */
 	/* read the key from file and compare with wanted */
 	cdbi_t l = klen, c;
 	const char *k = (const char*)key;
 	if (*dlenp)
 	  *dlenp = cdb_unpack(rbuf + 4); /* save value length */
 	for(;;) {
 	  if (!l) /* the whole key read and matches, return */
 	    return 1;
 	  c = l > sizeof(rbuf) ? sizeof(rbuf) : l;
 	  if (cdb_bread(fd, rbuf, c) < 0)
 	    return -1;
 	  if (memcmp(rbuf, k, c) != 0) /* no, it differs, stop here */
 	    break;
 	  k += c; l -= c;
 	}
       }
       needseek = 1; /* we're looked to other place, should seek back */
     }
     if (!--httodo)
       return 0;
     if (++hti == htsize) {
       hti = htstart;
       needseek = 1;
     }
   }
 }
 
 cdbi_t
 cdb_unpack(const unsigned char buf[4])
 {
   cdbi_t n = buf[3];
   n <<= 8; n |= buf[2];
   n <<= 8; n |= buf[1];
   n <<= 8; n |= buf[0];
   return n;
 }
 
 /* Add record with key (KEY,KLEN) and value (VAL,VLEN) to a database.
    Returns 0 on success or negative value on error.  Note that this
    routine does not checks if given key already exists, but cdb_find()
    will not see second record with the same key.  It is not possible
    to continue building a database if cdb_make_add() returned an error
    indicator. */
 int
 cdb_make_add(struct cdb_make *cdbmp,
 	     const void *key, cdbi_t klen,
 	     const void *val, cdbi_t vlen)
 {
   unsigned char rlen[8];
   cdbi_t hval;
   struct cdb_rl *rl;
   if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
       vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
     gpg_err_set_errno (ENOMEM);
     return -1;
   }
   hval = cdb_hash(key, klen);
   rl = cdbmp->cdb_rec[hval&255];
   if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
     rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
     if (!rl) {
       gpg_err_set_errno (ENOMEM);
       return -1;
     }
     rl->cnt = 0;
     rl->next = cdbmp->cdb_rec[hval&255];
     cdbmp->cdb_rec[hval&255] = rl;
   }
   rl->rec[rl->cnt].hval = hval;
   rl->rec[rl->cnt].rpos = cdbmp->cdb_dpos;
   ++rl->cnt;
   ++cdbmp->cdb_rcnt;
   cdb_pack(klen, rlen);
   cdb_pack(vlen, rlen + 4);
   if (make_write(cdbmp, rlen, 8) < 0 ||
       make_write(cdbmp, key, klen) < 0 ||
       make_write(cdbmp, val, vlen) < 0)
     return -1;
   return 0;
 }
 
 int
 cdb_make_put(struct cdb_make *cdbmp,
 	     const void *key, cdbi_t klen,
 	     const void *val, cdbi_t vlen,
 	     int flags)
 {
   unsigned char rlen[8];
   cdbi_t hval = cdb_hash(key, klen);
   struct cdb_rl *rl;
   int c, r;
 
   switch(flags) {
     case CDB_PUT_REPLACE:
     case CDB_PUT_INSERT:
     case CDB_PUT_WARN:
       c = make_find(cdbmp, key, klen, hval, &rl);
       if (c < 0)
 	return -1;
       if (c) {
 	if (flags == CDB_PUT_INSERT) {
 	  gpg_err_set_errno (EEXIST);
 	  return 1;
 	}
 	else if (flags == CDB_PUT_REPLACE) {
 	  --c;
 	  r = 1;
 	  break;
 	}
 	else
 	  r = 1;
       }
       /* fall */
 
     case CDB_PUT_ADD:
       rl = cdbmp->cdb_rec[hval&255];
       if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
  	rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
 	if (!rl) {
 	  gpg_err_set_errno (ENOMEM);
 	  return -1;
 	}
 	rl->cnt = 0;
 	rl->next = cdbmp->cdb_rec[hval&255];
 	cdbmp->cdb_rec[hval&255] = rl;
       }
       c = rl->cnt;
       r = 0;
       break;
 
     default:
       gpg_err_set_errno (EINVAL);
       return -1;
   }
 
   if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
       vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
     gpg_err_set_errno (ENOMEM);
     return -1;
   }
   rl->rec[c].hval = hval;
   rl->rec[c].rpos = cdbmp->cdb_dpos;
   if (c == rl->cnt) {
     ++rl->cnt;
     ++cdbmp->cdb_rcnt;
   }
   cdb_pack(klen, rlen);
   cdb_pack(vlen, rlen + 4);
   if (make_write(cdbmp, rlen, 8) < 0 ||
       make_write(cdbmp, key, klen) < 0 ||
       make_write(cdbmp, val, vlen) < 0)
     return -1;
   return r;
 }
 
 
 static int
 match(int fd, cdbi_t pos, const char *key, cdbi_t klen)
 {
   unsigned char buf[64]; /*XXX cdb_buf may be used here instead */
   if (lseek(fd, pos, SEEK_SET) < 0 || read(fd, buf, 8) != 8)
     return -1;
   if (cdb_unpack(buf) != klen)
     return 0;
 
   while(klen > sizeof(buf)) {
     if (read(fd, buf, sizeof(buf)) != sizeof(buf))
       return -1;
     if (memcmp(buf, key, sizeof(buf)) != 0)
       return 0;
     key += sizeof(buf);
     klen -= sizeof(buf);
   }
   if (klen) {
     if (read(fd, buf, klen) != klen)
       return -1;
     if (memcmp(buf, key, klen) != 0)
       return 0;
   }
   return 1;
 }
 
 
 static int
 make_find (struct cdb_make *cdbmp,
            const void *key, cdbi_t klen, cdbi_t hval,
            struct cdb_rl **rlp)
 {
   struct cdb_rl *rl = cdbmp->cdb_rec[hval&255];
   int r, i;
   int seeked = 0;
   while(rl) {
     for(i = rl->cnt - 1; i >= 0; --i) { /* search backward */
       if (rl->rec[i].hval != hval)
 	continue;
       /*XXX this explicit flush may be unnecessary having
        * smarter match() that looks to cdb_buf too, but
        * most of a time here spent in finding hash values
        * (above), not keys */
       if (cdbmp->cdb_bpos != cdbmp->cdb_buf) {
         if (write(cdbmp->cdb_fd, cdbmp->cdb_buf,
 	          cdbmp->cdb_bpos - cdbmp->cdb_buf) < 0)
           return -1;
         cdbmp->cdb_bpos = cdbmp->cdb_buf;
       }
       seeked = 1;
       r = match(cdbmp->cdb_fd, rl->rec[i].rpos, key, klen);
       if (!r)
 	continue;
       if (r < 0)
 	return -1;
       if (lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
         return -1;
       if (rlp)
 	*rlp = rl;
       return i + 1;
     }
     rl = rl->next;
   }
   if (seeked && lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
     return -1;
   return 0;
 }
 
 int
 cdb_make_exists(struct cdb_make *cdbmp,
                 const void *key, cdbi_t klen)
 {
   return make_find(cdbmp, key, klen, cdb_hash(key, klen), NULL);
 }
 
 
 void
 cdb_pack(cdbi_t num, unsigned char buf[4])
 {
   buf[0] = num & 255; num >>= 8;
   buf[1] = num & 255; num >>= 8;
   buf[2] = num & 255;
   buf[3] = num >> 8;
 }
 
 
 /* Initializes structure to create a database.  File FD should be
    opened read-write and should be seekable.  Returns 0 on success or
    negative value on error. */
 int
 cdb_make_start(struct cdb_make *cdbmp, int fd)
 {
   memset (cdbmp, 0, sizeof *cdbmp);
   cdbmp->cdb_fd = fd;
   cdbmp->cdb_dpos = 2048;
   cdbmp->cdb_bpos = cdbmp->cdb_buf + 2048;
   return 0;
 }
 
 
 static int
 ewrite(int fd, const char *buf, int len)
 {
   while(len) {
     int l = write(fd, buf, len);
     if (l < 0 && errno != EINTR)
       return -1;
     if (l > 0)
       {
         len -= l;
         buf += l;
       }
   }
   return 0;
 }
 
 static int
 make_write(struct cdb_make *cdbmp, const char *ptr, cdbi_t len)
 {
   cdbi_t l = sizeof(cdbmp->cdb_buf) - (cdbmp->cdb_bpos - cdbmp->cdb_buf);
   cdbmp->cdb_dpos += len;
   if (len > l) {
     memcpy(cdbmp->cdb_bpos, ptr, l);
     if (ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf, sizeof(cdbmp->cdb_buf)) < 0)
       return -1;
     ptr += l; len -= l;
     l = len / sizeof(cdbmp->cdb_buf);
     if (l) {
       l *= sizeof(cdbmp->cdb_buf);
       if (ewrite(cdbmp->cdb_fd, ptr, l) < 0)
 	return -1;
       ptr += l; len -= l;
     }
     cdbmp->cdb_bpos = cdbmp->cdb_buf;
   }
   if (len) {
     memcpy(cdbmp->cdb_bpos, ptr, len);
     cdbmp->cdb_bpos += len;
   }
   return 0;
 }
 
 static int
 cdb_make_finish_internal(struct cdb_make *cdbmp)
 {
   cdbi_t hcnt[256];		/* hash table counts */
   cdbi_t hpos[256];		/* hash table positions */
   struct cdb_rec *htab;
   unsigned char *p;
   struct cdb_rl *rl;
   cdbi_t hsize;
   unsigned t, i;
 
   if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt) {
     gpg_err_set_errno (ENOMEM);
     return -1;
   }
 
   /* count htab sizes and reorder reclists */
   hsize = 0;
   for (t = 0; t < 256; ++t) {
     struct cdb_rl *rlt = NULL;
     i = 0;
     rl = cdbmp->cdb_rec[t];
     while(rl) {
       struct cdb_rl *rln = rl->next;
       rl->next = rlt;
       rlt = rl;
       i += rl->cnt;
       rl = rln;
     }
     cdbmp->cdb_rec[t] = rlt;
     if (hsize < (hcnt[t] = i << 1))
       hsize = hcnt[t];
   }
 
   /* allocate memory to hold max htable */
   htab = (struct cdb_rec*)malloc((hsize + 2) * sizeof(struct cdb_rec));
   if (!htab) {
     gpg_err_set_errno (ENOENT);
     return -1;
   }
   p = (unsigned char *)htab;
   htab += 2;
 
   /* build hash tables */
   for (t = 0; t < 256; ++t) {
     cdbi_t len, hi;
     hpos[t] = cdbmp->cdb_dpos;
     if ((len = hcnt[t]) == 0)
       continue;
     for (i = 0; i < len; ++i)
       htab[i].hval = htab[i].rpos = 0;
     for (rl = cdbmp->cdb_rec[t]; rl; rl = rl->next)
       for (i = 0; i < rl->cnt; ++i) {
 	hi = (rl->rec[i].hval >> 8) % len;
 	while(htab[hi].rpos)
 	  if (++hi == len)
 	    hi = 0;
 	htab[hi] = rl->rec[i];
       }
     for (i = 0; i < len; ++i) {
       cdb_pack(htab[i].hval, p + (i << 3));
       cdb_pack(htab[i].rpos, p + (i << 3) + 4);
     }
     if (make_write(cdbmp, p, len << 3) < 0) {
       free(p);
       return -1;
     }
   }
   free(p);
   if (cdbmp->cdb_bpos != cdbmp->cdb_buf &&
       ewrite(cdbmp->cdb_fd, cdbmp->cdb_buf,
 	     cdbmp->cdb_bpos - cdbmp->cdb_buf) != 0)
       return -1;
   p = cdbmp->cdb_buf;
   for (t = 0; t < 256; ++t) {
     cdb_pack(hpos[t], p + (t << 3));
     cdb_pack(hcnt[t], p + (t << 3) + 4);
   }
   if (lseek(cdbmp->cdb_fd, 0, 0) != 0 ||
       ewrite(cdbmp->cdb_fd, p, 2048) != 0)
     return -1;
 
   return 0;
 }
 
 static void
 cdb_make_free(struct cdb_make *cdbmp)
 {
   unsigned t;
   for(t = 0; t < 256; ++t) {
     struct cdb_rl *rl = cdbmp->cdb_rec[t];
     while(rl) {
       struct cdb_rl *tm = rl;
       rl = rl->next;
       free(tm);
     }
   }
 }
 
 
 
 /* Finalizes database file, constructing all needed indexes, and frees
    memory structures.  It does not close the file descriptor.  Returns
    0 on success or a negative value on error. */
 int
 cdb_make_finish(struct cdb_make *cdbmp)
 {
   int r = cdb_make_finish_internal(cdbmp);
   cdb_make_free(cdbmp);
   return r;
 }
 
 
 cdbi_t
 cdb_hash(const void *buf, cdbi_t len)
 {
   register const unsigned char *p = (const unsigned char *)buf;
   register const unsigned char *end = p + len;
   register cdbi_t hash = 5381;	/* start value */
   while (p < end)
     hash = (hash + (hash << 5)) ^ *p++;
   return hash;
 }
diff --git a/dirmngr/crlcache.c b/dirmngr/crlcache.c
index 5f0430525..12d451060 100644
--- a/dirmngr/crlcache.c
+++ b/dirmngr/crlcache.c
@@ -1,2551 +1,2576 @@
 /* crlcache.c - LDAP access
  * Copyright (C) 2002 Klarälvdalens Datakonsult AB
  * Copyright (C) 2003, 2004, 2005, 2008 g10 Code GmbH
  *
  * This file is part of DirMngr.
  *
  * DirMngr is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
  * DirMngr is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 /* 
 
    1. To keep track of the CRLs actually cached and to store the meta
       information of the CRLs a simple record oriented text file is
       used.  Fields in the file are colon (':') separated and values
       containing colons or linefeeds are percent escaped (e.g. a colon
       itself is represented as "%3A"). 
 
       The first field is a record type identifier, so that the file is
       useful to keep track of other meta data too.  
 
       The name of the file is "DIR.txt".
 
 
    1.1. Comment record
 
         Field 1: Constant beginning with "#".
 
         Other fields are not defined and such a record is simply
         skipped during processing.
 
    1.2. Version record
 
         Field 1: Constant "v"
         Field 2: Version number of this file.  Must be 1.
 
         This record must be the first non-comment record record and
         there shall only exist one record of this type.
 
    1.3. CRL cache record
 
         Field 1: Constant "c", "u" or "i".
                  A "c" or "u" indicate a valid cache entry, however
                  "u" requires that a user root certificate check needs
                  to be done.
                  An "i" indicates an invalid cache entry which should
                  not be used but still exists so that it can be
                  updated at NEXT_UPDATE. 
         Field 2: Hexadecimal encoded SHA-1 hash of the issuer DN using
                  uppercase letters.
         Field 3: Issuer DN in RFC-2253 notation.
         Field 4: URL used to retrieve the corresponding CRL.
         Field 5: 15 character ISO timestamp with THIS_UPDATE.
         Field 6: 15 character ISO timestamp with NEXT_UPDATE.
         Field 7: Hexadecimal encoded MD-5 hash of the DB file to detect
                  accidental modified (i.e. deleted and created) cache files.
         Field 8: optional CRL number as a hex string.
         Field 9:  AuthorityKeyID.issuer, each Name separated by 0x01
         Field 10: AuthorityKeyID.serial
         Field 11: Hex fingerprint of trust anchor if field 1 is 'u'.
 
    2. Layout of the standard CRL Cache DB file:
 
       We use records of variable length with this structure
 
       n  bytes  Serialnumber (binary) used as key
                 thus there is no need to store the length explicitly with DB2.
       1  byte   Reason for revocation 
                 (currently the KSBA reason flags are used)
       15 bytes  ISO date of revocation (e.g. 19980815T142000)
                 Note that there is no terminating 0 stored.
 
       The filename used is the hexadecimal (using uppercase letters)
       SHA-1 hash value of the issuer DN prefixed with a "crl-" and
       suffixed with a ".db".  Thus the length of the filename is 47.
       
 
 */
 
 #include <config.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <assert.h>
 #include <dirent.h>
 #include <fcntl.h>
 #include <unistd.h>
 #ifndef HAVE_W32_SYSTEM
 #include <sys/utsname.h>
 #endif
 #ifdef MKDIR_TAKES_ONE_ARG
 #undef mkdir
 #define mkdir(a,b) mkdir(a)
 #endif
 
 #include "dirmngr.h"
 #include "validate.h"
 #include "certcache.h"
 #include "crlcache.h"
 #include "crlfetch.h"
 #include "misc.h"
 #include "cdb.h"
 #include "estream-printf.h"
 
 /* Change this whenever the format changes */
 #define DBDIR_D (opt.system_daemon? "crls.d" : "dirmngr-cache.d")
 #define DBDIRFILE "DIR.txt"
 #define DBDIRVERSION 1
 
 /* The number of DB files we may have open at one time.  We need to
    limit this because there is no guarantee that the number of issuers
    has a upper limit.  We are currently using mmap, so it is a good
    idea anyway to limit the number of opened cache files. */
 #define MAX_OPEN_DB_FILES 5
 
 
 static const char oidstr_crlNumber[] = "2.5.29.20";
 static const char oidstr_issuingDistributionPoint[] = "2.5.29.28";
 static const char oidstr_authorityKeyIdentifier[] = "2.5.29.35";
 
 
 /* Definition of one cached item. */
 struct crl_cache_entry_s 
 {
   struct crl_cache_entry_s *next;
   int deleted;        /* True if marked for deletion. */
   int mark;           /* Internally used by update_dir. */
   unsigned int lineno;/* A 0 indicates a new entry. */
   char *release_ptr;  /* The actual allocated memory. */
   char *url;          /* Points into RELEASE_PTR. */
   char *issuer;       /* Ditto. */
   char *issuer_hash;  /* Ditto. */
   char *dbfile_hash;  /* MD5 sum of the cache file, points into RELEASE_PTR.*/
   int invalid;        /* Can't use this CRL. */
   int user_trust_req; /* User supplied root certificate required.  */
   char *check_trust_anchor;  /* Malloced fingerprint.  */
   ksba_isotime_t this_update;
   ksba_isotime_t next_update;
   ksba_isotime_t last_refresh; /* Use for the force_crl_refresh feature. */
   char *crl_number;
   char *authority_issuer;
   char *authority_serialno;
 
   struct cdb *cdb;             /* The cache file handle or NULL if not open. */
 
   unsigned int cdb_use_count;  /* Current use count. */
   unsigned int cdb_lru_count;  /* Used for LRU purposes. */
   int dbfile_checked;          /* Set to true if the dbfile_hash value has
                                   been checked one. */
 };
 
 
 /* Definition of the entire cache object. */
 struct crl_cache_s 
 {
   crl_cache_entry_t entries;
 };
 
 typedef struct crl_cache_s *crl_cache_t;
 
 
 /* Prototypes.  */
 static crl_cache_entry_t find_entry (crl_cache_entry_t first,
                                      const char *issuer_hash);
 
 
 
-/* The currently loaded cache object.  This isi usually initialized
+/* The currently loaded cache object.  This is usually initialized
    right at startup.  */
 static crl_cache_t current_cache;
 
 
 
 
 
 /* Return the current cache object or bail out if it is has not yet
    been initialized.  */
 static crl_cache_t
 get_current_cache (void)
 {
   if (!current_cache)
     log_fatal ("CRL cache has not yet been initialized\n");
   return current_cache;
 }
 
 
 /* 
    Create ae directory if it does not yet exists.  Returns on
    success, or -1 on error.
  */
 static int
 create_directory_if_needed (const char *name)
 {
   DIR *dir;
   char *fname;
 
   fname = make_filename (opt.homedir_cache, name, NULL);
   dir = opendir (fname);
   if (!dir)
     {
       log_info (_("creating directory `%s'\n"), fname);
       if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR) )
         {
           int save_errno = errno;
           log_error (_("error creating directory `%s': %s\n"),
                      fname, strerror (errno));
           xfree (fname);
           gpg_err_set_errno (save_errno);
           return -1;
         }
     } 
   else
     closedir (dir);
   xfree (fname);
   return 0;
 }
 
 /* Remove all files from the cache directory.  If FORCE is not true,
    some sanity checks on the filenames are done. Return 0 if
    everything went fine. */
 static int
 cleanup_cache_dir (int force)
 {
   char *dname = make_filename (opt.homedir_cache, DBDIR_D, NULL);
   DIR *dir;
   struct dirent *de;
   int problem = 0;
 
   if (!force)
     { /* Very minor sanity checks. */
       if (!strcmp (dname, "~/") || !strcmp (dname, "/" ))
         {
           log_error (_("ignoring database dir `%s'\n"), dname);
           xfree (dname);
           return -1;
         }
     }
 
   dir = opendir (dname);
   if (!dir)
     {
       log_error (_("error reading directory `%s': %s\n"),
                  dname, strerror (errno));
       xfree (dname);
       return -1;
     }
 
   while ((de = readdir (dir)))
     {
       if (strcmp (de->d_name, "." ) && strcmp (de->d_name, ".."))
         {
           char *cdbname = make_filename (dname, de->d_name, NULL);
           int okay;
           struct stat sbuf;
      
           if (force)
             okay = 1;
           else
             okay = (!stat (cdbname, &sbuf) && S_ISREG (sbuf.st_mode));
 
           if (okay)
             {
               log_info (_("removing cache file `%s'\n"), cdbname);
               if (gnupg_remove (cdbname))
                 {
                   log_error ("failed to remove `%s': %s\n",
                              cdbname, strerror (errno));
                   problem = -1;
                 }
             }
           else
             log_info (_("not removing file `%s'\n"), cdbname);
           xfree (cdbname);
         }
     }	  
   xfree (dname);
   closedir (dir);
   return problem;
 }
 
 
 /* Read the next line from the file FP and return the line in an
    malloced buffer.  Return NULL on error or EOF.  There is no
    limitation os the line length.  The trailing linefeed has been
    removed, the function will read the last line of a file, even if
    that is not terminated by a LF. */
 static char *
 next_line_from_file (estream_t fp, gpg_error_t *r_err)
 {
   char buf[300];
   char *largebuf = NULL;
   size_t buflen;
   size_t len = 0;
   unsigned char *p;
   int c;
   char *tmpbuf;
 
   *r_err = 0;
   p = buf;
   buflen = sizeof buf - 1;
   while ((c=es_getc (fp)) != EOF && c != '\n')
     {
       if (len >= buflen)
         {
           if (!largebuf)
             {
               buflen += 1024;
               largebuf = xtrymalloc ( buflen + 1 );
               if (!largebuf)
                 {
                   *r_err = gpg_error_from_syserror ();
                   return NULL;
                 }
               memcpy (largebuf, buf, len);
             }
           else
             {
               buflen += 1024;
               tmpbuf = xtryrealloc (largebuf, buflen + 1);
               if (!tmpbuf)
                 {
                   *r_err = gpg_error_from_syserror ();
                   xfree (largebuf);
                   return NULL;
                 }
               largebuf = tmpbuf;
             }
           p = largebuf;
         }
       p[len++] = c;
     }
   if (c == EOF && !len)
     return NULL;
   p[len] = 0;
       
   if (largebuf)
     tmpbuf = xtryrealloc (largebuf, len+1);
   else
     tmpbuf = xtrystrdup (buf);
   if (!tmpbuf)
     {
       *r_err = gpg_error_from_syserror ();
       xfree (largebuf);
     }
   return tmpbuf;
 }
 
 
 /* Release one cache entry.  */
 static void
 release_one_cache_entry (crl_cache_entry_t entry)
 {
   if (entry)
     {
       if (entry->cdb)
         {
           int fd = cdb_fileno (entry->cdb);
           cdb_free (entry->cdb);
           xfree (entry->cdb);
           if (close (fd))
             log_error (_("error closing cache file: %s\n"), strerror(errno));
         }
       xfree (entry->release_ptr);
       xfree (entry->check_trust_anchor);
       xfree (entry);
     }
 }
 
 
 /* Release the CACHE object. */
 static void
 release_cache (crl_cache_t cache)
 {
   crl_cache_entry_t entry, entry2;
 
   if (!cache)
     return;
 
   for (entry = cache->entries; entry; entry = entry2)
     {
       entry2 = entry->next;
       release_one_cache_entry (entry);
-  }
+    }
   cache->entries = NULL;
   xfree (cache);
 }
 
 
 /* Open the dir file FNAME or create a new one if it does not yet
    exist. */
 static estream_t
 open_dir_file (const char *fname)
 {
   estream_t fp;
 
   fp = es_fopen (fname, "r");
   if (!fp)
     {
       log_error (_("failed to open cache dir file `%s': %s\n"),
                  fname, strerror (errno));
 
       /* Make sure that the directory exists, try to create if otherwise. */
       if (create_directory_if_needed (NULL) 
           || create_directory_if_needed (DBDIR_D)) 
         return NULL;
       fp = es_fopen (fname, "w");
       if (!fp)
         {
           log_error (_("error creating new cache dir file `%s': %s\n"),
                      fname, strerror (errno));
           return NULL;
         }
       es_fprintf (fp, "v:%d:\n", DBDIRVERSION);
       if (es_ferror (fp))
         {
           log_error (_("error writing new cache dir file `%s': %s\n"),
                      fname, strerror (errno));
           es_fclose (fp);
           return NULL;
         }
       if (es_fclose (fp))
         {
           log_error (_("error closing new cache dir file `%s': %s\n"),
                      fname, strerror (errno));
           return NULL;
         }
 
       log_info (_("new cache dir file `%s' created\n"), fname);
 
       fp = es_fopen (fname, "r");
       if (!fp)
         {
           log_error (_("failed to re-open cache dir file `%s': %s\n"),
                      fname, strerror (errno));
           return NULL;
         }
     }
 
   return fp;
 }
 
 /* Helper for open_dir. */
 static gpg_error_t
 check_dir_version (estream_t *fpadr, const char *fname,
                          unsigned int *lineno,
                          int cleanup_on_mismatch)
 {
   char *line;
   gpg_error_t lineerr = 0;
   estream_t fp = *fpadr;
   int created = 0;
 
  retry:
   while ((line = next_line_from_file (fp, &lineerr)))
     {
       ++*lineno;
       if (*line == 'v' && line[1] == ':')
         break;
       else if (*line != '#')
         {
           log_error (_("first record of `%s' is not the version\n"), fname);
           xfree (line);
           return gpg_error (GPG_ERR_CONFIGURATION);
         }
       xfree (line);
     }
   if (lineerr)
     return lineerr;
 
   if (strtol (line+2, NULL, 10) != DBDIRVERSION)
     {
       if (!created && cleanup_on_mismatch)
         {
           log_error (_("old version of cache directory - cleaning up\n"));
           es_fclose (fp);
           *fpadr = NULL;
           if (!cleanup_cache_dir (1))
             {
               *lineno = 0;
               fp = *fpadr = open_dir_file (fname);
               if (!fp)
                 {
                   xfree (line);
                   return gpg_error (GPG_ERR_CONFIGURATION);
                 }
               created = 1;
               goto retry;
             }
         }
       log_error (_("old version of cache directory - giving up\n"));
       xfree (line);
       return gpg_error (GPG_ERR_CONFIGURATION);
     }
   xfree (line);
   return 0;
 }
 
 
 /* Open the dir file and read in all available information.  Store
    that in a newly allocated cache object and return that if
    everything worked out fine.  Create the cache directory and the dir
    if it does not yet exist.  Remove all files in that directory if
    the version does not match. */
 static gpg_error_t
 open_dir (crl_cache_t *r_cache)
 {
   crl_cache_t cache;
   char *fname; 
   char *line = NULL;
   gpg_error_t lineerr = 0;
   estream_t fp;
   crl_cache_entry_t entry, *entrytail;
   unsigned int lineno;
   gpg_error_t err = 0;
   int anyerr = 0;
 
   cache = xtrycalloc (1, sizeof *cache); 
   if (!cache)
     return gpg_error_from_syserror ();
 
   fname = make_filename (opt.homedir_cache, DBDIR_D, DBDIRFILE, NULL);
 
   lineno = 0;
   fp = open_dir_file (fname);
   if (!fp)
     {
       err = gpg_error (GPG_ERR_CONFIGURATION);
       goto leave;
     }
 
   err = check_dir_version (&fp, fname, &lineno, 1);
   if (err)
     goto leave;
 
 
   /* Read in all supported entries from the dir file. */
   cache->entries = NULL;
   entrytail = &cache->entries;
   xfree (line);
   while ((line = next_line_from_file (fp, &lineerr)))
     {
       int fieldno;
       char *p, *endp;
 
       lineno++;
       if ( *line == 'c' || *line == 'u' || *line == 'i' )
         {
           entry = xtrycalloc (1, sizeof *entry);
           if (!entry)
             {
               err = gpg_error_from_syserror ();
               goto leave;
             }
           entry->lineno = lineno;
           entry->release_ptr = line;
           if (*line == 'i')
             {
               entry->invalid = atoi (line+1);
               if (entry->invalid < 1)
                 entry->invalid = 1;
             }
           else if (*line == 'u')
             entry->user_trust_req = 1;
 
           for (fieldno=1, p = line; p; p = endp, fieldno++)
             {
               endp = strchr (p, ':');
               if (endp)
                 *endp++ = '\0';
 
               switch (fieldno)
                 {
                 case 1: /* record type */ break;
                 case 2: entry->issuer_hash = p; break;
                 case 3: entry->issuer = unpercent_string (p); break;
                 case 4: entry->url = unpercent_string (p); break;
                 case 5: strncpy (entry->this_update, p, 15); break;
                 case 6: strncpy (entry->next_update, p, 15); break;
                 case 7: entry->dbfile_hash = p; break;
                 case 8: if (*p) entry->crl_number = p; break;
                 case 9: 
                   if (*p)
                     entry->authority_issuer = unpercent_string (p);
                   break;
                 case 10: 
                   if (*p)
                     entry->authority_serialno = unpercent_string (p);
                   break;
                 case 11: 
                   if (*p)
                     entry->check_trust_anchor = xtrystrdup (p);
                   break;
                 default:
                   if (*p)
                     log_info (_("extra field detected in crl record of "
                                 "`%s' line %u\n"), fname, lineno);
                   break;
                 }
             }
 
           if (!entry->issuer_hash)
             {
               log_info (_("invalid line detected in `%s' line %u\n"),
                         fname, lineno);
               xfree (entry);
               entry = NULL;
             }
           else if (find_entry (cache->entries, entry->issuer_hash))
             {
               /* Fixme: The duplicate checking used is not very
                  effective for large numbers of issuers. */
               log_info (_("duplicate entry detected in `%s' line %u\n"),
                         fname, lineno);
               xfree (entry);
               entry = NULL;
             }
           else
             {
               line = NULL; 
               *entrytail = entry;
               entrytail = &entry->next;
             }
         }
       else if (*line == '#')
         ;
       else
         log_info (_("unsupported record type in `%s' line %u skipped\n"),
                   fname, lineno);
 
       if (line)
         xfree (line);
     }
   if (lineerr)
     {
       err = lineerr;
       log_error (_("error reading `%s': %s\n"), fname, gpg_strerror (err));
       goto leave;
     }
   if (es_ferror (fp))
     {
       log_error (_("error reading `%s': %s\n"), fname, strerror (errno));
       err = gpg_error (GPG_ERR_CONFIGURATION);
       goto leave;
     }
 
   /* Now do some basic checks on the data. */
   for (entry = cache->entries; entry; entry = entry->next)
     {
       assert (entry->lineno);
       if (strlen (entry->issuer_hash) != 40)
         {
           anyerr++;
           log_error (_("invalid issuer hash in `%s' line %u\n"),
                      fname, entry->lineno);
         }
       else if ( !*entry->issuer )
         {
           anyerr++;
           log_error (_("no issuer DN in `%s' line %u\n"),
                      fname, entry->lineno);
         }
       else if ( check_isotime (entry->this_update)
                 || check_isotime (entry->next_update))
         {
           anyerr++;
           log_error (_("invalid timestamp in `%s' line %u\n"),
                      fname, entry->lineno);
         }
 
       /* Checks not leading to an immediate fail. */
       if (strlen (entry->dbfile_hash) != 32)
         log_info (_("WARNING: invalid cache file hash in `%s' line %u\n"),
                   fname, entry->lineno); 
     }
      
   if (anyerr)
     {
       log_error (_("detected errors in cache dir file\n"));
       log_info (_("please check the reason and manually delete that file\n"));
       err = gpg_error (GPG_ERR_CONFIGURATION);
     }
 
 
  leave:
   es_fclose (fp);
   xfree (line);
   xfree (fname);
   if (err)
     {
       release_cache (cache);
       cache = NULL;
     }
   *r_cache = cache;
   return err;
 }
 
 static void
 write_percented_string (const char *s, estream_t fp)
 {
   for (; *s; s++)
     if (*s == ':')
       es_fputs ("%3A", fp);
     else if (*s == '\n')
       es_fputs ("%0A", fp);
     else if (*s == '\r')
       es_fputs ("%0D", fp);
     else
       es_putc (*s, fp);
 }
 
 
 static void
 write_dir_line_crl (estream_t fp, crl_cache_entry_t e)
 {
   if (e->invalid)
     es_fprintf (fp, "i%d", e->invalid);
   else if (e->user_trust_req)
     es_putc ('u', fp);
   else
     es_putc ('c', fp);
   es_putc (':', fp);
   es_fputs (e->issuer_hash, fp);
   es_putc (':', fp);
   write_percented_string (e->issuer, fp);
   es_putc (':', fp);
   write_percented_string (e->url, fp);
   es_putc (':', fp);
   es_fwrite (e->this_update, 15, 1, fp); 
   es_putc (':', fp);
   es_fwrite (e->next_update, 15, 1, fp); 
   es_putc (':', fp);
   es_fputs (e->dbfile_hash, fp);
   es_putc (':', fp);
   if (e->crl_number)
     es_fputs (e->crl_number, fp);
   es_putc (':', fp);
   if (e->authority_issuer)
     write_percented_string (e->authority_issuer, fp);
   es_putc (':', fp);
   if (e->authority_serialno)
     es_fputs (e->authority_serialno, fp);
   es_putc (':', fp);
   if (e->check_trust_anchor && e->user_trust_req)
     es_fputs (e->check_trust_anchor, fp);
   es_putc ('\n', fp);
 }
 
 
 /* Update the current dir file using the cache. */
 static gpg_error_t
 update_dir (crl_cache_t cache)
 {
   char *fname = NULL;
   char *tmpfname = NULL;
   char *line = NULL;
   gpg_error_t lineerr = 0;
   estream_t fp;
   estream_t fpout = NULL;
   crl_cache_entry_t e;
   unsigned int lineno;
   gpg_error_t err = 0;
 
   fname = make_filename (opt.homedir_cache, DBDIR_D, DBDIRFILE, NULL);
 
   /* Fixme: Take an update file lock here. */
 
   for (e= cache->entries; e; e = e->next)
     e->mark = 1;
 
   lineno = 0;
   fp = es_fopen (fname, "r");
   if (!fp)
     {
       err = gpg_error_from_errno (errno);
       log_error (_("failed to open cache dir file `%s': %s\n"),
                  fname, strerror (errno));
       goto leave;
     }
   err = check_dir_version (&fp, fname, &lineno, 0);
   if (err)
     goto leave;
   es_rewind (fp);
   lineno = 0;
 
   /* Create a temporary DIR file. */
   {
     char *tmpbuf, *p;
     const char *nodename;
 #ifndef HAVE_W32_SYSTEM
     struct utsname utsbuf;
 #endif
     
 #ifdef HAVE_W32_SYSTEM
     nodename = "unknown";
 #else
     if (uname (&utsbuf))
       nodename = "unknown";
     else
       nodename = utsbuf.nodename;
 #endif
 
     estream_asprintf (&tmpbuf, "DIR-tmp-%s-%u-%p.txt.tmp",
                       nodename, (unsigned int)getpid (), &tmpbuf);
     if (!tmpbuf)
       {
         err = gpg_error_from_errno (errno);
         log_error (_("failed to create temporary cache dir file `%s': %s\n"),
                    tmpfname, strerror (errno));
         goto leave;
       }
     for (p=tmpbuf; *p; p++)
       if (*p == '/')
         *p = '.';
     tmpfname = make_filename (opt.homedir_cache, DBDIR_D, tmpbuf, NULL);
     xfree (tmpbuf);
   }
   fpout = es_fopen (tmpfname, "w");
   if (!fpout)
     {
       err = gpg_error_from_errno (errno);
       log_error (_("failed to create temporary cache dir file `%s': %s\n"),
                  tmpfname, strerror (errno));
       goto leave;
     }
 
   while ((line = next_line_from_file (fp, &lineerr)))
     {
       lineno++;
       if (*line == 'c' || *line == 'u' || *line == 'i')
         {
           /* Extract the issuer hash field. */
           char *fieldp, *endp;
 
           fieldp = strchr (line, ':');
           endp = fieldp? strchr (++fieldp, ':') : NULL;
           if (endp)
             {
               /* There should be no percent within the issuer hash
                  field, thus we can compare it pretty easily. */
               *endp = 0;
               e = find_entry ( cache->entries, fieldp);
               *endp = ':'; /* Restore orginal line. */
               if (e && e->deleted) 
                 {
                   /* Marked for deletion, so don't write it. */
                   e->mark = 0; 
                 }
               else if (e)
                 {
                   /* Yep, this is valid entry we know about; write it out */
                   write_dir_line_crl (fpout, e);
                   e->mark = 0;
                 }
               else
                 { /* We ignore entries we don't have in our cache
                      because they may have been added in the meantime
                      by other instances of dirmngr. */
                   es_fprintf (fpout, "# Next line added by "
                               "another process; our pid is %lu\n", 
                               (unsigned long)getpid ());
                   es_fputs (line, fpout);
                   es_putc ('\n', fpout);
                 }
             }
           else
             {
               es_fputs ("# Invalid line detected: ", fpout);
               es_fputs (line, fpout);
               es_putc ('\n', fpout);
             }
         }
       else 
         {
           /* Write out all non CRL lines as they are. */
           es_fputs (line, fpout);
           es_putc ('\n', fpout);
         }
 
       xfree (line);
     }
   if (!es_ferror (fp) && !es_ferror (fpout) && !lineerr)
     {
       /* Write out the remaining entries. */
       for (e= cache->entries; e; e = e->next)
         if (e->mark)
           {
             if (!e->deleted)
               write_dir_line_crl (fpout, e);
             e->mark = 0;
           }
     }
   if (lineerr)
     {
       err = lineerr;
       log_error (_("error reading `%s': %s\n"), fname, gpg_strerror (err));
       goto leave;
     }
   if (es_ferror (fp))
     {
       err = gpg_error_from_errno (errno);
       log_error (_("error reading `%s': %s\n"), fname, strerror (errno));
     }
   if (es_ferror (fpout))
     {
       err = gpg_error_from_errno (errno);
       log_error (_("error writing `%s': %s\n"), tmpfname, strerror (errno));
     }
   if (err)
     goto leave;
 
   /* Rename the files. */
   es_fclose (fp);
   fp = NULL;
   if (es_fclose (fpout))
     {
       err = gpg_error_from_errno (errno);
       log_error (_("error closing `%s': %s\n"), tmpfname, strerror (errno));
       goto leave;
     }
   fpout = NULL;
 
 #ifdef HAVE_W32_SYSTEM
   /* No atomic mv on W32 systems.  */
   gnupg_remove (fname);
 #endif
   if (rename (tmpfname, fname))
     {
       err = gpg_error_from_errno (errno);
       log_error (_("error renaming `%s' to `%s': %s\n"),
                  tmpfname, fname, strerror (errno));
       goto leave;
     }
 
  leave:
   /* Fixme: Relinquish update lock. */
   xfree (line);
   es_fclose (fp);
   xfree (fname);
   if (fpout)
     {
       es_fclose (fpout);
       if (err && tmpfname)
         gnupg_remove (tmpfname);
     }
   xfree (tmpfname);
   return err;
 }
 
 
 
 
 /* Create the filename for the cache file from the 40 byte ISSUER_HASH
    string. Caller must release the return string. */
 static char *
 make_db_file_name (const char *issuer_hash)
 {
   char bname[50];
 
   assert (strlen (issuer_hash) == 40);
   memcpy (bname, "crl-", 4);
   memcpy (bname + 4, issuer_hash, 40);
   strcpy (bname + 44, ".db");
   return make_filename (opt.homedir_cache, DBDIR_D, bname, NULL);
 }
 
 
 /* Hash the file FNAME and return the MD5 digest in MD5BUFFER. The
    caller must allocate MD%buffer wityh at least 16 bytes. Returns 0
    on success. */
 static int
 hash_dbfile (const char *fname, unsigned char *md5buffer)
 {
   estream_t fp;
   char *buffer;
   size_t n;
   gcry_md_hd_t md5;
   gpg_err_code_t err;
 
   buffer = xtrymalloc (65536);
   fp = buffer? es_fopen (fname, "rb") : NULL;
   if (!fp)
     {
       log_error (_("can't hash `%s': %s\n"), fname, strerror (errno));
       xfree (buffer);
       return -1;
     }
 
   err = gcry_md_open (&md5, GCRY_MD_MD5, 0);
   if (err)
     {
       log_error (_("error setting up MD5 hash context: %s\n"),
                  gpg_strerror (err));
       xfree (buffer);
       es_fclose (fp);
       return -1;
     }
 
   /* We better hash some information about the cache file layout in. */
   sprintf (buffer, "%.100s/%.100s:%d", DBDIR_D, DBDIRFILE, DBDIRVERSION);
   gcry_md_write (md5, buffer, strlen (buffer));
     
   for (;;)
     {
       n = es_fread (buffer, 1, 65536, fp);
       if (n < 65536 && es_ferror (fp))
         {
           log_error (_("error hashing `%s': %s\n"), fname, strerror (errno));
           xfree (buffer);
           es_fclose (fp);
           gcry_md_close (md5);
           return -1;
         }
       if (!n)
         break;
       gcry_md_write (md5, buffer, n);
     }
   es_fclose (fp);
   xfree (buffer);
   gcry_md_final (md5);
 
   memcpy (md5buffer, gcry_md_read (md5, GCRY_MD_MD5), 16);
   gcry_md_close (md5);
   return 0;
 }
 
 /* Compare the file FNAME against the dexified MD5 hash MD5HASH and
    return 0 if they match. */
 static int
 check_dbfile (const char *fname, const char *md5hexvalue)
 {
   unsigned char buffer1[16], buffer2[16];
 
   if (strlen (md5hexvalue) != 32)
     {
       log_error (_("invalid formatted checksum for `%s'\n"), fname);
       return -1;
     }
   unhexify (buffer1, md5hexvalue);
 
   if (hash_dbfile (fname, buffer2))
     return -1;
 
   return memcmp (buffer1, buffer2, 16);
 }
 
 
 /* Open the cache file for ENTRY.  This function implements a caching
    strategy and might close unused cache files. It is required to use
    unlock_db_file after using the file. */ 
 static struct cdb *
 lock_db_file (crl_cache_t cache, crl_cache_entry_t entry)
 {
   char *fname;
   int fd;
   int open_count;
   crl_cache_entry_t e;
 
   if (entry->cdb)
     {
       entry->cdb_use_count++;
       return entry->cdb;
     }
 
   for (open_count = 0, e = cache->entries; e; e = e->next)
     {
       if (e->cdb)
         open_count++;
 /*       log_debug ("CACHE: cdb=%p use_count=%u lru_count=%u\n", */
 /*                  e->cdb,e->cdb_use_count,e->cdb_lru_count); */
     }
 
   /* If there are too many file open, find the least recent used DB
      file and close it.  Note that for Pth thread safeness we need to
      use a loop here. */
   while (open_count >= MAX_OPEN_DB_FILES )
     {
       crl_cache_entry_t last_e = NULL;
       unsigned int last_lru = (unsigned int)(-1);
 
       for (e = cache->entries; e; e = e->next)
         if (e->cdb && !e->cdb_use_count && e->cdb_lru_count < last_lru)
           {
             last_lru = e->cdb_lru_count;
             last_e = e;
           }
       if (!last_e)
         {
           log_error (_("too many open cache files; can't open anymore\n"));
           return NULL;
         }
 
 /*       log_debug ("CACHE: closing file at cdb=%p\n", last_e->cdb); */
 
       fd = cdb_fileno (last_e->cdb);
       cdb_free (last_e->cdb);
       xfree (last_e->cdb);
       last_e->cdb = NULL;
       if (close (fd))
         log_error (_("error closing cache file: %s\n"), strerror(errno));
       open_count--;
     }
 
 
   fname = make_db_file_name (entry->issuer_hash);
   if (opt.verbose)
     log_info (_("opening cache file `%s'\n"), fname );
 
   if (!entry->dbfile_checked)
     {
       if (!check_dbfile (fname, entry->dbfile_hash))
         entry->dbfile_checked = 1;
       /* Note, in case of an error we don't print an error here but
          let require the caller to do that check. */
     }
 
   entry->cdb = xtrycalloc (1, sizeof *entry->cdb);
   if (!entry->cdb)
     {
       xfree (fname);
       return NULL;
     }
   fd = open (fname, O_RDONLY);
   if (fd == -1)
     {
       log_error (_("error opening cache file `%s': %s\n"),
                  fname, strerror (errno));
       xfree (entry->cdb);
       entry->cdb = NULL;
       xfree (fname);
       return NULL;
     }
   if (cdb_init (entry->cdb, fd))
     {
       log_error (_("error initializing cache file `%s' for reading: %s\n"),
                  fname, strerror (errno));
       xfree (entry->cdb);
       entry->cdb = NULL;
       close (fd);
       xfree (fname);
       return NULL;
     }
   xfree (fname);
 
   entry->cdb_use_count = 1;
   entry->cdb_lru_count = 0;
 
   return entry->cdb;
 }
 
 /* Unlock a cache file, so that it can be reused. */
 static void
 unlock_db_file (crl_cache_t cache, crl_cache_entry_t entry)
 {
   if (!entry->cdb)
     log_error (_("calling unlock_db_file on a closed file\n"));
   else if (!entry->cdb_use_count)
     log_error (_("calling unlock_db_file on an unlocked file\n"));
   else 
     {
       entry->cdb_use_count--;
       entry->cdb_lru_count++;
     }
 
   /* If the entry was marked for deletion in the meantime do it now.
      We do this for the sake of Pth thread safeness. */
   if (!entry->cdb_use_count && entry->deleted)
     {
       crl_cache_entry_t eprev, enext;
 
       enext = entry->next;
       for (eprev = cache->entries;
            eprev && eprev->next != entry; eprev = eprev->next)
         ;
       assert (eprev);
       if (eprev == cache->entries)
         cache->entries = enext;
       else
         eprev->next = enext;
+      /* FIXME: Do we leak ENTRY? */
     }
 }
 
 
 /* Find ISSUER_HASH in our cache FIRST. This may be used to enumerate
    the linked list we use to keep the CRLs of an issuer. */
 static crl_cache_entry_t 
 find_entry (crl_cache_entry_t first, const char *issuer_hash)
 {
   while (first && (first->deleted || strcmp (issuer_hash, first->issuer_hash)))
     first = first->next;
   return first;    
 }
 
 
-
 /* Create a new CRL cache. This fucntion is usually called only once.
    never fail. */
 void
 crl_cache_init(void)
 {
   crl_cache_t cache = NULL;
   gpg_error_t err;
 
   if (current_cache)
     {
       log_error ("crl cache has already been initialized - not doing twice\n");
       return;
     }
 
   err = open_dir (&cache);
   if (err) 
     log_fatal (_("failed to create a new cache object: %s\n"),
                gpg_strerror (err));
   current_cache = cache;
 }
 
 
 /* Remove the cache information and all its resources.  Note that we
    still keep the cache on disk. */
 void 
 crl_cache_deinit (void)
 {
   if (current_cache)
     {
       release_cache (current_cache);
       current_cache = NULL;
     }
 }
 
 
 /* Delete the cache from disk. Return 0 on success.*/
 int 
 crl_cache_flush (void)
 {
   int rc;
 
   rc = cleanup_cache_dir (0)? -1 : 0;
 
   return rc;
 }
 
 
 /* Check whether the certificate identified by ISSUER_HASH and
    SN/SNLEN is valid; i.e. not listed in our cache.  With
    FORCE_REFRESH set to true, a new CRL will be retrieved even if the
    cache has not yet expired.  We use a 30 minutes threshold here so
    that invoking this function several times won't load the CRL over
    and over.  */
 static crl_cache_result_t 
 cache_isvalid (ctrl_t ctrl, const char *issuer_hash,
                const unsigned char *sn, size_t snlen,
                int force_refresh)
 {
   crl_cache_t cache = get_current_cache ();
   crl_cache_result_t retval;
   struct cdb *cdb;
   int rc;
   crl_cache_entry_t entry;
   gnupg_isotime_t current_time;
   size_t n;
 
   (void)ctrl;
 
   entry = find_entry (cache->entries, issuer_hash);
   if (!entry)
     {
       log_info (_("no CRL available for issuer id %s\n"), issuer_hash );
       return CRL_CACHE_DONTKNOW;
     }
 
   gnupg_get_isotime (current_time);
   if (strcmp (entry->next_update, current_time) < 0 )
     {
       log_info (_("cached CRL for issuer id %s too old; update required\n"),
                 issuer_hash);
       return CRL_CACHE_DONTKNOW;
     }
   if (force_refresh)
     {
       gnupg_isotime_t tmptime;
       
       if (*entry->last_refresh)
         {
           gnupg_copy_time (tmptime, entry->last_refresh);
           add_seconds_to_isotime (tmptime, 30 * 60);
           if (strcmp (tmptime, current_time) < 0 )
             {
               log_info (_("force-crl-refresh active and %d minutes passed for"
                           " issuer id %s; update required\n"), 
                         30, issuer_hash);
               return CRL_CACHE_DONTKNOW;
             }
         }
       else
         {
           log_info (_("force-crl-refresh active for"
                       " issuer id %s; update required\n"), 
                     issuer_hash);
           return CRL_CACHE_DONTKNOW;
         }
     }
 
   if (entry->invalid)
     {
       log_info (_("available CRL for issuer ID %s can't be used\n"),
                 issuer_hash);
       return CRL_CACHE_CANTUSE;
     }
 
   cdb = lock_db_file (cache, entry);
   if (!cdb)
     return CRL_CACHE_DONTKNOW; /* Hmmm, not the best error code. */
   
   if (!entry->dbfile_checked)
     {
       log_error (_("cached CRL for issuer id %s tampered; we need to update\n")
                  , issuer_hash);
       unlock_db_file (cache, entry);
       return CRL_CACHE_DONTKNOW;
     }
 
   rc = cdb_find (cdb, sn, snlen);
   if (rc == 1) 
     {
       n = cdb_datalen (cdb);
       if (n != 16)
         {
           log_error (_("WARNING: invalid cache record length for S/N "));
           log_printhex ("", sn, snlen);
         }
       else if (opt.verbose)
         {
           unsigned char record[16];
           char *tmp = hexify_data (sn, snlen);
 
           if (cdb_read (cdb, record, n, cdb_datapos (cdb)))
             log_error (_("problem reading cache record for S/N %s: %s\n"),
                        tmp, strerror (errno));
           else
             log_info (_("S/N %s is not valid; reason=%02X  date=%.15s\n"),
                       tmp, *record, record+1);
           xfree (tmp);
         }
       retval = CRL_CACHE_INVALID;
     }
   else if (!rc)
     {
       if (opt.verbose)
         {
           char *serialno = hexify_data (sn, snlen);
           log_info (_("S/N %s is valid, it is not listed in the CRL\n"),
                     serialno );
           xfree (serialno);
         }
       retval = CRL_CACHE_VALID;
     }
   else 
     {
       log_error (_("error getting data from cache file: %s\n"),
                  strerror (errno));
       retval = CRL_CACHE_DONTKNOW;
     }
 
 
   if (entry->user_trust_req
       && (retval == CRL_CACHE_VALID || retval == CRL_CACHE_INVALID))
     {
       if (!entry->check_trust_anchor)
         {
           log_error ("inconsistent data on user trust check\n");
           retval = CRL_CACHE_CANTUSE;
         }
       else if (get_istrusted_from_client (ctrl, entry->check_trust_anchor))
         {
           if (opt.verbose)
             log_info ("no system trust and client does not trust either\n");
           retval = CRL_CACHE_CANTUSE;
         }
       else
         {
           /* Okay, the CRL is considered valid by the client and thus
              we can return the result as is.  */
         }
     }
 
   unlock_db_file (cache, entry);
 
   return retval;
 }
 
 
 /* Check whether the certificate identified by ISSUER_HASH and
    SERIALNO is valid; i.e. not listed in our cache.  With
    FORCE_REFRESH set to true, a new CRL will be retrieved even if the
    cache has not yet expired.  We use a 30 minutes threshold here so
    that invoking this function several times won't load the CRL over
    and over.  */
 crl_cache_result_t 
 crl_cache_isvalid (ctrl_t ctrl, const char *issuer_hash, const char *serialno,
                    int force_refresh)
 {
   crl_cache_result_t result;
   unsigned char snbuf_buffer[50];
   unsigned char *snbuf;
   size_t n;
 
   n = strlen (serialno)/2+1;
   if (n < sizeof snbuf_buffer - 1)
     snbuf = snbuf_buffer;
   else
     {
       snbuf = xtrymalloc (n);
       if (!snbuf)
         return CRL_CACHE_DONTKNOW;
     }
 
   n = unhexify (snbuf, serialno);
 
   result = cache_isvalid (ctrl, issuer_hash, snbuf, n, force_refresh);
 
   if (snbuf != snbuf_buffer)
     xfree (snbuf);
 
   return result;
 }  
 
 
 /* Check whether the certificate CERT is valid; i.e. not listed in our
    cache.  With FORCE_REFRESH set to true, a new CRL will be retrieved
    even if the cache has not yet expired.  We use a 30 minutes
    threshold here so that invoking this function several times won't
    load the CRL over and over.  */
 gpg_error_t
 crl_cache_cert_isvalid (ctrl_t ctrl, ksba_cert_t cert,
                         int force_refresh)
 {
   gpg_error_t err;
   crl_cache_result_t result;
   unsigned char issuerhash[20];
   char issuerhash_hex[41];
   ksba_sexp_t serial;
   unsigned char *sn;
   size_t snlen;
   char *endp, *tmp;
   int i;
 
   /* Compute the hash value of the issuer name.  */
   tmp = ksba_cert_get_issuer (cert, 0);
   if (!tmp)
     {
       log_error ("oops: issuer missing in certificate\n");
       return gpg_error (GPG_ERR_INV_CERT_OBJ);
     }
   gcry_md_hash_buffer (GCRY_MD_SHA1, issuerhash, tmp, strlen (tmp));
   xfree (tmp);
   for (i=0,tmp=issuerhash_hex; i < 20; i++, tmp += 2)
     sprintf (tmp, "%02X", issuerhash[i]);
   
   /* Get the serial number.  */
   serial = ksba_cert_get_serial (cert);
   if (!serial)
     {
       log_error ("oops: S/N missing in certificate\n");
       return gpg_error (GPG_ERR_INV_CERT_OBJ);
     }
   sn = serial;
   if (*sn != '(')
     {
       log_error ("oops: invalid S/N\n");
       xfree (serial);
       return gpg_error (GPG_ERR_INV_CERT_OBJ);
     }
   sn++;
   snlen = strtoul (sn, &endp, 10);
   sn = endp;
   if (*sn != ':')
     {
       log_error ("oops: invalid S/N\n");
       xfree (serial);
       return gpg_error (GPG_ERR_INV_CERT_OBJ);
     }
   sn++;
 
   /* Check the cache.  */
   result = cache_isvalid (ctrl, issuerhash_hex, sn, snlen, force_refresh);
   switch (result)
     {
     case CRL_CACHE_VALID:
       err = 0;
       break;
     case CRL_CACHE_INVALID:
       err = gpg_error (GPG_ERR_CERT_REVOKED);
       break;
     case CRL_CACHE_DONTKNOW: 
       err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
     case CRL_CACHE_CANTUSE: 
       err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
       break;
     default:
       log_fatal ("cache_isvalid returned invalid status code %d\n", result);
     }
 
   xfree (serial);
   return err;
 }  
 
 
 /* Prepare a hash context for the signature verification.  Input is
    the CRL and the output is the hash context MD as well as the uses
    algorithm identifier ALGO. */
 static gpg_error_t
 start_sig_check (ksba_crl_t crl, gcry_md_hd_t *md, int *algo) 
 {
   gpg_error_t err;
   const char *algoid;
 
   algoid = ksba_crl_get_digest_algo (crl);
   *algo = gcry_md_map_name (algoid);
   if (!*algo) 
     {
       log_error (_("unknown hash algorithm `%s'\n"), algoid? algoid:"?");
       return gpg_error (GPG_ERR_DIGEST_ALGO);
     }
 
   err = gcry_md_open (md, *algo, 0);
   if (err)
     {
       log_error (_("gcry_md_open for algorithm %d failed: %s\n"),
                  *algo, gcry_strerror (err));
       return err;
     }
   if (DBG_HASHING)
     gcry_md_debug (*md, "hash.cert");
 
   ksba_crl_set_hash_function (crl, HASH_FNC, *md);  
   return 0;
 }
 
 
 /* Finish a hash context and verify the signature.  This function
    should return 0 on a good signature, GPG_ERR_BAD_SIGNATURE if the
    signature does not verify or any other error code. CRL is the CRL
    object we are working on, MD the hash context and ISSUER_CERT the
    certificate of the CRL issuer.  This function closes MD.  */
 static gpg_error_t
 finish_sig_check (ksba_crl_t crl, gcry_md_hd_t md, int algo,
                   ksba_cert_t issuer_cert)
 {
   gpg_error_t err;
   ksba_sexp_t sigval = NULL, pubkey = NULL;
   const char *s;
   char algoname[50];
   size_t n;
   gcry_sexp_t s_sig = NULL, s_hash = NULL, s_pkey = NULL;
   unsigned int i;
 
   /* This also stops debugging on the MD.  */
   gcry_md_final (md);
 
   /* Get and convert the signature value. */
   sigval = ksba_crl_get_sig_val (crl);
   n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
   if (!n) 
     {
       log_error (_("got an invalid S-expression from libksba\n"));
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto leave;
     }
   err = gcry_sexp_sscan (&s_sig, NULL, sigval, n);
   if (err) 
     {
       log_error (_("converting S-expression failed: %s\n"),
                  gcry_strerror (err));
       goto leave;
     }
 	
   /* Get and convert the public key for the issuer certificate. */
   if (DBG_X509)
     dump_cert ("crl_issuer_cert", issuer_cert);
   pubkey = ksba_cert_get_public_key (issuer_cert);
   n = gcry_sexp_canon_len (pubkey, 0, NULL, NULL);
   if (!n) 
     {
       log_error (_("got an invalid S-expression from libksba\n"));
       err = gpg_error (GPG_ERR_INV_SEXP);
       goto leave;
     }
   err = gcry_sexp_sscan (&s_pkey, NULL, pubkey, n);
   if (err) 
     {
       log_error (_("converting S-expression failed: %s\n"),
                  gcry_strerror (err));
       goto leave;
     }
 
   /* Create an S-expression with the actual hash value. */
   s = gcry_md_algo_name (algo);
   for (i = 0; *s && i < sizeof(algoname) - 1; s++, i++)
     algoname[i] = ascii_tolower (*s);
   algoname[i] = 0;
   err = gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))", 
                          algoname,
                          gcry_md_get_algo_dlen (algo), gcry_md_read (md, algo));
   if (err) 
     {
       log_error (_("creating S-expression failed: %s\n"), gcry_strerror (err));
       goto leave;
     }
 
   /* Pass this on to the signature verification. */
   err = gcry_pk_verify (s_sig, s_hash, s_pkey);
   if (DBG_X509)
     log_debug ("gcry_pk_verify: %s\n", gpg_strerror (err));
 
  leave:
   xfree (sigval);
   xfree (pubkey);
   gcry_sexp_release (s_sig);
   gcry_sexp_release (s_hash);
   gcry_sexp_release (s_pkey);
   gcry_md_close (md);
 
   return err;
 }
 
 
 /* Call this to match a start_sig_check that can not be completed
    normally.  */
 static void
 abort_sig_check (ksba_crl_t crl, gcry_md_hd_t md)
 {
   (void)crl;
   gcry_md_close (md);
 }
 
 
 /* Workhorse of the CRL loading machinery.  The CRL is read using the
    CRL object and stored in the data base file DB with the name FNAME
    (only used for printing error messages).  That DB should be a
    temporary one and not the actual one.  If the function fails the
    caller should delete this temporary database file.  CTRL is
    required to retrieve certificates using the general dirmngr
    callback service.  R_CRLISSUER returns an allocated string with the
    crl-issuer DN, THIS_UPDATE and NEXT_UPDATE are filled with the
    corresponding data from the CRL.  Note that these values might get
    set even if the CRL processing fails at a later step; thus the
    caller should free *R_ISSUER even if the function returns with an
    error.  R_TRUST_ANCHOR is set on exit to NULL or a string with the
    hexified fingerprint of the root certificate, if checking this
    certificate for trustiness is required.
 */ 
 static int 
 crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
                   struct cdb_make *cdb, const char *fname,
                   char **r_crlissuer,
                   ksba_isotime_t thisupdate, ksba_isotime_t nextupdate,
                   char **r_trust_anchor)
 {  
   gpg_error_t err;
   ksba_stop_reason_t stopreason;
   ksba_cert_t crlissuer_cert = NULL;
   gcry_md_hd_t md = NULL;
   int algo = 0;
   size_t n;
   
   (void)fname;
 
   *r_crlissuer = NULL;
   *thisupdate = *nextupdate = 0;
   *r_trust_anchor = NULL;
 
   /* Start of the KSBA parser loop. */
   do
     {
       err = ksba_crl_parse (crl, &stopreason);
       if (err)
         {
           log_error (_("ksba_crl_parse failed: %s\n"), gpg_strerror (err) );
           goto failure;
         }
 
       switch (stopreason)
         {
         case KSBA_SR_BEGIN_ITEMS:
           {
             if (start_sig_check (crl, &md, &algo ))
               goto failure;
           
             err = ksba_crl_get_update_times (crl, thisupdate, nextupdate);
             if (err)
               {
                 log_error (_("error getting update times of CRL: %s\n"),
                            gpg_strerror (err));	  
                 err = gpg_error (GPG_ERR_INV_CRL);
                 goto failure;
               }
 
             if (opt.verbose || !*nextupdate)
               log_info (_("update times of this CRL: this=%s next=%s\n"), 
                         thisupdate, nextupdate);   
             if (!*nextupdate)
               {
                 log_info (_("nextUpdate not given; "
                             "assuming a validity period of one day\n"));
                 gnupg_copy_time (nextupdate, thisupdate);
                 add_seconds_to_isotime (nextupdate, 86400);
               }
           }
           break;
       
         case KSBA_SR_GOT_ITEM:
           {
             ksba_sexp_t serial;
             const unsigned char *p;
             ksba_isotime_t rdate;
             ksba_crl_reason_t reason;
             int rc;
             unsigned char record[1+15];
 
             err = ksba_crl_get_item (crl, &serial, rdate, &reason);
             if (err)
               {
                 log_error (_("error getting CRL item: %s\n"),
                            gpg_strerror (err));
                 err = gpg_error (GPG_ERR_INV_CRL);
                 ksba_free (serial);
                 goto failure;
               }
             p = serial_to_buffer (serial, &n);
             if (!p)
               BUG ();
             record[0] = (reason & 0xff);
             memcpy (record+1, rdate, 15); 
             rc = cdb_make_add (cdb, p, n, record, 1+15);
             if (rc)
               {
                 err = gpg_error_from_errno (errno);
                 log_error (_("error inserting item into "
                              "temporary cache file: %s\n"),
                            strerror (errno));
                 goto failure;
               }
 
             ksba_free (serial);
           }
           break;
       
         case KSBA_SR_END_ITEMS:
           break;
       
         case KSBA_SR_READY:
           {
             char *crlissuer;
             ksba_name_t authid;
             ksba_sexp_t authidsn;
             ksba_sexp_t keyid;
 
             /* We need to look for the issuer only after having read
                all items.  The issuer itselfs comes before the items
                but the optional authorityKeyIdentifier comes after the
                items. */
             err = ksba_crl_get_issuer (crl, &crlissuer);
             if( err )
               {
                 log_error (_("no CRL issuer found in CRL: %s\n"),
                            gpg_strerror (err) );
                 err = gpg_error (GPG_ERR_INV_CRL);
                 goto failure;
               }
 	    /* Note: This should be released by ksba_free, not xfree.
 	       May need a memory reallocation dance.  */
             *r_crlissuer = crlissuer; /* (Do it here so we don't need
                                          to free it later) */
 
             if (!ksba_crl_get_auth_key_id (crl, &keyid, &authid, &authidsn))
               {
                 const char *s;
 
                 if (opt.verbose)
                   log_info (_("locating CRL issuer certificate by "
                               "authorityKeyIdentifier\n"));
                 
                 s = ksba_name_enum (authid, 0);
                 if (s && *authidsn)
                   crlissuer_cert = find_cert_bysn (ctrl, s, authidsn);
                 if (!crlissuer_cert && keyid)
                   crlissuer_cert = find_cert_bysubject (ctrl,
                                                         crlissuer, keyid);
 
                 if (!crlissuer_cert)
                   {
                     log_info ("CRL issuer certificate ");
                     if (keyid)
                       {
                         log_printf ("{");
                         dump_serial (keyid);
                         log_printf ("} ");
                       }
                     if (authidsn)
                       {
                         log_printf ("(#");
                         dump_serial (authidsn);
                         log_printf ("/");
                         dump_string (s);
                         log_printf (") ");
                       }
                     log_printf ("not found\n");
                   }
                 ksba_name_release (authid);
                 xfree (authidsn);
                 xfree (keyid);
               }
             else
               crlissuer_cert = find_cert_bysubject (ctrl, crlissuer, NULL);
             err = 0;
             if (!crlissuer_cert)
               {
                 err = gpg_error (GPG_ERR_MISSING_CERT);
                 goto failure;
               }
         
             err = finish_sig_check (crl, md, algo, crlissuer_cert);
             if (err)
               {
                 log_error (_("CRL signature verification failed: %s\n"), 
                            gpg_strerror (err));
                 goto failure;
               }
 	    md = NULL;
 
             err = validate_cert_chain (ctrl, crlissuer_cert, NULL,
                                        VALIDATE_MODE_CRL_RECURSIVE,
                                        r_trust_anchor);
             if (err)
               {
                 log_error (_("error checking validity of CRL "
                              "issuer certificate: %s\n"), 
                            gpg_strerror (err));
                 goto failure;
               }
 
           }
           break;
       
         default:
           log_debug ("crl_parse_insert: unknown stop reason\n");
           err = gpg_error (GPG_ERR_BUG);
           goto failure;
         }
     } 
   while (stopreason != KSBA_SR_READY);
   assert (!err);
 
 
  failure:
   if (md)
     abort_sig_check (crl, md);
   ksba_cert_release (crlissuer_cert);
   return err;
 }
 
 
 
 /* Return the crlNumber extension as an allocated hex string or NULL
    if there is none. */
 static char *
 get_crl_number (ksba_crl_t crl)
 {
   gpg_error_t err;
   ksba_sexp_t number;
   char *string;
 
   err = ksba_crl_get_crl_number (crl, &number);
   if (err)
     return NULL;
   string = serial_hex (number);
   ksba_free (number);
   return string;
 }
 
 
 /* Return the authorityKeyIdentifier or NULL if it is not available.
    The issuer name may consists of several parts - they are delimted by
    0x01. */
 static char *
 get_auth_key_id (ksba_crl_t crl, char **serialno)
 {
   gpg_error_t err;
   ksba_name_t name;
   ksba_sexp_t sn;
   int idx;
   const char *s;
   char *string;
   size_t length;
 
   *serialno = NULL;
   err = ksba_crl_get_auth_key_id (crl, NULL, &name, &sn);
   if (err)
     return NULL;
   *serialno = serial_hex (sn);
   ksba_free (sn);
 
   if (!name)
     return xstrdup ("");
   
   length = 0;
   for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
     {
       char *p = ksba_name_get_uri (name, idx);
       length += strlen (p?p:s) + 1;
       xfree (p);
     }
   string = xtrymalloc (length+1);
   if (string)
     {
       *string = 0;
       for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
         {
           char *p = ksba_name_get_uri (name, idx);
           if (*string)
             strcat (string, "\x01");
           strcat (string, p?p:s);
           xfree (p);
         }
     }
   ksba_name_release (name);
   return string;
 }
 
 
 
 /* Insert the CRL retrieved using URL into the cache specified by
    CACHE.  The CRL itself will be read from the stream FP and is
    expected in binary format.
 
    Called by:
       crl_cache_load
          cmd_loadcrl
          --load-crl
       crl_cache_reload_crl
          cmd_isvalid
          cmd_checkcrl
       cmd_loadcrl
       --fetch-crl
       
  */
 gpg_error_t
 crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader)
 {
   crl_cache_t cache = get_current_cache ();
   gpg_error_t err, err2;
   ksba_crl_t crl;
   char *fname = NULL;
   char *newfname = NULL;
   struct cdb_make cdb;
   int fd_cdb = -1;
   char *issuer = NULL;
   char *issuer_hash = NULL;
   ksba_isotime_t thisupdate, nextupdate;
   crl_cache_entry_t entry = NULL;
   crl_cache_entry_t e;
   gnupg_isotime_t current_time;
   char *checksum = NULL;
   int invalidate_crl = 0;
   int idx;
   const char *oid;
   int critical;
   char *trust_anchor = NULL;
 
   /* FIXME: We should acquire a mutex for the URL, so that we don't
      simultaneously enter the same CRL twice.  However this needs to be
      interweaved with the checking function.*/
  
   err2 = 0;
 
   err = ksba_crl_new (&crl);
   if (err)
     {
       log_error (_("ksba_crl_new failed: %s\n"), gpg_strerror (err));
       goto leave;
     }
   
   err = ksba_crl_set_reader (crl, reader);
   if ( err )
     {
       log_error (_("ksba_crl_set_reader failed: %s\n"), gpg_strerror (err));
       goto leave;
     }
 
   /* Create a temporary cache file to load the CRL into. */
   {
     char *tmpfname, *p;
     const char *nodename;
 #ifndef HAVE_W32_SYSTEM
     struct utsname utsbuf;
 #endif
 
 #ifdef HAVE_W32_SYSTEM
     nodename = "unknown";
 #else
     if (uname (&utsbuf))
       nodename = "unknown";
     else
       nodename = utsbuf.nodename;
 #endif
 
     estream_asprintf (&tmpfname, "crl-tmp-%s-%u-%p.db.tmp",
                       nodename, (unsigned int)getpid (), &tmpfname);
     if (!tmpfname)
       {
         err = gpg_error_from_syserror ();
         goto leave;
       }
     for (p=tmpfname; *p; p++)
       if (*p == '/')
         *p = '.';
     fname = make_filename (opt.homedir_cache, DBDIR_D, tmpfname, NULL);
     xfree (tmpfname);
     if (!gnupg_remove (fname))
       log_info (_("removed stale temporary cache file `%s'\n"), fname);
     else if (errno != ENOENT) 
       {
         err = gpg_error_from_syserror ();
         log_error (_("problem removing stale temporary cache file `%s': %s\n"),
                    fname, gpg_strerror (err));
         goto leave;
       }
   }
 
   fd_cdb = open (fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
   if (fd_cdb == -1)
     {
       err = gpg_error_from_errno (errno);
       log_error (_("error creating temporary cache file `%s': %s\n"),
                  fname, strerror (errno));
       goto leave;
     }
   cdb_make_start(&cdb, fd_cdb);
 
   err = crl_parse_insert (ctrl, crl, &cdb, fname,
                           &issuer, thisupdate, nextupdate, &trust_anchor);
   if (err)
     {
       log_error (_("crl_parse_insert failed: %s\n"), gpg_strerror (err));
       /* Error in cleanup ignored.  */
       cdb_make_finish (&cdb);
       goto leave;
     }
 
   /* Finish the database. */
   if (cdb_make_finish (&cdb))
     {
       err = gpg_error_from_errno (errno);
       log_error (_("error finishing temporary cache file `%s': %s\n"),
                  fname, strerror (errno));
       goto leave;
     }
   if (close (fd_cdb))
     {
       err = gpg_error_from_errno (errno);
       log_error (_("error closing temporary cache file `%s': %s\n"),
                  fname, strerror (errno));
       goto leave;
     }
   fd_cdb = -1;
 
 
   /* Create a checksum. */
   {
     unsigned char md5buf[16];
 
     if (hash_dbfile (fname, md5buf))
       {
         err = gpg_error (GPG_ERR_CHECKSUM);
         goto leave;
       }
     checksum = hexify_data (md5buf, 16);
   }
 
 
   /* Check whether that new CRL is still not expired. */
   gnupg_get_isotime (current_time);
   if (strcmp (nextupdate, current_time) < 0 )
     {
       if (opt.force)
         log_info (_("WARNING: new CRL still too old; it expired on %s "
                     "- loading anyway\n"),  nextupdate);
       else
         {
           log_error (_("new CRL still too old; it expired on %s\n"),
                      nextupdate);
           if (!err2)
             err2 = gpg_error (GPG_ERR_CRL_TOO_OLD);
           invalidate_crl |= 1;
         }
     }
 
   /* Check for unknown critical extensions. */
   for (idx=0; !(err=ksba_crl_get_extension (crl, idx, &oid, &critical,
                                               NULL, NULL)); idx++)
     {
       if (!critical
           || !strcmp (oid, oidstr_authorityKeyIdentifier)
           || !strcmp (oid, oidstr_crlNumber) )
         continue;
       log_error (_("unknown critical CRL extension %s\n"), oid);
       if (!err2)
         err2 = gpg_error (GPG_ERR_INV_CRL);
       invalidate_crl |= 2;
     }
   if (gpg_err_code (err) == GPG_ERR_EOF 
       || gpg_err_code (err) == GPG_ERR_NO_DATA )
     err = 0;
   if (err)
     {
       log_error (_("error reading CRL extensions: %s\n"), gpg_strerror (err));
       err = gpg_error (GPG_ERR_INV_CRL);
     }
 
 
   /* Create an hex encoded SHA-1 hash of the issuer DN to be
      used as the key for the cache. */
   issuer_hash = hashify_data (issuer, strlen (issuer));
 
   /* Create an ENTRY. */
   entry = xtrycalloc (1, sizeof *entry);
   if (!entry)
     {
       err = gpg_error_from_syserror ();
       goto leave;
     }
   entry->release_ptr = xtrymalloc (strlen (issuer_hash) + 1 
                                    + strlen (issuer) + 1
                                    + strlen (url) + 1 
                                    + strlen (checksum) + 1);
   if (!entry->release_ptr)
     {
       err = gpg_error_from_syserror ();
       xfree (entry);
       entry = NULL;
       goto leave;
     }
   entry->issuer_hash = entry->release_ptr;
   entry->issuer = stpcpy (entry->issuer_hash, issuer_hash) + 1;
   entry->url = stpcpy (entry->issuer, issuer) + 1;
   entry->dbfile_hash = stpcpy (entry->url, url) + 1;
   strcpy (entry->dbfile_hash, checksum);
   gnupg_copy_time (entry->this_update, thisupdate); 
   gnupg_copy_time (entry->next_update, nextupdate); 
   gnupg_copy_time (entry->last_refresh, current_time);
   entry->crl_number = get_crl_number (crl);
   entry->authority_issuer = get_auth_key_id (crl, &entry->authority_serialno);
   entry->invalid = invalidate_crl;
   entry->user_trust_req = !!trust_anchor;
   entry->check_trust_anchor = trust_anchor;
   trust_anchor = NULL;
 
   /* Check whether we already have an entry for this issuer and mark
      it as deleted. We better use a loop, just in case duplicates got
      somehow into the list. */
   for (e = cache->entries; (e=find_entry (e, entry->issuer_hash)); e = e->next)
     e->deleted = 1;
   
   /* Rename the temporary DB to the real name. */
   newfname = make_db_file_name (entry->issuer_hash);
   if (opt.verbose)
     log_info (_("creating cache file `%s'\n"), newfname);
+
+  /* Just in case close unused matching files.  Actually we need this
+     only under Windows but saving file descriptors is never bad.  */
+  {
+    int any;
+    do 
+      {
+        any = 0;
+        for (e = cache->entries; e; e = e->next)
+          if (!e->cdb_use_count && e->cdb
+              && !strcmp (e->issuer_hash, entry->issuer_hash))
+            {
+              int fd = cdb_fileno (e->cdb);
+              cdb_free (e->cdb);
+              xfree (e->cdb);
+              e->cdb = NULL;
+              if (close (fd))
+                log_error (_("error closing cache file: %s\n"),
+                           strerror(errno));
+              any = 1;
+              break;
+            }
+      }
+    while (any);
+  }
 #ifdef HAVE_W32_SYSTEM
   gnupg_remove (newfname);
 #endif
   if (rename (fname, newfname))
     {
       err = gpg_error_from_syserror ();
       log_error (_("problem renaming `%s' to `%s': %s\n"),
                  fname, newfname, gpg_strerror (err));
       goto leave;
     }
   xfree (fname); fname = NULL; /*(let the cleanup code not try to remove it)*/
 
   /* Link the new entry in. */
   entry->next = cache->entries;
   cache->entries = entry;
   entry = NULL;
 
   err = update_dir (cache);
   if (err)
     {
       log_error (_("updating the DIR file failed - "
                    "cache entry will get lost with the next program start\n"));
       err = 0; /* Keep on running. */
     }
 
 
  leave:
   release_one_cache_entry (entry);
   if (fd_cdb != -1)
     close (fd_cdb);
   if (fname)
     {
       gnupg_remove (fname);
       xfree (fname);
     }
   xfree (newfname);
   ksba_crl_release (crl);
   xfree (issuer);
   xfree (issuer_hash);
   xfree (checksum);
   xfree (trust_anchor);
   return err ? err : err2;
 }
 
 
 /* Print one cached entry E in a human readable format to stream
    FP. Return 0 on success. */
 static gpg_error_t
 list_one_crl_entry (crl_cache_t cache, crl_cache_entry_t e, estream_t fp)
 {
   struct cdb_find cdbfp;
   struct cdb *cdb;
   int rc;
   int warn = 0;
   const unsigned char *s;
 
   es_fputs ("--------------------------------------------------------\n", fp );
   es_fprintf (fp, _("Begin CRL dump (retrieved via %s)\n"), e->url );
   es_fprintf (fp, " Issuer:\t%s\n", e->issuer );
   es_fprintf (fp, " Issuer Hash:\t%s\n", e->issuer_hash );
   es_fprintf (fp, " This Update:\t%s\n", e->this_update ); 
   es_fprintf (fp, " Next Update:\t%s\n", e->next_update ); 
   es_fprintf (fp, " CRL Number :\t%s\n", e->crl_number? e->crl_number: "none");
   es_fprintf (fp, " AuthKeyId  :\t%s\n",
               e->authority_serialno? e->authority_serialno:"none");
   if (e->authority_serialno && e->authority_issuer)
     {
       es_fputs ("             \t", fp);
       for (s=e->authority_issuer; *s; s++)
         if (*s == '\x01')
           es_fputs ("\n             \t", fp);
         else
           es_putc (*s, fp);
       es_putc ('\n', fp);
     }
   es_fprintf (fp, " Trust Check:\t%s\n", 
               !e->user_trust_req? "[system]" :
               e->check_trust_anchor? e->check_trust_anchor:"[missing]");
 
   if ((e->invalid & 1))
     es_fprintf (fp, _(" ERROR: The CRL will not be used "
                       "because it was still too old after an update!\n"));
   if ((e->invalid & 2))
     es_fprintf (fp, _(" ERROR: The CRL will not be used "
                       "due to an unknown critical extension!\n"));
   if ((e->invalid & ~3))
     es_fprintf (fp, _(" ERROR: The CRL will not be used\n"));
 
   cdb = lock_db_file (cache, e);
   if (!cdb)
     return gpg_error (GPG_ERR_GENERAL);
 
   if (!e->dbfile_checked)
     es_fprintf (fp, _(" ERROR: This cached CRL may has been tampered with!\n"));
 
   es_putc ('\n', fp);
 
   rc = cdb_findinit (&cdbfp, cdb, NULL, 0);
   while (!rc && (rc=cdb_findnext (&cdbfp)) > 0 )
     {
       unsigned char keyrecord[256];
       unsigned char record[16];
       int reason;
       int any = 0;
       cdbi_t n;
       cdbi_t i;
 
       rc = 0;
       n = cdb_datalen (cdb);
       if (n != 16)
         {
           log_error (_(" WARNING: invalid cache record length\n"));
           warn = 1;
           continue;
         }
 
       if (cdb_read (cdb, record, n, cdb_datapos (cdb)))
         {
           log_error (_("problem reading cache record: %s\n"),
                      strerror (errno));
           warn = 1;
           continue;
         }
     
       n = cdb_keylen (cdb);
       if (n > sizeof keyrecord)
         n = sizeof keyrecord;
       if (cdb_read (cdb, keyrecord, n, cdb_keypos (cdb)))
         {
           log_error (_("problem reading cache key: %s\n"), strerror (errno));
           warn = 1;
           continue;
         }
 
       reason = *record;
       es_fputs ("  ", fp);
       for (i = 0; i < n; i++)
         es_fprintf (fp, "%02X", keyrecord[i]);
       es_fputs (":\t reasons( ", fp);
     
       if (reason & KSBA_CRLREASON_UNSPECIFIED)
         es_fputs( "unspecified ", fp ), any = 1;
       if (reason & KSBA_CRLREASON_KEY_COMPROMISE )
         es_fputs( "key_compromise ", fp ), any = 1; 
       if (reason & KSBA_CRLREASON_CA_COMPROMISE )
         es_fputs( "ca_compromise ", fp ), any = 1; 
       if (reason & KSBA_CRLREASON_AFFILIATION_CHANGED )
         es_fputs( "affiliation_changed ", fp ), any = 1; 
       if (reason & KSBA_CRLREASON_SUPERSEDED )
         es_fputs( "superseeded", fp ), any = 1; 
       if (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION )
         es_fputs( "cessation_of_operation", fp ), any = 1; 
       if (reason & KSBA_CRLREASON_CERTIFICATE_HOLD )
         es_fputs( "certificate_hold", fp ), any = 1; 
       if (reason && !any)
         es_fputs( "other", fp ); 
       
       es_fprintf (fp, ") rdate: %.15s\n", record+1);
     } 
   if (rc)
     log_error (_("error reading cache entry from db: %s\n"), strerror (rc));
 
   unlock_db_file (cache, e);
   es_fprintf (fp, _("End CRL dump\n") );
   es_putc ('\n', fp);
 
   return (rc||warn)? gpg_error (GPG_ERR_GENERAL) : 0;
 }
 
 
 /* Print the contents of the CRL CACHE in a human readable format to
    stream FP. */
 gpg_error_t 
 crl_cache_list (estream_t fp) 
 {
   crl_cache_t cache = get_current_cache ();
   crl_cache_entry_t entry;
   gpg_error_t err = 0;
 
   for (entry = cache->entries;
        entry && !entry->deleted && !err;
        entry = entry->next ) 
     err = list_one_crl_entry (cache, entry, fp);
 
   return err;
 }
 
 
 /* Load the CRL containing the file named FILENAME into our CRL cache. */
 gpg_error_t
 crl_cache_load (ctrl_t ctrl, const char *filename)
 {
   gpg_error_t err;
   estream_t fp;
   ksba_reader_t reader;
 
   fp = es_fopen (filename, "r");
   if (!fp)
     {
       err = gpg_error_from_errno (errno);
       log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
       return err;
     }
 
   err = create_estream_ksba_reader (&reader, fp);
   if (!err)
     {
       err = crl_cache_insert (ctrl, filename, reader);
       ksba_reader_release (reader);
     }
   es_fclose (fp);
   return err;
 }
 
 
 /* Locate the corresponding CRL for the certificate CERT, read and
    verify the CRL and store it in the cache.  */
 gpg_error_t
 crl_cache_reload_crl (ctrl_t ctrl, ksba_cert_t cert) 
 {
   gpg_error_t err;
   ksba_reader_t reader = NULL;
   char *issuer = NULL;
   ksba_name_t distpoint = NULL;
   ksba_name_t issuername = NULL;
   char *distpoint_uri = NULL;
   char *issuername_uri = NULL;
   int any_dist_point = 0;
   int seq;
 
   /* Loop over all distribution points, get the CRLs and put them into
      the cache. */
   if (opt.verbose)
     log_info ("checking distribution points\n");
   seq = 0;
   while ( !(err = ksba_cert_get_crl_dist_point (cert, seq++,
                                                 &distpoint,
                                                 &issuername, NULL )))
     {
       int name_seq; 
       gpg_error_t last_err = 0;
 
       if (!distpoint && !issuername)
         {
           if (opt.verbose)
             log_info ("no issuer name and no distribution point\n");
           break; /* Not allowed; i.e. an invalid certificate.  We give
                     up here and hope that the default method returns a
                     suitable CRL. */
         }
 
       xfree (issuername_uri); issuername_uri = NULL;
 
       /* Get the URIs.  We do this in a loop to iterate over all names
          in the crlDP. */
       for (name_seq=0; ksba_name_enum (distpoint, name_seq); name_seq++)
         {
           xfree (distpoint_uri); distpoint_uri = NULL;
           distpoint_uri = ksba_name_get_uri (distpoint, name_seq);
           if (!distpoint_uri)
             continue;
           
           if (!strncmp (distpoint_uri, "ldap:", 5)
               || !strncmp (distpoint_uri, "ldaps:", 6))
             {
               if (opt.ignore_ldap_dp)
                 continue;
             }
           else if (!strncmp (distpoint_uri, "http:", 5)
                    || !strncmp (distpoint_uri, "https:", 6))
             {
               if (opt.ignore_http_dp)
                 continue;
             }
           else
             continue; /* Skip unknown schemes. */
           
           any_dist_point = 1;
           
           if (opt.verbose)
             log_info ("fetching CRL from `%s'\n", distpoint_uri);
           err = crl_fetch (ctrl, distpoint_uri, &reader);
           if (err)
             {
               log_error (_("crl_fetch via DP failed: %s\n"),
                          gpg_strerror (err));
               last_err = err;
               continue; /* with the next name. */
             }
           
           if (opt.verbose)
             log_info ("inserting CRL (reader %p)\n", reader);
           err = crl_cache_insert (ctrl, distpoint_uri, reader); 
           if (err)
             {
               log_error (_("crl_cache_insert via DP failed: %s\n"),
                          gpg_strerror (err));
               last_err = err;
               continue; /* with the next name. */
             }
           last_err = 0;
           break; /* Ready. */
         }
       if (last_err)
         {
           err = last_err;
           goto leave;
         }
       
       ksba_name_release (distpoint); distpoint = NULL;
 
       /* We don't do anything with issuername_uri yet but we keep the
          code for documentation. */
       issuername_uri =  ksba_name_get_uri (issuername, 0); 
       ksba_name_release (issuername); issuername = NULL;
 
     }
   if (gpg_err_code (err) == GPG_ERR_EOF)
     err = 0;
 
   /* If we did not found any distpoint, try something reasonable. */
   if (!any_dist_point )
     {
       if (opt.verbose)
         log_info ("no distribution point - trying issuer name\n");
       
       if (reader)
         {
           crl_close_reader (reader);
           reader = NULL;
         }
 
       issuer = ksba_cert_get_issuer (cert, 0);
       if (!issuer) 
         {
           log_error ("oops: issuer missing in certificate\n");
           err = gpg_error (GPG_ERR_INV_CERT_OBJ); 
           goto leave;
         }
 
       if (opt.verbose)
         log_info ("fetching CRL from default location\n");
       err = crl_fetch_default (ctrl, issuer, &reader);
       if (err)
           {
             log_error ("crl_fetch via issuer failed: %s\n",
                        gpg_strerror (err));
             goto leave;
           }
 
       if (opt.verbose)
         log_info ("inserting CRL (reader %p)\n", reader);
       err = crl_cache_insert (ctrl, "default location(s)", reader);
       if (err)
         {
           log_error (_("crl_cache_insert via issuer failed: %s\n"),
                      gpg_strerror (err));
           goto leave;
         }
     }
 
  leave:
   if (reader)
     crl_close_reader (reader);
   xfree (distpoint_uri);
   xfree (issuername_uri);
   ksba_name_release (distpoint); 
   ksba_name_release (issuername); 
   ksba_free (issuer);
   return err;
 }
 
diff --git a/tools/ChangeLog b/tools/ChangeLog
index c6ac33207..110e43ef1 100644
--- a/tools/ChangeLog
+++ b/tools/ChangeLog
@@ -1,1248 +1,1254 @@
+2010-12-14  Werner Koch  <wk@g10code.com>
+
+	* gpgconf-comp.c (gc_options_gpg_agent, gc_options_scdaemon)
+	(gc_options_gpg, gc_options_gpgsm, gc_options_dirmngr): Define to
+	NULL if corresponding BUILD_WITH_foo is not defined.
+
 2010-12-02  Werner Koch  <wk@g10code.com>
 
 	* no-libgcrypt.c (gcry_cipher_algo_name): New.
 
 2010-11-23  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (gpgconf_LDFLAGS): Add extra_bin_ldflags.
 
 2010-11-17  Marcus Brinkmann  <mb@g10code.com>
 
 	* gogconf.c: Revert accidental debug output commit.
 
 2010-10-27  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c (confucius_mktmpdir): Use TMPDIR.
 
 2010-10-14  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c: Add option --agent-program.
 
 	* gpg-connect-agent.c (start_agent): Rewrite using the
 	start_new_gpg_agent function.
 
 	* gpgconf-comp.c (gpg_agent_runtime_change): Use gpg-connect-agent
 	on all platforms.
 
 2010-10-06  Werner Koch  <wk@g10code.com>
 
 	* watchgnupg.c (print_version): Add option --time-only.
 
 2010-10-05  Werner Koch  <wk@g10code.com>
 
 	* watchgnupg.c (main): Support TCP and local socket listening.
 	(main): Factor some code out to ..
 	(setup_client): this.
 	(err): New.
 	(client_list): New.
 
 2010-08-25  Werner Koch  <wk@g10code.com>
 
 	* gpgtar-extract.c (create_directory): Add .p7m as known
 	extension.
 
 	* gpgtar.c: Add -t as short option for --list-archive.
 	* gpgtar-extract.c (gpgtar_extract): Use filename "-" for stdin.
 	Fix dirprefix setting.
 	* gpgtar-list.c (gpgtar_list): Ditto.
 
 2010-08-24  Werner Koch  <wk@g10code.com>
 
 	* gpgtar.c (opts): Fix --cms and --openpgp names.
 
 2010-08-23  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (GPGNAME) [W32CE]: s/gpg2/gpg/.
 	(get_config_filename) [W32CE]: Adjust absolute file name check.
 
 	* gpgconf-comp.c (retrieve_options_from_program)
 	(retrieve_options_from_file, retrieve_options_from_program)
 	(copy_file, gc_process_gpgconf_conf): Do not use es_ferror after a
 	failed es_fclose.  Note that the stream is in any case invalid
 	after calling es_fclose and that es_fclose does set ERRNO.
 
 	* Makefile.am (maybe_commonpth_libs): New.
 	(gpgconf_LDADD): Use it.
 
 2010-08-20  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (collect_error_output): Remove extra CRs.
 
 2010-08-19  Werner Koch  <wk@g10code.com>
 
 	* gpgconf.c (main): Fix --check-options.
 
 	* gpgconf-comp.c (gc_component_check_options): Replace
 	gnupg_spawn_process_fd by gnupg_spawn_process.
 	(retrieve_options_from_program): Ditto.
 	(collect_error_output): Change to use estream.
 
 	* gpgconf-comp.c: Add new backend and component for PINENTRY.
 	(gc_component_check_options): Use --version to test the pinentry.
 	(gc_component_retrieve_options, gc_component_change_options):
 	Ignore the pinentry component.
 
 2010-08-16  Werner Koch  <wk@g10code.com>
 
 	* gpgconf.c (get_outfp): Change to use estream.
 	(main): Replace fprintf by es_fprintf.
 	* gpgconf-comp.c (gc_component_list_components)
 	(gc_check_programs, gc_component_list_options)
 	(gc_component_change_options, gc_component_check_options)
 	(list_one_option, gc_process_gpgconf_conf): Replace FILE* args by
 	estream_t.
 
 2010-08-13  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (gpgkey2ssh_LDADD): Add NETLIBS.
 
 2010-08-11  Werner Koch  <wk@g10code.com>
 
 	* gpgtar-create.c (gpgtar_create): Allow "-" for stdout in
 	opt.outfile.  Switch es_stdout to binary mode.
 
 2010-08-09  Werner Koch  <wk@g10code.com>
 
 	* watchgnupg.c: Inlcude in.h and inet.h.
 	(main): Support tcp connections.
 
 	* gpgtar.c (main): Add options -T and --null.
 	* gpgtar-create.c (gpgtar_create): Implement option --null.
 
 2010-07-16  Werner Koch  <wk@g10code.com>
 
 	* gpgtar-create.c: Rewrite to better support W32.
 
 2010-07-01  Werner Koch  <wk@g10code.com>
 
 	* gpgtar.c: Add option --set-filename.
 
 2010-06-24  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gpg_agent_runtime_change)
 	(scdaemon_runtime_change, retrieve_options_from_program): Use HANG
 	option for gnupg_wait_progress.  Fixes regression from 2010-06-09.
 
 2010-06-07  Werner Koch  <wk@g10code.com>
 
 	* gpgtar.c, gpgtar.h, gpgtar-list.c, gpgtar-create.c
 	* gpgtar-extract.c: New.
 	* Makefile.am (commonpth_libs): New.
 	(gpgtar_SOURCES, gpgtar_CFLAGS, gpgtar_LDADD): New.
 	(bin_PROGRAMS) [!W32CE]: Add gpgtar.
 
 2010-04-20  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (option_check_validity): Use dummy variables to
 	silence gcc warning.
 
 2010-04-14  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (bin_PROGRAMS) [W32CE]: Exclude gpgkey2ssh.
 	(noinst_PROGRAMS) [W32CE]: Don't build them.
 	(pwquery_libs) [W32CE]: Set to empty.
 
 2010-03-25  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (opt_libassuan_libs) [W32CE]: New.
 	(gpgconf_LDADD): Use it.
 
 	* gpgconf-comp.c: Include signal.h only if available.  Use
 	gpg_err_set_errno.
 	(key_matches_user_or_group) [W32CE]: Do not match any user.
 
 2010-03-15  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (my_dgettext):
 	s/gettext_select_utf8/gettext_use_utf8/.
 
 2010-03-10  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (common_libs): Remove libjnlib.a.
 
 2010-03-08  Werner Koch  <wk@g10code.com>
 
 	* no-libgcrypt.c (gcry_create_nonce): New.
 
 2010-02-26  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (main): New option --tcp-socket.
 
 2010-01-10  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c (utmp.h): Remove header; it is not used.
 
 2009-12-18  Werner Koch  <wk@g10code.com>
 
 	* applygnupgdefaults (errorfile): Use mktemp.  Fixes bug#1146.
 
 2009-12-08  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpg-connect-agent.c (main): Convert posix fd to assuan fd.
 
 2009-12-07  Werner Koch  <wk@g10code.com>
 
 	* no-libgcrypt.c (gcry_strdup): Actually copy the string.
 
 2009-11-23  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gc_options_gpg): Add default_pubkey_algo.
 
 2009-11-05  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpg-connect-agent.c (start_agent): Update use of
 	assuan_socket_connect and assuan_pipe_connect.
 
 2009-11-04  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (read_and_print_response): Add arg WITHHASH.
 	(main): Pass true for WITHHASH for the HELP command.
 
 2009-09-23  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpg-connect-agent.c (getinfo_pid_cb, read_and_print_response)
 	(main): Update to new Assuan API.
 
 2009-07-21  Werner Koch  <wk@g10code.com>
 
 	* gpgsplit.c (my_strusage): Remove i18n stuff.
 
 2009-07-07  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (start_agent): Adjust for changed args of
 	send_pinentry_environment.
 
 2009-06-30  Werner Koch  <wk@g10code.com>
 
 	* ccidmon.c (parse_line_sniffusb): Take also TAB as delimiter.
 
 2009-06-29  Werner Koch  <wk@g10code.com>
 
 	* ccidmon.c (parse_line_sniffusb): New.
 	(main): Add option --sniffusb.
 
 2009-06-08  Werner Koch  <wk@g10code.com>
 
 	* gpgconf.c (main): Call gnupg_reopen_std.  Should fix bug#1072.
 
 2009-05-19  Werner Koch  <wk@g10code.com>
 
 	* watchgnupg.c: Include jnlib/mischelp.h if required.
 	(main): Use SUN_LEN.
 
 2009-04-17  Werner Koch  <wk@g10code.com>
 
 	* ccidmon.c: New.
 
 2009-03-03  Werner Koch  <wk@g10code.com>
 
 	* gpgconf.c: New command --reload.
 
 	* gpgconf-comp.c (gc_component_reload): New.
 
 2009-03-02  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (scdaemon_runtime_change): Killsc d only if it is
 	not running.
 
 2009-02-27  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gpg_agent_runtime_change): Declare static.
 	(scdaemon_runtime_change): New.
 	(gc_backend_scdaemon): Register new function.
 	(gc_options_scdaemon): Make most options runtime changable.
 
 2009-01-20  Werner Koch  <wk@g10code.com>
 
 	* gpgconf.c (main): Print more directories.
 
 2008-12-09  Werner Koch  <wk@g10code.com>
 
 	* gpg-check-pattern.c (main): Call i18n_init before
 	init_common_subsystems.
 	* gpg-connect-agent.c (main): Ditto.
 	* gpgconf.c (main): Ditto.
 	* symcryptrun.c (main): Ditto.
 
 2008-12-08  Werner Koch  <wk@g10code.com>
 
 	* gpgkey2ssh.c (main): Change order of output for RSA. Change name
 	of DSA identifier.  Reported by Daniel Kahn Gillmor.  This is
 	bug#901.
 
 2008-12-05  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (opts): Use ARGPARSE_ macros.
 	(start_agent) [W32]: Start agent if not running.
 
 2008-12-03  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c <scdaemon>: Add option --card-timeout.  Remove
 	unused option --disable-opensc.
 
 2008-10-20  Werner Koch  <wk@g10code.com>
 
 	* gpgsplit.c (write_part): Remove unused arg FNAME.  Change caller.
 	(do_split): Ditto.
 
 	* no-libgcrypt.c (gcry_control): Mark unused arg.
 	* gpg-connect-agent.c (do_recvfd): Ditto.
 	* gpgparsemail.c (mime_signed_begin, mime_encrypted_begin): Ditto.
 	(pkcs7_begin): Ditto.
 
 2008-10-01  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (main): New command datafile.
 	(read_and_print_response): Print to the defined datafile.
 
 2008-09-30  Werner Koch  <wk@g10code.com>
 
 	* gpgconf.c (main) <aListDirs>: Print the bindir.
 
 2008-08-06  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_options_gpgsm): Change type of keyserver
 	option to GC_ARG_TYPE_LDAP_SERVER.
 
 	* gpgconf-comp.c (retrieve_options_from_file): Transfer the
 	NO_CHANGE flag from the file name option to the list option.
 
 2008-06-19  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (GC_ARG_TYPE_ALIAS_LIST): New.
 	(gc_arg_type): Add fallback type.
 	(gc_options_gpg): Add option "group".
 
 2008-06-12  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_options_gpgsm): Add option keyserver.
 
 2008-05-26  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c: Replace pathname by filename everywhere.
 
 	* gpgconf.c (enum cmd_and_opt_values): Add aListDirs.
 	(opts): Add aListDirs option.
 	(main): Handle aListDirs.
 	* gpgconf.h (gc_percent_escape): New declaration.
 	* gpgconf-comp.c (my_percent_escape): Make non-static and rename
 	to ...
 	(gc_percent_escape): ... this.  Change all callers.
 	
 2008-05-26  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gpg_agent_runtime_change) [W32]: Issue
 	"reloadagent" command to gpg-agent.
 
 	* gpg-connect-agent.c (main): Allow server command on the command
 	line.
 
 2008-05-20  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf.h (gc_component_check_programs): Rename to ...
 	(gc_check_programs): ... this.
 	(gc_component_change_options): Add argument OUT.
 	(gc_component_check_options): New function.
 	* gpgconf.c (enum cmd_and_opt_values): New option aCheckOptions.
 	(opts): Add new option aCheckOptions (aka --check-options).
 	(main): Handle new option aCheckOptions.
 	* gpgconf-comp.c (gc_component_check_programs): Rename to ...
 	(gc_check_programs): ... this.  Refactor core of it to ...
 	(gc_component_check_options): ... this new function.
 	(gc_component_change_options): Add new argument OUT.  Externally
 	verify all changes.  Implement option --dry-run.
 
 2008-05-09  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (my_dgettext) [USE_SIMPLE_GETTEXT]:  Hack to
 	parly support translations.
 
 2008-04-08  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gc_options_gpg): Add --auto-key-locate.
 
 2008-03-26  Werner Koch  <wk@g10code.com>
 
 	* make-dns-cert.c: Include unistd.h.  Use config.h if requested.
 	(cert_key): Protect read against EINTR.
 	(main): Print SVN revision for standalone version.
 
 2008-03-05  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (arithmetic_op): Add logical not, or and and.
 	(get_var_ext): Add functions errcode, errsource and errstring.
 	(read_and_print_response): Store server reply in $? variable.
 	(main): Implement IF command.
 
 2008-02-27  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (option_check_validity): For now, error out on
 	empty strings.
 	(enum): Add GC_ARG_TYPE_PUB_KEY and GC_ARG_TYPE_SEC_KEY.
 
 2008-02-01  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_component_list_options): Fix memcpy.
 	Reported by Marc Mutz.
 
 2008-01-22  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Use gnupg domain for honor-http-proxy.  Make
 	"LDAP server list" group title translatable.
 
 2008-01-17  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (change_options_program): Strip duplicated
 	utf8-strings entries for gnupg backend.  Don't create them either.
 
 2007-12-10  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_component_list_options): Fix up expert level
 	of group.
 
 2007-12-04  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_component_list_components): Do not print a
 	trailing semi-colon to ensure forward compatibility, as this would
 	indicate another empty field.
 	(gc_process_gpgconf_conf): Likewise.
 
 2007-11-15  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (start_agent): Adjust changed
 	send_pinentry_environment.
 
 2007-10-24  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (substitute_line): Restore temporary nul
 	marker.
 	(main): Add /while command.
 
 2007-10-23  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gc_process_gpgconf_conf): Add arg
 	LISTFP.  Changed all callers.
 	* gpgconf.h: Add gc_error.
 	* gpgconf.c: Add command --list-config.
 	(get_outfp): New.
 	(main): Make --output work.
 
 	* gpgconf-comp.c (gc_options_gpg_agent): Replace accidently used
 	GC_BACKEND_SCDAEMON.  We should consider to create these tables
 	from plain files.
 
 2007-10-22  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (retrieve_options_from_program): Replace use of
 	popen by our gnupg_spawn_process_fd.  This is required because
 	popen under Windows can't handle long filenames.
 
 2007-10-19  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c (confucius_get_pass): Use utf8 switching functions.
 
 	* gpg-connect-agent.c (get_var_ext): New.
 	(substitute_line): Use it.
 	(assign_variable): Implement /slet in terms of get_var_ext.
 	(main): New option -s/--subst.
 	(add_definq): Add arg IS_VAR.  Change all callers.
 	(main): Add command /definq.
 	(handle_inquire): Implement new command.
 	(substitute_line_copy): New.
 	(unescape_string, unpercent_string): New.
 	* no-libgcrypt.c (gcry_set_outofcore_handler) 
 	(gcry_set_fatalerror_handler, gcry_set_log_handler): New.
 	* Makefile.am (gpg_connect_agent_LDADD): Link to libreadline.
 
 	* gpgconf-comp.c (retrieve_options_from_file): Don't call fclose
 	with NULL.  Fixes bug 842.
 
 2007-10-12  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (substitute_line): Allow ${foo} syntax.
 
 2007-10-11  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (get_var): Expand environment variables.
 	Suggested by Marc Mutz.
 	(set_var): Return the value.
 	(assign_variable): Add arg syslet.
 	(main): New command /slet.
 	(gnu_getcwd): New.
 	(assign_variable): Add tag cwd, and *dir.
 
 2007-10-02  Werner Koch  <wk@g10code.com>
 
 	* no-libgcrypt.c (gcry_malloc_secure): New.
 
 	* gpg-connect-agent.c (set_var, set_int_var, get_var)
 	(substitute_line, show_variables, assign_variable)
 	(do_open, do_close, do_showopen): New.
 	(main): Add new commands /nosubst, /subst, /let, /showvar, /open,
 	/close and /showopen.
 	(main): New commands /run and /bye.
 
 2007-10-01  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (do_sendfd): Use INT2FD for assuan_sendfd.
 
 2007-09-26  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (main): Print the first response from the
 	server.
 
 2007-09-14  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Make a string translatable.
 
 2007-09-04  Moritz Schulte  <moritz@g10code.com>
 
 	* gpgsm-gencert.sh: Use printf instead of echo.
 
 2007-09-04  Moritz Schulte  <moritz@g10code.com>
 
 	* gpgkey2ssh.c: Include sysutils.h so that gnupg_tmpfile() is
 	declared.
 
 2007-08-31  Werner Koch  <wk@g10code.com>
 
 	* gpgparsemail.c: Support PGP/MIME signed messages.
 
 	* gpgconf-comp.c (gc_component_list_components): List the programs
 	names.
 
 2007-08-29  Werner Koch  <wk@g10code.com>
 
 	* gpgconf.c: New command --check-programs.
 	* gpgconf-comp.c (gc_component_check_programs): New.
 	(gc_backend): Add member MODULE_NAME and add these module names.
 	(retrieve_options_from_program): Use module name so that we use an
 	absolute file name and don't rely on $PATH.
 	(collect_error_output): New.
 	* no-libgcrypt.c (gcry_control): New.
 
 2007-08-28  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c <gpg-agent>: Add options --max-passphrase-days
 	and --enable-passphrase-history.
 
 2007-08-27  Werner Koch  <wk@g10code.com>
 
 	* gpg-check-pattern.c: New
 	* Makefile.am (libexec_PROGRAMS): Add unless DISABLE_REGEX.
 
 2007-08-24  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c <gpg-agent>: Add options --check-passphrase-pattern,
 	--min-passphrase-nonalpha and --enforce-passphrase-constraints and
 	move them into a new "passphrase policy" group.
 	(gc_component) [W32]: Enable dirmngr.
 
 2007-08-21  Werner Koch  <wk@g10code.com>
 
 	* gpgkey2ssh.c (key_to_blob): Use gnupg_tmpfile().
 
 2007-08-02  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Factor the public GC_OPT_FLAG constants out and
 	include gc-opt-flags.h.
 
 2007-07-17  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Add --encrypt-to and --default-key to gpg and
 	gpgsm.
 
 2007-07-16  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpg-connect-agent.c (main): Bail out if write fails.
 
 2007-07-05  Marcus Brinkmann  <marcus@g10code.de>
 
 	* symcryptrun.c (confucius_get_pass): Define orig_codeset if
 	[ENABLE_NLS], not [HAVE_LANGINFO_CODESET].
 
 2007-06-26  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (key_matches_user_or_group) [W32]: Implement user
 	name matching.
 	(GPGNAME): New.  Use it instead of "gpg".
 	(gc_component) [W32]:  Disable dirmngr for now.
 	(gc_component_retrieve_options): Ignore components without options.
 	(gc_component_change_options): Ditto.
 	(gc_component_list_options): Ditto.
 	(gc_component_find, gc_component_list_components): Ditto.
 
 2007-06-19  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (percent_escape): Rename to my_percent_escape.
 	Changed all callers.
 
 2007-06-18  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (retrieve_options_from_file): Close LIST_FILE.
 	(copy_file): In error case, save/restore errno.  Close SRC and DST.
 	(gc_component_change_options): Catch error from unlink().  Remove
 	target backup file before rename().
 
 2007-06-15  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (copy_file) [HAVE_W32_SYSTEM]: New function.
 	(change_options_file, change_options_program) [HAVE_W32_SYSTEM]:
 	Copy backup file.
 	(gc_component_change_options) [HAVE_W32_SYSTEM]: Non-atomic replace.
 	(gc_process_gpgconf_conf): Rename fname to fname_arg and
 	fname_buffer to fname, initialize fname with fname_arg, discarding
 	const qualifier.
 
 2007-06-15  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (symcryptrun_LDADD): It is LIBICONV and not LIBINCONV.
 	(gpgconf_LDADD, symcryptrun_LDADD): Add W32SOCKLIBS.
 
 2007-06-14  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c (main): Setup default socket name for
 	simple-pwquery.
 	(MAP_SPWQ_ERROR_IMPL): New.  Use it for all spwq error returns.
 
 2007-06-12  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gc_process_gpgconf_conf): Replace
 	GNUPG_SYSCONFDIR by a function call.
 
 	* gpg-connect-agent.c (main): Replace some calls by
 	init_common_subsystems.
 	* gpgconf.c (main): Ditto.
 	* symcryptrun.c (main): Ditto.
 
 2007-06-11  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c (main) [W32]: Call pth_init.
 	* gpgconf.c (main) [W32]: Call pth_init
 	* gpg-connect-agent.c (main) [W32]: Call pth_init.
 
 2007-06-06  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (bin_PROGRAMS) [W32]: Do not build gpgparsemail.
 
 	* gpgconf-comp.c [W32]: Do not include pwd.h and grp.h.
 	(key_matches_user_or_group) [W32]: For now always return false.
 
 	* symcryptrun.c (i18n_init): Remove.
 	* gpgconf.c (i18n_init): Remove.
 	* gpg-connect-agent.c (i18n_init): Remove.
 
 2007-05-19  Marcus Brinkmann  <marcus@g10code.de>
 
 	* symcryptrun.c (confucius_get_pass): Free ORIG_CODESET on error.
 
 2007-05-08  Werner Koch  <wk@g10code.com>
 
 	* sockprox.c: New.  It needs to be build manually. By Moritz
 	Schulte.
 
 2007-04-20  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c (my_gcry_logger): Removed.
 	(main): Call setup_libgcrypt_logging.
 
 2007-04-03  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Allow changing of --allow-mark-trusted.
 
 	* gpg-connect-agent.c (main): New option --decode and commands
 	decode and undecode.
 	(read_and_print_response): Implement option.
 
 2007-03-20  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gc_options_gpgsm): Add p12-charset.
 
 2007-03-07  Werner Koch  <wk@g10code.com>
 
 	* applygnupgdefaults: New.
 	* Makefile.am (sbin_SCRIPTS): Add it
 
 2007-03-06  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Include pwd.h and grp.h.
 	(GC_OPT_FLAG_NO_CHANGE): New.
 	(gc_component_change_options): Implement it.
 	(gc_options_gpg_agent): Add options for all ttl values and
 	min-passphrase-length.  Apply new flag to some of them.
 	(gc_process_gpgconf_conf, key_matches_user_or_group): New.
 	(gc_component_change_options): Factor some code out to ..
 	(change_one_value): .. new. 
 	(gc_component_retrieve_options): Allow -1 for COMPONENT to iterate
 	over al components.
 	* gpgconf.c (main): New commands --check-config and
 	--apply-defaults.  Call gc_process_gpgconf_conf.
 
 2007-01-31  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (symcryptrun_LDADD): Add LIBICONV.
 	(gpgkey2ssh_LDADD): Ditto.
 
 2006-12-13  David Shaw  <dshaw@jabberwocky.com>
 
 	* Makefile.am (gpgsplit_LDADD): Link to LIBINTL if we're using the
 	built-in code.
 
 2006-12-07  David Shaw  <dshaw@jabberwocky.com>
 
 	* Makefile.am: Link to iconv for jnlib dependency.
 
 2006-11-23  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (gpg_connect_agent_LDADD): Add NETLIBS.
 
 2006-11-21  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (list_one_option): Cast print size_t arg.
 
 2006-11-17  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Made disable-keypad a basic option.
 
 2006-11-03  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c: Include signal.h and include pth.h only if test
 	asserts that it exists.
 
 2006-10-23  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c <gpgsm>: Add --cipher-algo.
 
 2006-10-20  Werner Koch  <wk@g10code.com>
 
 	* gpgsm-gencert.sh: Enhanced the main menu. 
 
 2006-10-12  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (gpg-zip, gpgsplit): Do not install due to a
 	conflict with gpg1.
 
 2006-10-11  Werner Koch  <wk@g10code.com>
 
 	* gpgsm-gencert.sh: Allow generation of card keys.
 
 2006-10-08  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (gpgkey2ssh_LDADD): Add LIBINTL. Suggested by
 	Andreas Metzler.
 
 2006-09-22  Werner Koch  <wk@g10code.com>
 
 	* no-libgcrypt.c: Changed license to a simple all permissive one.
 
 2006-09-20  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am: Changes to allow parallel make runs.
 
 2006-09-12  Werner Koch  <wk@g10code.com>
 
  	Replaced all call gpg_error_from_errno(errno) by
 	gpg_error_from_syserror().
 
 	* gpg-connect-agent.c (read_and_print_response): With verbosity
 	level 2 also print comment lines.
 
 2006-09-06  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c: Switch everything to new Assuan error code
 	style.
 
 	* no-libgcrypt.c (out_of_core): Reanmed to ...
 	(out_of_memory): .. this to avoid name clash with util.h.
 
 2006-08-21  Werner Koch  <wk@g10code.com>
 
 	* gpgsplit.c: New. Taken from 1.4. Adjusted to GnuPG2.
 
 	* Makefile.am (noinst_PROGRAMS): New.
 
 2006-06-09  Marcus Brinkmann  <marcus@g10code.de>
 
 	* Makefile.am (gpgconf_LDADD): Add $(GPG_ERROR_LIBS).
 	(gpgkey2ssh_LDADD): Add ../jnlib/libjnlib.a.
 
 2006-05-23  Werner Koch  <wk@g10code.com>
 
 	* gpgparsemail.c: Include config.h if available
 	(stpcpy): Conditional include it.
 
 	* gpgconf-comp.c (hextobyte): Removed as it is now availble in
 	jnlib.
 
 2005-12-20  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gc_options_gpg): Add allow-pka-lookup.
 
 2005-12-14  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (bin_PROGRAMS): Build gpgparsemail.
 
 	* gpgparsemail.c (pkcs7_begin): New.
 	(parse_message, message_cb): Add support of direct pkcs signatures.
 
 2005-10-19  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (gc_options_scdaemon): New option --disable-keypad.
 
 2005-09-22  Werner Koch  <wk@g10code.com>
 
 	* rfc822parse.c (parse_field): Tread Content-Disposition special.
 
 2005-10-08  Marcus Brinkmann  <marcus@g10code.de>
 
 	* Makefile.am (watchgnupg_LDADD): New variable.
 
 	* Makefile.am (gpgconf_LDADD): Add ../gl/libgnu.a after
 	../common/libcommon.a.
 	(symcryptrun_LDADD, gpg_connect_agent_LDADD, gpgkey2ssh_LDADD):
 	Likewise.
 
 2005-09-29  Marcus Brinkmann  <marcus@g10code.de>
 
 	* Makefile.am (AM_CFLAGS): Add $(LIBGCRYPT_CFLAGS).
 
 2005-09-06  Werner Koch  <wk@g10code.com>
 
 	* rfc822parse.c, rfc822parse.h:  Changed license to LGPL.
 
 2005-08-01  Werner Koch  <wk@g10code.com>
 
 	* gpgsm-gencert.sh: Allow entering a keygrip to generate a CSR from
 	an existing key.
 
 2005-07-21  Werner Koch  <wk@g10code.com>
 
 	* gpgsm-gencert.sh: Reworked to allow for multiple email addresses
 	as well as DNsanmes and URi.  Present the parameter file before
 	creating the certificate.
 
 2005-07-04  Marcus Brinkmann  <marcus@g10code.de>
 
 	* symcryptrun.c (SYMC_BAD_PASSPHRASE, SYMC_CANCELED): New symbols,
 	use instead constants.
 	(hash_string): New function copied from simple-gettext.c.
 	(confucius_get_pass): Take new argument CACHEID.
 	(confucius_process): Calculate cacheid and pass it to
 	confucius_get_pass.  Clear passphrase from cache if necessary.
 
 2005-06-16  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (read_and_print_response): Made LINELEN a
 	size_t.
 
 2005-06-04  Marcus Brinkmann  <marcus@g10code.de>
 
 	* symcryptrun.c (main): Allow any number of arguments, don't use
 	first argument as input file name.  Pass extra arguments to
 	confucius_main.
 	(confucius_main): Accept new arguments argc and argv and pass them
 	to confucius_process.
 	(confucius_process): Accept new arguments argc and argv and pass
 	them to the confucius process.
 
 2005-06-01  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c: Include mkdtemp.h. 
 
 2005-05-31  Werner Koch  <wk@g10code.com>
 
 	* watchgnupg.c: Make sure that PF_LCOAL and AF_LOCAL are defines.
 	Noted by Ray Link.
 
 2005-05-28  Moritz Schulte  <moritz@g10code.com>
 
 	* gpgkey2ssh.c: New file.
 	* Makefile.am (bin_PROGRAMS): Added gpgkey2ssh.
 
 2005-05-20  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (add_definq, show_definq, clear_definq)
 	(handle_inquire): New.
 	(read_and_print_response): Handle INQUIRE command.
 	(main): Implement control commands.
 
 2005-04-21  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c (main): Optionally allow the input file as command
 	line argument.
 
 	* gpgconf-comp.c: Add gpgsm option disable-trusted-cert-crl-check.
 
 2005-04-20  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Add gpg-agent:disable-scdaemon.
 
 2005-04-19  Marcus Brinkmann  <marcus@g10code.de>
 
 	* symcryptrun.c: Add --input option.
 
 2005-04-15  Marcus Brinkmann  <marcus@g10code.de>
 
 	* symcryptrun.c (TEMP_FAILURE_RETRY): Define if not defined.
 
 	* symcryptrun.c (remove_file): New function.
 	(confucius_copy_file): Accept new argument PLAIN and shred the
 	file if it is set on error.
 
 	* Makefile.am: Define symcryptrun make variable depending on
 	BUILD_SYMCRYPTUN.
 	(bin_PROGRAMS): Add ${symcryptrun} instead symcryptrun.
 	(symcryptrun_LDADD): Use $(LIBUTIL_LIBS) instead of -lutil.
 
 2005-04-11  Werner Koch  <wk@g10code.com>
 
 	* symcryptrun.c (confucius_mktmpdir): Changed to use mkdtmp(3).
 
 2005-04-11  Marcus Brinkmann  <marcus@g10code.de>
 
 	* symcryptrun.c: Implement config file parsing.
 	
 	* Makefile.am (bin_PROGRAMS): Add symcryptrun.
 	(symcryptrun_SOURCES, symcryptrun_LDADD): New variables.
 	* symcryptrun.c: New file.
 
 2005-03-31  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c (start_agent): Use PATHSEP_C instead of ':'.
 
 2005-03-09  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c <dirmngr>: Add honor-http-proxy.
 
 2005-02-25  Werner Koch  <wk@g10code.com>
 
 	* no-libgcrypt.c (gcry_strdup): New.
 
 2005-02-24  Werner Koch  <wk@g10code.com>
 
 	* gpg-connect-agent.c: New.
 	* Makefile.am: Add it. 
 
 2004-12-21  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (get_config_pathname) [DOSISH]: Detect absolute
 	pathnames with a drive letter.
 
 2004-12-15  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (bin_PROGRAMS) [W32]: Do not build watchgnupg.
 
 	* gpgconf-comp.c (gpg_agent_runtime_change) [W32]: No way yet to
 	send a signal.  Disable.
 	(change_options_file, change_options_program) [W32]: No link(2),
 	so we disable it.
 	(gc_component_change_options): Use rename instead of link.
 
 2004-12-13  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c <ignore-ocsp-service-url>: Fixed typo.
 
 2004-11-24  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c <dirmngr>: Add --ignore-http-dp, --ignore-ldap-dp
 	and --ignore-ocsp-service-url.
 
 2004-11-23  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c <dirmngr>: Add the proxy options.
 	<gpgsm>: Add --prefer-system-daemon.
 
 2004-11-11  Werner Koch  <wk@g10code.com>
 
 	* watchgnupg.c (main): Fixed test for read error.
 
 2004-10-22  Werner Koch  <wk@g10code.com>
 
 	* Makefile.am (bin_SCRIPTS): Add gpgsm-gencert.sh
 
 	* gpgsm-gencert.sh: Fixed copyright; its part of GnuPG thus FSF.
 
 2004-10-01  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Made all strings for --log-file read the same.
 	
 2004-10-01  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c (my_dgettext): Also switch codeset and directory
 	for the other used domains (i.e. dirmngr).
 
 	* gpgconf.c (main): Fixed translation markers.
 
 2004-09-30  Werner Koch  <wk@g10code.com>
 
 	* gpgconf.c (i18n_init): Always use LC_ALL.
 
 	* Makefile.am: Adjusted for gettext 0.14.
 
 2004-09-29  Werner Koch  <wk@g10code.com>
 
 	* gpgconf-comp.c: Made the entries fro GROUPs translatable.
 	Include i18n.h.
 	(my_dgettext): Hack to use the gnupg2 domain.
 
 2004-08-09  Moritz Schulte  <moritz@g10code.com>
 
 	* gpgsm-gencert.sh: New file.
 
 2004-06-16  Werner Koch  <wk@gnupg.org>
 
 	* rfc822parse.c (rfc822parse_get_field): Add arg VALUEOFF.
 
 2004-06-14  Werner Koch  <wk@gnupg.org>
 
 	* no-libgcrypt.c (gcry_realloc, gcry_xmalloc, gcry_xcalloc): New.
 
 	* gpgconf-comp.c (retrieve_options_from_program) 
 	(retrieve_options_from_file, change_options_file) 
 	(change_options_program, gc_component_change_options): Replaced
 	getline by read_line and test for allocation failure.
 
 2004-05-21  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_options_dirmngr): Remove CRL group, put its
 	only option "max-replies" into LDAP group.
 	(gc_component): Change description of dirmngr to "Directory
 	Manager".
 
 	* gpgconf-comp.c (gc_component_change_options): Move the
 	per-process backup file into a standard location.
 
 2004-05-03  Werner Koch  <wk@gnupg.org>
 
 	* gpgconf-comp.c: Add --allow-mark-trusted for the gpg-agent.
 
 2004-04-30  Werner Koch  <wk@gnupg.org>
 
 	* gpgconf-comp.c: Added more runtime flags for the gpg-agent
 	backend.
 
 2004-04-29  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (change_options_program): Turn on utf8-strings in
 	the gpgconf specific part of the config file for the GnuPG
 	backend.
 
 2004-04-28  Werner Koch  <wk@gnupg.org>
 
 	* gpgconf-comp.c: Add --ocsp-signer for the dirmngr backend.
 
 2004-04-20  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_options_gpg_agent): Change type of
 	ignore-cache-for-signing option to GC_ARG_TYPE_NONE.
 
 2004-04-07  Werner Koch  <wk@gnupg.org>
 
 	* gpgconf-comp.c (my_dgettext): Switch the codeset once to utf-8.
 	Allow building with out NLS.
 
 2004-03-23  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_options_dirmngr): Set GC_OPT_FLAG_ARG_OPT for
 	"LDAP Server".
 	(change_options_file): Remove assertion that tests that this flag
 	is not present.  Handle an empty string in OPTION->new_value.
 
 	* gpgconf.c (main): Remove obsolete warning.
 
 2004-03-23  Werner Koch  <wk@gnupg.org>
 
 	* gpgconf-comp.c (gc_options_gpg): New.
 	(gc_component_t, gc_component): Add GC_BACKEND_GPG.
 	(gc_options_dirmngr): Add allow-ocsp.
 
 2004-03-23  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_flag): Add missing flags.
 
 	* gpgconf-comp.c: Include <signal.h>.
 	(gc_backend): Add new member runtime_change.
 	(gpg_agent_runtime_change): New function.
 	(gc_component_change_options): New variable runtime.  Initialize
 	it.  If an option is changed that has the GC_OPT_FLAG_RUNTIME bit
 	set, also set the corresponding runtime variable.  Finally, call
 	the runtime_change callback of the backend if needed.	
 
 2004-03-16  Werner Koch  <wk@gnupg.org>
 
 	* gpgconf-comp.c (gc_options_gpg_agent): Implemented.
 	(gc_options_gpgsm, gc_options_scdaemon): Implemented.
 	(gc_backend_t): Add GC_BACKEND_SCDAEMON.
 
 2004-03-12  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_component_change_options): Set the filenames
 	of the option's backend, not of the component.
 	Also use GC_BACKEND_NR, not GC_COMPONENT_NR.
 
 2004-03-09  Werner Koch  <wk@gnupg.org>
 
 	* gpgconf-comp.c [_riscos_]: Removed special code for RISC OS; we
 	don't want to clutter our code with system dependent stuff.
 
 2004-03-08  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (retrieve_options_from_file): Quote each string
 	in the list, not only the first.
 
 2004-02-26  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_component_list_options): Do not print empty
 	groups.
 
 	* gpgconf-comp.c (option_check_validity): Check if option is
 	active.
 	(change_options_file): Implement.
 
 	* gpgconf-comp.c (retrieve_options_from_program): Remove broken
 	string handling.
 
 	* gpgconf-comp.c (change_options_program): Support all types of
 	options, including list types.
 
 	* README.gpgconf: Fix description of arguments.
 	* gpgconf-comp.c (option_check_validity): Rewritten to properly
 	support optional arguments in lists.
 
 	* README.gpgconf: Add info about optional arg and arg type 0.
 	* gpgconf-comp.c (gc_component_change_options): Parse list of
 	arg type 0 options.
 	(option_check_validity): Add new argument NEW_VALUE_NR.  Perform
 	rigorous validity checks.
 	(change_options_program): Disable an option also if we have a new
 	value for it.
 
 2004-02-25  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_component_list_options): Correct output for
 	lists of arg type none.
 	(struct gc_option): Add new member new_flags.
 	(option_check_validity): Check OPTION->new_flags beside
 	OPTION->new_value.  Add new argument FLAGS.
 	(gc_component_change_options): Support default flag correctly.
 	(change_options_program): Likewise.
 
 2004-02-24  Marcus Brinkmann  <marcus@g10code.de>
 
 	* README.gpgconf: Revert last change.  Add new flags "default",
 	"default desc" and "no arg desc".  Add new field ARGDEF.  Add new
 	field FLAG to backend interface.
 	* gpgconf-comp.c (struct gc_option): Make flags of type unsigned
 	long.
 	(gc_component_list_options): Adjust type for flags.
 	Add default argument field.
 	(retrieve_options_from_program): Use "1" as value for non-option
 	arguments, not "Y".
 	(gc_component_change_options): Read in flags from input.
 
 2004-02-23  Marcus Brinkmann  <marcus@g10code.de>
 
 	* README.gpgconf: Change meaning of type 0 options value if it is
 	the empty string or "0".
 
 	* gpgconf.h (struct): Add member runtime.
 	* gpgconf.c: Add new option oRuntime.
 	(main): Same here.
 
 	* gpgconf-comp.c (hextobyte): New function.
 	(percent_deescape): New function.
 	(get_config_pathname): Percent deescape pathname if taken from
 	option (default) value.  Use default value only if it exists and
 	is not empty.  Use empty string otherwise.  Don't include leading
 	quote in pathname.
 	(change_options_program): Percent deescape string before writing
 	it out.
 	
 	* gpgconf-comp.c (gc_component_list_options): Do not skip groups
 	on output.
 
 2004-02-18  Werner Koch  <wk@gnupg.org>
 
 	* gpgconf-comp.c: Added empty components for gpgsm and scdaemon.
 
 2004-02-12  Werner Koch  <wk@gnupg.org>
 
 	* watchgnupg.c (main): Implement option "--".
 	(print_version): New.
 
 	* Makefile.am: Include cmacros.am for common flags.
 
 2004-02-03  Werner Koch  <wk@gnupg.org>
 
 	* addgnupghome: Try to use getent, so that it also works for NIS
 	setups.
 
 2004-01-31  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c: Some bug fixes, parse only defaults from the
 	program, and read the current values from the configuration file
 	directly.
 
 2004-01-30  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-comp.c (gc_error): New function, use it instead of
 	error() throughout.
 
 	* gpgconf-comp.c: Use xmalloc, libcommon's asctimestamp and
 	gnupg_get_time, fix error() invocation and use getline()
 	consistently.
 	
 2004-01-30  Werner Koch  <wk@gnupg.org>
 
 	* addgnupghome: Also set the group of copied files. 
 
 2004-01-30  Werner Koch  <wk@gnupg.org>
 
 	* Makefile.am (sbin_SCRIPTS): New, to install addgnupghome.
 	(EXTRA_DIST): Added rfc822parse.c rfc822parse.h gpgparsemail.c
 	which might be useful for debugging.
 
 2004-01-29  Werner Koch  <wk@gnupg.org>
 
 	* addgnupghome: New.
 
 2004-01-29  Marcus Brinkmann  <marcus@g10code.de>
 
 	* gpgconf-list.c: File removed.
 	* README.gpgconf: New file.
 	* gpgconf-comp.c: New file.
 	* Makefile.am (gpgconf_SOURCES): Remove gpgconf-list.c, add
 	gpgconf-comp.c.
 
 2004-01-16  Werner Koch  <wk@gnupg.org>
 
 	* watchgnupg.c (main): Need to use FD_ISSET for the client
 	descriptors too; aiiih.  Set the listening socket to non-blocking.
 
 2004-01-10  Werner Koch  <wk@gnupg.org>
 
 	* Makefile.am: Use GPG_ERROR_CFLAGS
 
 2004-01-05  Werner Koch  <wk@gnupg.org>
 
 	* Manifest: New.
 	* gpgconf.c, gpgconf.h, gpgconf-list.c: New. A skeleton for now.
 	* no-libgcrypt.c: New.
 	* Makefile.am: Add above.
 
 2003-12-23  Werner Koch  <wk@gnupg.org>
 
 	* Makefile.am: New.
 	* watchgnupg.c: New.
 
 
  Copyright 2003, 2004, 2005, 2006, 2007, 2008,
 	   2009, 2010 Free Software Foundation, Inc.
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
  modifications, as long as this notice is preserved.
 
  This file is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
index d0372469d..74feadb6c 100644
--- a/tools/gpgconf-comp.c
+++ b/tools/gpgconf-comp.c
@@ -1,3626 +1,3643 @@
 /* gpgconf-comp.c - Configuration utility for GnuPG.
  * Copyright (C) 2004, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with GnuPG; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #if HAVE_CONFIG_H
 #include <config.h>
 #endif
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <assert.h>
 #include <errno.h>
 #include <time.h>
 #include <stdarg.h>
 #ifdef HAVE_SIGNAL_H
 # include <signal.h>
 #endif
 #include <ctype.h>
 #ifdef HAVE_W32_SYSTEM
 # define WIN32_LEAN_AND_MEAN 1
 # include <windows.h>
 #else
 # include <pwd.h>
 # include <grp.h>
 #endif
 
 /* For log_logv(), asctimestamp(), gnupg_get_time ().  */
 #define JNLIB_NEED_LOG_LOGV
 #include "util.h"
 #include "i18n.h"
 #include "exechelp.h"
 
 #include "gc-opt-flags.h"
 #include "gpgconf.h"
 
-
 /* There is a problem with gpg 1.4 under Windows: --gpgconf-list
    returns a plain filename without escaping.  As long as we have not
    fixed that we need to use gpg2.  */
 #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
 #define GPGNAME "gpg2"
 #else
 #define GPGNAME "gpg"
 #endif
 
 
 /* TODO:
    Components: Add more components and their options.
    Robustness: Do more validation.  Call programs to do validation for us.
    Add options to change backend binary path.
    Extract binary path for some backends from gpgsm/gpg config.
 */
 
 
 #if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
 void gc_error (int status, int errnum, const char *fmt, ...) \
   __attribute__ ((format (printf, 3, 4)));
 #endif
 
 /* Output a diagnostic message.  If ERRNUM is not 0, then the output
    is followed by a colon, a white space, and the error string for the
    error number ERRNUM.  In any case the output is finished by a
    newline.  The message is prepended by the program name, a colon,
    and a whitespace.  The output may be further formatted or
    redirected by the jnlib logging facility.  */
 void
 gc_error (int status, int errnum, const char *fmt, ...)
 {
   va_list arg_ptr;
 
   va_start (arg_ptr, fmt);
   log_logv (JNLIB_LOG_ERROR, fmt, arg_ptr);
   va_end (arg_ptr);
 
   if (errnum)
     log_printf (": %s\n", strerror (errnum));
   else
     log_printf ("\n");
 
   if (status)
     {
       log_printf (NULL);
       log_printf ("fatal error (exit status %i)\n", status);
       exit (status);
     }
 }
 
 
 /* Forward declaration.  */
 static void gpg_agent_runtime_change (void);
 static void scdaemon_runtime_change (void);
 
 /* Backend configuration.  Backends are used to decide how the default
    and current value of an option can be determined, and how the
    option can be changed.  To every option in every component belongs
    exactly one backend that controls and determines the option.  Some
    backends are programs from the GPG system.  Others might be
    implemented by GPGConf itself.  If you change this enum, don't
    forget to update GC_BACKEND below.  */
 typedef enum
   {
     /* Any backend, used for find_option ().  */
     GC_BACKEND_ANY,
 
     /* The Gnu Privacy Guard.  */
     GC_BACKEND_GPG,
 
     /* The Gnu Privacy Guard for S/MIME.  */
     GC_BACKEND_GPGSM,
 
     /* The GPG Agent.  */
     GC_BACKEND_GPG_AGENT,
 
     /* The GnuPG SCDaemon.  */
     GC_BACKEND_SCDAEMON,
 
     /* The GnuPG directory manager.  */
     GC_BACKEND_DIRMNGR,
 
     /* The LDAP server list file for the director manager.  */
     GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST,
 
     /* The Pinentry (not a part of GnuPG, proper).  */
     GC_BACKEND_PINENTRY,
 
     /* The number of the above entries.  */
     GC_BACKEND_NR
   } gc_backend_t;
 
 
 /* To be able to implement generic algorithms for the various
    backends, we collect all information about them in this struct.  */
 static struct
 {
   /* The name of the backend.  */
   const char *name;
 
   /* The name of the program that acts as the backend.  Some backends
      don't have an associated program, but are implemented directly by
      GPGConf.  In this case, PROGRAM is NULL.  */
   char *program;
 
   /* The module name (GNUPG_MODULE_NAME_foo) as defined by
      ../common/util.h.  This value is used to get the actual installed
      path of the program.  0 is used if no backend program is
      available. */
   char module_name;
 
   /* The runtime change callback.  */
   void (*runtime_change) (void);
 
   /* The option name for the configuration filename of this backend.
      This must be an absolute filename.  It can be an option from a
      different backend (but then ordering of the options might
      matter).  Note: This must be unique among all components.  */
   const char *option_config_filename;
 
   /* If this is a file backend rather than a program backend, then
      this is the name of the option associated with the file.  */
   const char *option_name;
 } gc_backend[GC_BACKEND_NR] =
   {
     { NULL },		/* GC_BACKEND_ANY dummy entry.  */
     { "GnuPG", GPGNAME, GNUPG_MODULE_NAME_GPG,
       NULL, "gpgconf-gpg.conf" },
     { "GPGSM", "gpgsm", GNUPG_MODULE_NAME_GPGSM,
       NULL, "gpgconf-gpgsm.conf" },
     { "GPG Agent", "gpg-agent", GNUPG_MODULE_NAME_AGENT, 
       gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" },
     { "SCDaemon", "scdaemon", GNUPG_MODULE_NAME_SCDAEMON,
       scdaemon_runtime_change, "gpgconf-scdaemon.conf" },
     { "DirMngr", "dirmngr", GNUPG_MODULE_NAME_DIRMNGR,
       NULL, "gpgconf-dirmngr.conf" },
     { "DirMngr LDAP Server List", NULL, 0, 
       NULL, "ldapserverlist-file", "LDAP Server" },
     { "Pinentry", "pinentry", GNUPG_MODULE_NAME_PINENTRY,
       NULL, "gpgconf-pinentry.conf" },
   };
 
 
 /* Option configuration.  */
 
 /* An option might take an argument, or not.  Argument types can be
    basic or complex.  Basic types are generic and easy to validate.
    Complex types provide more specific information about the intended
    use, but can be difficult to validate.  If you add to this enum,
    don't forget to update GC_ARG_TYPE below.  YOU MUST NOT CHANGE THE
    NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE EXTERNAL
    INTERFACE.  */
 typedef enum
   {
     /* Basic argument types.  */
 
     /* No argument.  */
     GC_ARG_TYPE_NONE = 0,
 
     /* A String argument.  */
     GC_ARG_TYPE_STRING = 1,
 
     /* A signed integer argument.  */
     GC_ARG_TYPE_INT32 = 2,
 
     /* An unsigned integer argument.  */
     GC_ARG_TYPE_UINT32 = 3,
 
     /* ADD NEW BASIC TYPE ENTRIES HERE.  */
 
     /* Complex argument types.  */
 
     /* A complete filename.  */
     GC_ARG_TYPE_FILENAME = 32,
 
     /* An LDAP server in the format
        HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN.  */
     GC_ARG_TYPE_LDAP_SERVER = 33,
 
     /* A 40 character fingerprint.  */
     GC_ARG_TYPE_KEY_FPR = 34,
 
     /* A user ID or key ID or fingerprint for a certificate.  */
     GC_ARG_TYPE_PUB_KEY = 35,
 
     /* A user ID or key ID or fingerprint for a certificate with a key.  */
     GC_ARG_TYPE_SEC_KEY = 36,
 
     /* A alias list made up of a key, an equal sign and a space
        separated list of values.  */
     GC_ARG_TYPE_ALIAS_LIST = 37,
 
     /* ADD NEW COMPLEX TYPE ENTRIES HERE.  */
 
     /* The number of the above entries.  */
     GC_ARG_TYPE_NR
   } gc_arg_type_t;
 
 
 /* For every argument, we record some information about it in the
    following struct.  */
 static struct
 {
   /* For every argument type exists a basic argument type that can be
      used as a fallback for input and validation purposes.  */
   gc_arg_type_t fallback;
 
   /* Human-readable name of the type.  */
   const char *name;
 } gc_arg_type[GC_ARG_TYPE_NR] =
   {
     /* The basic argument types have their own types as fallback.  */
     { GC_ARG_TYPE_NONE, "none" },
     { GC_ARG_TYPE_STRING, "string" },
     { GC_ARG_TYPE_INT32, "int32" },
     { GC_ARG_TYPE_UINT32, "uint32" },
 
     /* Reserved basic type entries for future extension.  */
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
     { GC_ARG_TYPE_NR, NULL }, { GC_ARG_TYPE_NR, NULL },
 
     /* The complex argument types have a basic type as fallback.  */
     { GC_ARG_TYPE_STRING, "filename" },
     { GC_ARG_TYPE_STRING, "ldap server" },
     { GC_ARG_TYPE_STRING, "key fpr" },
     { GC_ARG_TYPE_STRING, "pub key" },
     { GC_ARG_TYPE_STRING, "sec key" },
     { GC_ARG_TYPE_STRING, "alias list" },
   };
 
 
 /* Every option has an associated expert level, than can be used to
    hide advanced and expert options from beginners.  If you add to
    this list, don't forget to update GC_LEVEL below.  YOU MUST NOT
    CHANGE THE NUMBERS OF THE EXISTING ENTRIES, AS THEY ARE PART OF THE
    EXTERNAL INTERFACE.  */
 typedef enum
   {
     /* The basic options should always be displayed.  */
     GC_LEVEL_BASIC,
 
     /* The advanced options may be hidden from beginners.  */
     GC_LEVEL_ADVANCED,
 
     /* The expert options should only be displayed to experts.  */
     GC_LEVEL_EXPERT,
 
     /* The invisible options should normally never be displayed.  */
     GC_LEVEL_INVISIBLE,
 
     /* The internal options are never exported, they mark options that
        are recorded for internal use only.  */
     GC_LEVEL_INTERNAL,
 
     /* ADD NEW ENTRIES HERE.  */
 
     /* The number of the above entries.  */
     GC_LEVEL_NR
   } gc_expert_level_t;
 
 /* A description for each expert level.  */
 static struct
 {
   const char *name;
 } gc_level[] =
   {
     { "basic" },
     { "advanced" },
     { "expert" },
     { "invisible" },
     { "internal" }
   };
 
 
 /* Option flags.  The flags which are used by the backends are defined
    by gc-opt-flags.h, included above.
 
    YOU MUST NOT CHANGE THE NUMBERS OF THE EXISTING FLAGS, AS THEY ARE
    PART OF THE EXTERNAL INTERFACE.  */
 
 /* Some entries in the option list are not options, but mark the
    beginning of a new group of options.  These entries have the GROUP
    flag set.  */
 #define GC_OPT_FLAG_GROUP	(1UL << 0)
 /* The ARG_OPT flag for an option indicates that the argument is
    optional.  This is never set for GC_ARG_TYPE_NONE options.  */
 #define GC_OPT_FLAG_ARG_OPT	(1UL << 1)
 /* The LIST flag for an option indicates that the option can occur
    several times.  A comma separated list of arguments is used as the
    argument value.  */
 #define GC_OPT_FLAG_LIST	(1UL << 2)
 /* The NO_CHANGE flag for an option indicates that the user should not
    be allowed to change this option using the standard gpgconf method.
    Frontends using gpgconf should grey out such options, so that only
    the current value is displayed.  */
 #define GC_OPT_FLAG_NO_CHANGE   (1UL <<7)
 
 
 /* A human-readable description for each flag.  */
 static struct
 {
   const char *name;
 } gc_flag[] =
   {
     { "group" },
     { "optional arg" },
     { "list" },
     { "runtime" },
     { "default" },
     { "default desc" },
     { "no arg desc" },
     { "no change" }
   };
 
 
 /* To each option, or group marker, the information in the GC_OPTION
    struct is provided.  If you change this, don't forget to update the
    option list of each component.  */
 struct gc_option
 {
   /* If this is NULL, then this is a terminator in an array of unknown
      length.  Otherwise, if this entry is a group marker (see FLAGS),
      then this is the name of the group described by this entry.
      Otherwise it is the name of the option described by this
      entry.  The name must not contain a colon.  */
   const char *name;
 
   /* The option flags.  If the GROUP flag is set, then this entry is a
      group marker, not an option, and only the fields LEVEL,
      DESC_DOMAIN and DESC are valid.  In all other cases, this entry
      describes a new option and all fields are valid.  */
   unsigned long flags;
 
   /* The expert level.  This field is valid for options and groups.  A
      group has the expert level of the lowest-level option in the
      group.  */
   gc_expert_level_t level;
 
   /* A gettext domain in which the following description can be found.
      If this is NULL, then DESC is not translated.  Valid for groups
      and options.
      
      Note that we try to keep the description of groups within the
      gnupg domain. 
      
      IMPORTANT: If you add a new domain please make sure to add a code
      set switching call to the function my_dgettext further below.  */
   const char *desc_domain;
 
   /* A gettext description for this group or option.  If it starts
      with a '|', then the string up to the next '|' describes the
      argument, and the description follows the second '|'. 
 
      In general enclosing these description in N_() is not required
      because the description should be identical to the one in the
      help menu of the respective program. */
   const char *desc;
 
   /* The following fields are only valid for options.  */
 
   /* The type of the option argument.  */
   gc_arg_type_t arg_type;
 
   /* The backend that implements this option.  */
   gc_backend_t backend;
 
   /* The following fields are set to NULL at startup (because all
      option's are declared as static variables).  They are at the end
      of the list so that they can be omitted from the option
      declarations.  */
 
   /* This is true if the option is supported by this version of the
      backend.  */
   int active;
 
   /* The default value for this option.  This is NULL if the option is
      not present in the backend, the empty string if no default is
      available, and otherwise a quoted string.  */
   char *default_value;
 
   /* The default argument is only valid if the "optional arg" flag is
      set, and specifies the default argument (value) that is used if
      the argument is omitted.  */
   char *default_arg;
 
   /* The current value of this option.  */
   char *value;
 
   /* The new flags for this option.  The only defined flag is actually
      GC_OPT_FLAG_DEFAULT, and it means that the option should be
      deleted.  In this case, NEW_VALUE is NULL.  */
   unsigned long new_flags;
 
   /* The new value of this option.  */
   char *new_value;
 };
 typedef struct gc_option gc_option_t;
 
 /* Use this macro to terminate an option list.  */
 #define GC_OPTION_NULL { NULL }
 
 
+#ifndef BUILD_WITH_AGENT
+#define gc_options_gpg_agent NULL
+#else
 /* The options of the GC_COMPONENT_GPG_AGENT component.  */
 static gc_option_t gc_options_gpg_agent[] =
  {
    /* The configuration file to which we write the changes.  */
    { "gpgconf-gpg-agent.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
 
    { "Monitor",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the diagnostic output") },
    { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
      "gnupg", "verbose",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
    { "quiet", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
      "gnupg", "be somewhat more quiet",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
 
    { "Configuration",
      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
      "gnupg", N_("Options controlling the configuration") },
    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", "|FILE|read options from FILE",
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
    { "disable-scdaemon", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", "do not use the SCdaemon",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Options useful for debugging") },
    { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
      "gnupg", "|LEVEL|set the debugging level to LEVEL",
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG_AGENT },
    { "log-file", GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
      "gnupg", N_("|FILE|write server mode logs to FILE"),
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
 
    { "Security",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the security") },
    { "default-cache-ttl", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_BASIC, "gnupg", 
      "|N|expire cached PINs after N seconds",
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "default-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_ADVANCED, "gnupg",
      N_("|N|expire SSH keys after N seconds"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "max-cache-ttl", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_EXPERT, "gnupg",
      N_("|N|set maximum PIN cache lifetime to N seconds"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "max-cache-ttl-ssh", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_EXPERT, "gnupg", 
      N_("|N|set maximum SSH key lifetime to N seconds"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "ignore-cache-for-signing", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_BASIC, "gnupg", "do not use the PIN cache when signing",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
    { "allow-mark-trusted", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_ADVANCED, "gnupg", "allow clients to mark keys as \"trusted\"",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
    { "no-grab", GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
      "gnupg", "do not grab keyboard and mouse",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
 
    { "Passphrase policy",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Options enforcing a passphrase policy") },
    { "enforce-passphrase-constraints", GC_OPT_FLAG_RUNTIME, 
      GC_LEVEL_EXPERT, "gnupg", 
      N_("do not allow to bypass the passphrase policy"),
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
    { "min-passphrase-len", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_ADVANCED, "gnupg", 
      N_("|N|set minimal required length for new passphrases to N"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "min-passphrase-nonalpha", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_EXPERT, "gnupg", 
      N_("|N|require at least N non-alpha characters for a new passphrase"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "check-passphrase-pattern", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_EXPERT,
      "gnupg", N_("|FILE|check new passphrases against pattern in FILE"),
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT },
    { "max-passphrase-days", GC_OPT_FLAG_RUNTIME,
      GC_LEVEL_EXPERT, "gnupg", 
      N_("|N|expire the passphrase after N days"),
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG_AGENT },
    { "enable-passphrase-history", GC_OPT_FLAG_RUNTIME, 
      GC_LEVEL_EXPERT, "gnupg", 
      N_("do not allow the reuse of old passphrases"),
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG_AGENT },
 
    GC_OPTION_NULL
  };
+#endif /*BUILD_WITH_AGENT*/
 
 
+#ifndef BUILD_WITH_SCDAEMON
+#define gc_options_scdaemon NULL
+#else
 /* The options of the GC_COMPONENT_SCDAEMON component.  */
 static gc_option_t gc_options_scdaemon[] =
  {
    /* The configuration file to which we write the changes.  */
    { "gpgconf-scdaemon.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
 
    { "Monitor",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the diagnostic output") },
    { "verbose", GC_OPT_FLAG_LIST|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
      "gnupg", "verbose",
      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", "be somewhat more quiet",
      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
 
    { "Configuration",
      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
      "gnupg", N_("Options controlling the configuration") },
    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", "|FILE|read options from FILE",
      GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
    { "reader-port", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
      "gnupg", "|N|connect to reader at port N",
      GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
    { "ctapi-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
      "gnupg", "|NAME|use NAME as ct-API driver",
      GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
    { "pcsc-driver", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
      "gnupg", "|NAME|use NAME as PC/SC driver",
      GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
    { "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
      "gnupg", "do not use the internal CCID driver",
      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
    { "disable-keypad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
      "gnupg", "do not use a reader's keypad",
      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
    { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
      "gnupg", "|N|disconnect the card after N seconds of inactivity",
      GC_ARG_TYPE_UINT32, GC_BACKEND_SCDAEMON },
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Options useful for debugging") },
    { "debug-level", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
      "gnupg", "|LEVEL|set the debugging level to LEVEL",
      GC_ARG_TYPE_STRING, GC_BACKEND_SCDAEMON },
    { "log-file", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_ADVANCED,
      "gnupg", N_("|FILE|write a log to FILE"),
      GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON },
 
    { "Security",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the security") },
    { "deny-admin", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
      "gnupg", "deny the use of admin card commands",
      GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
 
 
    GC_OPTION_NULL
  };
+#endif /*BUILD_WITH_SCDAEMON*/
 
-
+#ifndef BUILD_WITH_GPG
+#define gc_options_gpg NULL
+#else
 /* The options of the GC_COMPONENT_GPG component.  */
 static gc_option_t gc_options_gpg[] =
  {
    /* The configuration file to which we write the changes.  */
    { "gpgconf-gpg.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
 
    { "Monitor",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the diagnostic output") },
    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
      "gnupg", "verbose",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", "be somewhat more quiet",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
 
    { "Configuration",
      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
      "gnupg", N_("Options controlling the configuration") },
    { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", N_("|NAME|use NAME as default secret key"),
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
    { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", N_("|NAME|encrypt to user ID NAME as well"),
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
    { "group", GC_OPT_FLAG_LIST, GC_LEVEL_ADVANCED,
      "gnupg", N_("|SPEC|set up email aliases"),
      GC_ARG_TYPE_ALIAS_LIST, GC_BACKEND_GPG },
    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", "|FILE|read options from FILE",
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
    { "default_pubkey_algo",
      (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
    
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Options useful for debugging") },
    { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
      "gnupg", "|LEVEL|set the debugging level to LEVEL",
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", N_("|FILE|write server mode logs to FILE"),
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG },
 /*    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE, */
 /*      NULL, NULL, */
 /*      GC_ARG_TYPE_UINT32, GC_BACKEND_GPG }, */
 
    { "Keyserver",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Configuration for Keyservers") },
    { "keyserver", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", N_("|URL|use keyserver at URL"),
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
    { "allow-pka-lookup", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", N_("allow PKA lookups (DNS requests)"),
      GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
    { "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address"),
      GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
 
 
 
 
    GC_OPTION_NULL
  };
+#endif /*BUILD_WITH_GPG*/
 
 
-
+#ifndef BUILD_WITH_GPGSM
+#define gc_options_gpgsm NULL
+#else
 /* The options of the GC_COMPONENT_GPGSM component.  */
 static gc_option_t gc_options_gpgsm[] =
  {
    /* The configuration file to which we write the changes.  */
    { "gpgconf-gpgsm.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
 
    { "Monitor",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the diagnostic output") },
    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
      "gnupg", "verbose",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", "be somewhat more quiet",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
 
    { "Configuration",
      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
      "gnupg", N_("Options controlling the configuration") },
    { "default-key", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", N_("|NAME|use NAME as default secret key"),
      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
    { "encrypt-to", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", N_("|NAME|encrypt to user ID NAME as well"),
      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", "|FILE|read options from FILE",
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
    { "prefer-system-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", "use system's dirmngr if available",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "disable-dirmngr", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", N_("disable all access to the dirmngr"),
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "p12-charset", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", N_("|NAME|use encoding NAME for PKCS#12 passphrases"),
      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
    { "keyserver", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
      "gnupg", N_("|SPEC|use this keyserver to lookup keys"),
      GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_GPGSM },
    { "default_pubkey_algo",
      (GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Options useful for debugging") },
    { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
      "gnupg", "|LEVEL|set the debugging level to LEVEL",
      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", N_("|FILE|write server mode logs to FILE"),
      GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM },
    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_UINT32, GC_BACKEND_GPGSM },
 
    { "Security",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the security") },
    { "disable-crl-checks", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", "never consult a CRL",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "disable-trusted-cert-crl-check", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", N_("do not check CRLs for root certificates"),
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "enable-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", "check validity using OCSP",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "include-certs", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "gnupg", "|N|number of certificates to include",
      GC_ARG_TYPE_INT32, GC_BACKEND_GPGSM },
    { "disable-policy-checks", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", "do not check certificate policies",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "auto-issuer-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "gnupg", "fetch missing issuer certificates",
      GC_ARG_TYPE_NONE, GC_BACKEND_GPGSM },
    { "cipher-algo", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", "|NAME|use cipher algorithm NAME",
      GC_ARG_TYPE_STRING, GC_BACKEND_GPGSM },
 
    GC_OPTION_NULL
  };
+#endif /*BUILD_WITH_GPGSM*/
 
 
+#ifndef BUILD_WITH_DIRMNGR
+#define gc_options_dirmngr NULL
+#else
 /* The options of the GC_COMPONENT_DIRMNGR component.  */
 static gc_option_t gc_options_dirmngr[] =
  {
    /* The configuration file to which we write the changes.  */
    { "gpgconf-dirmngr.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
 
    { "Monitor",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the diagnostic output") },
    { "verbose", GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
      "dirmngr", "verbose",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "quiet", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "be somewhat more quiet",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "no-greeting", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
 
    { "Format",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the format of the output") },
    { "sh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "sh-style command output",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "csh", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "csh-style command output",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    
    { "Configuration",
      GC_OPT_FLAG_GROUP, GC_LEVEL_EXPERT,
      "gnupg", N_("Options controlling the configuration") },
    { "options", GC_OPT_FLAG_NONE, GC_LEVEL_EXPERT,
      "dirmngr", "|FILE|read options from FILE",
      GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
 
    { "Debug",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Options useful for debugging") },
    { "debug-level", GC_OPT_FLAG_ARG_OPT, GC_LEVEL_ADVANCED,
      "dirmngr", "|LEVEL|set the debugging level to LEVEL",
      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
    { "no-detach", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "do not detach from the console",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "log-file", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", N_("|FILE|write server mode logs to FILE"),
      GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
    { "debug-wait", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
    { "faked-system-time", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
      NULL, NULL,
      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
 
    { "Enforcement",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Options controlling the interactivity and enforcement") },
    { "batch", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "run without asking a user",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "force", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "force loading of outdated CRLs",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
 
    { "HTTP",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Configuration for HTTP servers") },
    { "disable-http", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "inhibit the use of HTTP",
       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "ignore-http-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "ignore HTTP CRL distribution points",
       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "|URL|redirect all HTTP requests to URL",
      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
    { "honor-http-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "gnupg", N_("use system's HTTP proxy setting"),
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
 
    { "LDAP",
      GC_OPT_FLAG_GROUP, GC_LEVEL_BASIC,
      "gnupg", N_("Configuration of LDAP servers to use") },
    { "disable-ldap", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "inhibit the use of LDAP",
       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "ignore-ldap-dp", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "ignore LDAP CRL distribution points",
       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "|HOST|use HOST for LDAP queries",
      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
    { "only-ldap-proxy", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "do not use fallback hosts with --ldap-proxy",
       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "add-servers", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "add new servers discovered in CRL distribution points"
      " to serverlist", GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "ldaptimeout", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "|N|set LDAP timeout to N seconds",
      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
    /* The following entry must not be removed, as it is required for
       the GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST.  */
    { "ldapserverlist-file",
      GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
      "dirmngr", "|FILE|read LDAP server list from FILE",
      GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR },
    /* This entry must come after at least one entry for
       GC_BACKEND_DIRMNGR in this component, so that the entry for
       "ldapserverlist-file will be initialized before this one.  */
    { "LDAP Server", GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_LIST, GC_LEVEL_BASIC,
      "gnupg", N_("LDAP server list"),
      GC_ARG_TYPE_LDAP_SERVER, GC_BACKEND_DIRMNGR_LDAP_SERVER_LIST },
    { "max-replies", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "|N|do not return more than N items in one query",
      GC_ARG_TYPE_UINT32, GC_BACKEND_DIRMNGR },
 
    { "OCSP",
      GC_OPT_FLAG_GROUP, GC_LEVEL_ADVANCED,
      "gnupg", N_("Configuration for OCSP") },
    { "allow-ocsp", GC_OPT_FLAG_NONE, GC_LEVEL_BASIC,
      "dirmngr", "allow sending OCSP requests",
      GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "ignore-ocsp-service-url", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "ignore certificate contained OCSP service URLs",
       GC_ARG_TYPE_NONE, GC_BACKEND_DIRMNGR },
    { "ocsp-responder", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "|URL|use OCSP responder at URL",
      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
    { "ocsp-signer", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
      "dirmngr", "|FPR|OCSP response signed by FPR",
      GC_ARG_TYPE_STRING, GC_BACKEND_DIRMNGR },
 
 
    GC_OPTION_NULL
  };
+#endif /*BUILD_WITH_DIRMNGR*/
 
 
 /* The options of the GC_COMPONENT_PINENTRY component.  */
 static gc_option_t gc_options_pinentry[] =
  {
    /* A dummy option to allow gc_component_list_components to find the
       pinentry backend.  Needs to be a conf file. */
    { "gpgconf-pinentry.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL,
      NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_PINENTRY },
 
    GC_OPTION_NULL
  };
 
 
 
 /* Component system.  Each component is a set of options that can be
    configured at the same time.  If you change this, don't forget to
    update GC_COMPONENT below.  */
 typedef enum
   {
     /* The classic GPG for OpenPGP.  */
     GC_COMPONENT_GPG,
 
     /* The GPG Agent.  */
     GC_COMPONENT_GPG_AGENT,
 
     /* The Smardcard Daemon.  */
     GC_COMPONENT_SCDAEMON,
 
     /* GPG for S/MIME.  */
     GC_COMPONENT_GPGSM,
 
     /* The LDAP Directory Manager for CRLs.  */
     GC_COMPONENT_DIRMNGR,
 
     /* The external Pinentry.  */
     GC_COMPONENT_PINENTRY,
 
     /* The number of components.  */
     GC_COMPONENT_NR
   } gc_component_t;
 
 
 /* The information associated with each component.  */
 static struct
 {
   /* The name of this component.  Must not contain a colon (':')
      character.  */
   const char *name;
 
   /* The gettext domain for the description DESC.  If this is NULL,
      then the description is not translated.  */
   const char *desc_domain;
 
   /* The description for this domain.  */
   const char *desc;
 
   /* The list of options for this component, terminated by
      GC_OPTION_NULL.  */
   gc_option_t *options;
 } gc_component[] =
   {
     { "gpg", NULL,   "GPG for OpenPGP", gc_options_gpg },
     { "gpg-agent", NULL, "GPG Agent", gc_options_gpg_agent },
     { "scdaemon", NULL, "Smartcard Daemon", gc_options_scdaemon },
     { "gpgsm", NULL, "GPG for S/MIME", gc_options_gpgsm },
     { "dirmngr", NULL, "Directory Manager", gc_options_dirmngr },
     { "pinentry", NULL, "PIN and Passphrase Entry", gc_options_pinentry }
   };
 
 
 
 /* Structure used to collect error output of the backend programs.  */
 struct error_line_s;
 typedef struct error_line_s *error_line_t;
 struct error_line_s
 {
   error_line_t next;   /* Link to next item.  */
   const char *fname;   /* Name of the config file (points into BUFFER).  */
   unsigned int lineno; /* Line number of the config file.  */
   const char *errtext; /* Text of the error message (points into BUFFER).  */
   char buffer[1];  /* Helper buffer.  */
 };
 
 
 
 /* Engine specific support.  */
 static void
 gpg_agent_runtime_change (void)
 {
   gpg_error_t err;
   const char *pgmname;
   const char *argv[2];
   pid_t pid;
   
   pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
   argv[0] = "reloadagent";
   argv[1] = NULL;
   
   err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
   if (!err)
     err = gnupg_wait_process (pgmname, pid, 1, NULL);
   if (err)
     gc_error (0, 0, "error running `%s%s': %s",
               pgmname, " reloadagent", gpg_strerror (err));
   gnupg_release_process (pid);
 }
 
 
 static void
 scdaemon_runtime_change (void)
 {
   gpg_error_t err;
   const char *pgmname;
   const char *argv[6];
   pid_t pid;
   
   /* We use "GETINFO app_running" to see whether the agent is already
      running and kill it only in this case.  This avoids an explicit
      starting of the agent in case it is not yet running.  There is
      obviously a race condition but that should not harm too much.  */
 
   pgmname = gnupg_module_name (GNUPG_MODULE_NAME_CONNECT_AGENT);
   argv[0] = "-s";
   argv[1] = "GETINFO scd_running";
   argv[2] = "/if ${! $?}";
   argv[3] = "scd killscd";
   argv[4] = "/end";
   argv[5] = NULL;
   
   err = gnupg_spawn_process_fd (pgmname, argv, -1, -1, -1, &pid);
   if (!err)
     err = gnupg_wait_process (pgmname, pid, 1, NULL);
   if (err)
     gc_error (0, 0, "error running `%s%s': %s",
               pgmname, " scd killscd", gpg_strerror (err));
   gnupg_release_process (pid);
 }
 
 
 /* Unconditionally reload COMPONENT or all components if COMPONENT is -1.  */
 void
 gc_component_reload (int component)
 {
   int runtime[GC_BACKEND_NR];
   gc_option_t *option;
   gc_backend_t backend;
 
   /* Set a flag for the backends to be reloaded.  */
   for (backend = 0; backend < GC_BACKEND_NR; backend++)
     runtime[backend] = 0;
   
   if (component == -1)
     {
       for (component = 0; component < GC_COMPONENT_NR; component++)
         {
           option = gc_component[component].options;
           for (; option && option->name; option++)
             runtime[option->backend] = 1;
         }
     }
   else
     {
       assert (component < GC_COMPONENT_NR);
       option = gc_component[component].options;
       for (; option && option->name; option++)
         runtime[option->backend] = 1;
     }
 
   /* Do the reload for all selected backends.  */
   for (backend = 0; backend < GC_BACKEND_NR; backend++)  
     {
       if (runtime[backend] && gc_backend[backend].runtime_change)
         (*gc_backend[backend].runtime_change) ();
     }
 }
 
 
 
 /* More or less Robust version of dgettext.  It has the side effect of
    switching the codeset to utf-8 because this is what we want to
    output.  In theory it is posible to keep the orginal code set and
    switch back for regular disgnostic output (redefine "_(" for that)
    but given the natur of this tool, being something invoked from
    other pograms, it does not make much sense.  */
 static const char *
 my_dgettext (const char *domain, const char *msgid)
 {
 #ifdef USE_SIMPLE_GETTEXT
   if (domain)
     {
       static int switched_codeset;
       char *text;
       
       if (!switched_codeset)
         {
           switched_codeset = 1;
           gettext_use_utf8 (1);
         }
 
       if (!strcmp (domain, "gnupg"))
         domain = PACKAGE_GT;
 
       /* FIXME: we have no dgettext, thus we can't switch.  */
 
       text = (char*)gettext (msgid);
       return text ? text : msgid;
     }
 #elif defined(ENABLE_NLS)
   if (domain)
     {
       static int switched_codeset;
       char *text;
       
       if (!switched_codeset)
         {
           switched_codeset = 1;
           bind_textdomain_codeset (PACKAGE_GT, "utf-8");
 
           bindtextdomain ("dirmngr", LOCALEDIR);
           bind_textdomain_codeset ("dirmngr", "utf-8");
    
         }
 
       /* Note: This is a hack to actually use the gnupg2 domain as
          long we are in a transition phase where gnupg 1.x and 1.9 may
          coexist. */
       if (!strcmp (domain, "gnupg"))
         domain = PACKAGE_GT;
 
       text = dgettext (domain, msgid);
       return text ? text : msgid;
     }
   else
 #endif
     return msgid;
 }
 
 
 /* Percent-Escape special characters.  The string is valid until the
    next invocation of the function.  */
 char *
 gc_percent_escape (const char *src)
 {
   static char *esc_str;
   static int esc_str_len;
   int new_len = 3 * strlen (src) + 1;
   char *dst;
 
   if (esc_str_len < new_len)
     {
       char *new_esc_str = realloc (esc_str, new_len);
       if (!new_esc_str)
 	gc_error (1, errno, "can not escape string");
       esc_str = new_esc_str;
       esc_str_len = new_len;
     }
 
   dst = esc_str;
   while (*src)
     {
       if (*src == '%')
 	{
 	  *(dst++) = '%';
 	  *(dst++) = '2';
 	  *(dst++) = '5';
 	}	  
       else if (*src == ':')
 	{
 	  /* The colon is used as field separator.  */
 	  *(dst++) = '%';
 	  *(dst++) = '3';
 	  *(dst++) = 'a';
 	}
       else if (*src == ',')
 	{
 	  /* The comma is used as list separator.  */
 	  *(dst++) = '%';
 	  *(dst++) = '2';
 	  *(dst++) = 'c';
 	}
       else
 	*(dst++) = *(src);
       src++;
     }
   *dst = '\0';
   return esc_str;
 }
 
 
 
 /* Percent-Deescape special characters.  The string is valid until the
    next invocation of the function.  */
 static char *
 percent_deescape (const char *src)
 {
   static char *str;
   static int str_len;
   int new_len = 3 * strlen (src) + 1;
   char *dst;
 
   if (str_len < new_len)
     {
       char *new_str = realloc (str, new_len);
       if (!new_str)
 	gc_error (1, errno, "can not deescape string");
       str = new_str;
       str_len = new_len;
     }
 
   dst = str;
   while (*src)
     {
       if (*src == '%')
 	{
 	  int val = hextobyte (src + 1);
 
 	  if (val < 0)
 	    gc_error (1, 0, "malformed end of string %s", src);
 
 	  *(dst++) = (char) val;
 	  src += 3;
 	}	  
       else
 	*(dst++) = *(src++);
     }
   *dst = '\0';
   return str;
 }
 
 
 /* List all components that are available.  */
 void
 gc_component_list_components (estream_t out)
 {
   gc_component_t component;
   gc_option_t *option;
   gc_backend_t backend;
   int backend_seen[GC_BACKEND_NR];
   const char *desc;
   const char *pgmname;
 
   for (component = 0; component < GC_COMPONENT_NR; component++)
     {
       option = gc_component[component].options;
       if (option)
         {
           for (backend = 0; backend < GC_BACKEND_NR; backend++)
             backend_seen[backend] = 0;
 
           pgmname = "";
           for (; option && option->name; option++)
             {
               if ((option->flags & GC_OPT_FLAG_GROUP))
                 continue;
               backend = option->backend;
               if (backend_seen[backend])
                 continue;
               backend_seen[backend] = 1;
               assert (backend != GC_BACKEND_ANY);
               if (gc_backend[backend].program
                   && !gc_backend[backend].module_name)
                 continue;
               pgmname = gnupg_module_name (gc_backend[backend].module_name);
               break;
             }
 
           desc = gc_component[component].desc;
           desc = my_dgettext (gc_component[component].desc_domain, desc);
           es_fprintf (out, "%s:%s:",
                       gc_component[component].name,  gc_percent_escape (desc));
           es_fprintf (out, "%s\n",  gc_percent_escape (pgmname));
         }
     }
 }
 
 
 
 static int
 all_digits_p (const char *p, size_t len)
 {
   if (!len)
     return 0; /* No. */
   for (; len; len--, p++)
     if (!isascii (*p) || !isdigit (*p))
       return 0; /* No.  */
   return 1; /* Yes.  */
 }
 
 
 /* Collect all error lines from stream FP. Only lines prefixed with
    TAG are considered.  Returns a list of error line items (which may
    be empty).  There is no error return.  */
 static error_line_t
 collect_error_output (estream_t fp, const char *tag)
 {
   char buffer[1024];
   char *p, *p2, *p3;
   int c, cont_line;
   unsigned int pos;
   error_line_t eitem, errlines, *errlines_tail;
   size_t taglen = strlen (tag);
 
   errlines = NULL;
   errlines_tail = &errlines;
   pos = 0;
   cont_line = 0;
   while ((c=es_getc (fp)) != EOF)
     {
       buffer[pos++] = c;
       if (pos >= sizeof buffer - 5 || c == '\n')
         {
           buffer[pos - (c == '\n')] = 0;
           if (cont_line)
             ; /*Ignore continuations of previous line. */
           else if (!strncmp (buffer, tag, taglen) && buffer[taglen] == ':') 
             {
               /* "gpgsm: foo:4: bla" */
               /* Yep, we are interested in this line.  */
               p = buffer + taglen + 1;
               while (*p == ' ' || *p == '\t')
                 p++;
               trim_trailing_spaces (p); /* Get rid of extra CRs.  */
               if (!*p)
                 ; /* Empty lines are ignored.  */
               else if ( (p2 = strchr (p, ':')) && (p3 = strchr (p2+1, ':'))
                         && all_digits_p (p2+1, p3 - (p2+1)))
                 {
                   /* Line in standard compiler format.  */
                   p3++;
                   while (*p3 == ' ' || *p3 == '\t')
                     p3++;
                   eitem = xmalloc (sizeof *eitem + strlen (p));
                   eitem->next = NULL;
                   strcpy (eitem->buffer, p);
                   eitem->fname = eitem->buffer;
                   eitem->buffer[p2-p] = 0;
                   eitem->errtext = eitem->buffer + (p3 - p);
                   /* (we already checked that there are only ascii
                      digits followed by a colon) */
                   eitem->lineno = 0;
                   for (p2++; isdigit (*p2); p2++)
                     eitem->lineno = eitem->lineno*10 + (*p2 - '0');
                   *errlines_tail = eitem;
                   errlines_tail = &eitem->next;
                 }
               else
                 {
                   /* Other error output.  */
                   eitem = xmalloc (sizeof *eitem + strlen (p));
                   eitem->next = NULL;
                   strcpy (eitem->buffer, p);
                   eitem->fname = NULL;
                   eitem->errtext = eitem->buffer;
                   eitem->lineno = 0;
                   *errlines_tail = eitem;
                   errlines_tail = &eitem->next;
                 }
             }
           pos = 0;
           /* If this was not a complete line mark that we are in a
              continuation.  */
           cont_line = (c != '\n');
         }
     }
   
   /* We ignore error lines not terminated by a LF.  */
   return errlines;
 }
 
 
 /* Check the options of a single component.  Returns 0 if everything
    is OK.  */
 int
 gc_component_check_options (int component, estream_t out, const char *conf_file)
 {
   gpg_error_t err;
   unsigned int result;
   int backend_seen[GC_BACKEND_NR];
   gc_backend_t backend;
   gc_option_t *option;
   const char *pgmname;
   const char *argv[4];
   int i;
   pid_t pid;
   int exitcode;
   estream_t errfp;
   error_line_t errlines;
 
   for (backend = 0; backend < GC_BACKEND_NR; backend++)
     backend_seen[backend] = 0;
 
   option = gc_component[component].options;
   for (; option && option->name; option++)
     {
       if ((option->flags & GC_OPT_FLAG_GROUP))
 	continue;
       backend = option->backend;
       if (backend_seen[backend])
 	continue;
       backend_seen[backend] = 1;
       assert (backend != GC_BACKEND_ANY);
       if (!gc_backend[backend].program)
 	continue;
       if (!gc_backend[backend].module_name)
 	continue;
 
       break;
     }
   if (! option || ! option->name)
     return 0;
 
   pgmname = gnupg_module_name (gc_backend[backend].module_name);
   i = 0;
   if (conf_file)
     {
       argv[i++] = "--options";
       argv[i++] = conf_file;
     }
   if (component == GC_COMPONENT_PINENTRY)
     argv[i++] = "--version";
   else
     argv[i++] = "--gpgconf-test";
   argv[i++] = NULL;
   
   result = 0;
   errlines = NULL;
   err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT, NULL, 0,
                              NULL, NULL, &errfp, &pid);
   if (err)
     result |= 1; /* Program could not be run.  */
   else 
     {
       errlines = collect_error_output (errfp, 
 				       gc_component[component].name);
       if (gnupg_wait_process (pgmname, pid, 1, &exitcode))
 	{
 	  if (exitcode == -1)
 	    result |= 1; /* Program could not be run or it
 			    terminated abnormally.  */
 	  result |= 2; /* Program returned an error.  */
 	}
       gnupg_release_process (pid);
       es_fclose (errfp);
     }
   
   /* If the program could not be run, we can't tell whether
      the config file is good.  */
   if (result & 1)
     result |= 2;  
   
   if (out)
     {
       const char *desc;
       error_line_t errptr;
 
       desc = gc_component[component].desc;
       desc = my_dgettext (gc_component[component].desc_domain, desc);
       es_fprintf (out, "%s:%s:",
                   gc_component[component].name, gc_percent_escape (desc));
       es_fputs (gc_percent_escape (pgmname), out);
       es_fprintf (out, ":%d:%d:", !(result & 1), !(result & 2));
       for (errptr = errlines; errptr; errptr = errptr->next)
 	{
 	  if (errptr != errlines)
 	    es_fputs ("\n:::::", out); /* Continuation line.  */
 	  if (errptr->fname)
 	    es_fputs (gc_percent_escape (errptr->fname), out);
 	  es_putc (':', out);
 	  if (errptr->fname)
 	    es_fprintf (out, "%u", errptr->lineno);
 	  es_putc (':', out);
 	  es_fputs (gc_percent_escape (errptr->errtext), out);
 	  es_putc (':', out);
 	}
       es_putc ('\n', out);
     }
 
   while (errlines)
     {
       error_line_t tmp = errlines->next;
       xfree (errlines);
       errlines = tmp;
     }
 
   return result;
 }
 
 
 
 /* Check all components that are available.  */
 void
 gc_check_programs (estream_t out)
 {
   gc_component_t component;
 
   for (component = 0; component < GC_COMPONENT_NR; component++)
     gc_component_check_options (component, out, NULL);
 }
 
 
 
 /* Find the component with the name NAME.  Returns -1 if not
    found.  */
 int
 gc_component_find (const char *name)
 {
   gc_component_t idx;
 
   for (idx = 0; idx < GC_COMPONENT_NR; idx++)
     {
       if (gc_component[idx].options
           && !strcmp (name, gc_component[idx].name))
 	return idx;
     }
   return -1;
 }
 
 
 /* List the option OPTION.  */
 static void
 list_one_option (const gc_option_t *option, estream_t out)
 {
   const char *desc = NULL;
   char *arg_name = NULL;
 
   if (option->desc)
     {
       desc = my_dgettext (option->desc_domain, option->desc);
 
       if (*desc == '|')
 	{
 	  const char *arg_tail = strchr (&desc[1], '|');
 
 	  if (arg_tail)
 	    {
 	      int arg_len = arg_tail - &desc[1];
 	      arg_name = xmalloc (arg_len + 1);
 	      memcpy (arg_name, &desc[1], arg_len);
 	      arg_name[arg_len] = '\0';
 	      desc = arg_tail + 1;
 	    }
 	}
     }
 
 
   /* YOU MUST NOT REORDER THE FIELDS IN THIS OUTPUT, AS THEIR ORDER IS
      PART OF THE EXTERNAL INTERFACE.  YOU MUST NOT REMOVE ANY
      FIELDS.  */
 
   /* The name field.  */
   es_fprintf (out, "%s", option->name);
 
   /* The flags field.  */
   es_fprintf (out, ":%lu", option->flags);
   if (opt.verbose)
     {
       es_putc (' ', out);
 	  
       if (!option->flags)
 	es_fprintf (out, "none");
       else
 	{
 	  unsigned long flags = option->flags;
 	  unsigned long flag = 0;
 	  unsigned long first = 1;
 
 	  while (flags)
 	    {
 	      if (flags & 1)
 		{
 		  if (first)
 		    first = 0;
 		  else
 		    es_putc (',', out);
 		  es_fprintf (out, "%s", gc_flag[flag].name);
 		}
 	      flags >>= 1;
 	      flag++;
 	    }
 	}
     }
 
   /* The level field.  */
   es_fprintf (out, ":%u", option->level);
   if (opt.verbose)
     es_fprintf (out, " %s", gc_level[option->level].name);
 
   /* The description field.  */
   es_fprintf (out, ":%s", desc ? gc_percent_escape (desc) : "");
   
   /* The type field.  */
   es_fprintf (out, ":%u", option->arg_type);
   if (opt.verbose)
     es_fprintf (out, " %s", gc_arg_type[option->arg_type].name);
 
   /* The alternate type field.  */
   es_fprintf (out, ":%u", gc_arg_type[option->arg_type].fallback);
   if (opt.verbose)
     es_fprintf (out, " %s",
                 gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
 
   /* The argument name field.  */
   es_fprintf (out, ":%s", arg_name ? gc_percent_escape (arg_name) : "");
   xfree (arg_name);
 
   /* The default value field.  */
   es_fprintf (out, ":%s", option->default_value ? option->default_value : "");
 
   /* The default argument field.  */
   es_fprintf (out, ":%s", option->default_arg ? option->default_arg : "");
 
   /* The value field.  */
   if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
       && (option->flags & GC_OPT_FLAG_LIST)
       && option->value)
     /* The special format "1,1,1,1,...,1" is converted to a number
        here.  */
     es_fprintf (out, ":%u", (unsigned int)((strlen (option->value) + 1) / 2));
   else
     es_fprintf (out, ":%s", option->value ? option->value : "");
 
   /* ADD NEW FIELDS HERE.  */
 
   es_putc ('\n', out);
 }
 
 
 /* List all options of the component COMPONENT.  */
 void
 gc_component_list_options (int component, estream_t out)
 {  
   const gc_option_t *option = gc_component[component].options;
 
   while (option && option->name)
     {
       /* Do not output unknown or internal options.  */
       if (!(option->flags & GC_OPT_FLAG_GROUP)
 	  && (!option->active || option->level == GC_LEVEL_INTERNAL))
 	{
 	  option++;
 	  continue;
 	}
 
       if (option->flags & GC_OPT_FLAG_GROUP)
 	{
 	  const gc_option_t *group_option = option + 1;
 	  gc_expert_level_t level = GC_LEVEL_NR;
 
 	  /* The manual states that the group level is always the
 	     minimum of the levels of all contained options.  Due to
 	     different active options, and because it is hard to
 	     maintain manually, we calculate it here.  The value in
 	     the global static table is ignored.  */
 	  
 	  while (group_option->name)
 	    {
 	      if (group_option->flags & GC_OPT_FLAG_GROUP)
 		break;
 	      if (group_option->level < level)
 		level = group_option->level;
 	      group_option++;
 	    }
 
 	  /* Check if group is empty.  */
 	  if (level != GC_LEVEL_NR)
 	    {
 	      gc_option_t opt_copy;
 
 	      /* Fix up the group level.  */
 	      memcpy (&opt_copy, option, sizeof (opt_copy));
 	      opt_copy.level = level;
 	      list_one_option (&opt_copy, out);
 	    }
 	}
       else
 	list_one_option (option, out);
 
       option++;
     }
 }
 
 
 /* Find the option NAME in component COMPONENT, for the backend
    BACKEND.  If BACKEND is GC_BACKEND_ANY, any backend will match.  */
 static gc_option_t *
 find_option (gc_component_t component, const char *name,
 	     gc_backend_t backend)
 {
   gc_option_t *option = gc_component[component].options;
   while (option->name)
     {
       if (!(option->flags & GC_OPT_FLAG_GROUP)
 	  && !strcmp (option->name, name)
 	  && (backend == GC_BACKEND_ANY || option->backend == backend))
 	break;
       option++;
     }
   return option->name ? option : NULL;
 }
 
 
 /* Determine the configuration filename for the component COMPONENT
    and backend BACKEND.  */
 static char *
 get_config_filename (gc_component_t component, gc_backend_t backend)
 {
   char *filename = NULL;
   gc_option_t *option = find_option
     (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
   assert (option);
   assert (option->arg_type == GC_ARG_TYPE_FILENAME);
   assert (!(option->flags & GC_OPT_FLAG_LIST));
 
   if (!option->active || !option->default_value)
     gc_error (1, 0, "Option %s, needed by backend %s, was not initialized",
 	      gc_backend[backend].option_config_filename,
 	      gc_backend[backend].name);
 
   if (option->value && *option->value)
     filename = percent_deescape (&option->value[1]);
   else if (option->default_value && *option->default_value)
     filename = percent_deescape (&option->default_value[1]);
   else
     filename = "";
 
 #if HAVE_W32CE_SYSTEM
   if (!(filename[0] == '/' || filename[0] == '\\'))
 #elif defined(HAVE_DOSISH_SYSTEM)
   if (!(filename[0] 
         && filename[1] == ':'
         && (filename[2] == '/' || filename[2] == '\\')))
 #else
   if (filename[0] != '/')
 #endif
     gc_error (1, 0, "Option %s, needed by backend %s, is not absolute",
 	      gc_backend[backend].option_config_filename,
 	      gc_backend[backend].name);
 
   return filename;
 }
 
 
 /* Retrieve the options for the component COMPONENT from backend
    BACKEND, which we already know is a program-type backend.  */
 static void
 retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
 {
   gpg_error_t err;
   const char *pgmname;
   const char *argv[2];
   estream_t outfp;
   int exitcode;
   pid_t pid;
   char *line = NULL;
   size_t line_len = 0;
   ssize_t length;
   estream_t config;
   char *config_filename;
 
   pgmname = (gc_backend[backend].module_name 
              ? gnupg_module_name (gc_backend[backend].module_name) 
              : gc_backend[backend].program );
   argv[0] = "--gpgconf-list";
   argv[1] = NULL;
 
   err = gnupg_spawn_process (pgmname, argv, GPG_ERR_SOURCE_DEFAULT, NULL, 0,
                              NULL, &outfp, NULL, &pid);
   if (err)
     {
       gc_error (1, 0, "could not gather active options from `%s': %s",
                 pgmname, gpg_strerror (err));
     }
 
   while ((length = es_read_line (outfp, &line, &line_len, NULL)) > 0)
     {
       gc_option_t *option;
       char *linep;
       unsigned long flags = 0;
       char *default_value = NULL;
       
       /* Strip newline and carriage return, if present.  */
       while (length > 0
 	     && (line[length - 1] == '\n' || line[length - 1] == '\r'))
 	line[--length] = '\0';
 
       linep = strchr (line, ':');
       if (linep)
 	*(linep++) = '\0';
       
       /* Extract additional flags.  Default to none.  */
       if (linep)
 	{
 	  char *end;
 	  char *tail;
 
 	  end = strchr (linep, ':');
 	  if (end)
 	    *(end++) = '\0';
 
 	  gpg_err_set_errno (0);
 	  flags = strtoul (linep, &tail, 0);
 	  if (errno)
 	    gc_error (1, errno, "malformed flags in option %s from %s",
                       line, pgmname);
 	  if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
 	    gc_error (1, 0, "garbage after flags in option %s from %s",
                       line, pgmname);
 
 	  linep = end;
 	}
 
       /* Extract default value, if present.  Default to empty if
 	 not.  */
       if (linep)
 	{
 	  char *end;
 
 	  end = strchr (linep, ':');
 	  if (end)
 	    *(end++) = '\0';
 
 	  if (flags & GC_OPT_FLAG_DEFAULT)
 	    default_value = linep;
 
 	  linep = end;
 	}
 
       /* Look up the option in the component and install the
 	 configuration data.  */
       option = find_option (component, line, backend);
       if (option)
 	{
 	  if (option->active)
 	    gc_error (1, errno, "option %s returned twice from %s",
 		      line, pgmname);
 	  option->active = 1;
 
 	  option->flags |= flags;
 	  if (default_value && *default_value)
 	    option->default_value = xstrdup (default_value);
 	}
     }
   if (length < 0 || es_ferror (outfp))
     gc_error (1, errno, "error reading from %s", pgmname);
   if (es_fclose (outfp))
     gc_error (1, errno, "error closing %s", pgmname);
 
   err = gnupg_wait_process (pgmname, pid, 1, &exitcode);
   if (err)
     gc_error (1, 0, "running %s failed (exitcode=%d): %s",
               pgmname, exitcode, gpg_strerror (err));
   gnupg_release_process (pid);
 
 
   /* At this point, we can parse the configuration file.  */
   config_filename = get_config_filename (component, backend);
 
   config = es_fopen (config_filename, "r");
   if (!config)
     gc_error (0, errno, "warning: can not open config file %s",
 	      config_filename);
   else
     {
       while ((length = es_read_line (config, &line, &line_len, NULL)) > 0)
 	{
 	  char *name;
 	  char *value;
 	  gc_option_t *option;
 	  
 	  name = line;
 	  while (*name == ' ' || *name == '\t')
 	    name++;
 	  if (!*name || *name == '#' || *name == '\r' || *name == '\n')
 	    continue;
 
 	  value = name;
 	  while (*value && *value != ' ' && *value != '\t'
 		 && *value != '#' && *value != '\r' && *value != '\n')
 	    value++;
 	  if (*value == ' ' || *value == '\t')
 	    {
 	      char *end;
 
 	      *(value++) = '\0';
 	      while (*value == ' ' || *value == '\t')
 		value++;
 
 	      end = value;
 	      while (*end && *end != '#' && *end != '\r' && *end != '\n')
 		end++;
 	      while (end > value && (end[-1] == ' ' || end[-1] == '\t'))
 		end--;
 	      *end = '\0';
 	    }
 	  else
 	    *value = '\0';
 
 	  /* Look up the option in the component and install the
 	     configuration data.  */
 	  option = find_option (component, line, backend);
 	  if (option)
 	    {
 	      char *opt_value;
 
 	      if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
 		{
 		  if (*value)
 		    gc_error (0, 0,
 			      "warning: ignoring argument %s for option %s",
 			      value, name);
 		  opt_value = xstrdup ("1");
 		}
 	      else if (gc_arg_type[option->arg_type].fallback
 		       == GC_ARG_TYPE_STRING)
 		opt_value = xasprintf ("\"%s", gc_percent_escape (value));
 	      else
 		{
 		  /* FIXME: Verify that the number is sane.  */
 		  opt_value = xstrdup (value);
 		}
 
 	      /* Now enter the option into the table.  */
 	      if (!(option->flags & GC_OPT_FLAG_LIST))
 		{
 		  if (option->value)
 		    free (option->value);
 		  option->value = opt_value;
 		}
 	      else
 		{
 		  if (!option->value)
 		    option->value = opt_value;
 		  else
 		    {
 		      char *opt_val = opt_value;
 
 		      option->value = xasprintf ("%s,%s", option->value,
 						 opt_val);
 		      xfree (opt_value);
 		    }
 		}
 	    }
 	}
 
       if (length < 0 || es_ferror (config))
 	gc_error (1, errno, "error reading from %s", config_filename);
       if (es_fclose (config))
 	gc_error (1, errno, "error closing %s", config_filename);
     }
 
   xfree (line);
 }
 
 
 /* Retrieve the options for the component COMPONENT from backend
    BACKEND, which we already know is of type file list.  */ 
 static void
 retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
 {
   gc_option_t *list_option;
   gc_option_t *config_option;
   char *list_filename;
   FILE *list_file;
   char *line = NULL;
   size_t line_len = 0;
   ssize_t length;
   char *list = NULL;
 
   list_option = find_option (component,
 			     gc_backend[backend].option_name, GC_BACKEND_ANY);
   assert (list_option);
   assert (!list_option->active);
 
   list_filename = get_config_filename (component, backend);
   list_file = fopen (list_filename, "r");
   if (!list_file)
     gc_error (0, errno, "warning: can not open list file %s", list_filename);
   else
     {
 
       while ((length = read_line (list_file, &line, &line_len, NULL)) > 0)
 	{
 	  char *start;
 	  char *end;
 	  char *new_list;
 
 	  start = line;
 	  while (*start == ' ' || *start == '\t')
 	    start++;
 	  if (!*start || *start == '#' || *start == '\r' || *start == '\n')
 	    continue;
 
 	  end = start;
 	  while (*end && *end != '#' && *end != '\r' && *end != '\n')
 	    end++;
 	  /* Walk back to skip trailing white spaces.  Looks evil, but
 	     works because of the conditions on START and END imposed
 	     at this point (END is at least START + 1, and START is
 	     not a whitespace character).  */
 	  while (*(end - 1) == ' ' || *(end - 1) == '\t')
 	    end--;
 	  *end = '\0';
 	  /* FIXME: Oh, no!  This is so lame!  Should use realloc and
 	     really append.  */
 	  if (list)
 	    {
 	      new_list = xasprintf ("%s,\"%s", list, gc_percent_escape (start));
 	      xfree (list);
 	      list = new_list;
 	    }
 	  else
 	    list = xasprintf ("\"%s", gc_percent_escape (start));
 	}
       if (length < 0 || ferror (list_file))
 	gc_error (1, errno, "can not read list file %s", list_filename);
     }
 
   list_option->active = 1;
   list_option->value = list;
 
   /* Fix up the read-only flag.  */
   config_option = find_option
     (component, gc_backend[backend].option_config_filename, GC_BACKEND_ANY);
   if (config_option->flags & GC_OPT_FLAG_NO_CHANGE)
     list_option->flags |= GC_OPT_FLAG_NO_CHANGE;
 
   if (list_file && fclose (list_file))
     gc_error (1, errno, "error closing %s", list_filename);
   xfree (line);
 }
 
 
 /* Retrieve the currently active options and their defaults from all
    involved backends for this component.  Using -1 for component will
    retrieve all options from all components. */
 void
 gc_component_retrieve_options (int component)
 {
   int process_all = 0;
   int backend_seen[GC_BACKEND_NR];
   gc_backend_t backend;
   gc_option_t *option;
 
   if (component == GC_COMPONENT_PINENTRY)
     return; /* Dummy module for now.  */
 
   for (backend = 0; backend < GC_BACKEND_NR; backend++)
     backend_seen[backend] = 0;
 
   if (component == -1)
     {
       process_all = 1;
       component = 0;
       assert (component < GC_COMPONENT_NR);
     }
       
   do
     {
       option = gc_component[component].options;
 
       while (option && option->name)
         {
           if (!(option->flags & GC_OPT_FLAG_GROUP))
             {
               backend = option->backend;
               
               if (backend_seen[backend])
                 {
                   option++;
                   continue;
                 }
               backend_seen[backend] = 1;
               
               assert (backend != GC_BACKEND_ANY);
               
               if (gc_backend[backend].program)
                 retrieve_options_from_program (component, backend);
               else
                 retrieve_options_from_file (component, backend);
             }
           option++;
         }
     }
   while (process_all && ++component < GC_COMPONENT_NR);
 
 }
 
 
 
 /* Perform a simple validity check based on the type.  Return in
    NEW_VALUE_NR the value of the number in NEW_VALUE if OPTION is of
    type GC_ARG_TYPE_NONE.  */
 static void
 option_check_validity (gc_option_t *option, unsigned long flags,
 		       char *new_value, unsigned long *new_value_nr)
 {
   char *arg;
 
   if (!option->active)
     gc_error (1, 0, "option %s not supported by backend %s",
               option->name, gc_backend[option->backend].name);
       
   if (option->new_flags || option->new_value)
     gc_error (1, 0, "option %s already changed", option->name);
 
   if (flags & GC_OPT_FLAG_DEFAULT)
     {
       if (*new_value)
 	gc_error (1, 0, "argument %s provided for deleted option %s",
 		  new_value, option->name);
 
       return;
     }
 
   /* GC_ARG_TYPE_NONE options have special list treatment.  */
   if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE)
     {
       char *tail;
 
       gpg_err_set_errno (0);
       *new_value_nr = strtoul (new_value, &tail, 0);
 
       if (errno)
 	gc_error (1, errno, "invalid argument for option %s",
 		  option->name);
       if (*tail)
 	gc_error (1, 0, "garbage after argument for option %s",
 		      option->name);
 
       if (!(option->flags & GC_OPT_FLAG_LIST))
 	{
 	  if (*new_value_nr != 1)
 	    gc_error (1, 0, "argument for non-list option %s of type 0 "
 		      "(none) must be 1", option->name);
 	}
       else
 	{
 	  if (*new_value_nr == 0)
 	    gc_error (1, 0, "argument for option %s of type 0 (none) "
 		      "must be positive", option->name);
 	}
 
       return;
     }
 
   arg = new_value;
   do
     {
       if (*arg == '\0' || *arg == ',')
 	{
 	  if (!(option->flags & GC_OPT_FLAG_ARG_OPT))
 	    gc_error (1, 0, "argument required for option %s", option->name);
 
 	  if (*arg == ',' && !(option->flags & GC_OPT_FLAG_LIST))
 	    gc_error (1, 0, "list found for non-list option %s", option->name);
 	}
       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_STRING)
 	{
 	  if (*arg != '"')
 	    gc_error (1, 0, "string argument for option %s must begin "
 		      "with a quote (\") character", option->name);
 
 	  /* FIXME: We do not allow empty string arguments for now, as
 	     we do not quote arguments in configuration files, and
 	     thus no argument is indistinguishable from the empty
 	     string.  */
 	  if (arg[1] == '\0' || arg[1] == ',')
 	    gc_error (1, 0, "empty string argument for option %s is "
 		      "currently not allowed.  Please report this!",
 		      option->name);
 	}
       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
 	{
 	  long res;
 
 	  gpg_err_set_errno (0);
 	  res = strtol (arg, &arg, 0);
 	  (void) res;
 
 	  if (errno)
 	    gc_error (1, errno, "invalid argument for option %s",
 		      option->name);
 
 	  if (*arg != '\0' && *arg != ',')
 	    gc_error (1, 0, "garbage after argument for option %s",
 		      option->name);
 	}
       else if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_INT32)
 	{
 	  unsigned long res;
 
 	  gpg_err_set_errno (0);
 	  res = strtoul (arg, &arg, 0);
 	  (void) res;
 
 	  if (errno)
 	    gc_error (1, errno, "invalid argument for option %s",
 		      option->name);
 
 	  if (*arg != '\0' && *arg != ',')
 	    gc_error (1, 0, "garbage after argument for option %s",
 		      option->name);
 	}
       arg = strchr (arg, ',');
       if (arg)
 	arg++;
     }
   while (arg && *arg);
 }
 
 #ifdef HAVE_W32_SYSTEM
 int
 copy_file (const char *src_name, const char *dst_name)
 {
 #define BUF_LEN 4096
   char buffer[BUF_LEN];
   int len;
   FILE *src;
   FILE *dst;
 
   src = fopen (src_name, "r");
   if (src == NULL)
     return -1;
 
   dst = fopen (dst_name, "w");
   if (dst == NULL)
     {
       int saved_err = errno;
       fclose (src);
       gpg_err_set_errno (saved_err);
       return -1;
     }
 
   do
     {
       int written;
 
       len = fread (buffer, 1, BUF_LEN, src);
       if (len == 0)
 	break;
       written = fwrite (buffer, 1, len, dst);
       if (written != len)
 	break;
     }
   while (!feof (src) && !ferror (src) && !ferror (dst));
 
   if (ferror (src) || ferror (dst) || !feof (src))
     {
       int saved_errno = errno;
       fclose (src);
       fclose (dst);
       unlink (dst_name);
       gpg_err_set_errno (saved_errno);
       return -1;
     }
 
   if (fclose (dst))
     gc_error (1, errno, "error closing %s", dst_name);
   if (fclose (src))
     gc_error (1, errno, "error closing %s", src_name);
 
   return 0;
 }
 #endif /* HAVE_W32_SYSTEM */
 
 
 /* Create and verify the new configuration file for the specified
    backend and component.  Returns 0 on success and -1 on error.  */
 static int
 change_options_file (gc_component_t component, gc_backend_t backend,
 		     char **src_filenamep, char **dest_filenamep,
 		     char **orig_filenamep)
 {
   static const char marker[] = "###+++--- GPGConf ---+++###";
   /* True if we are within the marker in the config file.  */
   int in_marker = 0;
   gc_option_t *option;
   char *line = NULL;
   size_t line_len;
   ssize_t length;
   int res;
   int fd;
   FILE *src_file = NULL;
   FILE *dest_file = NULL;
   char *src_filename;
   char *dest_filename;
   char *orig_filename;
   char *arg;
   char *cur_arg = NULL;
 
   option = find_option (component,
 			gc_backend[backend].option_name, GC_BACKEND_ANY);
   assert (option);
   assert (option->active);
   assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE);
 
   /* FIXME.  Throughout the function, do better error reporting.  */
   /* Note that get_config_filename() calls percent_deescape(), so we
      call this before processing the arguments.  */
   dest_filename = xstrdup (get_config_filename (component, backend));
   src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, (int)getpid ());
   orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename,(int)getpid ());
 
   arg = option->new_value;
   if (arg && arg[0] == '\0')
     arg = NULL;
   else if (arg)
     {
       char *end;
 
       arg++;
       end = strchr (arg, ',');
       if (end)
 	*end = '\0';
 
       cur_arg = percent_deescape (arg);
       if (end)
 	{
 	  *end = ',';
 	  arg = end + 1;
 	}
       else
 	arg = NULL;
     }
 
 #ifdef HAVE_W32_SYSTEM
   res = copy_file (dest_filename, orig_filename);
 #else
   res = link (dest_filename, orig_filename);
 #endif
   if (res < 0 && errno != ENOENT)
     return -1;
   if (res < 0)
     {
       xfree (orig_filename);
       orig_filename = NULL;
     }
 
   /* We now initialize the return strings, so the caller can do the
      cleanup for us.  */
   *src_filenamep = src_filename;
   *dest_filenamep = dest_filename;
   *orig_filenamep = orig_filename;
 
   /* Use open() so that we can use O_EXCL.  */
   fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
   if (fd < 0)
     return -1;
   src_file = fdopen (fd, "w");
   res = errno;
   if (!src_file)
     {
       gpg_err_set_errno (res);
       return -1;
     }
 
   /* Only if ORIG_FILENAME is not NULL did the configuration file
      exist already.  In this case, we will copy its content into the
      new configuration file, changing it to our liking in the
      process.  */
   if (orig_filename)
     {
       dest_file = fopen (dest_filename, "r");
       if (!dest_file)
 	goto change_file_one_err;
 
       while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
 	{
 	  int disable = 0;
 	  char *start;
 
 	  if (!strncmp (marker, line, sizeof (marker) - 1))
 	    {
 	      if (!in_marker)
 		in_marker = 1;
 	      else
 		break;
 	    }
 
 	  start = line;
 	  while (*start == ' ' || *start == '\t')
 	    start++;
 	  if (*start && *start != '\r' && *start != '\n' && *start != '#')
 	    {
 	      char *end;
 	      char *endp;
 	      char saved_end;
 
 	      endp = start;
 	      end = endp;
 
 	      /* Search for the end of the line.  */
 	      while (*endp && *endp != '#' && *endp != '\r' && *endp != '\n')
 		{
 		  endp++;
 		  if (*endp && *endp != ' ' && *endp != '\t'
 		      && *endp != '\r' && *endp != '\n' && *endp != '#')
 		    end = endp + 1;
 		}
 	      saved_end = *end;
 	      *end = '\0';
 
 	      if ((option->new_flags & GC_OPT_FLAG_DEFAULT)
 		  || !cur_arg || strcmp (start, cur_arg))
 		disable = 1;
 	      else
 		{
 		  /* Find next argument.  */
 		  if (arg)
 		    {
 		      char *arg_end;
 
 		      arg++;
 		      arg_end = strchr (arg, ',');
 		      if (arg_end)
 			*arg_end = '\0';
 
 		      cur_arg = percent_deescape (arg);
 		      if (arg_end)
 			{
 			  *arg_end = ',';
 			  arg = arg_end + 1;
 			}
 		      else
 			arg = NULL;
 		    }
 		  else
 		    cur_arg = NULL;
 		}
 
 	      *end = saved_end;
 	    }
 
 	  if (disable)
 	    {
 	      if (!in_marker)
 		{
 		  fprintf (src_file,
 			   "# GPGConf disabled this option here at %s\n",
 			   asctimestamp (gnupg_get_time ()));
 		  if (ferror (src_file))
 		    goto change_file_one_err;
 		  fprintf (src_file, "# %s", line);
 		  if (ferror (src_file))
 		    goto change_file_one_err;
 		}
 	    }
 	  else
 	    {
 	      fprintf (src_file, "%s", line);
 	      if (ferror (src_file))
 		goto change_file_one_err;
 	    }
 	}
       if (length < 0 || ferror (dest_file))
 	goto change_file_one_err;
     }
 
   if (!in_marker)
     {
       /* There was no marker.  This is the first time we edit the
 	 file.  We add our own marker at the end of the file and
 	 proceed.  Note that we first write a newline, this guards us
 	 against files which lack the newline at the end of the last
 	 line, while it doesn't hurt us in all other cases.  */
       fprintf (src_file, "\n%s\n", marker);
       if (ferror (src_file))
 	goto change_file_one_err;
     }
 
   /* At this point, we have copied everything up to the end marker
      into the new file, except for the arguments we are going to add.
      Now, dump the new arguments and write the end marker, possibly
      followed by the rest of the original file.  */
   while (cur_arg)
     {
       fprintf (src_file, "%s\n", cur_arg);
 
       /* Find next argument.  */
       if (arg)
 	{
 	  char *end;
 
 	  arg++;
 	  end = strchr (arg, ',');
 	  if (end)
 	    *end = '\0';
 
 	  cur_arg = percent_deescape (arg);
 	  if (end)
 	    {
 	      *end = ',';
 	      arg = end + 1;
 	    }
 	  else
 	    arg = NULL;
 	}
       else
 	cur_arg = NULL;
     }
 
   fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
   if (ferror (src_file))
     goto change_file_one_err;
 
   if (!in_marker)
     {
       fprintf (src_file, "# GPGConf edited this configuration file.\n");
       if (ferror (src_file))
 	goto change_file_one_err;
       fprintf (src_file, "# It will disable options before this marked "
 	       "block, but it will\n");
       if (ferror (src_file))
 	goto change_file_one_err;
       fprintf (src_file, "# never change anything below these lines.\n");
       if (ferror (src_file))
 	goto change_file_one_err;
     }
   if (dest_file)
     {
       while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
 	{
 	  fprintf (src_file, "%s", line);
 	  if (ferror (src_file))
 	    goto change_file_one_err;
 	}
       if (length < 0 || ferror (dest_file))
 	goto change_file_one_err;
     }
   xfree (line);
   line = NULL;
 
   res = fclose (src_file);
   if (res)
     {
       res = errno;
       close (fd);
       if (dest_file)
 	fclose (dest_file);
       gpg_err_set_errno (res);
       return -1;
     }
   close (fd);
   if (dest_file)
     {
       res = fclose (dest_file);
       if (res)
 	return -1;
     }
   return 0;
 
  change_file_one_err:
   xfree (line);
   res = errno;
   if (src_file)
     {
       fclose (src_file);
       close (fd);
     }
   if (dest_file)
     fclose (dest_file);
   gpg_err_set_errno (res);
   return -1;
 }
 
 
 /* Create and verify the new configuration file for the specified
    backend and component.  Returns 0 on success and -1 on error.  */
 static int
 change_options_program (gc_component_t component, gc_backend_t backend,
 			char **src_filenamep, char **dest_filenamep,
 			char **orig_filenamep)
 {
   static const char marker[] = "###+++--- GPGConf ---+++###";
   /* True if we are within the marker in the config file.  */
   int in_marker = 0;
   gc_option_t *option;
   char *line = NULL;
   size_t line_len;
   ssize_t length;
   int res;
   int fd;
   FILE *src_file = NULL;
   FILE *dest_file = NULL;
   char *src_filename;
   char *dest_filename;
   char *orig_filename;
   /* Special hack for gpg, see below.  */
   int utf8strings_seen = 0;
 
   /* FIXME.  Throughout the function, do better error reporting.  */
   dest_filename = xstrdup (get_config_filename (component, backend));
   src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, (int)getpid ());
   orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename,(int)getpid ());
 
 #ifdef HAVE_W32_SYSTEM
   res = copy_file (dest_filename, orig_filename);
 #else
   res = link (dest_filename, orig_filename);
 #endif
   if (res < 0 && errno != ENOENT)
     return -1;
   if (res < 0)
     {
       xfree (orig_filename);
       orig_filename = NULL;
     }
 
   /* We now initialize the return strings, so the caller can do the
      cleanup for us.  */
   *src_filenamep = src_filename;
   *dest_filenamep = dest_filename;
   *orig_filenamep = orig_filename;
 
   /* Use open() so that we can use O_EXCL.  */
   fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
   if (fd < 0)
     return -1;
   src_file = fdopen (fd, "w");
   res = errno;
   if (!src_file)
     {
       gpg_err_set_errno (res);
       return -1;
     }
 
   /* Only if ORIG_FILENAME is not NULL did the configuration file
      exist already.  In this case, we will copy its content into the
      new configuration file, changing it to our liking in the
      process.  */
   if (orig_filename)
     {
       dest_file = fopen (dest_filename, "r");
       if (!dest_file)
 	goto change_one_err;
 
       while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
 	{
 	  int disable = 0;
 	  char *start;
 
 	  if (!strncmp (marker, line, sizeof (marker) - 1))
 	    {
 	      if (!in_marker)
 		in_marker = 1;
 	      else
 		break;
 	    }
 	  else if (backend == GC_BACKEND_GPG && in_marker
 		   && ! strcmp ("utf8-strings\n", line))
 	    {
 	      /* Strip duplicated entries.  */
 	      if (utf8strings_seen)
 		disable = 1;
 	      else
 		utf8strings_seen = 1;
 	    }
 
 	  start = line;
 	  while (*start == ' ' || *start == '\t')
 	    start++;
 	  if (*start && *start != '\r' && *start != '\n' && *start != '#')
 	    {
 	      char *end;
 	      char saved_end;
 
 	      end = start;
 	      while (*end && *end != ' ' && *end != '\t'
 		     && *end != '\r' && *end != '\n' && *end != '#')
 		end++;
 	      saved_end = *end;
 	      *end = '\0';
 
 	      option = find_option (component, start, backend);
 	      *end = saved_end;
 	      if (option && ((option->new_flags & GC_OPT_FLAG_DEFAULT)
 			     || option->new_value))
 		disable = 1;
 	    }
 	  if (disable)
 	    {
 	      if (!in_marker)
 		{
 		  fprintf (src_file,
 			   "# GPGConf disabled this option here at %s\n",
 			   asctimestamp (gnupg_get_time ()));
 		  if (ferror (src_file))
 		    goto change_one_err;
 		  fprintf (src_file, "# %s", line);
 		  if (ferror (src_file))
 		    goto change_one_err;
 		}
 	    }
 	  else
 	    {
 	      fprintf (src_file, "%s", line);
 	      if (ferror (src_file))
 		goto change_one_err;
 	    }
 	}
       if (length < 0 || ferror (dest_file))
 	goto change_one_err;
     }
 
   if (!in_marker)
     {
       /* There was no marker.  This is the first time we edit the
 	 file.  We add our own marker at the end of the file and
 	 proceed.  Note that we first write a newline, this guards us
 	 against files which lack the newline at the end of the last
 	 line, while it doesn't hurt us in all other cases.  */
       fprintf (src_file, "\n%s\n", marker);
       if (ferror (src_file))
 	goto change_one_err;
     }
   /* At this point, we have copied everything up to the end marker
      into the new file, except for the options we are going to change.
      Now, dump the changed options (except for those we are going to
      revert to their default), and write the end marker, possibly
      followed by the rest of the original file.  */
 
   /* We have to turn on UTF8 strings for GnuPG.  */
   if (backend == GC_BACKEND_GPG && ! utf8strings_seen)
     fprintf (src_file, "utf8-strings\n");
 
   option = gc_component[component].options;
   while (option->name)
     {
       if (!(option->flags & GC_OPT_FLAG_GROUP)
 	  && option->backend == backend
 	  && option->new_value)
 	{
 	  char *arg = option->new_value;
 
 	  do
 	    {
 	      if (*arg == '\0' || *arg == ',')
 		{
 		  fprintf (src_file, "%s\n", option->name);
 		  if (ferror (src_file))
 		    goto change_one_err;
 		}
 	      else if (gc_arg_type[option->arg_type].fallback
 		       == GC_ARG_TYPE_NONE)
 		{
 		  assert (*arg == '1');
 		  fprintf (src_file, "%s\n", option->name);
 		  if (ferror (src_file))
 		    goto change_one_err;
 
 		  arg++;
 		}
 	      else if (gc_arg_type[option->arg_type].fallback
 		       == GC_ARG_TYPE_STRING)
 		{
 		  char *end;
 		  
 		  assert (*arg == '"');
 		  arg++;
 		  
 		  end = strchr (arg, ',');
 		  if (end)
 		    *end = '\0';
 
 		  fprintf (src_file, "%s %s\n", option->name,
 			   percent_deescape (arg));
 		  if (ferror (src_file))
 		    goto change_one_err;
 
 		  if (end)
 		    *end = ',';
 		  arg = end;
 		}
 	      else
 		{
 		  char *end;
 
 		  end = strchr (arg, ',');
 		  if (end)
 		    *end = '\0';
 
 		  fprintf (src_file, "%s %s\n", option->name, arg);
 		  if (ferror (src_file))
 		    goto change_one_err;
 
 		  if (end)
 		    *end = ',';
 		  arg = end;
 		}
 
 	      assert (arg == NULL || *arg == '\0' || *arg == ',');
 	      if (arg && *arg == ',')
 		arg++;
 	    }
 	  while (arg && *arg);
 	}
       option++;
     }
 
   fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
   if (ferror (src_file))
     goto change_one_err;
 
   if (!in_marker)
     {
       fprintf (src_file, "# GPGConf edited this configuration file.\n");
       if (ferror (src_file))
 	goto change_one_err;
       fprintf (src_file, "# It will disable options before this marked "
 	       "block, but it will\n");
       if (ferror (src_file))
 	goto change_one_err;
       fprintf (src_file, "# never change anything below these lines.\n");
       if (ferror (src_file))
 	goto change_one_err;
     }
   if (dest_file)
     {
       while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
 	{
 	  fprintf (src_file, "%s", line);
 	  if (ferror (src_file))
 	    goto change_one_err;
 	}
       if (length < 0 || ferror (dest_file))
 	goto change_one_err;
     }
   xfree (line);
   line = NULL;
 
   res = fclose (src_file);
   if (res)
     {
       res = errno;
       close (fd);
       if (dest_file)
 	fclose (dest_file);
       gpg_err_set_errno (res);
       return -1;
     }
   close (fd);
   if (dest_file)
     {
       res = fclose (dest_file);
       if (res)
 	return -1;
     }
   return 0;
 
  change_one_err:
   xfree (line);
   res = errno;
   if (src_file)
     {
       fclose (src_file);
       close (fd);
     }
   if (dest_file)
     fclose (dest_file);
   gpg_err_set_errno (res);
   return -1;
 }
 
 
 /* Common code for gc_component_change_options and
    gc_process_gpgconf_conf.  */
 static void
 change_one_value (gc_option_t *option, int *runtime,
                   unsigned long flags, char *new_value)
 {
   unsigned long new_value_nr = 0;
 
   option_check_validity (option, flags, new_value, &new_value_nr);
 
   if (option->flags & GC_OPT_FLAG_RUNTIME)
     runtime[option->backend] = 1;
 
   option->new_flags = flags;
   if (!(flags & GC_OPT_FLAG_DEFAULT))
     {
       if (gc_arg_type[option->arg_type].fallback == GC_ARG_TYPE_NONE
           && (option->flags & GC_OPT_FLAG_LIST))
         {
           char *str;
 
           /* We convert the number to a list of 1's for convenient
              list handling.  */
           assert (new_value_nr > 0);
           option->new_value = xmalloc ((2 * (new_value_nr - 1) + 1) + 1);
           str = option->new_value;
           *(str++) = '1';
           while (--new_value_nr > 0)
             {
               *(str++) = ',';
               *(str++) = '1';
             }
           *(str++) = '\0';
         }
       else
         option->new_value = xstrdup (new_value);
     }
 }
 
 
 /* Read the modifications from IN and apply them.  If IN is NULL the
    modifications are expected to already have been set to the global
    table. */
 void
 gc_component_change_options (int component, estream_t in, estream_t out)
 {
   int err = 0;
   int runtime[GC_BACKEND_NR];
   char *src_filename[GC_BACKEND_NR];
   char *dest_filename[GC_BACKEND_NR];
   char *orig_filename[GC_BACKEND_NR];
   gc_backend_t backend;
   gc_option_t *option;
   char *line = NULL;
   size_t line_len = 0;
   ssize_t length;
 
   if (component == GC_COMPONENT_PINENTRY)
     return; /* Dummy component for now.  */
 
   for (backend = 0; backend < GC_BACKEND_NR; backend++)
     {
       runtime[backend] = 0;
       src_filename[backend] = NULL;
       dest_filename[backend] = NULL;
       orig_filename[backend] = NULL;
     }
 
   if (in)
     {
       /* Read options from the file IN.  */
       while ((length = es_read_line (in, &line, &line_len, NULL)) > 0)
         {
           char *linep;
           unsigned long flags = 0;
           char *new_value = "";
           
           /* Strip newline and carriage return, if present.  */
           while (length > 0
                  && (line[length - 1] == '\n' || line[length - 1] == '\r'))
             line[--length] = '\0';
           
           linep = strchr (line, ':');
           if (linep)
             *(linep++) = '\0';
           
           /* Extract additional flags.  Default to none.  */
           if (linep)
             {
               char *end;
               char *tail;
 
               end = strchr (linep, ':');
               if (end)
                 *(end++) = '\0';
               
               gpg_err_set_errno (0);
               flags = strtoul (linep, &tail, 0);
               if (errno)
                 gc_error (1, errno, "malformed flags in option %s", line);
               if (!(*tail == '\0' || *tail == ':' || *tail == ' '))
                 gc_error (1, 0, "garbage after flags in option %s", line);
               
               linep = end;
             }
 
           /* Don't allow setting of the no change flag.  */
           flags &= ~GC_OPT_FLAG_NO_CHANGE;
           
           /* Extract default value, if present.  Default to empty if not.  */
           if (linep)
             {
               char *end;
               end = strchr (linep, ':');
               if (end)
                 *(end++) = '\0';
               new_value = linep;
               linep = end;
             }
           
           option = find_option (component, line, GC_BACKEND_ANY);
           if (!option)
             gc_error (1, 0, "unknown option %s", line);
           
           if ((option->flags & GC_OPT_FLAG_NO_CHANGE))
             {
               gc_error (0, 0, "ignoring new value for option %s",
                         option->name);
               continue;
             }
           
           change_one_value (option, runtime, flags, new_value);
         }
     }
 
   /* Now that we have collected and locally verified the changes,
      write them out to new configuration files, verify them
      externally, and then commit them.  */
   option = gc_component[component].options;
   while (option && option->name)
     {
       /* Go on if we have already seen this backend, or if there is
 	 nothing to do.  */
       if (src_filename[option->backend]
 	  || !(option->new_flags || option->new_value))
 	{
 	  option++;
 	  continue;
 	}
 
       if (gc_backend[option->backend].program)
 	{
 	  err = change_options_program (component, option->backend,
 					&src_filename[option->backend],
 					&dest_filename[option->backend],
 					&orig_filename[option->backend]);
 	  if (! err)
 	    {
 	      /* External verification.  */
 	      err = gc_component_check_options (component, out,
 						src_filename[option->backend]);
 	      if (err)
 		{
 		  gc_error (0, 0,
 			    _("External verification of component %s failed"),
 			    gc_component[component].name);
 		  gpg_err_set_errno (EINVAL);
 		}
 	    }
 
 	}
       else
 	err = change_options_file (component, option->backend,
 				   &src_filename[option->backend],
 				   &dest_filename[option->backend],
 				   &orig_filename[option->backend]);
 	
       if (err)
 	break;
 	  
       option++;
     }
 
   if (! err && ! opt.dry_run)
     {
       int i;
 
       for (i = 0; i < GC_BACKEND_NR; i++)
 	{
 	  if (src_filename[i])
 	    {
 	      /* FIXME: Make a verification here.  */
 
 	      assert (dest_filename[i]);
 
 	      if (orig_filename[i])
 		{
 #ifdef HAVE_W32_SYSTEM
 		  /* There is no atomic update on W32.  */
 		  err = unlink (dest_filename[i]);
 #endif /* HAVE_W32_SYSTEM */
 		  if (!err)
 		    err = rename (src_filename[i], dest_filename[i]);
 		}
 	      else
 		{
 #ifdef HAVE_W32_SYSTEM
 		  /* We skip the unlink if we expect the file not to
 		     be there.  */
                   err = rename (src_filename[i], dest_filename[i]);
 #else /* HAVE_W32_SYSTEM */
 		  /* This is a bit safer than rename() because we
 		     expect DEST_FILENAME not to be there.  If it
 		     happens to be there, this will fail.  */
 		  err = link (src_filename[i], dest_filename[i]);
 		  if (!err)
 		    err = unlink (src_filename[i]);
 #endif /* !HAVE_W32_SYSTEM */
 		}
 	      if (err)
 		break;
 	      src_filename[i] = NULL;
 	    }
 	}
     }
 
   if (err || opt.dry_run)
     {
       int i;
       int saved_errno = errno;
 
       /* An error occured or a dry-run is requested.  */
       for (i = 0; i < GC_BACKEND_NR; i++)
 	{
 	  if (src_filename[i])
 	    {
 	      /* The change was not yet committed.  */
 	      unlink (src_filename[i]);
 	      if (orig_filename[i])
 		unlink (orig_filename[i]);
 	    }
 	  else
 	    {
 	      /* The changes were already committed.  FIXME: This is a
 		 tad dangerous, as we don't know if we don't overwrite
 		 a version of the file that is even newer than the one
 		 we just installed.  */
 	      if (orig_filename[i])
 		{
 #ifdef HAVE_W32_SYSTEM
 		  /* There is no atomic update on W32.  */
 		  unlink (dest_filename[i]);
 #endif /* HAVE_W32_SYSTEM */
 		  rename (orig_filename[i], dest_filename[i]);
 		}
 	      else
 		unlink (dest_filename[i]);
 	    }
 	}
       if (err)
 	gc_error (1, saved_errno, "could not commit changes");
 
       /* Fall-through for dry run.  */
       goto leave;
     }
 
   /* If it all worked, notify the daemons of the changes.  */
   if (opt.runtime)
     for (backend = 0; backend < GC_BACKEND_NR; backend++)  
       {
 	if (runtime[backend] && gc_backend[backend].runtime_change)
 	  (*gc_backend[backend].runtime_change) ();
       }
 
   /* Move the per-process backup file into its place.  */
   for (backend = 0; backend < GC_BACKEND_NR; backend++)  
     if (orig_filename[backend])
       {
 	char *backup_filename;
 
 	assert (dest_filename[backend]);
 
 	backup_filename = xasprintf ("%s.gpgconf.bak", dest_filename[backend]);
 
 #ifdef HAVE_W32_SYSTEM
 	/* There is no atomic update on W32.  */
 	unlink (backup_filename);
 #endif /* HAVE_W32_SYSTEM */
 	rename (orig_filename[backend], backup_filename);
       }
 
  leave:
   xfree (line);
 }
 
 
 /* Check whether USER matches the current user of one of its group.
    This function may change USER.  Returns true is there is a
    match.  */
 static int
 key_matches_user_or_group (char *user)
 {
   char *group;
 
   if (*user == '*' && user[1] == 0)
     return 1; /* A single asterisk matches all users.  */
 
   group = strchr (user, ':');
   if (group)
     *group++ = 0;
 
 #ifdef HAVE_W32_SYSTEM
   /* Under Windows we don't support groups. */   
   if (group && *group)
     gc_error (0, 0, _("Note that group specifications are ignored\n"));
 #ifndef HAVE_W32CE_SYSTEM
   if (*user)
     {
       static char *my_name;
 
       if (!my_name)
         {
           char tmp[1];
           DWORD size = 1;
 
           GetUserNameA (tmp, &size);
           my_name = xmalloc (size);
           if (!GetUserNameA (my_name, &size))
             gc_error (1,0, "error getting current user name: %s",
                       w32_strerror (-1));
         }
 
       if (!strcmp (user, my_name))
         return 1; /* Found.  */
     }
 #endif /*HAVE_W32CE_SYSTEM*/
 #else /*!HAVE_W32_SYSTEM*/
   /* First check whether the user matches.  */
   if (*user)
     {
       static char *my_name;
 
       if (!my_name)
         {
           struct passwd *pw = getpwuid ( getuid () );
           if (!pw)
             gc_error (1, errno, "getpwuid failed for current user");
           my_name = xstrdup (pw->pw_name);
         }
       if (!strcmp (user, my_name))
         return 1; /* Found.  */
     }
 
   /* If that failed, check whether a group matches.  */
   if (group && *group)
     {
       static char *my_group;
       static char **my_supgroups;
       int n;
 
       if (!my_group)
         {
           struct group *gr = getgrgid ( getgid () );
           if (!gr)
             gc_error (1, errno, "getgrgid failed for current user");
           my_group = xstrdup (gr->gr_name);
         }
       if (!strcmp (group, my_group))
         return 1; /* Found.  */
 
       if (!my_supgroups)
         {
           int ngids;
           gid_t *gids;
 
           ngids = getgroups (0, NULL);
           gids  = xcalloc (ngids+1, sizeof *gids);
           ngids = getgroups (ngids, gids);
           if (ngids < 0)
             gc_error (1, errno, "getgroups failed for current user");
           my_supgroups = xcalloc (ngids+1, sizeof *my_supgroups);
           for (n=0; n < ngids; n++)
             {
               struct group *gr = getgrgid ( gids[n] );
               if (!gr)
                 gc_error (1, errno, "getgrgid failed for supplementary group");
               my_supgroups[n] = xstrdup (gr->gr_name);
             }
           xfree (gids);
         }
 
       for (n=0; my_supgroups[n]; n++)
         if (!strcmp (group, my_supgroups[n]))
           return 1; /* Found.  */
     }
 #endif /*!HAVE_W32_SYSTEM*/
   return 0; /* No match.  */
 }
 
 
 
 /* Read and process the global configuration file for gpgconf.  This
    optional file is used to update our internal tables at runtime and
    may also be used to set new default values.  If FNAME is NULL the
    default name will be used.  With UPDATE set to true the internal
    tables are actually updated; if not set, only a syntax check is
    done.  If DEFAULTS is true the global options are written to the
    configuration files.  If LISTFP is set, no changes are done but the
    configuration file is printed to LISTFP in a colon separated format.
 
    Returns 0 on success or if the config file is not present; -1 is
    returned on error. */
 int
 gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults,
                          estream_t listfp)
 {
   int result = 0;
   char *line = NULL;
   size_t line_len = 0;
   ssize_t length;
   FILE *config;
   int lineno = 0;
   int in_rule = 0;
   int got_match = 0;
   int runtime[GC_BACKEND_NR];
   int used_components[GC_COMPONENT_NR];
   int backend_id, component_id;
   char *fname;
 
   if (fname_arg)
     fname = xstrdup (fname_arg);
   else
     fname = make_filename (gnupg_sysconfdir (), "gpgconf.conf", NULL);
 
   for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
     runtime[backend_id] = 0;
   for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++)
     used_components[component_id] = 0;
 
   config = fopen (fname, "r");
   if (!config)
     {
       /* Do not print an error if the file is not available, except
          when running in syntax check mode.  */
       if (errno != ENOENT || !update)
         {
           gc_error (0, errno, "can not open global config file `%s'", fname);
           result = -1;
         }
       xfree (fname);
       return result;
     }
 
   while ((length = read_line (config, &line, &line_len, NULL)) > 0)
     {
       char *key, *component, *option, *flags, *value;
       char *empty;
       gc_option_t *option_info = NULL;
       char *p;
       int is_continuation;
       
       lineno++;
       key = line;
       while (*key == ' ' || *key == '\t')
         key++;
       if (!*key || *key == '#' || *key == '\r' || *key == '\n')
         continue;
 
       is_continuation = (key != line);
 
       /* Parse the key field.  */
       if (!is_continuation && got_match)
         break;  /* Finish after the first match.  */
       else if (!is_continuation)
         {
           in_rule = 0;
           for (p=key+1; *p && !strchr (" \t\r\n", *p); p++)
             ;
           if (!*p)
             {
               gc_error (0, 0, "missing rule at `%s', line %d", fname, lineno);
               result = -1;
               continue;
             }
           *p++ = 0;
           component = p;
         }
       else if (!in_rule)
         {
           gc_error (0, 0, "continuation but no rule at `%s', line %d",
                     fname, lineno);
           result = -1;
           continue;
         }
       else
         {
           component = key;
           key = NULL;
         }
 
       in_rule = 1;
 
       /* Parse the component.  */
       while (*component == ' ' || *component == '\t')
         component++;
       for (p=component; *p && !strchr (" \t\r\n", *p); p++)
         ;
       if (p == component)
         {
           gc_error (0, 0, "missing component at `%s', line %d",
                     fname, lineno);
           result = -1;
           continue;
         }
       empty = p;
       *p++ = 0;
       option = p;
       component_id = gc_component_find (component);
       if (component_id < 0)
         {
           gc_error (0, 0, "unknown component at `%s', line %d",
                     fname, lineno);
           result = -1;
         }
 
       /* Parse the option name.  */
       while (*option == ' ' || *option == '\t')
         option++;
       for (p=option; *p && !strchr (" \t\r\n", *p); p++)
         ;
       if (p == option)
         {
           gc_error (0, 0, "missing option at `%s', line %d",
                     fname, lineno);
           result = -1;
           continue;
         }
       *p++ = 0;
       flags = p;
       if ( component_id != -1)
         {
           option_info = find_option (component_id, option, GC_BACKEND_ANY);
           if (!option_info)
             {
               gc_error (0, 0, "unknown option at `%s', line %d",
                         fname, lineno);
               result = -1;
             }
         }
 
 
       /* Parse the optional flags.  */
       while (*flags == ' ' || *flags == '\t')
         flags++;
       if (*flags == '[')
         {
           flags++;
           p = strchr (flags, ']');
           if (!p)
             {
               gc_error (0, 0, "syntax error in rule at `%s', line %d",
                         fname, lineno);
               result = -1;
               continue;
             }
           *p++ = 0;
           value = p;
         }
       else  /* No flags given.  */
         {
           value = flags;
           flags = NULL;
         }
 
       /* Parse the optional value.  */
       while (*value == ' ' || *value == '\t')
        value++;
       for (p=value; *p && !strchr ("\r\n", *p); p++)
         ;
       if (p == value)
         value = empty; /* No value given; let it point to an empty string.  */
       else
         {
           /* Strip trailing white space.  */
           *p = 0;
           for (p--; p > value && (*p == ' ' || *p == '\t'); p--)
             *p = 0;
         }
 
       /* Check flag combinations.  */
       if (!flags)
         ;
       else if (!strcmp (flags, "default"))
         {
           if (*value)
             {
               gc_error (0, 0, "flag \"default\" may not be combined "
                         "with a value at `%s', line %d",
                         fname, lineno);
               result = -1;
             }
         }
       else if (!strcmp (flags, "change"))
         ;
       else if (!strcmp (flags, "no-change"))
         ;
       else
         {
           gc_error (0, 0, "unknown flag at `%s', line %d",
                     fname, lineno);
           result = -1;
         }
 
       /* In list mode we print out all records.  */
       if (listfp && !result)
         {
           /* If this is a new ruleset, print a key record.  */
           if (!is_continuation)
             {
               char *group = strchr (key, ':');
               if (group)
                 {
                   *group++ = 0;
                   if ((p = strchr (group, ':')))
                     *p = 0; /* We better strip any extra stuff. */
                 }                    
               
               es_fprintf (listfp, "k:%s:", gc_percent_escape (key));
               es_fprintf (listfp, "%s\n", group? gc_percent_escape (group):"");
             }
 
           /* All other lines are rule records.  */
           es_fprintf (listfp, "r:::%s:%s:%s:",
                       gc_component[component_id].name,                     
                       option_info->name? option_info->name : "",
                       flags? flags : "");
           if (value != empty)
             es_fprintf (listfp, "\"%s", gc_percent_escape (value));
           
           es_putc ('\n', listfp);
         }
 
       /* Check whether the key matches but do this only if we are not
          running in syntax check mode. */
       if ( update 
            && !result && !listfp
            && (got_match || (key && key_matches_user_or_group (key))) )
         {
           int newflags = 0;
 
           got_match = 1;
 
           /* Apply the flags from gpgconf.conf.  */
           if (!flags)
             ;
           else if (!strcmp (flags, "default"))
             newflags |= GC_OPT_FLAG_DEFAULT;
           else if (!strcmp (flags, "no-change"))
             option_info->flags |= GC_OPT_FLAG_NO_CHANGE;
           else if (!strcmp (flags, "change"))
             option_info->flags &= ~GC_OPT_FLAG_NO_CHANGE;
 
           if (defaults)
             {
               assert (component_id >= 0 && component_id < GC_COMPONENT_NR);
               used_components[component_id] = 1;
 
               /* Here we explicitly allow to update the value again.  */
               if (newflags)
                 {
                   option_info->new_flags = 0;
                 }
               if (*value)
                 {
                   xfree (option_info->new_value);
                   option_info->new_value = NULL;
                 }
               change_one_value (option_info, runtime, newflags, value);
             }
         }
     }
 
   if (length < 0 || ferror (config))
     {
       gc_error (0, errno, "error reading from `%s'", fname);
       result = -1;
     }
   if (fclose (config))
     gc_error (0, errno, "error closing `%s'", fname);
 
   xfree (line);
 
   /* If it all worked, process the options. */
   if (!result && update && defaults && !listfp)
     {
       /* We need to switch off the runtime update, so that we can do
          it later all at once. */
       int save_opt_runtime = opt.runtime;
       opt.runtime = 0;
 
       for (component_id = 0; component_id < GC_COMPONENT_NR; component_id++)
         {
           gc_component_change_options (component_id, NULL, NULL);
         }
       opt.runtime = save_opt_runtime;
 
       if (opt.runtime)
         {
           for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)  
             if (runtime[backend_id] && gc_backend[backend_id].runtime_change)
               (*gc_backend[backend_id].runtime_change) ();
         }
     }
 
   xfree (fname);
   return result;
 }