[svn] dirmngr - r248 - in trunk: . m4 src

svn author marcus cvs at cvs.gnupg.org
Thu Jul 26 01:20:53 CEST 2007


Author: marcus
Date: 2007-07-26 01:20:23 +0200 (Thu, 26 Jul 2007)
New Revision: 248

Added:
   trunk/src/ldap-url.c
   trunk/src/vasprintf.c
Modified:
   trunk/ChangeLog
   trunk/README
   trunk/acinclude.m4
   trunk/configure.ac
   trunk/m4/ChangeLog
   trunk/m4/Makefile.am
   trunk/m4/gnupg-pth.m4
   trunk/src/ChangeLog
   trunk/src/Makefile.am
   trunk/src/dirmngr.c
   trunk/src/dirmngr_ldap.c
   trunk/src/ldap.c
   trunk/src/no-libgcrypt.h
   trunk/src/util.h
Log:
2007-07-26  Marcus Brinkmann  <marcus at g10code.de>

	* acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Remove macro.
	(GNUPG_CHECK_VA_COPY): Add macro.
	* configure.ac: Call AM_ICONV and add vasprintf as a replacement
	function (checking GNUPG_CHECK_VA_COPY if necessary).
m4/
2007-07-26  Marcus Brinkmann  <marcus at g10code.de>

	* Makefile.am (EXTRA_DIST): Add estream.m4.
	* estream.m4: New file.
	* gnupg-pth.m4: Remove exception for W32 systems.  The canonical
	check works and is necessary.
src/
2007-07-26  Marcus Brinkmann  <marcus at g10code.de>

	* 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>.


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/ChangeLog	2007-07-25 23:20:23 UTC (rev 248)
@@ -1,3 +1,10 @@
+2007-07-26  Marcus Brinkmann  <marcus at g10code.de>
+
+	* acinclude.m4 (GNUPG_PTH_VERSION_CHECK): Remove macro.
+	(GNUPG_CHECK_VA_COPY): Add macro.
+	* configure.ac: Call AM_ICONV and add vasprintf as a replacement
+	function (checking GNUPG_CHECK_VA_COPY if necessary).
+
 2007-07-20  Marcus Brinkmann  <marcus at g10code.de>
 
 	* acinclude.m4 (GNUPG_FUNC_MKDIR_TAKES_ONE_ARG): New.

Modified: trunk/README
===================================================================
--- trunk/README	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/README	2007-07-25 23:20:23 UTC (rev 248)
@@ -17,7 +17,12 @@
     See the file COPYING for copyright and warranty information. See
     the file AUTHORS for contact addresses and code history.
 
+    On W32 targets, the URL extension of OpenLDAP is included which is
+    provided in src/ldap-url.c.  This file has a different copyright
+    from the rest of the package.  Please see that file for more
+    details.
 
+
     Installation
     ------------
     Please read the file INSTALL. Here is a quick summary:

Modified: trunk/acinclude.m4
===================================================================
--- trunk/acinclude.m4	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/acinclude.m4	2007-07-25 23:20:23 UTC (rev 248)
@@ -35,48 +35,6 @@
     fi
   ])
 
-# GNUPG_PTH_VERSION_CHECK(REQUIRED)
-# 
-# If the version is sufficient, HAVE_PTH will be set to yes.
-#
-# Taken form the m4 macros which come with Pth
-AC_DEFUN([GNUPG_PTH_VERSION_CHECK],
-  [
-    _pth_version=`$PTH_CONFIG --version | awk 'NR==1 {print [$]3}'`
-    _req_version="ifelse([$1],,1.2.0,$1)"
-    for _var in _pth_version _req_version; do
-        eval "_val=\"\$${_var}\""
-        _major=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\1/'`
-        _minor=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\2/'`
-        _rtype=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\3/'`
-        _micro=`echo $_val | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\([[ab.]]\)\([[0-9]]*\)/\4/'`
-        case $_rtype in
-            "a" ) _rtype=0 ;;
-            "b" ) _rtype=1 ;;
-            "." ) _rtype=2 ;;
-        esac
-        _hex=`echo dummy | awk '{ printf("%d%02d%1d%02d", major, minor, rtype, micro); }' \
-              "major=$_major" "minor=$_minor" "rtype=$_rtype" "micro=$_micro"`
-        eval "${_var}_hex=\"\$_hex\""
-    done
-    have_pth=no
-    if test ".$_pth_version_hex" != .; then
-        if test ".$_req_version_hex" != .; then
-            if test $_pth_version_hex -ge $_req_version_hex; then
-                have_pth=yes
-            fi
-        fi
-    fi
-    if test $have_pth = no; then
-       AC_MSG_WARN([[
-***
-*** Found Pth version $_pth_version, but require at least
-*** version $_req_version.  Please upgrade Pth first.
-***]])
-    fi    
-  ])
-
-
 dnl Stolen from gcc
 dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead
 dnl of the usual 2.
@@ -100,3 +58,46 @@
             [Defined if mkdir() does not take permission flags])
 fi
 ])
+
+
+dnl GNUPG_CHECK_VA_COPY()
+dnl   Do some check on how to implement va_copy.
+dnl   May define MUST_COPY_VA_BY_VAL.
+dnl   Actual test code taken from glib-1.1.
+AC_DEFUN([GNUPG_CHECK_VA_COPY],
+[ AC_MSG_CHECKING(whether va_lists must be copied by value)
+  AC_CACHE_VAL(gnupg_cv_must_copy_va_byval,[
+    if test "$cross_compiling" = yes; then
+      gnupg_cv_must_copy_va_byval=no
+    else
+      gnupg_cv_must_copy_va_byval=no
+      AC_TRY_RUN([
+       #include <stdarg.h>
+       void f (int i, ...)
+       {
+          va_list args1, args2;
+          va_start (args1, i);
+          args2 = args1;
+          if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+            exit (1);
+          va_end (args1);
+          va_end (args2);
+       }
+      
+       int main()
+       {
+          f (0, 42);
+            return 0;
+       }
+      ],gnupg_cv_must_copy_va_byval=yes)
+    fi
+  ])
+  if test "$gnupg_cv_must_copy_va_byval" = yes; then
+     AC_DEFINE(MUST_COPY_VA_BYVAL,1,[used to implement the va_copy macro])
+  fi
+  if test "$cross_compiling" = yes; then
+    AC_MSG_RESULT(assuming $gnupg_cv_must_copy_va_byval)
+  else
+    AC_MSG_RESULT($gnupg_cv_must_copy_va_byval)
+  fi
+])

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/configure.ac	2007-07-25 23:20:23 UTC (rev 248)
@@ -99,7 +99,6 @@
 #AC_ARG_PROGRAM
 AC_SYS_LARGEFILE
 
-
 AC_ARG_ENABLE(gcc-warnings,
 	      AC_HELP_STRING([--enable-gcc-warnings],
 			     [enable more verbose gcc warnings]),
@@ -180,7 +179,13 @@
 #
 # Checks for libraries.
 #
+AM_ICONV
 
+AC_REPLACE_FUNCS(vasprintf)
+if test "$ac_cv_func_vasprintf" != yes; then
+  GNUPG_CHECK_VA_COPY
+fi
+
 #
 # We need the GNU Pth library
 #

Modified: trunk/m4/ChangeLog
===================================================================
--- trunk/m4/ChangeLog	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/m4/ChangeLog	2007-07-25 23:20:23 UTC (rev 248)
@@ -1,6 +1,9 @@
-2007-06-22  Marcus Brinkmann  <marcus at g10code.de>
+2007-07-26  Marcus Brinkmann  <marcus at g10code.de>
 
+	* Makefile.am (EXTRA_DIST): Add estream.m4.
 	* estream.m4: New file.
+	* gnupg-pth.m4: Remove exception for W32 systems.  The canonical
+	check works and is necessary.
 
 2006-11-17  Werner Koch  <wk at g10code.com>
 
@@ -90,4 +93,4 @@
 
 
 	
-	
\ No newline at end of file
+	

Modified: trunk/m4/Makefile.am
===================================================================
--- trunk/m4/Makefile.am	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/m4/Makefile.am	2007-07-25 23:20:23 UTC (rev 248)
@@ -4,7 +4,7 @@
              lcmessage.m4 lib-ld.m4 lib-link.m4 lib-prefix.m4 longdouble.m4 \
 	     longlong.m4 nls.m4 po.m4 printf-posix.m4 progtest.m4 signed.m4 \
 	     size_max.m4 stdint_h.m4 uintmax_t.m4 ulonglong.m4 \
-             wchar_t.m4 wint_t.m4 xsize.m4
+             wchar_t.m4 wint_t.m4 xsize.m4 estream.m4
 
 EXTRA_DIST += autobuild.m4
 EXTRA_DIST += gpg-error.m4 ksba.m4 libassuan.m4 libgcrypt.m4

Modified: trunk/m4/gnupg-pth.m4
===================================================================
--- trunk/m4/gnupg-pth.m4	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/m4/gnupg-pth.m4	2007-07-25 23:20:23 UTC (rev 248)
@@ -91,9 +91,7 @@
   fi
   AC_PATH_PROG(PTH_CONFIG, pth-config, no)
   tmp=ifelse([$1], ,1.3.7,$1)
-  test -z "$have_w32_system" && have_w32_system="no"
-  if test "$have_w32_system" = no; then
-   if test "$PTH_CONFIG" != "no"; then
+  if test "$PTH_CONFIG" != "no"; then
     GNUPG_PTH_VERSION_CHECK($tmp)
     if test $have_pth = yes; then      
        PTH_CFLAGS=`$PTH_CONFIG --cflags`
@@ -102,12 +100,6 @@
        AC_DEFINE(HAVE_PTH, 1,
                 [Defined if the GNU Pth is available])
     fi
-   fi
-  else 
-   have_pth=yes
-   PTH_CFLAGS=""
-   PTH_LIBS=""
-   AC_DEFINE(HAVE_PTH, 1)
   fi
   AC_SUBST(PTH_CFLAGS)
   AC_SUBST(PTH_LIBS)

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/ChangeLog	2007-07-25 23:20:23 UTC (rev 248)
@@ -1,3 +1,17 @@
+2007-07-26  Marcus Brinkmann  <marcus at g10code.de>
+
+	* 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 at g10code.de>
 
 	* Makefile.am (dirmngr_SOURCES): Add exechelp.h and exechelp.c.

Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/Makefile.am	2007-07-25 23:20:23 UTC (rev 248)
@@ -25,6 +25,7 @@
 EXTRA_DIST = Manifest
 
 bin_PROGRAMS = dirmngr dirmngr-client
+
 libexec_PROGRAMS = dirmngr_ldap
 
 AM_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" 
@@ -48,14 +49,19 @@
 dirmngr_LDADD = ../jnlib/libjnlib.a $(LIBOBJS) $(LIBASSUAN_PTH_LIBS)  \
 	$(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBINTL)
 
+if HAVE_W32_SYSTEM
+ldap_url = ldap-url.c
+else
+ldap_url =
+endif
+
 dirmngr_ldap_SOURCES = dirmngr_ldap.c i18n.h util.h \
-                       no-libgcrypt.c no-libgcrypt.h 
+                       no-libgcrypt.c no-libgcrypt.h $(ldap_url)
 dirmngr_ldap_CFLAGS = $(GPG_ERROR_CFLAGS)
 dirmngr_ldap_LDFLAGS =
-dirmngr_ldap_LDADD = ../jnlib/libjnlib.a $(LIBOBJS) $(GPG_ERROR_LIBS) \
-		    $(LDAPLIBS) $(LIBINTL)
+dirmngr_ldap_LDADD = $(ldap_ldadd) ../jnlib/libjnlib.a $(LIBOBJS) \
+		     $(GPG_ERROR_LIBS) $(LDAPLIBS) $(LIBINTL)
 
-
 dirmngr_client_SOURCES = dirmngr-client.c i18n.h util.h b64enc.c \
                          no-libgcrypt.c no-libgcrypt.h 
 dirmngr_client_LDADD = ../jnlib/libjnlib.a $(LIBOBJS) $(LIBASSUAN_LIBS) \

Modified: trunk/src/dirmngr.c
===================================================================
--- trunk/src/dirmngr.c	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/dirmngr.c	2007-07-25 23:20:23 UTC (rev 248)
@@ -875,6 +875,11 @@
         log_info (_("listening on socket `%s'\n"), socket_name );
 
       fflush (NULL);
+
+#ifdef HAVE_W32_SYSTEM
+      pid = getpid ();
+      printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid);
+#else
       pid = pth_fork ();
       if (pid == (pid_t)-1) 
         {
@@ -949,6 +954,7 @@
               dirmngr_exit (1);
             }
         }
+#endif
 
       launch_reaper_thread ();
       cert_cache_init ();

Modified: trunk/src/dirmngr_ldap.c
===================================================================
--- trunk/src/dirmngr_ldap.c	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/dirmngr_ldap.c	2007-07-25 23:20:23 UTC (rev 248)
@@ -42,8 +42,8 @@
 #include "../jnlib/strlist.h"
 
 #include "i18n.h"
+#include "no-libgcrypt.h"
 #include "util.h"
-#include "no-libgcrypt.h"
 
 #define DEFAULT_LDAP_TIMEOUT 100 /* Arbitrary long timeout. */
 
@@ -255,17 +255,19 @@
 
   if (opt.alarm_timeout)
     {
-#if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
+#ifndef HAVE_W32_SYSTEM
+# if defined(HAVE_SIGACTION) && defined(HAVE_STRUCT_SIGACTION)
       struct sigaction act;
       
       act.sa_handler = catch_alarm;
       sigemptyset (&act.sa_mask);
       act.sa_flags = 0;
       if (sigaction (SIGALRM,&act,NULL))
-#else 
+# else 
       if (signal (SIGALRM, catch_alarm) == SIG_ERR)
+# endif
+          log_fatal ("unable to register timeout handler\n");
 #endif
-          log_fatal ("unable to register timeout handler\n");
     }
 
   for (; argc; argc--, argv++)
@@ -286,12 +288,14 @@
 static void
 set_timeout (void)
 {
+#ifndef HAVE_W32_SYSTEM
+  /* FIXME for W32.  */
   if (opt.alarm_timeout)
     alarm (opt.alarm_timeout);
+#endif
 }
 
 
-
 /* Helper for fetch_ldap().  */
 static int
 print_ldap_entries (LDAP *ld, LDAPMessage *msg, char *want_attr)

Added: trunk/src/ldap-url.c
===================================================================
--- trunk/src/ldap-url.c	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/ldap-url.c	2007-07-25 23:20:23 UTC (rev 248)
@@ -0,0 +1,928 @@
+/* The following code comes from the OpenLDAP project.  The references
+   to the COPYRIGHT file below refer to the corresponding file in the
+   OpenLDAP distribution, which is reproduced here in full:
+
+Copyright 1998-2004 The OpenLDAP Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted only as authorized by the OpenLDAP
+Public License.
+
+A copy of this license is available in the file LICENSE in the
+top-level directory of the distribution or, alternatively, at
+<http://www.OpenLDAP.org/license.html>.
+
+OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+
+Individual files and/or contributed packages may be copyright by
+other parties and subject to additional restrictions.
+
+This work is derived from the University of Michigan LDAP v3.3
+distribution.  Information concerning this software is available
+at <http://www.umich.edu/~dirsvcs/ldap/>.
+
+This work also contains materials derived from public sources.
+
+Additional information about OpenLDAP can be obtained at
+<http://www.openldap.org/>.
+
+---
+
+Portions Copyright 1998-2004 Kurt D. Zeilenga.
+Portions Copyright 1998-2004 Net Boolean Incorporated.
+Portions Copyright 2001-2004 IBM Corporation.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted only as authorized by the OpenLDAP
+Public License.
+
+---
+
+Portions Copyright 1999-2003 Howard Y.H. Chu.
+Portions Copyright 1999-2003 Symas Corporation.
+Portions Copyright 1998-2003 Hallvard B. Furuseth.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that this notice is preserved.
+The names of the copyright holders may not be used to endorse or
+promote products derived from this software without their specific
+prior written permission.  This software is provided ``as is''
+without express or implied warranty.
+
+---
+
+Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
+All rights reserved.
+
+Redistribution and use in source and binary forms are permitted
+provided that this notice is preserved and that due credit is given
+to the University of Michigan at Ann Arbor.  The name of the
+University may not be used to endorse or promote products derived
+from this software without specific prior written permission.  This
+software is provided ``as is'' without express or implied warranty.  */
+
+
+#include <config.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ldap.h>
+
+#define LDAP_URL_URLCOLON "URL:"
+#define LDAP_URL_URLCOLON_LEN   (sizeof(LDAP_URL_URLCOLON)-1)
+#define LDAP_URL_PREFIX         "ldap://"
+#define LDAP_URL_PREFIX_LEN     (sizeof(LDAP_URL_PREFIX)-1)
+#define LDAPS_URL_PREFIX                "ldaps://"
+#define LDAPS_URL_PREFIX_LEN    (sizeof(LDAPS_URL_PREFIX)-1)
+#define LDAPI_URL_PREFIX        "ldapi://"
+#define LDAPI_URL_PREFIX_LEN    (sizeof(LDAPI_URL_PREFIX)-1)
+#define LDAP_VFREE(v)           { int _i; for (_i = 0; (v)[_i]; _i++) free((v)[_i]); }
+#define LDAP_FREE		free
+#define LDAP_STRDUP		strdup
+#define LDAP_CALLOC		calloc
+#define LDAP_MALLOC		malloc
+#define LDAP_REALLOC		realloc
+#define ldap_utf8_strchr	strchr
+#define ldap_utf8_strtok(n,d,s) strtok (n,d)
+#define Debug(a,b,c,d,e)	
+void ldap_pvt_hex_unescape( char *s );
+
+
+/* $OpenLDAP: pkg/ldap/libraries/libldap/charray.c,v 1.9.2.2 2003/03/03 17:10:04 kurt Exp $ */
+/*
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* charray.c - routines for dealing with char * arrays */
+
+int
+ldap_charray_add(
+    char	***a,
+    char	*s
+)
+{
+	int	n;
+
+	if ( *a == NULL ) {
+		*a = (char **) LDAP_MALLOC( 2 * sizeof(char *) );
+		n = 0;
+
+		if( *a == NULL ) {
+			return -1;
+		}
+
+	} else {
+		char **new;
+
+		for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
+			;	/* NULL */
+		}
+
+		new = (char **) LDAP_REALLOC( (char *) *a,
+		    (n + 2) * sizeof(char *) );
+
+		if( new == NULL ) {
+			/* caller is required to call ldap_charray_free(*a) */
+			return -1;
+		}
+
+		*a = new;
+	}
+
+	(*a)[n] = LDAP_STRDUP(s);
+
+	if( (*a)[n] == NULL ) {
+		return 1;
+	}
+
+	(*a)[++n] = NULL;
+
+	return 0;
+}
+
+int
+ldap_charray_merge(
+    char	***a,
+    char	**s
+)
+{
+	int	i, n, nn;
+	char **aa;
+
+	for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
+		;	/* NULL */
+	}
+	for ( nn = 0; s[nn] != NULL; nn++ ) {
+		;	/* NULL */
+	}
+
+	aa = (char **) LDAP_REALLOC( (char *) *a, (n + nn + 1) * sizeof(char *) );
+
+	if( aa == NULL ) {
+		return -1;
+	}
+
+	*a = aa;
+
+	for ( i = 0; i < nn; i++ ) {
+		(*a)[n + i] = LDAP_STRDUP(s[i]);
+
+		if( (*a)[n + i] == NULL ) {
+			for( --i ; i >= 0 ; i-- ) {
+				LDAP_FREE( (*a)[n + i] );
+				(*a)[n + i] = NULL;
+			}
+			return -1;
+		}
+	}
+
+	(*a)[n + nn] = NULL;
+	return 0;
+}
+
+void
+ldap_charray_free( char **a )
+{
+	char	**p;
+
+	if ( a == NULL ) {
+		return;
+	}
+
+	for ( p = a; *p != NULL; p++ ) {
+		if ( *p != NULL ) {
+			LDAP_FREE( *p );
+		}
+	}
+
+	LDAP_FREE( (char *) a );
+}
+
+int
+ldap_charray_inlist(
+    char	**a,
+    char	*s
+)
+{
+	int	i;
+
+	if( a == NULL ) return 0;
+
+	for ( i=0; a[i] != NULL; i++ ) {
+		if ( strcasecmp( s, a[i] ) == 0 ) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+char **
+ldap_charray_dup( char **a )
+{
+	int	i;
+	char	**new;
+
+	for ( i = 0; a[i] != NULL; i++ )
+		;	/* NULL */
+
+	new = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
+
+	if( new == NULL ) {
+		return NULL;
+	}
+
+	for ( i = 0; a[i] != NULL; i++ ) {
+		new[i] = LDAP_STRDUP( a[i] );
+
+		if( new[i] == NULL ) {
+			for( --i ; i >= 0 ; i-- ) {
+				LDAP_FREE( new[i] );
+			}
+			LDAP_FREE( new );
+			return NULL;
+		}
+	}
+	new[i] = NULL;
+
+	return( new );
+}
+
+char **
+ldap_str2charray( const char *str_in, const char *brkstr )
+{
+	char	**res;
+	char	*str, *s;
+	char	*lasts;
+	int	i;
+
+	/* protect the input string from strtok */
+	str = LDAP_STRDUP( str_in );
+	if( str == NULL ) {
+		return NULL;
+	}
+
+	i = 1;
+	for ( s = str; *s; s++ ) {
+		if ( ldap_utf8_strchr( brkstr, s ) != NULL ) {
+			i++;
+		}
+	}
+
+	res = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
+
+	if( res == NULL ) {
+		LDAP_FREE( str );
+		return NULL;
+	}
+
+	i = 0;
+
+	for ( s = ldap_utf8_strtok( str, brkstr, &lasts );
+		s != NULL;
+		s = ldap_utf8_strtok( NULL, brkstr, &lasts ) )
+	{
+		res[i] = LDAP_STRDUP( s );
+
+		if(res[i] == NULL) {
+			for( --i ; i >= 0 ; i-- ) {
+				LDAP_FREE( res[i] );
+			}
+			LDAP_FREE( res );
+			LDAP_FREE( str );
+			return NULL;
+		}
+
+		i++;
+	}
+
+	res[i] = NULL;
+
+	LDAP_FREE( str );
+	return( res );
+}
+
+char * ldap_charray2str( char **a, const char *sep )
+{
+	char *s, **v, *p;
+	int len;
+	int slen;
+
+	if( sep == NULL ) sep = " ";
+
+	slen = strlen( sep );
+	len = 0;
+
+	for ( v = a; *v != NULL; v++ ) {
+		len += strlen( *v ) + slen;
+	}
+
+	if ( len == 0 ) {
+		return NULL;
+	}
+
+	/* trim extra sep len */
+	len -= slen;
+
+	s = LDAP_MALLOC ( len + 1 );
+
+	if ( s == NULL ) {
+		return NULL;	
+	}
+
+	p = s;
+	for ( v = a; *v != NULL; v++ ) {
+		if ( v != a ) {
+			strncpy( p, sep, slen );
+			p += slen;
+		}
+
+		len = strlen( *v );
+		strncpy( p, *v, len );
+		p += len;
+	}
+
+	*p = '\0';
+	return s;
+}
+
+
+
+/* $OpenLDAP: pkg/ldap/libraries/libldap/url.c,v 1.64.2.5 2003/03/03 17:10:05 kurt Exp $ */
+/*
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*  Portions
+ *  Copyright (c) 1996 Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  LIBLDAP url.c -- LDAP URL (RFC 2255) related routines
+ *
+ *  LDAP URLs look like this:
+ *    ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
+ *
+ *  where:
+ *   attributes is a comma separated list
+ *   scope is one of these three strings:  base one sub (default=base)
+ *   filter is an string-represented filter as in RFC 2254
+ *
+ *  e.g.,  ldap://host:port/dc=com?o,cn?base?(o=openldap)?extension
+ *
+ *  We also tolerate URLs that look like: <ldapurl> and <URL:ldapurl>
+ */
+
+/* local functions */
+static const char* skip_url_prefix LDAP_P((
+	const char *url,
+	int *enclosedp,
+	const char **scheme ));
+
+int
+ldap_is_ldap_url( LDAP_CONST char *url )
+{
+	int	enclosed;
+	const char * scheme;
+
+	if( url == NULL ) {
+		return 0;
+	}
+
+	if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
+		return 0;
+	}
+
+	return 1;
+}
+
+
+static const char*
+skip_url_prefix(
+	const char *url,
+	int *enclosedp,
+	const char **scheme )
+{
+	/*
+ 	 * return non-zero if this looks like a LDAP URL; zero if not
+ 	 * if non-zero returned, *urlp will be moved past "ldap://" part of URL
+ 	 */
+	const char *p;
+
+	if ( url == NULL ) {
+		return( NULL );
+	}
+
+	p = url;
+
+	/* skip leading '<' (if any) */
+	if ( *p == '<' ) {
+		*enclosedp = 1;
+		++p;
+	} else {
+		*enclosedp = 0;
+	}
+
+	/* skip leading "URL:" (if any) */
+	if ( strncasecmp( p, LDAP_URL_URLCOLON, LDAP_URL_URLCOLON_LEN ) == 0 ) {
+		p += LDAP_URL_URLCOLON_LEN;
+	}
+
+	/* check for "ldap://" prefix */
+	if ( strncasecmp( p, LDAP_URL_PREFIX, LDAP_URL_PREFIX_LEN ) == 0 ) {
+		/* skip over "ldap://" prefix and return success */
+		p += LDAP_URL_PREFIX_LEN;
+		*scheme = "ldap";
+		return( p );
+	}
+
+	/* check for "ldaps://" prefix */
+	if ( strncasecmp( p, LDAPS_URL_PREFIX, LDAPS_URL_PREFIX_LEN ) == 0 ) {
+		/* skip over "ldaps://" prefix and return success */
+		p += LDAPS_URL_PREFIX_LEN;
+		*scheme = "ldaps";
+		return( p );
+	}
+
+	/* check for "ldapi://" prefix */
+	if ( strncasecmp( p, LDAPI_URL_PREFIX, LDAPI_URL_PREFIX_LEN ) == 0 ) {
+		/* skip over "ldapi://" prefix and return success */
+		p += LDAPI_URL_PREFIX_LEN;
+		*scheme = "ldapi";
+		return( p );
+	}
+
+#ifdef LDAP_CONNECTIONLESS
+	/* check for "cldap://" prefix */
+	if ( strncasecmp( p, LDAPC_URL_PREFIX, LDAPC_URL_PREFIX_LEN ) == 0 ) {
+		/* skip over "cldap://" prefix and return success */
+		p += LDAPC_URL_PREFIX_LEN;
+		*scheme = "cldap";
+		return( p );
+	}
+#endif
+
+	return( NULL );
+}
+
+
+static int str2scope( const char *p )
+{
+	if ( strcasecmp( p, "one" ) == 0 ) {
+		return LDAP_SCOPE_ONELEVEL;
+
+	} else if ( strcasecmp( p, "onetree" ) == 0 ) {
+		return LDAP_SCOPE_ONELEVEL;
+
+	} else if ( strcasecmp( p, "base" ) == 0 ) {
+		return LDAP_SCOPE_BASE;
+
+	} else if ( strcasecmp( p, "sub" ) == 0 ) {
+		return LDAP_SCOPE_SUBTREE;
+
+	} else if ( strcasecmp( p, "subtree" ) == 0 ) {
+		return LDAP_SCOPE_SUBTREE;
+	}
+
+	return( -1 );
+}
+
+
+int
+ldap_url_parse_ext( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
+{
+/*
+ *  Pick apart the pieces of an LDAP URL.
+ */
+
+	LDAPURLDesc	*ludp;
+	char	*p, *q, *r;
+	int		i, enclosed;
+	const char *scheme = NULL;
+	const char *url_tmp;
+	char *url;
+
+	if( url_in == NULL || ludpp == NULL ) {
+		return LDAP_URL_ERR_PARAM;
+	}
+
+#ifndef LDAP_INT_IN_KERNEL
+	/* Global options may not be created yet
+	 * We can't test if the global options are initialized
+	 * because a call to LDAP_INT_GLOBAL_OPT() will try to allocate
+	 * the options and cause infinite recursion
+	 */
+#ifdef NEW_LOGGING
+	LDAP_LOG ( OPERATION, ENTRY, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 );
+#else
+	Debug( LDAP_DEBUG_TRACE, "ldap_url_parse_ext(%s)\n", url_in, 0, 0 );
+#endif
+#endif
+
+	*ludpp = NULL;	/* pessimistic */
+
+	url_tmp = skip_url_prefix( url_in, &enclosed, &scheme );
+
+	if ( url_tmp == NULL ) {
+		return LDAP_URL_ERR_BADSCHEME;
+	}
+
+	assert( scheme );
+
+	/* make working copy of the remainder of the URL */
+	url = LDAP_STRDUP( url_tmp );
+	if ( url == NULL ) {
+		return LDAP_URL_ERR_MEM;
+	}
+
+	if ( enclosed ) {
+		p = &url[strlen(url)-1];
+
+		if( *p != '>' ) {
+			LDAP_FREE( url );
+			return LDAP_URL_ERR_BADENCLOSURE;
+		}
+
+		*p = '\0';
+	}
+
+	/* allocate return struct */
+	ludp = (LDAPURLDesc *)LDAP_CALLOC( 1, sizeof( LDAPURLDesc ));
+
+	if ( ludp == NULL ) {
+		LDAP_FREE( url );
+		return LDAP_URL_ERR_MEM;
+	}
+
+	ludp->lud_next = NULL;
+	ludp->lud_host = NULL;
+	ludp->lud_port = 0;
+	ludp->lud_dn = NULL;
+	ludp->lud_attrs = NULL;
+	ludp->lud_filter = NULL;
+	ludp->lud_scope = LDAP_SCOPE_DEFAULT;
+	ludp->lud_filter = NULL;
+	ludp->lud_exts = NULL;
+
+	ludp->lud_scheme = LDAP_STRDUP( scheme );
+
+	if ( ludp->lud_scheme == NULL ) {
+		LDAP_FREE( url );
+		ldap_free_urldesc( ludp );
+		return LDAP_URL_ERR_MEM;
+	}
+
+	/* scan forward for '/' that marks end of hostport and begin. of dn */
+	p = strchr( url, '/' );
+
+	if( p != NULL ) {
+		/* terminate hostport; point to start of dn */
+		*p++ = '\0';
+	}
+
+	/* IPv6 syntax with [ip address]:port */
+	if ( *url == '[' ) {
+		r = strchr( url, ']' );
+		if ( r == NULL ) {
+			LDAP_FREE( url );
+			ldap_free_urldesc( ludp );
+			return LDAP_URL_ERR_BADURL;
+		}
+		*r++ = '\0';
+		q = strchr( r, ':' );
+	} else {
+		q = strchr( url, ':' );
+	}
+
+	if ( q != NULL ) {
+		*q++ = '\0';
+		ldap_pvt_hex_unescape( q );
+
+		if( *q == '\0' ) {
+			LDAP_FREE( url );
+			ldap_free_urldesc( ludp );
+			return LDAP_URL_ERR_BADURL;
+		}
+
+		ludp->lud_port = atoi( q );
+	}
+
+	ldap_pvt_hex_unescape( url );
+
+	/* If [ip address]:port syntax, url is [ip and we skip the [ */
+	ludp->lud_host = LDAP_STRDUP( url + ( *url == '[' ) );
+
+	if( ludp->lud_host == NULL ) {
+		LDAP_FREE( url );
+		ldap_free_urldesc( ludp );
+		return LDAP_URL_ERR_MEM;
+	}
+
+	/*
+	 * Kludge.  ldap://111.222.333.444:389??cn=abc,o=company
+	 *
+	 * On early Novell releases, search references/referrals were returned
+	 * in this format, i.e., the dn was kind of in the scope position,
+	 * but the required slash is missing. The whole thing is illegal syntax,
+	 * but we need to account for it. Fortunately it can't be confused with
+	 * anything real.
+	 */
+	if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
+		q++;		
+		/* ? immediately followed by question */
+		if( *q == '?') {
+			q++;
+			if( *q != '\0' ) {
+				/* parse dn part */
+				ldap_pvt_hex_unescape( q );
+				ludp->lud_dn = LDAP_STRDUP( q );
+			} else {
+				ludp->lud_dn = LDAP_STRDUP( "" );
+			}
+
+			if( ludp->lud_dn == NULL ) {
+				LDAP_FREE( url );
+				ldap_free_urldesc( ludp );
+				return LDAP_URL_ERR_MEM;
+			}
+		}
+	}
+
+	if( p == NULL ) {
+		LDAP_FREE( url );
+		*ludpp = ludp;
+		return LDAP_URL_SUCCESS;
+	}
+
+	/* scan forward for '?' that may marks end of dn */
+	q = strchr( p, '?' );
+
+	if( q != NULL ) {
+		/* terminate dn part */
+		*q++ = '\0';
+	}
+
+	if( *p != '\0' ) {
+		/* parse dn part */
+		ldap_pvt_hex_unescape( p );
+		ludp->lud_dn = LDAP_STRDUP( p );
+	} else {
+		ludp->lud_dn = LDAP_STRDUP( "" );
+	}
+
+	if( ludp->lud_dn == NULL ) {
+		LDAP_FREE( url );
+		ldap_free_urldesc( ludp );
+		return LDAP_URL_ERR_MEM;
+	}
+
+	if( q == NULL ) {
+		/* no more */
+		LDAP_FREE( url );
+		*ludpp = ludp;
+		return LDAP_URL_SUCCESS;
+	}
+
+	/* scan forward for '?' that may marks end of attributes */
+	p = q;
+	q = strchr( p, '?' );
+
+	if( q != NULL ) {
+		/* terminate attributes part */
+		*q++ = '\0';
+	}
+
+	if( *p != '\0' ) {
+		/* parse attributes */
+		ldap_pvt_hex_unescape( p );
+		ludp->lud_attrs = ldap_str2charray( p, "," );
+
+		if( ludp->lud_attrs == NULL ) {
+			LDAP_FREE( url );
+			ldap_free_urldesc( ludp );
+			return LDAP_URL_ERR_BADATTRS;
+		}
+	}
+
+	if ( q == NULL ) {
+		/* no more */
+		LDAP_FREE( url );
+		*ludpp = ludp;
+		return LDAP_URL_SUCCESS;
+	}
+
+	/* scan forward for '?' that may marks end of scope */
+	p = q;
+	q = strchr( p, '?' );
+
+	if( q != NULL ) {
+		/* terminate the scope part */
+		*q++ = '\0';
+	}
+
+	if( *p != '\0' ) {
+		/* parse the scope */
+		ldap_pvt_hex_unescape( p );
+		ludp->lud_scope = str2scope( p );
+
+		if( ludp->lud_scope == -1 ) {
+			LDAP_FREE( url );
+			ldap_free_urldesc( ludp );
+			return LDAP_URL_ERR_BADSCOPE;
+		}
+	}
+
+	if ( q == NULL ) {
+		/* no more */
+		LDAP_FREE( url );
+		*ludpp = ludp;
+		return LDAP_URL_SUCCESS;
+	}
+
+	/* scan forward for '?' that may marks end of filter */
+	p = q;
+	q = strchr( p, '?' );
+
+	if( q != NULL ) {
+		/* terminate the filter part */
+		*q++ = '\0';
+	}
+
+	if( *p != '\0' ) {
+		/* parse the filter */
+		ldap_pvt_hex_unescape( p );
+
+		if( ! *p ) {
+			/* missing filter */
+			LDAP_FREE( url );
+			ldap_free_urldesc( ludp );
+			return LDAP_URL_ERR_BADFILTER;
+		}
+
+		LDAP_FREE( ludp->lud_filter );
+		ludp->lud_filter = LDAP_STRDUP( p );
+
+		if( ludp->lud_filter == NULL ) {
+			LDAP_FREE( url );
+			ldap_free_urldesc( ludp );
+			return LDAP_URL_ERR_MEM;
+		}
+	}
+
+	if ( q == NULL ) {
+		/* no more */
+		LDAP_FREE( url );
+		*ludpp = ludp;
+		return LDAP_URL_SUCCESS;
+	}
+
+	/* scan forward for '?' that may marks end of extensions */
+	p = q;
+	q = strchr( p, '?' );
+
+	if( q != NULL ) {
+		/* extra '?' */
+		LDAP_FREE( url );
+		ldap_free_urldesc( ludp );
+		return LDAP_URL_ERR_BADURL;
+	}
+
+	/* parse the extensions */
+	ludp->lud_exts = ldap_str2charray( p, "," );
+
+	if( ludp->lud_exts == NULL ) {
+		LDAP_FREE( url );
+		ldap_free_urldesc( ludp );
+		return LDAP_URL_ERR_BADEXTS;
+	}
+
+	for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
+		ldap_pvt_hex_unescape( ludp->lud_exts[i] );
+
+		if( *ludp->lud_exts[i] == '!' ) {
+			/* count the number of critical extensions */
+			ludp->lud_crit_exts++;
+		}
+	}
+
+	if( i == 0 ) {
+		/* must have 1 or more */
+		LDAP_FREE( url );
+		ldap_free_urldesc( ludp );
+		return LDAP_URL_ERR_BADEXTS;
+	}
+
+	/* no more */
+	*ludpp = ludp;
+	LDAP_FREE( url );
+	return LDAP_URL_SUCCESS;
+}
+
+int
+ldap_url_parse( LDAP_CONST char *url_in, LDAPURLDesc **ludpp )
+{
+	int rc = ldap_url_parse_ext( url_in, ludpp );
+
+	if( rc != LDAP_URL_SUCCESS ) {
+		return rc;
+	}
+
+	if ((*ludpp)->lud_scope == LDAP_SCOPE_DEFAULT) {
+		(*ludpp)->lud_scope = LDAP_SCOPE_BASE;
+	}
+
+	if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') {
+		LDAP_FREE( (*ludpp)->lud_host );
+		(*ludpp)->lud_host = NULL;
+	}
+
+	if ((*ludpp)->lud_port == 0) {
+		if( strcmp((*ludpp)->lud_scheme, "ldap") == 0 ) {
+			(*ludpp)->lud_port = LDAP_PORT;
+#ifdef LDAP_CONNECTIONLESS
+		} else if( strcmp((*ludpp)->lud_scheme, "cldap") == 0 ) {
+			(*ludpp)->lud_port = LDAP_PORT;
+#endif
+		} else if( strcmp((*ludpp)->lud_scheme, "ldaps") == 0 ) {
+			(*ludpp)->lud_port = LDAPS_PORT;
+		}
+	}
+
+	return rc;
+}
+
+
+void
+ldap_free_urldesc( LDAPURLDesc *ludp )
+{
+	if ( ludp == NULL ) {
+		return;
+	}
+	
+	if ( ludp->lud_scheme != NULL ) {
+		LDAP_FREE( ludp->lud_scheme );
+	}
+
+	if ( ludp->lud_host != NULL ) {
+		LDAP_FREE( ludp->lud_host );
+	}
+
+	if ( ludp->lud_dn != NULL ) {
+		LDAP_FREE( ludp->lud_dn );
+	}
+
+	if ( ludp->lud_filter != NULL ) {
+		LDAP_FREE( ludp->lud_filter);
+	}
+
+	if ( ludp->lud_attrs != NULL ) {
+		LDAP_VFREE( ludp->lud_attrs );
+	}
+
+	if ( ludp->lud_exts != NULL ) {
+		LDAP_VFREE( ludp->lud_exts );
+	}
+
+	LDAP_FREE( ludp );
+}
+
+
+static int
+ldap_int_unhex( int c )
+{
+	return( c >= '0' && c <= '9' ? c - '0'
+	    : c >= 'A' && c <= 'F' ? c - 'A' + 10
+	    : c - 'a' + 10 );
+}
+
+void
+ldap_pvt_hex_unescape( char *s )
+{
+	/*
+	 * Remove URL hex escapes from s... done in place.  The basic concept for
+	 * this routine is borrowed from the WWW library HTUnEscape() routine.
+	 */
+	char	*p;
+
+	for ( p = s; *s != '\0'; ++s ) {
+		if ( *s == '%' ) {
+			if ( *++s == '\0' ) {
+				break;
+			}
+			*p = ldap_int_unhex( *s ) << 4;
+			if ( *++s == '\0' ) {
+				break;
+			}
+			*p++ += ldap_int_unhex( *s );
+		} else {
+			*p++ = *s;
+		}
+	}
+
+	*p = '\0';
+}
+

Modified: trunk/src/ldap.c
===================================================================
--- trunk/src/ldap.c	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/ldap.c	2007-07-25 23:20:23 UTC (rev 248)
@@ -37,6 +37,11 @@
 #include "dirmngr.h"
 #include "misc.h"
 
+#if HAVE_W32_SYSTEM
+#define setenv(a,b,c) SetEnvironmentVariable ((a),(b))
+#define pth_yield(a) /* FIXME */
+#endif
+
 /* In case sysconf does not return a value we need to have a limit. */
 #ifdef _POSIX_OPEN_MAX
 #define MAX_OPEN_FDS _POSIX_OPEN_MAX

Modified: trunk/src/no-libgcrypt.h
===================================================================
--- trunk/src/no-libgcrypt.h	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/no-libgcrypt.h	2007-07-25 23:20:23 UTC (rev 248)
@@ -21,6 +21,8 @@
 #ifndef NO_LIBGCRYPT_H
 #define NO_LIBGCRYPT_H
 
+#define NO_LIBGCRYPT 1
+
 void *gcry_malloc (size_t n);
 void *gcry_xmalloc (size_t n);
 void *gcry_realloc (void *a, size_t n);

Modified: trunk/src/util.h
===================================================================
--- trunk/src/util.h	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/util.h	2007-07-25 23:20:23 UTC (rev 248)
@@ -22,7 +22,9 @@
 #define UTIL_H
 
 #include <gpg-error.h>
+#ifndef NO_LIBGCRYPT
 #include <gcrypt.h>
+#endif
 
 /* Get all the stuff from jnlib. */
 #include "../jnlib/logging.h"

Added: trunk/src/vasprintf.c
===================================================================
--- trunk/src/vasprintf.c	2007-07-23 16:22:05 UTC (rev 247)
+++ trunk/src/vasprintf.c	2007-07-25 23:20:23 UTC (rev 248)
@@ -0,0 +1,192 @@
+/* Like vsprintf but provides a pointer to malloc'd storage, which must
+   be freed by the caller.
+   Copyright (C) 1994, 2002 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+
+#ifndef va_copy /* According to POSIX, va_copy is a macro. */
+#if defined (__GNUC__) && defined (__PPC__) \
+     && (defined (_CALL_SYSV) || defined (_WIN32))
+#define va_copy(d, s) (*(d) = *(s))
+#elif defined (MUST_COPY_VA_BYVAL)
+#define va_copy(d, s) ((d) = (s))
+#else 
+#define va_copy(d, s) memcpy ((d), (s), sizeof (va_list))
+#endif 
+#endif 
+
+
+#ifdef TEST
+int global_total_width;
+#endif
+
+static int int_vasprintf (char **, const char *, va_list *);
+
+static int
+int_vasprintf (result, format, args)
+     char **result;
+     const char *format;
+     va_list *args;
+{
+  const char *p = format;
+  /* Add one to make sure that it is never zero, which might cause malloc
+     to return NULL.  */
+  int total_width = strlen (format) + 1;
+  va_list ap;
+
+  va_copy (ap, *args);
+
+  while (*p != '\0')
+    {
+      if (*p++ == '%')
+	{
+	  while (strchr ("-+ #0", *p))
+	    ++p;
+	  if (*p == '*')
+	    {
+	      ++p;
+	      total_width += abs (va_arg (ap, int));
+	    }
+	  else
+	    total_width += strtoul (p, (char **) &p, 10);
+	  if (*p == '.')
+	    {
+	      ++p;
+	      if (*p == '*')
+		{
+		  ++p;
+		  total_width += abs (va_arg (ap, int));
+		}
+	      else
+	      total_width += strtoul (p, (char **) &p, 10);
+	    }
+	  while (strchr ("hlL", *p))
+	    ++p;
+	  /* Should be big enough for any format specifier except %s and floats.  */
+	  total_width += 30;
+	  switch (*p)
+	    {
+	    case 'd':
+	    case 'i':
+	    case 'o':
+	    case 'u':
+	    case 'x':
+	    case 'X':
+	    case 'c':
+	      (void) va_arg (ap, int);
+	      break;
+	    case 'f':
+	    case 'e':
+	    case 'E':
+	    case 'g':
+	    case 'G':
+	      (void) va_arg (ap, double);
+	      /* Since an ieee double can have an exponent of 307, we'll
+		 make the buffer wide enough to cover the gross case. */
+	      total_width += 307;
+	      break;
+	    case 's':
+              {
+                char *tmp = va_arg (ap, char *);
+                if (tmp)
+                  total_width += strlen (tmp);
+                else /* in case the vsprintf does prints a text */
+                  total_width += 25; /* e.g. "(null pointer reference)" */
+              }
+	      break;
+	    case 'p':
+	    case 'n':
+	      (void) va_arg (ap, char *);
+	      break;
+	    }
+	  p++;
+	}
+    }
+#ifdef TEST
+  global_total_width = total_width;
+#endif
+  *result = malloc (total_width);
+  if (*result != NULL)
+    return vsprintf (*result, format, *args);
+  else
+    return 0;
+}
+
+int
+vasprintf (result, format, args)
+     char **result;
+     const char *format;
+#if defined (_BSD_VA_LIST_) && defined (__FreeBSD__)
+     _BSD_VA_LIST_ args;
+#else
+     va_list args;
+#endif
+{
+  return int_vasprintf (result, format, &args);
+}
+
+
+int
+asprintf (char **buf, const char *fmt, ...)
+{
+  int status;
+  va_list ap;
+
+  va_start (ap, fmt);
+  status = vasprintf (buf, fmt, ap);
+  va_end (ap);
+  return status;
+}
+
+
+#ifdef TEST
+void
+checkit (const char* format, ...)
+{
+  va_list args;
+  char *result;
+
+  va_start (args, format);
+  vasprintf (&result, format, args);
+  if (strlen (result) < global_total_width)
+    printf ("PASS: ");
+  else
+    printf ("FAIL: ");
+  printf ("%d %s\n", global_total_width, result);
+}
+
+int
+main (void)
+{
+  checkit ("%d", 0x12345678);
+  checkit ("%200d", 5);
+  checkit ("%.300d", 6);
+  checkit ("%100.150d", 7);
+  checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
+777777777777777777333333333333366666666666622222222222777777777777733333");
+  checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
+}
+#endif /* TEST */




More information about the Gnupg-commits mailing list