]> git.sur5r.net Git - openldap/commitdiff
mostly logging
authorKurt Zeilenga <kurt@openldap.org>
Sun, 28 Jul 2002 21:18:10 +0000 (21:18 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Sun, 28 Jul 2002 21:18:10 +0000 (21:18 +0000)
27 files changed:
contrib/ldapsasl/README [new file with mode: 0644]
contrib/ldapsasl/ldapdb.c [new file with mode: 0644]
libraries/Makefile.in [new file with mode: 0644]
libraries/libavl/Makefile.in [new file with mode: 0644]
libraries/liblber/Makefile.in [new file with mode: 0644]
libraries/liblber/debug.c [new file with mode: 0644]
libraries/liblber/decode.c
libraries/liblber/encode.c
libraries/liblber/io.c
libraries/liblber/lber-int.h [new file with mode: 0644]
libraries/liblber/liblber.dsp [new file with mode: 0644]
libraries/libldap_r/thr_posix.c [new file with mode: 0644]
libraries/libldbm/ldbm.c
libraries/liblunicode/Makefile.in
libraries/liblunicode/ucdata/ucdata.c
libraries/liblunicode/ucdata/ucgendat.c
libraries/liblutil/Makefile.in [new file with mode: 0644]
libraries/liblutil/debug.c [deleted file]
libraries/liblutil/getopt.c [new file with mode: 0644]
libraries/liblutil/liblutil.dsp [new file with mode: 0644]
libraries/liblutil/ntservice.c [new file with mode: 0644]
libraries/liblutil/sasl.c [new file with mode: 0644]
libraries/liblutil/stdio.c [new file with mode: 0644]
libraries/liblutil/utils.c [new file with mode: 0644]
libraries/librewrite/map.c
libraries/librewrite/parse.c
libraries/librewrite/rewrite.c [new file with mode: 0644]

diff --git a/contrib/ldapsasl/README b/contrib/ldapsasl/README
new file mode 100644 (file)
index 0000000..36c3f6b
--- /dev/null
@@ -0,0 +1,50 @@
+LDAP auxprop plugin for SASL-enabled servers.
+Copyright (C) 2002 by Howard Chu, hyc@symas.com
+
+This software is an experimental proof-of-concept and is not intended for
+general use. It is licensed under the terms ofthe OpenLDAP license.
+
+The file ldapdb.c was written for Cyrus SASL 2.1.3 and OpenLDAP 2.1.3.
+It can be compiled by copying into the Cyrus SASL source tree, in the
+plugins subdirectory. No configuration or build script is provided.
+
+To compile, type "make ldapdb.lo". To link, you'll have to copy the
+link rule for one of the other plugins. Below is a sample on my Linux
+system:
+
+       /bin/sh ./libtool --mode=link gcc  -Wall -W -g -O2 -L/usr/local/lib -Wl,-rpath,/usr/local/lib -module -export-dynamic -rpath /usr/lib/sasl2 -o libldapdb.la  -version-info 2:4:0 ldapdb.lo -lldap -llber -lssl -lcrypto
+
+Once installed, you need to add some config items to the SASL server's
+config file in /usr/lib/sasl2. For example:
+
+ldapdb_uri: ldapi://
+ldapdb_id: root
+ldapdb_pw: secret
+ldapdb_mech: PLAIN
+
+This config assumes an LDAP server on the same machine as the server
+that is using SASL. The LDAP server must be configured to map the SASL
+authcId "root" into a DN that has proxy authorization privileges to
+every account that is allowed to login to this server. (See the OpenLDAP
+Admin Guide for details.)
+
+Unlike other LDAP-enabled plugins for other services that are common
+on the web, this plugin does not require you to configure DN search
+patterns to map usernames to LDAP DNs. This plugin requires SASL name
+mapping to be configured on the target slapd. This approach keeps the
+LDAP-specific configuration details in one place, the slapd.conf, and
+makes the configuration of remote services much simpler.
+
+One additional keyword "ldapdb_rc" may be specified in the config file.
+The filename specified here will be put into the server's LDAPRC
+environment variable, and libldap-specific config options may be set
+in that ldaprc file. The main purpose behind this option is to allow
+a client TLS certificate to be configured, so that SASL/EXTERNAL may
+be used between the SASL server and the LDAP server. This is the most
+optimal way to use this plugin when the servers are on separate machines.
+
+This plugin likely has very poor performance. You'll need something
+better for a real production environment. Please send feedback via the
+openldap-software mailing list for now.
+
+  -- Howard Chu, 2002-07-12
diff --git a/contrib/ldapsasl/ldapdb.c b/contrib/ldapsasl/ldapdb.c
new file mode 100644 (file)
index 0000000..0772aea
--- /dev/null
@@ -0,0 +1,220 @@
+/* SASL LDAP auxprop implementation
+ * Copyright (C) 2002 Howard Chu, hyc@symas.com
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include "sasl.h"
+#include "saslutil.h"
+#include "saslplug.h"
+
+#include "plugin_common.h"
+
+#include <ldap.h>
+
+static char ldapdb[] = "ldapdb";
+
+SASL_AUXPROP_PLUG_INIT( ldapdb )
+
+typedef struct ldapctx {
+       const char *uri;        /* URI of LDAP server */
+       const char *id; /* SASL authcid to bind as */
+       const char *pw; /* password for bind */
+       const char *mech;       /* SASL mech */
+} ldapctx;
+
+typedef struct gluectx {
+       ldapctx *lc;
+       sasl_server_params_t *lp;
+       const char *user;
+} gluectx;
+
+static int ldapdb_interact(LDAP *ld, unsigned flags __attribute__((unused)),
+       void *def, void *inter)
+{
+       sasl_interact_t *in = inter;
+       gluectx *gc = def;
+       const char *p;
+
+       for (;in->id != SASL_CB_LIST_END;in++)
+       {
+               p = NULL;
+               switch(in->id)
+               {
+                       case SASL_CB_GETREALM:
+                               ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &p);
+                               break;          
+                       case SASL_CB_AUTHNAME:
+                               p = gc->lc->id;
+                               break;
+                       case SASL_CB_PASS:
+                               p = gc->lc->pw;
+                               break;
+                       case SASL_CB_USER:
+                               p = gc->user;
+                               break;
+               }
+               if (p)
+               {
+                       int l = strlen(p);
+                       in->result = gc->lp->utils->malloc(l+1);
+                       if (!in->result)
+                               return LDAP_NO_MEMORY;
+                       strcpy((char *)in->result, p);
+                       in->len = l;
+               }
+       }
+       return LDAP_SUCCESS;
+}
+
+static void ldapdb_auxprop_lookup(void *glob_context,
+                                 sasl_server_params_t *sparams,
+                                 unsigned flags,
+                                 const char *user,
+                                 unsigned ulen)
+{
+    ldapctx *ctx = glob_context;
+    int ret, i, n, *aindx;
+    const struct propval *pr;
+    LDAP *ld = NULL;
+    gluectx gc = { ctx, sparams, NULL };
+    struct berval *dn = NULL, **bvals;
+    LDAPMessage *msg, *res;
+    char **attrs = NULL, *authzid = NULL;
+    
+    if(!ctx || !sparams || !user) return;
+
+    pr = sparams->utils->prop_get(sparams->propctx);
+    if(!pr) return;
+
+    /* count how many attrs to fetch */
+    for(i = 0, n = 0; pr[i].name; i++) {
+       if(pr[i].name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID))
+           continue;
+       if(pr[i].values && !(flags & SASL_AUXPROP_OVERRIDE))
+           continue;
+       n++;
+    }
+    /* nothing to do, bail out */
+    if (!n) return;
+
+    /* alloc an array of attr names for search, and index to the props */
+    attrs = sparams->utils->malloc((n+1)*sizeof(char *)*2);
+    if (!attrs) return;
+
+    aindx = (int *)(attrs + n + 1);
+
+    /* copy attr list */
+    for (i=0, n=0; pr[i].name; i++) {
+       if(pr[i].name[0] == '*' && (flags & SASL_AUXPROP_AUTHZID))
+           continue;
+       if(pr[i].values && !(flags & SASL_AUXPROP_OVERRIDE))
+           continue;
+       attrs[n] = (char *)pr[i].name;
+       if (pr[i].name[0] == '*') attrs[n]++;
+       aindx[n] = i;
+       n++;
+    }
+    attrs[n] = NULL;
+       
+    if(ldap_initialize(&ld, ctx->uri)) {
+       sparams->utils->free(attrs);
+       return;
+    }
+
+    authzid = sparams->utils->malloc(ulen + sizeof("u:"));
+    if (!authzid) goto done;
+    strcpy(authzid, "u:");
+    strcpy(authzid+2, user);
+    gc.user = authzid;
+
+    i = LDAP_VERSION3;
+    ret = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &i);
+
+    ret = ldap_sasl_interactive_bind_s(ld, NULL, ctx->mech, NULL, NULL,
+       LDAP_SASL_QUIET, ldapdb_interact, &gc);
+    if (ret != LDAP_SUCCESS) goto done;
+    
+    ret = ldap_extended_operation_s(ld, LDAP_EXOP_X_WHO_AM_I, NULL, NULL,
+       NULL, NULL, &dn);
+    if (ret != LDAP_SUCCESS || !dn) goto done;
+    
+    if (dn->bv_val && !strncmp(dn->bv_val, "dn:", 3))
+    ret = ldap_search_s(ld, dn->bv_val+3, LDAP_SCOPE_BASE, "(objectclass=*)",
+       attrs, 0, &res);
+    ber_bvfree(dn);
+
+    if (ret != LDAP_SUCCESS) goto done;
+
+    for(msg=ldap_first_message(ld, res); msg; msg=ldap_next_message(ld, msg))
+    {
+       if (ldap_msgtype(msg) != LDAP_RES_SEARCH_ENTRY) continue;
+       for (i=0; i<n; i++)
+       {
+           bvals = ldap_get_values_len(ld, msg, attrs[i]);
+           if (!bvals) continue;
+           if (pr[aindx[i]].values)
+               sparams->utils->prop_erase(sparams->propctx, pr[aindx[i]].name);
+           sparams->utils->prop_set(sparams->propctx, pr[aindx[i]].name,
+                                bvals[0]->bv_val, bvals[0]->bv_len);
+           ber_bvecfree(bvals);
+       }
+    }
+    ldap_msgfree(res);
+
+ done:
+    if(authzid) sparams->utils->free(authzid);
+    if(attrs) sparams->utils->free(attrs);
+    if(ld) ldap_unbind(ld);
+}
+
+static void ldapdb_auxprop_free(void *glob_ctx, const sasl_utils_t *utils)
+{
+       utils->free(glob_ctx);
+}
+
+static sasl_auxprop_plug_t ldapdb_auxprop_plugin = {
+    0,           /* Features */
+    0,           /* spare */
+    NULL,        /* glob_context */
+    ldapdb_auxprop_free,       /* auxprop_free */
+    ldapdb_auxprop_lookup, /* auxprop_lookup */
+    ldapdb,    /* name */
+    NULL         /* spare */
+};
+
+int ldapdb_auxprop_plug_init(const sasl_utils_t *utils,
+                             int max_version,
+                             int *out_version,
+                             sasl_auxprop_plug_t **plug,
+                             const char *plugname __attribute__((unused))) 
+{
+    ldapctx tmp, *p;
+    const char *s;
+
+    if(!out_version || !plug) return SASL_BADPARAM;
+
+    if(max_version < SASL_AUXPROP_PLUG_VERSION) return SASL_BADVERS;
+    
+    utils->getopt(utils->getopt_context, ldapdb, "ldapdb_uri", &tmp.uri, NULL);
+    if(!tmp.uri) return SASL_BADPARAM;
+
+    utils->getopt(utils->getopt_context, ldapdb, "ldapdb_id", &tmp.id, NULL);
+    utils->getopt(utils->getopt_context, ldapdb, "ldapdb_pw", &tmp.pw, NULL);
+    utils->getopt(utils->getopt_context, ldapdb, "ldapdb_mech", &tmp.mech, NULL);
+    utils->getopt(utils->getopt_context, ldapdb, "ldapdb_rc", &s, NULL);
+    if(s && setenv("LDAPRC", s, 1)) return SASL_BADPARAM;
+
+    p = utils->malloc(sizeof(ldapctx));
+    if (!p) return SASL_NOMEM;
+    *p = tmp;
+    ldapdb_auxprop_plugin.glob_context = p;
+
+    *out_version = SASL_AUXPROP_PLUG_VERSION;
+
+    *plug = &ldapdb_auxprop_plugin;
+
+    return SASL_OK;
+}
diff --git a/libraries/Makefile.in b/libraries/Makefile.in
new file mode 100644 (file)
index 0000000..f07cb00
--- /dev/null
@@ -0,0 +1,10 @@
+# $OpenLDAP$
+## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+##
+## Libraries Makefile for OpenLDAP
+
+SUBDIRS= liblutil liblunicode libldif \
+       liblber libldap libldap_r \
+       libavl libldbm librewrite
+
diff --git a/libraries/libavl/Makefile.in b/libraries/libavl/Makefile.in
new file mode 100644 (file)
index 0000000..f9c8e44
--- /dev/null
@@ -0,0 +1,20 @@
+# $OpenLDAP$
+## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+##
+## LIBAVL
+##
+
+SRCS = avl.c testavl.c
+XSRCS = version.c
+OBJS = avl.o
+
+LDAP_INCDIR= ../../include       
+LDAP_LIBDIR= ../../libraries
+
+LIBRARY = libavl.a
+PROGRAMS       = testavl
+XLIBS = $(LIBRARY) $(LDAP_LIBLBER_LA) $(LDAP_LIBLUTIL_A)
+
+testavl:       $(XLIBS) testavl.o
+       $(LTLINK) -o $@ testavl.o $(LIBS)
diff --git a/libraries/liblber/Makefile.in b/libraries/liblber/Makefile.in
new file mode 100644 (file)
index 0000000..87da856
--- /dev/null
@@ -0,0 +1,40 @@
+# $OpenLDAP$
+## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+##
+## LIBLBER
+##
+
+LIBRARY = liblber.la
+
+NT_SRCS = nt_err.c
+NT_OBJS = nt_err.lo
+
+LIB_DEFS = -DLBER_LIBRARY
+
+SRCS= assert.c decode.c encode.c io.c bprint.c debug.c \
+       memory.c options.c sockbuf.c $(@PLAT@_SRCS)
+OBJS= assert.lo decode.lo encode.lo io.lo bprint.lo debug.lo\
+       memory.lo options.lo sockbuf.lo $(@PLAT@_OBJS)
+XSRCS= version.c
+
+PROGRAMS= dtest etest idtest
+
+LDAP_INCDIR= ../../include
+LDAP_LIBDIR= ../../libraries
+
+XLIBS = $(LIBRARY) $(LDAP_LIBLUTIL_A)
+XXLIBS = 
+NT_LINK_LIBS = $(AC_LIBS)
+
+dtest:    $(XLIBS) dtest.o
+       $(LTLINK) -o $@ dtest.o $(LIBS)
+etest:  $(XLIBS) etest.o
+       $(LTLINK) -o $@ etest.o $(LIBS)
+idtest:  $(XLIBS) idtest.o
+       $(LTLINK) -o $@ idtest.o $(LIBS)
+
+install-local: FORCE
+       -$(MKDIR) $(DESTDIR)$(libdir)
+       $(LTINSTALL) $(INSTALLFLAGS) -m 644 $(LIBRARY) $(DESTDIR)$(libdir)
+
diff --git a/libraries/liblber/debug.c b/libraries/liblber/debug.c
new file mode 100644 (file)
index 0000000..8d182d8
--- /dev/null
@@ -0,0 +1,328 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/stdarg.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+#include <ac/ctype.h>
+
+#ifdef LDAP_SYSLOG
+#include <ac/syslog.h>
+#endif
+
+#include "ldap_log.h"
+#include "ldap_defaults.h"
+#include "lber.h"
+#include "ldap_pvt.h"
+
+struct DEBUGLEVEL
+{
+       char *subsystem;
+       int  level;
+};
+
+int ldap_loglevels[LDAP_SUBSYS_NUM];
+static long   numLevels = 0;
+
+static FILE *log_file = NULL;
+static int global_level = 0;
+
+#ifdef LDAP_SYSLOG
+static int use_syslog = 0;
+
+static int debug2syslog(int l) {
+       switch (l) {
+       case LDAP_LEVEL_EMERG:  return LOG_EMERG;
+       case LDAP_LEVEL_ALERT:  return LOG_ALERT;
+       case LDAP_LEVEL_CRIT:   return LOG_CRIT;
+       case LDAP_LEVEL_ERR:    return LOG_ERR;
+       case LDAP_LEVEL_WARNING:        return LOG_WARNING;
+       case LDAP_LEVEL_NOTICE: return LOG_NOTICE;
+       case LDAP_LEVEL_INFO:   return LOG_INFO;
+       }
+       return LOG_DEBUG;
+}
+#endif
+
+static char *lutil_levels[] = {"emergency", "alert", "critical",
+                          "error", "warning", "notice",
+                          "information", "entry", "args",
+                          "results", "detail1", "detail2",
+                          NULL};
+
+static char *lutil_subsys[LDAP_SUBSYS_NUM] = {"global","operation", "transport",
+                               "connection", "filter", "ber", 
+                               "config", "acl", "cache", "index", 
+                               "ldif", "tools", "slapd", "slurpd",
+                               "backend", "back_bdb", "back_ldbm", 
+                               "back_ldap", "back_meta", "back_mon" };
+
+int lutil_mnem2subsys( const char *subsys )
+{
+    int i;
+    for( i = 0; i < LDAP_SUBSYS_NUM; i++ )
+    {
+               if ( !strcasecmp( subsys, lutil_subsys[i] ) )
+               {
+               return i;
+               }
+    }
+    return -1;
+}
+
+void lutil_set_all_backends( level )
+{
+    int i;
+
+    for( i = 0; i < LDAP_SUBSYS_NUM; i++ )
+    {
+               if ( !strncasecmp( "back_", lutil_subsys[i], strlen("back_") ) )
+               {
+                       ldap_loglevels[i] = level;
+               }
+    }
+}
+
+int lutil_mnem2level( const char *level )
+{
+    int i;
+    for( i = 0; lutil_levels[i] != NULL; i++ )
+    {
+       if ( !strcasecmp( level, lutil_levels[i] ) )
+       {
+           return i;
+       }
+    }
+    return -1;
+}
+
+static int addSubsys( const char *subsys, int level )
+{
+       int subsys_num;
+
+       if ( !strcasecmp( subsys, "backend" ) )
+       {
+               lutil_set_all_backends( level );
+               return level;
+       }
+       else
+       {
+               subsys_num = lutil_mnem2subsys(subsys);
+               if(subsys_num < 0)
+               {
+                       fprintf(stderr, "Unknown Subsystem name [ %s ] - Discarded\n", 
+                               subsys);
+                       fflush(stderr);
+                       return -1;
+               }
+
+               ldap_loglevels[subsys_num] = level;
+               return level;
+       }
+       return -1;
+}
+
+int lutil_set_debug_level( const char* subsys, int level )
+{
+    return( addSubsys( subsys, level ) );
+}
+
+int lutil_debug_file( FILE *file )
+{
+       log_file = file;
+       ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
+
+       return 0;
+}
+
+void lutil_log_int(
+       FILE* file,
+       const char *subsys, int level,
+       const char *fmt, va_list vl )
+{
+#ifdef HAVE_WINSOCK
+       time_t now;
+       struct tm *today;
+#endif
+       size_t i;
+       char * t_subsys;
+       char * tmp;
+
+       t_subsys = strdup(subsys);
+       
+       for(tmp = t_subsys, i = 0; i < strlen(t_subsys); i++, tmp++)
+               *tmp = TOUPPER( (unsigned char) *tmp );
+
+#ifdef LDAP_SYSLOG
+       /* we're configured to use syslog */
+       if( use_syslog ) {
+#ifdef HAVE_VSYSLOG
+               vsyslog( debug2syslog(level), fmt, vl );
+#else
+               char data[4096];
+               vsnprintf( data, sizeof(data), fmt, vl );
+               syslog( debug2syslog(level), data );
+#endif
+               return;
+       }
+#endif
+
+#if 0
+#ifdef HAVE_WINSOCK
+       if( log_file == NULL ) {
+               log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
+
+               if ( log_file == NULL )
+                       log_file = fopen( "openldap.log", "w" );
+
+               if ( log_file == NULL )
+                       return;
+
+               ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
+       }
+#endif
+#endif
+
+       if( file == NULL ) {
+               /*
+                * Use stderr unless file was specified via:
+                *   ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
+                */
+               file = stderr;
+       }
+
+#ifdef HAVE_WINSOCK
+       /*
+        * Stick the time in the buffer to output when using Winsock
+        * as NT can't pipe to a timestamp program like Unix can.
+        * This, of course, makes some logs hard to read.
+     */
+       time( &now );
+       today = localtime( &now );
+       fprintf( file, "%4d%02d%02d:%02d:%02d:%02d ",
+               today->tm_year + 1900, today->tm_mon + 1,
+               today->tm_mday, today->tm_hour,
+               today->tm_min, today->tm_sec );
+#endif
+
+       /*
+        * format the output data.
+        */
+
+       fprintf(file, "\n%s:: ", t_subsys ); 
+       vfprintf( file, fmt, vl );
+       fflush( file );
+}
+
+/*
+ * The primary logging routine.         Takes the subsystem being logged from, the
+ * level of the log output and the format and data.  Send this on to the
+ * internal routine with the print file, if any.
+ */
+void lutil_log( const int subsys, int level, const char *fmt, ... )
+{
+       FILE* outfile = NULL;
+       va_list vl;
+       va_start( vl, fmt );
+       ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
+       lutil_log_int( outfile, lutil_subsys[subsys], level, fmt, vl );
+       va_end( vl );
+}
+
+void lutil_log_initialize(int argc, char **argv)
+{
+    int i;
+    /*
+     * Start by setting the hook for the libraries to use this logging
+     * routine.
+     */
+    ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
+
+    if ( argc == 0 ) return;
+    /*
+     * Now go through the command line options to set the debugging
+     * levels
+     */
+    for( i = 0; i < argc; i++ )
+    {
+               char *next = argv[i];
+       
+               if ( i < argc-1 && next[0] == '-' && next[1] == 'd' )
+               {
+                       char subsys[64];
+                       int level;
+               char *optarg = argv[i+1];
+               char *index = strchr( optarg, '=' );
+               if ( index != NULL )
+               {
+                               *index = 0;
+                               strcpy ( subsys, optarg );
+                               level = atoi( index+1 );
+                               if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
+                               lutil_set_debug_level( subsys, level );
+                               *index = '=';
+               }
+               else
+               {
+                               global_level = atoi( optarg );
+                               ldap_loglevels[0] = global_level;
+                               /* 
+                               * if a negative number was used, make the global level the
+                               * maximum sane level.
+                               */
+                               if ( global_level < 0 ) 
+                               {
+                                       global_level = 65535;
+                                       ldap_loglevels[0] = 65535;
+                       }
+               }
+               }
+    }
+}
+
+void (lutil_debug)( int debug, int level, const char *fmt, ... )
+{
+       char buffer[4096];
+       va_list vl;
+
+       if ( !(level & debug ) )
+               return;
+
+#ifdef HAVE_WINSOCK
+       if( log_file == NULL ) {
+               log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
+
+               if ( log_file == NULL )
+                       log_file = fopen( "openldap.log", "w" );
+
+               if ( log_file == NULL )
+                       return;
+
+               ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
+       }
+#endif
+       va_start( vl, fmt );
+
+#ifdef HAVE_VSNPRINTF
+       vsnprintf( buffer, sizeof(buffer), fmt, vl );
+#else
+       vsprintf( buffer, fmt, vl );
+#endif
+       buffer[sizeof(buffer)-1] = '\0';
+
+       if( log_file != NULL ) {
+               fputs( buffer, log_file );
+               fflush( log_file );
+       }
+
+       fputs( buffer, stderr );
+       va_end( vl );
+}
index a722c9eb7a319a12ad027c85310c1d9c6264ccb4..e69bb496fa0673f09e6397519a45dfa8625427dd 100644 (file)
@@ -1,5 +1,10 @@
 /* decode.c - ber input decoding routines */
+/* $OpenLDAP$ */
 /*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
  * Copyright (c) 1990 Regents of the University of Michigan.
  * All rights reserved.
  *
  * is provided ``as is'' without express or implied warranty.
  */
 
+#include "portable.h"
+
 #include <stdio.h>
-#ifdef MACOS
-#include <stdlib.h>
-#include <stdarg.h>
-#include "macos.h"
-#else /* MACOS */
-#if defined(NeXT) || defined(VMS)
-#include <stdlib.h>
-#else /* next || vms */
-#include <malloc.h>
-#endif /* next || vms */
-#if defined(BC31) || defined(_WIN32)
-#include <stdarg.h>
-#else /* BC31 || _WIN32 */
-#include <varargs.h>
-#endif /* BC31 || _WIN32 */
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#ifdef PCNFS
-#include <tklib.h>
-#endif /* PCNFS */
-#endif /* MACOS */
-
-#if defined( DOS ) || defined( _WIN32 )
-#include "msdos.h"
-#endif /* DOS */
-
-#include <string.h>
-#include "lber.h"
-
-#ifdef LDAP_DEBUG
-int    lber_debug;
-#endif
 
-#ifdef NEEDPROTOS
-static int ber_getnint( BerElement *ber, long *num, int len );
-#endif /* NEEDPROTOS */
+#include <ac/stdlib.h>
+
+#include <ac/stdarg.h>
+#include <ac/string.h>
+#include <ac/socket.h>
 
+#include "lber-int.h"
+
+static ber_len_t ber_getnint LDAP_P((
+       BerElement *ber,
+       ber_int_t *num,
+       ber_len_t len ));
 
 /* return the tag - LBER_DEFAULT returned means trouble */
-unsigned long
+ber_tag_t
 ber_get_tag( BerElement *ber )
 {
        unsigned char   xbyte;
-       unsigned long   tag;
-       char            *tagp;
-       int             i;
+       ber_tag_t       tag;
+       unsigned int    i;
 
-       if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
-               return( LBER_DEFAULT );
+       assert( ber != NULL );
+       assert( LBER_VALID( ber ) );
 
-       if ( (xbyte & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK )
-               return( (unsigned long) xbyte );
+       if ( ber_pvt_ber_remaining( ber ) < 1 ) {
+               return LBER_DEFAULT;
+       }
 
-       tagp = (char *) &tag;
-       tagp[0] = xbyte;
-       for ( i = 1; i < sizeof(long); i++ ) {
-               if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 )
-                       return( LBER_DEFAULT );
+       if ( ber->ber_ptr == ber->ber_buf )
+               tag = *(unsigned char *)ber->ber_ptr;
+       else
+               tag = ber->ber_tag;
+       ber->ber_ptr++;
 
-               tagp[i] = xbyte;
+       if ( (tag & LBER_BIG_TAG_MASK) != LBER_BIG_TAG_MASK ) {
+               return tag;
+       }
+
+       for ( i = 1; i < sizeof(ber_tag_t); i++ ) {
+               if ( ber_read( ber, (char *) &xbyte, 1 ) != 1 ) {
+                       return LBER_DEFAULT;
+               }
 
-               if ( ! (xbyte & LBER_MORE_TAG_MASK) )
+               tag <<= 8;
+               tag |= 0x00ffUL & (ber_tag_t) xbyte;
+
+               if ( ! (xbyte & LBER_MORE_TAG_MASK) ) {
                        break;
+               }
        }
 
        /* tag too big! */
-       if ( i == sizeof(long) )
-               return( LBER_DEFAULT );
+       if ( i == sizeof(ber_tag_t) ) {
+               return LBER_DEFAULT;
+       }
 
-       /* want leading, not trailing 0's */
-       return( tag >> (sizeof(long) - i - 1) );
+       return tag;
 }
 
-unsigned long
-ber_skip_tag( BerElement *ber, unsigned long *len )
+ber_tag_t
+ber_skip_tag( BerElement *ber, ber_len_t *len )
 {
-       unsigned long   tag;
+       ber_tag_t       tag;
        unsigned char   lc;
-       int             noctets, diff;
-       unsigned long   netlen;
+       ber_len_t       i, noctets;
+       unsigned char netlen[sizeof(ber_len_t)];
+
+       assert( ber != NULL );
+       assert( len != NULL );
+       assert( LBER_VALID( ber ) );
 
        /*
         * Any ber element looks like this: tag length contents.
@@ -104,57 +101,93 @@ ber_skip_tag( BerElement *ber, unsigned long *len )
         *      2) primitive encodings used whenever possible
         */
 
+       *len = 0;
+
        /*
         * First, we read the tag.
         */
 
-       if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT )
-               return( LBER_DEFAULT );
+       if ( (tag = ber_get_tag( ber )) == LBER_DEFAULT ) {
+               return LBER_DEFAULT;
+       }
 
        /*
         * Next, read the length.  The first byte contains the length of
-        * the length.  If bit 8 is set, the length is the long form,
+        * the length.  If bit 8 is set, the length is the long form,
         * otherwise it's the short form.  We don't allow a length that's
-        * greater than what we can hold in an unsigned long.
+        * greater than what we can hold in a ber_len_t.
         */
 
-       *len = netlen = 0;
        if ( ber_read( ber, (char *) &lc, 1 ) != 1 )
-               return( LBER_DEFAULT );
-       if ( lc & 0x80 ) {
-               noctets = (lc & 0x7f);
-               if ( noctets > sizeof(unsigned long) )
-                       return( LBER_DEFAULT );
-               diff = sizeof(unsigned long) - noctets;
-               if ( ber_read( ber, (char *) &netlen + diff, noctets )
-                   != noctets )
-                       return( LBER_DEFAULT );
-               *len = LBER_NTOHL( netlen );
+               return LBER_DEFAULT;
+
+       if ( lc & 0x80U ) {
+               noctets = (lc & 0x7fU);
+
+               if ( noctets > sizeof(ber_len_t) ) {
+                       return LBER_DEFAULT;
+               }
+
+               if( (unsigned) ber_read( ber, netlen, noctets ) != noctets ) {
+                       return LBER_DEFAULT;
+               }
+
+               for( i = 0; i < noctets; i++ ) {
+                       *len <<= 8;
+                       *len |= netlen[i];
+               }
+
        } else {
                *len = lc;
        }
 
-       return( tag );
+       /* BER length should be non-negative */
+       if( *len < 0 ) {
+               return LBER_DEFAULT;
+       }
+
+       /* BER element should have enough data left */
+       if( *len > (ber_len_t) ber_pvt_ber_remaining( ber ) ) {
+               return LBER_DEFAULT;
+       }
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
+
+       return tag;
 }
 
-unsigned long
-ber_peek_tag( BerElement *ber, unsigned long *len )
+ber_tag_t
+ber_peek_tag(
+       BerElement *ber,
+       ber_len_t *len )
 {
-       char            *save;
-       unsigned long   tag;
+       /*
+        * This implementation assumes ber_skip_tag() only
+        * modifies ber_ptr field of the BerElement.
+        */
+
+       char *save;
+       ber_tag_t       tag, old;
 
+       old = ber->ber_tag;
        save = ber->ber_ptr;
        tag = ber_skip_tag( ber, len );
        ber->ber_ptr = save;
+       ber->ber_tag = old;
 
-       return( tag );
+       return tag;
 }
 
-static int
-ber_getnint( BerElement *ber, long *num, int len )
+static ber_len_t
+ber_getnint(
+       BerElement *ber,
+       ber_int_t *num,
+       ber_len_t len )
 {
-       int     diff, sign, i;
-       long    netnum;
+       unsigned char buf[sizeof(ber_int_t)];
+
+       assert( ber != NULL );
+       assert( num != NULL );
+       assert( LBER_VALID( ber ) );
 
        /*
         * The tag and length have already been stripped off.  We should
@@ -163,281 +196,496 @@ ber_getnint( BerElement *ber, long *num, int len )
         * extend after we read it in.
         */
 
-       if ( len > sizeof(long) )
-               return( -1 );
+       if ( len > sizeof(ber_int_t) ) {
+               return -1;
+       }
+
+       /* read into the low-order bytes of our buffer */
+       if ( (ber_len_t) ber_read( ber, (char *) buf, len ) != len ) {
+               return -1;
+       }
 
-       netnum = 0;
-       diff = sizeof(long) - len;
-       /* read into the low-order bytes of netnum */
-       if ( ber_read( ber, ((char *) &netnum) + diff, len ) != len )
-               return( -1 );
+       if( len ) {
+               /* sign extend if necessary */
+               ber_len_t i;
+               ber_int_t netnum = 0x80 & buf[0] ? -1 : 0;
 
-       /* sign extend if necessary */
-       sign = ((0x80 << ((len - 1) * 8)) & netnum);
-       if ( sign && len < sizeof(long) ) {
-               for ( i = sizeof(long) - 1; i > len - 1; i-- ) {
-                       netnum |= (0xffL << (i * 8));
+               /* shift in the bytes */
+               for( i=0 ; i<len; i++ ) {
+                       netnum = (netnum << 8 ) | buf[i];
                }
+
+               *num = netnum;
+
+       } else {
+               *num = 0;
        }
-       *num = LBER_NTOHL( netnum );
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
 
-       return( len );
+       return len;
 }
 
-unsigned long
-ber_get_int( BerElement *ber, long *num )
+ber_tag_t
+ber_get_int(
+       BerElement *ber,
+       ber_int_t *num )
 {
-       unsigned long   tag, len;
+       ber_tag_t       tag;
+       ber_len_t       len;
 
-       if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
-               return( LBER_DEFAULT );
+       assert( ber != NULL );
+       assert( LBER_VALID( ber ) );
 
-       if ( ber_getnint( ber, num, (int)len ) != len )
-               return( LBER_DEFAULT );
-       else
-               return( tag );
+       if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) {
+               return LBER_DEFAULT;
+       }
+
+       if ( ber_getnint( ber, num, len ) != len ) {
+               return LBER_DEFAULT;
+       }
+       
+       return tag;
 }
 
-unsigned long
-ber_get_stringb( BerElement *ber, char *buf, unsigned long *len )
+ber_tag_t
+ber_get_enum(
+       BerElement *ber,
+       ber_int_t *num )
 {
-       unsigned long   datalen, tag;
-#ifdef STR_TRANSLATION
-       char            *transbuf;
-#endif /* STR_TRANSLATION */
+       return ber_get_int( ber, num );
+}
 
-       if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
-               return( LBER_DEFAULT );
-       if ( datalen > (*len - 1) )
-               return( LBER_DEFAULT );
+ber_tag_t
+ber_get_stringb(
+       BerElement *ber,
+       char *buf,
+       ber_len_t *len )
+{
+       ber_len_t       datalen;
+       ber_tag_t       tag;
 
-       if ( ber_read( ber, buf, datalen ) != datalen )
-               return( LBER_DEFAULT );
+       assert( ber != NULL );
+       assert( LBER_VALID( ber ) );
+
+       if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
+               return LBER_DEFAULT;
+       }
+
+       /* must fit within allocated space with termination */
+       if ( datalen >= *len ) {
+               return LBER_DEFAULT;
+       }
+
+       if ( (ber_len_t) ber_read( ber, buf, datalen ) != datalen ) {
+               return LBER_DEFAULT;
+       }
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
 
        buf[datalen] = '\0';
 
-#ifdef STR_TRANSLATION
-       if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
-           && ber->ber_decode_translate_proc != NULL ) {
-               transbuf = buf;
-               ++datalen;
-               if ( (*(ber->ber_decode_translate_proc))( &transbuf, &datalen,
-                   0 ) != 0 ) {
-                       return( LBER_DEFAULT );
+       *len = datalen;
+       return tag;
+}
+
+/* Definitions for recursive get_string
+ *
+ * ChArray, BvArray, and BvVec are self-explanatory.
+ * BvOff is a struct berval embedded in an array of larger structures
+ * of siz bytes at off bytes from the beginning of the struct.
+ */
+enum bgbvc { ChArray, BvArray, BvVec, BvOff };
+
+/* Use this single cookie for state, to keep actual
+ * stack use to the absolute minimum.
+ */
+typedef struct bgbvr {
+       enum bgbvc choice;
+       BerElement *ber;
+       ber_tag_t tag;
+       ber_len_t len;
+       char *last;
+       int alloc;
+       ber_len_t siz;
+       ber_len_t off;
+       union {
+               char ***c;
+               BerVarray *ba;
+               struct berval ***bv;
+       } res;
+} bgbvr;
+
+/* Recursive get_string, for decoding a vector of strings. The number
+ * of elements in the vector is limited only by available stack space.
+ * Each invocation consumes 24 bytes of stack on a 32-bit machine.
+ */
+static ber_tag_t
+ber_get_stringbvr( bgbvr *b, int n )
+{
+       struct berval bv, *bvp = NULL;
+
+       if ( n )
+               b->tag = ber_next_element( b->ber, &b->len, b->last );
+       else
+               b->tag = ber_first_element( b->ber, &b->len, &b->last );
+
+       if ( b->tag == LBER_DEFAULT )
+       {
+               b->len = n;
+
+               if ( n == 0 ) {
+                       *b->res.c = NULL;
+                       return 0;
                }
-               if ( datalen > *len ) {
-                       free( transbuf );
-                       return( LBER_DEFAULT );
+               /* Allocate the result vector */
+               switch (b->choice) {
+               case ChArray:
+                       *b->res.c = LBER_MALLOC( (n+1) * sizeof( char * ));
+                       if ( *b->res.c == NULL )
+                               return LBER_DEFAULT;
+                       (*b->res.c)[n] = NULL;
+                       break;
+               case BvArray:
+                       *b->res.ba = LBER_MALLOC( (n+1) * sizeof( struct berval ));
+                       if ( *b->res.ba == NULL )
+                               return LBER_DEFAULT;
+                       (*b->res.ba)[n].bv_val = NULL;
+                       break;
+               case BvVec:
+                       *b->res.bv = LBER_MALLOC( (n+1) * sizeof( struct berval *));
+                       if ( *b->res.bv == NULL )
+                               return LBER_DEFAULT;
+                       (*b->res.bv)[n] = NULL;
+                       break;
+               case BvOff:
+                       *b->res.ba = LBER_MALLOC( (n+1) * b->siz );
+                       if ( *b->res.ba == NULL )
+                               return LBER_DEFAULT;
+                       ((struct berval *)((long)(*b->res.ba) + n*b->siz +
+                               b->off))->bv_val = NULL;
+                       break;
                }
-               SAFEMEMCPY( buf, transbuf, datalen );
-               free( transbuf );
-               --datalen;
+               return 0;
        }
-#endif /* STR_TRANSLATION */
 
-       *len = datalen;
-       return( tag );
+       /* Do all local allocs before the recursion. Then there
+        * cannot possibly be any failures on the return trip.
+        */
+       if ( b->choice == BvVec )
+               bvp = LBER_MALLOC( sizeof( struct berval ));
+
+       if ( ber_get_stringbv( b->ber, &bv, b->alloc ) == LBER_DEFAULT ) {
+               if ( bvp ) LBER_FREE( bvp );
+               return LBER_DEFAULT;
+       }
+
+       b->tag = ber_get_stringbvr( b, n+1 );
+       
+       if ( b->tag == 0 )
+       {
+               /* store my result */
+               switch (b->choice) {
+               case ChArray:
+                       (*b->res.c)[n] = bv.bv_val;
+                       break;
+               case BvArray:
+                       (*b->res.ba)[n] = bv;
+                       break;
+               case BvVec:
+                       (*b->res.bv)[n] = bvp;
+                       *bvp = bv;
+                       break;
+               case BvOff:
+                       *(BerVarray)((long)(*b->res.ba)+n*b->siz+b->off) = bv;
+               }
+       } else {
+               /* Failure will propagate up and free in reverse
+                * order, which is actually ideal.
+                */
+               if ( b->alloc ) LBER_FREE( bv.bv_val );
+               if ( bvp ) LBER_FREE( bvp );
+       }
+       return b->tag;
 }
 
-unsigned long
-ber_get_stringa( BerElement *ber, char **buf )
+ber_tag_t
+ber_get_stringbv( BerElement *ber, struct berval *bv, int alloc )
 {
-       unsigned long   datalen, tag;
-
-       if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
-               return( LBER_DEFAULT );
-
-       if ( (*buf = (char *) malloc( (size_t)datalen + 1 )) == NULL )
-               return( LBER_DEFAULT );
-
-       if ( ber_read( ber, *buf, datalen ) != datalen )
-               return( LBER_DEFAULT );
-       (*buf)[datalen] = '\0';
-
-#ifdef STR_TRANSLATION
-       if ( datalen > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
-           && ber->ber_decode_translate_proc != NULL ) {
-               ++datalen;
-               if ( (*(ber->ber_decode_translate_proc))( buf, &datalen, 1 )
-                   != 0 ) {
-                       free( *buf );
-                       return( LBER_DEFAULT );
+       ber_tag_t       tag;
+
+       assert( ber != NULL );
+       assert( bv != NULL );
+
+       assert( LBER_VALID( ber ) );
+
+       if ( (tag = ber_skip_tag( ber, &bv->bv_len )) == LBER_DEFAULT ) {
+               bv->bv_val = NULL;
+               return LBER_DEFAULT;
+       }
+
+       if ( (ber_len_t) ber_pvt_ber_remaining( ber ) < bv->bv_len ) {
+               return LBER_DEFAULT;
+       }
+
+       if ( alloc ) {
+               if ( (bv->bv_val = (char *) LBER_MALLOC( bv->bv_len + 1 )) == NULL ) {
+                       return LBER_DEFAULT;
+               }
+
+               if ( bv->bv_len > 0 && (ber_len_t) ber_read( ber, bv->bv_val,
+                       bv->bv_len ) != bv->bv_len ) {
+                       LBER_FREE( bv->bv_val );
+                       bv->bv_val = NULL;
+                       return LBER_DEFAULT;
                }
+       } else {
+               bv->bv_val = ber->ber_ptr;
+               ber->ber_ptr += bv->bv_len;
        }
-#endif /* STR_TRANSLATION */
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
+       bv->bv_val[bv->bv_len] = '\0';
 
-       return( tag );
+       return tag;
+}
+
+ber_tag_t
+ber_get_stringa( BerElement *ber, char **buf )
+{
+       BerValue        bv;
+       ber_tag_t       tag;
+
+       assert( buf != NULL );
+
+       tag = ber_get_stringbv( ber, &bv, 1 );
+       *buf = bv.bv_val;
+
+       return tag;
 }
 
-unsigned long
+ber_tag_t
 ber_get_stringal( BerElement *ber, struct berval **bv )
 {
-       unsigned long   len, tag;
-
-       if ( (*bv = (struct berval *) malloc( sizeof(struct berval) )) == NULL )
-               return( LBER_DEFAULT );
-
-       if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
-               return( LBER_DEFAULT );
-
-       if ( ((*bv)->bv_val = (char *) malloc( (size_t)len + 1 )) == NULL )
-               return( LBER_DEFAULT );
-
-       if ( ber_read( ber, (*bv)->bv_val, len ) != len )
-               return( LBER_DEFAULT );
-       ((*bv)->bv_val)[len] = '\0';
-       (*bv)->bv_len = len;
-
-#ifdef STR_TRANSLATION
-       if ( len > 0 && ( ber->ber_options & LBER_TRANSLATE_STRINGS ) != 0
-           && ber->ber_decode_translate_proc != NULL ) {
-               ++len;
-               if ( (*(ber->ber_decode_translate_proc))( &((*bv)->bv_val),
-                   &len, 1 ) != 0 ) {
-                       free( (*bv)->bv_val );
-                       return( LBER_DEFAULT );
-               }
-               (*bv)->bv_len = len - 1;
+       ber_tag_t       tag;
+
+       assert( ber != NULL );
+       assert( bv != NULL );
+
+       *bv = (struct berval *) LBER_MALLOC( sizeof(struct berval) );
+       if ( *bv == NULL ) {
+               return LBER_DEFAULT;
        }
-#endif /* STR_TRANSLATION */
 
-       return( tag );
+       tag = ber_get_stringbv( ber, *bv, 1 );
+       if ( tag == LBER_DEFAULT ) {
+               LBER_FREE( *bv );
+               *bv = NULL;
+       }
+       return tag;
 }
 
-unsigned long
-ber_get_bitstringa( BerElement *ber, char **buf, unsigned long *blen )
+ber_tag_t
+ber_get_bitstringa(
+       BerElement *ber,
+       char **buf,
+       ber_len_t *blen )
 {
-       unsigned long   datalen, tag;
+       ber_len_t       datalen;
+       ber_tag_t       tag;
        unsigned char   unusedbits;
 
-       if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT )
-               return( LBER_DEFAULT );
+       assert( ber != NULL );
+       assert( buf != NULL );
+       assert( blen != NULL );
+
+       assert( LBER_VALID( ber ) );
+
+       if ( (tag = ber_skip_tag( ber, &datalen )) == LBER_DEFAULT ) {
+               *buf = NULL;
+               return LBER_DEFAULT;
+       }
        --datalen;
 
-       if ( (*buf = (char *) malloc( (size_t)datalen )) == NULL )
-               return( LBER_DEFAULT );
+       if ( (*buf = (char *) LBER_MALLOC( datalen )) == NULL ) {
+               return LBER_DEFAULT;
+       }
 
-       if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 )
-               return( LBER_DEFAULT );
+       if ( ber_read( ber, (char *)&unusedbits, 1 ) != 1 ) {
+               LBER_FREE( buf );
+               *buf = NULL;
+               return LBER_DEFAULT;
+       }
 
-       if ( ber_read( ber, *buf, datalen ) != datalen )
-               return( LBER_DEFAULT );
+       if ( (ber_len_t) ber_read( ber, *buf, datalen ) != datalen ) {
+               LBER_FREE( buf );
+               *buf = NULL;
+               return LBER_DEFAULT;
+       }
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
 
        *blen = datalen * 8 - unusedbits;
-       return( tag );
+       return tag;
 }
 
-unsigned long
+ber_tag_t
 ber_get_null( BerElement *ber )
 {
-       unsigned long   len, tag;
+       ber_len_t       len;
+       ber_tag_t       tag;
+
+       assert( ber != NULL );
+       assert( LBER_VALID( ber ) );
 
-       if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
-               return( LBER_DEFAULT );
+       if ( (tag = ber_skip_tag( ber, &len )) == LBER_DEFAULT ) {
+               return LBER_DEFAULT;
+       }
 
-       if ( len != 0 )
-               return( LBER_DEFAULT );
+       if ( len != 0 ) {
+               return LBER_DEFAULT;
+       }
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
 
        return( tag );
 }
 
-unsigned long
-ber_get_boolean( BerElement *ber, int *boolval )
+ber_tag_t
+ber_get_boolean(
+       BerElement *ber,
+       ber_int_t *boolval )
 {
-       long    longbool;
-       int     rc;
+       ber_int_t       longbool;
+       ber_tag_t       rc;
+
+       assert( ber != NULL );
+       assert( boolval != NULL );
+
+       assert( LBER_VALID( ber ) );
 
        rc = ber_get_int( ber, &longbool );
        *boolval = longbool;
 
-       return( rc );
+       return rc;
 }
 
-unsigned long
-ber_first_element( BerElement *ber, unsigned long *len, char **last )
+ber_tag_t
+ber_first_element(
+       BerElement *ber,
+       ber_len_t *len,
+       char **last )
 {
+       assert( ber != NULL );
+       assert( len != NULL );
+       assert( last != NULL );
+
        /* skip the sequence header, use the len to mark where to stop */
        if ( ber_skip_tag( ber, len ) == LBER_DEFAULT ) {
-               return( LBER_DEFAULT );
+               *last = NULL;
+               return LBER_DEFAULT;
        }
+       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
 
        *last = ber->ber_ptr + *len;
 
        if ( *last == ber->ber_ptr ) {
-               return( LBER_DEFAULT );
+               return LBER_DEFAULT;
        }
 
-       return( ber_peek_tag( ber, len ) );
+       return ber_peek_tag( ber, len );
 }
 
-unsigned long
-ber_next_element( BerElement *ber, unsigned long *len, char *last )
+ber_tag_t
+ber_next_element(
+       BerElement *ber,
+       ber_len_t *len,
+       LDAP_CONST char *last )
 {
+       assert( ber != NULL );
+       assert( len != NULL );
+       assert( last != NULL );
+
+       assert( LBER_VALID( ber ) );
+
        if ( ber->ber_ptr == last ) {
-               return( LBER_DEFAULT );
+               return LBER_DEFAULT;
        }
 
-       return( ber_peek_tag( ber, len ) );
+       return ber_peek_tag( ber, len );
 }
 
 /* VARARGS */
-unsigned long
-ber_scanf(
-#if defined( MACOS ) || defined( BC31 ) || defined( _WIN32 )
-       BerElement *ber, char *fmt, ... )
-#else
-       va_alist )
-va_dcl
-#endif
+ber_tag_t
+ber_scanf ( BerElement *ber,
+       LDAP_CONST char *fmt,
+       ... )
 {
        va_list         ap;
-#if !defined( MACOS ) && !defined( BC31 ) && !defined( _WIN32 )
-       BerElement      *ber;
-       char            *fmt;
-#endif
+       LDAP_CONST char         *fmt_reset;
+       char            *s, **ss;
+#ifdef TMP_SLOTS
        char            *last;
-       char            *s, **ss, ***sss;
-       struct berval   ***bv, **bvp, *bval;
-       int             *i, j;
-       long            *l, rc, tag;
-       unsigned long   len;
+       char ***sss;
+       ber_tag_t tag;
+       struct berval ***bv;
+       int j;
+#endif
+       struct berval   **bvp, *bval;
+       ber_int_t       *i;
+       ber_len_t       *l;
+       ber_tag_t       *t;
+       ber_tag_t       rc;
+       ber_len_t       len;
 
-#if defined( MACOS ) || defined( BC31 ) || defined( _WIN32 )
        va_start( ap, fmt );
-#else
-       va_start( ap );
-       ber = va_arg( ap, BerElement * );
-       fmt = va_arg( ap, char * );
-#endif
 
-#ifdef LDAP_DEBUG
-       if ( lber_debug & 64 ) {
-               fprintf( stderr, "ber_scanf fmt (%s) ber:\n", fmt );
-               ber_dump( ber, 1 );
-       }
+       assert( ber != NULL );
+       assert( fmt != NULL );
+
+       assert( LBER_VALID( ber ) );
+
+       fmt_reset = fmt;
+
+#ifdef NEW_LOGGING
+       LDAP_LOG( BER, ENTRY, "ber_scanf fmt (%s) ber:\n", fmt, 0, 0 );
+
+       if ( LDAP_LOGS_TEST(BER, DETAIL2 ))
+                       BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 ));
+#else
+       ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
+               "ber_scanf fmt (%s) ber:\n", fmt );
+       ber_log_dump( LDAP_DEBUG_BER, ber->ber_debug, ber, 1 );
 #endif
 
        for ( rc = 0; *fmt && rc != LBER_DEFAULT; fmt++ ) {
+               /* When this is modified, remember to update
+                * the error-cleanup code below accordingly. */
                switch ( *fmt ) {
+               case '!': { /* Hook */
+                               BERDecodeCallback *f;
+                               void *p;
+
+                               f = va_arg( ap, BERDecodeCallback * );
+                               p = va_arg( ap, void * );
+
+                               rc = (*f)( ber, p, 0 );
+                       } break;
+
                case 'a':       /* octet string - allocate storage as needed */
                        ss = va_arg( ap, char ** );
                        rc = ber_get_stringa( ber, ss );
                        break;
 
                case 'b':       /* boolean */
-                       i = va_arg( ap, int * );
+                       i = va_arg( ap, ber_int_t * );
                        rc = ber_get_boolean( ber, i );
                        break;
 
                case 'e':       /* enumerated */
                case 'i':       /* int */
-                       l = va_arg( ap, long * );
-                       rc = ber_get_int( ber, l );
+                       i = va_arg( ap, ber_int_t * );
+                       rc = ber_get_int( ber, i );
                        break;
 
                case 'l':       /* length of next item */
-                       l = va_arg( ap, long * );
-                       rc = ber_peek_tag( ber, (unsigned long *)l );
+                       l = va_arg( ap, ber_len_t * );
+                       rc = ber_peek_tag( ber, l );
                        break;
 
                case 'n':       /* null */
@@ -446,14 +694,18 @@ va_dcl
 
                case 's':       /* octet string - in a buffer */
                        s = va_arg( ap, char * );
-                       l = va_arg( ap, long * );
-                       rc = ber_get_stringb( ber, s, (unsigned long *)l );
+                       l = va_arg( ap, ber_len_t * );
+                       rc = ber_get_stringb( ber, s, l );
+                       break;
+
+               case 'm':       /* octet string in berval, in-place */
+                       bval = va_arg( ap, struct berval * );
+                       rc = ber_get_stringbv( ber, bval, 0 );
                        break;
 
                case 'o':       /* octet string in a supplied berval */
                        bval = va_arg( ap, struct berval * );
-                       ber_peek_tag( ber, &bval->bv_len );
-                       rc = ber_get_stringa( ber, &bval->bv_val );
+                       rc = ber_get_stringbv( ber, bval, 1 );
                        break;
 
                case 'O':       /* octet string - allocate & include length */
@@ -463,71 +715,79 @@ va_dcl
 
                case 'B':       /* bit string - allocate storage as needed */
                        ss = va_arg( ap, char ** );
-                       l = va_arg( ap, long * ); /* for length, in bits */
-                       rc = ber_get_bitstringa( ber, ss, (unsigned long *)l );
+                       l = va_arg( ap, ber_len_t * ); /* for length, in bits */
+                       rc = ber_get_bitstringa( ber, ss, l );
                        break;
 
                case 't':       /* tag of next item */
-                       i = va_arg( ap, int * );
-                       *i = rc = ber_peek_tag( ber, &len );
+                       t = va_arg( ap, ber_tag_t * );
+                       *t = rc = ber_peek_tag( ber, &len );
                        break;
 
                case 'T':       /* skip tag of next item */
-                       i = va_arg( ap, int * );
-                       *i = rc = ber_skip_tag( ber, &len );
+                       t = va_arg( ap, ber_tag_t * );
+                       *t = rc = ber_skip_tag( ber, &len );
                        break;
 
                case 'v':       /* sequence of strings */
-                       sss = va_arg( ap, char *** );
-                       *sss = NULL;
-                       j = 0;
-                       for ( tag = ber_first_element( ber, &len, &last );
-                           tag != LBER_DEFAULT && rc != LBER_DEFAULT;
-                           tag = ber_next_element( ber, &len, last ) ) {
-                               if ( *sss == NULL ) {
-                                       *sss = (char **) malloc(
-                                           2 * sizeof(char *) );
-                               } else {
-                                       *sss = (char **) realloc( *sss,
-                                           (j + 2) * sizeof(char *) );
-                               }
-                               rc = ber_get_stringa( ber, &((*sss)[j]) );
-                               j++;
-                       }
-                       if ( j > 0 )
-                               (*sss)[j] = NULL;
+               {
+                       bgbvr cookie = { ChArray };
+                       cookie.ber = ber;
+                       cookie.res.c = va_arg( ap, char *** );
+                       cookie.alloc = 1;
+                       rc = ber_get_stringbvr( &cookie, 0 );
                        break;
+               }
 
                case 'V':       /* sequence of strings + lengths */
-                       bv = va_arg( ap, struct berval *** );
-                       *bv = NULL;
-                       j = 0;
-                       for ( tag = ber_first_element( ber, &len, &last );
-                           tag != LBER_DEFAULT && rc != LBER_DEFAULT;
-                           tag = ber_next_element( ber, &len, last ) ) {
-                               if ( *bv == NULL ) {
-                                       *bv = (struct berval **) malloc(
-                                           2 * sizeof(struct berval *) );
-                               } else {
-                                       *bv = (struct berval **) realloc( *bv,
-                                           (j + 2) * sizeof(struct berval *) );
-                               }
-                               rc = ber_get_stringal( ber, &((*bv)[j]) );
-                               j++;
-                       }
-                       if ( j > 0 )
-                               (*bv)[j] = NULL;
+               {
+                       bgbvr cookie = { BvVec };
+                       cookie.ber = ber;
+                       cookie.res.bv = va_arg( ap, struct berval *** );
+                       cookie.alloc = 1;
+                       rc = ber_get_stringbvr( &cookie, 0 );
+                       break;
+               }
+
+               case 'W':       /* bvarray */
+               {
+                       bgbvr cookie = { BvArray };
+                       cookie.ber = ber;
+                       cookie.res.ba = va_arg( ap, struct berval ** );
+                       cookie.alloc = 1;
+                       rc = ber_get_stringbvr( &cookie, 0 );
                        break;
+               }
+
+               case 'M':       /* bvoffarray - must include address of
+                                * a record len, and record offset.
+                                * number of records will be returned thru
+                                * len ptr on finish. parsed in-place.
+                                */
+               {
+                       bgbvr cookie = { BvOff };
+                       cookie.ber = ber;
+                       cookie.res.ba = va_arg( ap, struct berval ** );
+                       cookie.alloc = 0;
+                       l = va_arg( ap, ber_len_t * );
+                       cookie.siz = *l;
+                       cookie.off = va_arg( ap, ber_len_t );
+                       rc = ber_get_stringbvr( &cookie, 0 );
+                       *l = cookie.len;
+                       break;
+               }
 
                case 'x':       /* skip the next element - whatever it is */
                        if ( (rc = ber_skip_tag( ber, &len )) == LBER_DEFAULT )
                                break;
                        ber->ber_ptr += len;
+                       ber->ber_tag = *(unsigned char *)ber->ber_ptr;
                        break;
 
                case '{':       /* begin sequence */
                case '[':       /* begin set */
-                       if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V' )
+                       if ( *(fmt + 1) != 'v' && *(fmt + 1) != 'V'
+                               && *(fmt + 1) != 'W' && *(fmt + 1) != 'M' )
                                rc = ber_skip_tag( ber, &len );
                        break;
 
@@ -536,63 +796,115 @@ va_dcl
                        break;
 
                default:
-#ifndef NO_USERINTERFACE
-                       fprintf( stderr, "unknown fmt %c\n", *fmt );
-#endif /* NO_USERINTERFACE */
+                       if( ber->ber_debug ) {
+#ifdef NEW_LOGGING
+                               LDAP_LOG( BER, ERR, 
+                                       "ber_scanf: unknown fmt %c\n", *fmt, 0, 0 );
+#else
+                               ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug,
+                                       "ber_scanf: unknown fmt %c\n", *fmt );
+#endif
+                       }
                        rc = LBER_DEFAULT;
                        break;
                }
        }
 
        va_end( ap );
+       if ( rc == LBER_DEFAULT ) {
+           /*
+            * Error.  Reclaim malloced memory that was given to the caller.
+            * Set allocated pointers to NULL, "data length" outvalues to 0.
+            */
+           va_start( ap, fmt );
 
-       return( rc );
-}
+           for ( ; fmt_reset < fmt; fmt_reset++ ) {
+               switch ( *fmt_reset ) {
+               case '!': { /* Hook */
+                               BERDecodeCallback *f;
+                               void *p;
 
-void
-ber_bvfree( struct berval *bv )
-{
-       if ( bv->bv_val != NULL )
-               free( bv->bv_val );
-       free( (char *) bv );
-}
+                               f = va_arg( ap, BERDecodeCallback * );
+                               p = va_arg( ap, void * );
 
-void
-ber_bvecfree( struct berval **bv )
-{
-       int     i;
+                               (void) (*f)( ber, p, 1 );
+                       } break;
 
-       for ( i = 0; bv[i] != NULL; i++ )
-               ber_bvfree( bv[i] );
-       free( (char *) bv );
-}
+               case 'a':       /* octet string - allocate storage as needed */
+                       ss = va_arg( ap, char ** );
+                       if ( *ss ) {
+                               LBER_FREE( *ss );
+                               *ss = NULL;
+                       }
+                       break;
 
-struct berval *
-ber_bvdup( struct berval *bv )
-{
-       struct berval   *new;
+               case 'b':       /* boolean */
+               case 'e':       /* enumerated */
+               case 'i':       /* int */
+                       (void) va_arg( ap, int * );
+                       break;
 
-       if ( (new = (struct berval *) malloc( sizeof(struct berval) ))
-           == NULL ) {
-               return( NULL );
-       }
-       if ( (new->bv_val = (char *) malloc( bv->bv_len + 1 )) == NULL ) {
-               return( NULL );
-       }
-       SAFEMEMCPY( new->bv_val, bv->bv_val, (size_t) bv->bv_len );
-       new->bv_val[bv->bv_len] = '\0';
-       new->bv_len = bv->bv_len;
+               case 's':       /* octet string - in a buffer */
+                       (void) va_arg( ap, char * );
+                       (void) va_arg( ap, ber_len_t * );
+                       break;
 
-       return( new );
-}
+               case 'l':       /* length of next item */
+                       (void) va_arg( ap, ber_len_t * );
+                       break;
 
+               case 't':       /* tag of next item */
+               case 'T':       /* skip tag of next item */
+                       (void) va_arg( ap, ber_tag_t * );
+                       break;
 
-#ifdef STR_TRANSLATION
-void
-ber_set_string_translators( BerElement *ber, BERTranslateProc encode_proc,
-       BERTranslateProc decode_proc )
-{
-    ber->ber_encode_translate_proc = encode_proc;
-    ber->ber_decode_translate_proc = decode_proc;
+               case 'o':       /* octet string in a supplied berval */
+                       bval = va_arg( ap, struct berval * );
+                       if ( bval->bv_val != NULL ) {
+                               LBER_FREE( bval->bv_val );
+                               bval->bv_val = NULL;
+                       }
+                       bval->bv_len = 0;
+                       break;
+
+               case 'O':       /* octet string - allocate & include length */
+                       bvp = va_arg( ap, struct berval ** );
+                       if ( *bvp ) {
+                               ber_bvfree( *bvp );
+                               *bvp = NULL;
+                       }
+                       break;
+
+               case 'B':       /* bit string - allocate storage as needed */
+                       ss = va_arg( ap, char ** );
+                       if ( *ss ) {
+                               LBER_FREE( *ss );
+                               *ss = NULL;
+                       }
+                       *(va_arg( ap, ber_len_t * )) = 0; /* for length, in bits */
+                       break;
+
+               case 'v':       /* sequence of strings */
+               case 'V':       /* sequence of strings + lengths */
+               case 'W':       /* BerVarray */
+               case 'm':       /* berval in-place */
+               case 'M':       /* BVoff array in-place */
+               case 'n':       /* null */
+               case 'x':       /* skip the next element - whatever it is */
+               case '{':       /* begin sequence */
+               case '[':       /* begin set */
+               case '}':       /* end sequence */
+               case ']':       /* end set */
+                       break;
+
+               default:
+                       /* format should be good */
+                       assert( 0 );
+               }
+           }
+
+           va_end( ap );
+       }
+
+       return rc;
 }
-#endif /* STR_TRANSLATION */
index 50eb6b5f9234af5e596f6da5ab4a3c084cada359..fefad6d3ecc6061850a2a800153b940e22118032 100644 (file)
@@ -812,8 +812,8 @@ ber_printf( BerElement *ber, LDAP_CONST char *fmt, ... )
                default:
                        if( ber->ber_debug ) {
 #ifdef NEW_LOGGING
-                               LDAP_LOG(( "liblber", LDAP_LEVEL_ERR,
-                                          "ber_printf: unknown fmt %c\n", *fmt ));
+                               LDAP_LOG( BER, ERR, 
+                                       "ber_printf: unknown fmt %c\n", *fmt, 0, 0 );
 #else
                                ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug,
                                        "ber_printf: unknown fmt %c\n", *fmt );
index 6474acd56d4f3481d0d48882a35a522644b70145..4e3a1cebd84ad07bcf6a9e510b9cd39d2caa16ab 100644 (file)
@@ -33,6 +33,7 @@
 #endif
 
 #include "lber-int.h"
+#include "ldap_log.h"
 
 ber_slen_t
 ber_read(
@@ -207,11 +208,14 @@ ber_flush( Sockbuf *sb, BerElement *ber, int freeit )
 
        if ( sb->sb_debug ) {
 #ifdef NEW_LOGGING
-               LDAP_LOG(( "liblber", LDAP_LEVEL_DETAIL1,
+               LDAP_LOG( BER, DETAIL1,
                           "ber_flush: %ld bytes to sd %ld%s\n",
                           towrite, (long)sb->sb_fd,
-                          ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" ));
-               BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 ));
+                          ber->ber_rwptr != ber->ber_buf ? " (re-flush)" : "" );
+
+               if(LDAP_LOGS_TEST(BER, DETAIL2))
+                               BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 ));
+
 #else
                ber_log_printf( LDAP_DEBUG_ANY, sb->sb_debug,
                        "ber_flush: %ld bytes to sd %ld%s\n",
@@ -441,7 +445,7 @@ ber_get_next(
        assert( LBER_VALID( ber ) );
 
 #ifdef NEW_LOGGING
-       LDAP_LOG(( "liblber", LDAP_LEVEL_ENTRY, "ber_get_next: enter\n" ));
+       LDAP_LOG( BER, ENTRY, "ber_get_next: enter\n", 0, 0, 0 );
 #else
        ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
                "ber_get_next\n" );
@@ -509,6 +513,8 @@ ber_get_next(
                        ber->ber_ptr = (char *)p;
                }
 
+               if (i == 1) continue;
+
                /* Now look for the length */
                if (*ber->ber_ptr & 0x80) {     /* multi-byte */
                        int llen = *(unsigned char *)ber->ber_ptr++ & 0x7f;
@@ -548,9 +554,9 @@ ber_get_next(
                        return LBER_DEFAULT;
                } else if ( sb->sb_max_incoming && ber->ber_len > sb->sb_max_incoming ) {
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "liblber", LDAP_LEVEL_ERR, 
+                       LDAP_LOG( BER, ERR, 
                                "ber_get_next: sockbuf_max_incoming limit hit "
-                               "(%d > %d)\n", ber->ber_len, sb->sb_max_incoming ));
+                               "(%d > %d)\n", ber->ber_len, sb->sb_max_incoming, 0 );
 #else
                        ber_log_printf( LDAP_DEBUG_CONNS, ber->ber_debug,
                                "ber_get_next: sockbuf_max_incoming limit hit "
@@ -616,10 +622,11 @@ done:
                *len = ber->ber_len;
                if ( ber->ber_debug ) {
 #ifdef NEW_LOGGING
-                       LDAP_LOG(( "liblber", LDAP_LEVEL_DETAIL1,
-                               "ber_get_next: tag 0x%lx len %ld\n",
-                               ber->ber_tag, ber->ber_len ));
-                       BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 ));
+                       LDAP_LOG( BER, DETAIL1, 
+                               "ber_get_next: tag 0x%lx len %ld\n", 
+                               ber->ber_tag, ber->ber_len, 0  );
+                       if(LDAP_LOGS_TEST(BER, DETAIL2))
+                                       BER_DUMP(( "liblber", LDAP_LEVEL_DETAIL2, ber, 1 ));
 #else
                        ber_log_printf( LDAP_DEBUG_TRACE, ber->ber_debug,
                                "ber_get_next: tag 0x%lx len %ld contents:\n",
diff --git a/libraries/liblber/lber-int.h b/libraries/liblber/lber-int.h
new file mode 100644 (file)
index 0000000..1d6ad83
--- /dev/null
@@ -0,0 +1,207 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Portions
+ * Copyright (c) 1990 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.
+ */
+
+#ifndef _LBER_INT_H
+#define _LBER_INT_H
+
+#include "lber.h"
+#include "ldap_log.h"
+#include "lber_pvt.h"
+#include "ldap_queue.h"
+
+LDAP_BEGIN_DECL
+
+typedef void (*BER_LOG_FN)(FILE *file,
+       const char *subsys, int level, const char *fmt, ... );
+
+LBER_V (BER_ERRNO_FN) ber_int_errno_fn;
+
+struct lber_options {
+       short lbo_valid;
+       unsigned short          lbo_options;
+       int                     lbo_debug;
+       long            lbo_meminuse;
+};
+
+#ifdef NEW_LOGGING
+/*
+#    ifdef LDAP_DEBUG
+#        ifdef LDAP_LOG
+#            undef LDAP_LOG
+#        endif
+#        define LDAP_LOG(a) ber_pvt_log_output a
+ */
+#        define BER_DUMP(a) ber_output_dump a
+/*
+#    else
+#        define LDAP_LOG(a)
+#        define BER_DUMP(a)
+#    endif
+ */
+#endif
+
+LBER_F( int ) ber_pvt_log_output(
+       const char *subsystem,
+       int level,
+       const char *fmt, ... );
+
+#define LBER_UNINITIALIZED             0x0
+#define LBER_INITIALIZED               0x1
+#define LBER_VALID_BERELEMENT  0x2
+#define LBER_VALID_SOCKBUF             0x3
+
+LBER_V (struct lber_options) ber_int_options;
+#define ber_int_debug ber_int_options.lbo_debug
+
+struct berelement {
+       struct          lber_options ber_opts;
+#define ber_valid              ber_opts.lbo_valid
+#define ber_options            ber_opts.lbo_options
+#define ber_debug              ber_opts.lbo_debug
+
+       /* Do not change the order of these 3 fields! see ber_get_next */
+       ber_tag_t       ber_tag;
+       ber_len_t       ber_len;
+       ber_tag_t       ber_usertag;
+
+       char            *ber_buf;
+       char            *ber_ptr;
+       char            *ber_end;
+
+       struct seqorset *ber_sos;
+       char            *ber_rwptr;
+};
+#define LBER_VALID(ber)        ((ber)->ber_valid==LBER_VALID_BERELEMENT)
+
+#define ber_pvt_ber_remaining(ber)     ((ber)->ber_end - (ber)->ber_ptr)
+#define ber_pvt_ber_total(ber)         ((ber)->ber_end - (ber)->ber_buf)
+#define ber_pvt_ber_write(ber)         ((ber)->ber_ptr - (ber)->ber_buf)
+
+struct sockbuf {
+       struct lber_options sb_opts;
+       Sockbuf_IO_Desc         *sb_iod;                /* I/O functions */
+#define        sb_valid                sb_opts.lbo_valid
+#define        sb_options              sb_opts.lbo_options
+#define        sb_debug                sb_opts.lbo_debug
+       ber_socket_t            sb_fd;
+       unsigned int            sb_trans_needs_read:1;
+       unsigned int            sb_trans_needs_write:1;
+       ber_len_t                       sb_max_incoming;
+};
+
+#define SOCKBUF_VALID( sb )    ( (sb)->sb_valid == LBER_VALID_SOCKBUF )
+
+struct seqorset {
+       BerElement      *sos_ber;
+       ber_len_t       sos_clen;
+       ber_tag_t       sos_tag;
+       char            *sos_first;
+       char            *sos_ptr;
+       struct seqorset *sos_next;
+};
+
+
+/*
+ * io.c
+ */
+LBER_F( int )
+ber_realloc LDAP_P((
+       BerElement *ber,
+       ber_len_t len ));
+
+/*
+ * bprint.c
+ */
+#define ber_log_printf ber_pvt_log_printf
+
+#ifdef NEW_LOGGING
+LBER_F( int )
+ber_output_dump LDAP_P((
+       const char *subsys,
+       int level,
+       BerElement *ber,
+       int inout ));
+#endif
+
+LBER_F( int )
+ber_log_bprint LDAP_P((
+       int errlvl,
+       int loglvl,
+       const char *data,
+       ber_len_t len ));
+
+LBER_F( int )
+ber_log_dump LDAP_P((
+       int errlvl,
+       int loglvl,
+       BerElement *ber,
+       int inout ));
+
+LBER_F( int )
+ber_log_sos_dump LDAP_P((
+       int errlvl,
+       int loglvl,
+       Seqorset *sos ));
+
+LBER_V (BER_LOG_FN) ber_int_log_proc;
+LBER_V (FILE *) ber_pvt_err_file;
+
+/* memory.c */
+       /* simple macros to realloc for now */
+LBER_V (BerMemoryFunctions *)  ber_int_memory_fns;
+LBER_F (char *)        ber_strndup( LDAP_CONST char *, ber_len_t );
+LBER_F (char *)        ber_strndup__( LDAP_CONST char *, size_t );
+
+#ifdef CSRIMALLOC
+#define LBER_MALLOC                    malloc
+#define LBER_CALLOC                    calloc
+#define LBER_REALLOC           realloc
+#define LBER_FREE                      free
+#define LBER_VFREE                     ber_memvfree
+#define LBER_STRDUP                    strdup
+#define LBER_STRNDUP           ber_strndup__
+
+#else
+#define LBER_MALLOC(s)         ber_memalloc((s))
+#define LBER_CALLOC(n,s)       ber_memcalloc((n),(s))
+#define LBER_REALLOC(p,s)      ber_memrealloc((p),(s))
+#define LBER_FREE(p)           ber_memfree((p))        
+#define LBER_VFREE(v)          ber_memvfree((void**)(v))
+#define LBER_STRDUP(s)         ber_strdup((s))
+#define LBER_STRNDUP(s,l)      ber_strndup((s),(l))
+#endif
+
+/* sockbuf.c */
+
+LBER_F(        int )
+ber_int_sb_init LDAP_P(( Sockbuf *sb ));
+
+LBER_F( int )
+ber_int_sb_close LDAP_P(( Sockbuf *sb ));
+
+LBER_F(        int )
+ber_int_sb_destroy LDAP_P(( Sockbuf *sb ));
+
+LBER_F( ber_slen_t )
+ber_int_sb_read LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
+
+LBER_F( ber_slen_t )
+ber_int_sb_write LDAP_P(( Sockbuf *sb, void *buf, ber_len_t len ));
+
+LDAP_END_DECL
+
+#endif /* _LBER_INT_H */
diff --git a/libraries/liblber/liblber.dsp b/libraries/liblber/liblber.dsp
new file mode 100644 (file)
index 0000000..02c8283
--- /dev/null
@@ -0,0 +1,229 @@
+# Microsoft Developer Studio Project File - Name="liblber" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=liblber - Win32 DLL Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "liblber.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "liblber.mak" CFG="liblber - Win32 DLL Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "liblber - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "liblber - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "liblber - Win32 Single Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "liblber - Win32 Single Release" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE "liblber - Win32 DLL Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "liblber - Win32 DLL Release" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF  "$(CFG)" == "liblber - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\Release"
+# PROP Intermediate_Dir "..\..\Release\liblber"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\Release\olber32.lib"
+
+!ELSEIF  "$(CFG)" == "liblber - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\Debug"
+# PROP Intermediate_Dir "..\..\Debug\liblber"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\Debug\olber32.lib"
+
+!ELSEIF  "$(CFG)" == "liblber - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "liblber_"
+# PROP BASE Intermediate_Dir "liblber_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\Sdebug"
+# PROP Intermediate_Dir "..\..\SDebug\liblber"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\Debug\olber32.lib"
+# ADD LIB32 /nologo /out:"..\..\SDebug\olber32.lib"
+
+!ELSEIF  "$(CFG)" == "liblber - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "liblber0"
+# PROP BASE Intermediate_Dir "liblber0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\SRelease"
+# PROP Intermediate_Dir "..\..\SRelease\liblber"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\Release\olber32.lib"
+# ADD LIB32 /nologo /out:"..\..\SRelease\olber32.lib"
+
+!ELSEIF  "$(CFG)" == "liblber - Win32 DLL Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "liblber_"
+# PROP BASE Intermediate_Dir "liblber_"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\DLLDebug"
+# PROP Intermediate_Dir "..\..\DLLDebug\liblber"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\Debug\olber32.lib"
+# ADD LIB32 /nologo /out:"..\..\DLLDebug\olber32.lib"
+
+!ELSEIF  "$(CFG)" == "liblber - Win32 DLL Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "liblber0"
+# PROP BASE Intermediate_Dir "liblber0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "liblber0"
+# PROP Intermediate_Dir "liblber0"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\..\Release\olber32.lib"
+# ADD LIB32 /nologo /out:"..\..\Release\olber32.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "liblber - Win32 Release"
+# Name "liblber - Win32 Debug"
+# Name "liblber - Win32 Single Debug"
+# Name "liblber - Win32 Single Release"
+# Name "liblber - Win32 DLL Debug"
+# Name "liblber - Win32 DLL Release"
+# Begin Source File
+
+SOURCE=.\bprint.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\debug.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\decode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\encode.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\io.c
+# End Source File
+# Begin Source File
+
+SOURCE=".\lber-int.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lber.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lber_pvt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lber_types.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\memory.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\nt_err.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\options.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sockbuf.c
+# End Source File
+# End Target
+# End Project
diff --git a/libraries/libldap_r/thr_posix.c b/libraries/libldap_r/thr_posix.c
new file mode 100644 (file)
index 0000000..fef18fe
--- /dev/null
@@ -0,0 +1,317 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted only
+ * as authorized by the OpenLDAP Public License.  A copy of this
+ * license is available at http://www.OpenLDAP.org/license.html or
+ * in file LICENSE in the top-level directory of the distribution.
+ */
+
+/* thr_posix.c - wrapper around posix and posixish thread implementations.
+ */
+
+#include "portable.h"
+
+#if defined( HAVE_PTHREADS )
+
+#include <ac/errno.h>
+
+#include "ldap_pvt_thread.h"
+
+
+#if HAVE_PTHREADS_D4
+#  define LDAP_INT_THREAD_ATTR_DEFAULT         pthread_attr_default
+#  define LDAP_INT_THREAD_CONDATTR_DEFAULT     pthread_condattr_default
+#  define LDAP_INT_THREAD_MUTEXATTR_DEFAULT    pthread_mutexattr_default
+#else
+#  define LDAP_INT_THREAD_ATTR_DEFAULT         NULL
+#  define LDAP_INT_THREAD_CONDATTR_DEFAULT     NULL
+#  define LDAP_INT_THREAD_MUTEXATTR_DEFAULT    NULL
+#endif
+
+
+int
+ldap_int_thread_initialize( void )
+{
+       return 0;
+}
+
+int
+ldap_int_thread_destroy( void )
+{
+#ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP
+       /* LinuxThreads: kill clones */
+       pthread_kill_other_threads_np();
+#endif
+       return 0;
+}
+
+#ifdef LDAP_THREAD_HAVE_SETCONCURRENCY
+int
+ldap_pvt_thread_set_concurrency(int n)
+{
+#ifdef HAVE_PTHREAD_SETCONCURRENCY
+       return pthread_setconcurrency( n );
+#elif HAVE_THR_SETCONCURRENCY
+       return thr_setconcurrency( n );
+#else
+       return 0;
+#endif
+}
+#endif
+
+#ifdef LDAP_THREAD_HAVE_GETCONCURRENCY
+int
+ldap_pvt_thread_get_concurrency(void)
+{
+#ifdef HAVE_PTHREAD_GETCONCURRENCY
+       return pthread_getconcurrency();
+#elif HAVE_THR_GETCONCURRENCY
+       return thr_getconcurrency();
+#else
+       return 0;
+#endif
+}
+#endif
+
+int 
+ldap_pvt_thread_create( ldap_pvt_thread_t * thread,
+       int detach,
+       void *(*start_routine)( void * ),
+       void *arg)
+{
+       int rtn;
+#if defined( HAVE_PTHREADS_FINAL )
+       pthread_attr_t attr;
+       pthread_attr_init(&attr);
+
+#if defined( PTHREAD_CREATE_JOINABLE ) || defined( PTHREAD_UNDETACHED )
+       if (!detach) {
+#if defined( PTHREAD_CREATE_JOINABLE )
+               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+#else
+               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_UNDETACHED);
+#endif
+#ifdef PTHREAD_CREATE_DETACHED
+       } else {
+               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+#elif HAVE_PTHREADS_OS390
+       } else {
+               int st = __DETACHED;
+               pthread_attr_setdetachstate(&attr, &st);
+#endif
+       }
+#endif
+
+#if defined(LDAP_PVT_THREAD_STACK_SIZE) && LDAP_PVT_THREAD_STACK_SIZE > 0
+       /* this should be tunable */
+       pthread_attr_setstacksize( &attr, LDAP_PVT_THREAD_STACK_SIZE );
+#endif
+
+       rtn = pthread_create( thread, &attr, start_routine, arg );
+#ifdef HAVE_PTHREADS_OS390
+       if ( rtn == -1 ) rtn = errno;
+#endif
+
+#if !defined( PTHREAD_CREATE_JOINABLE ) && !defined( PTHREAD_UNDETACHED )
+       if( detach ) {
+#ifdef HAVE_PTHREADS_OS390
+               (void) pthread_detach( thread );
+#else
+               (void) pthread_detach( *thread );
+#endif
+       }
+#endif
+       pthread_attr_destroy(&attr);
+
+#else
+       rtn = pthread_create( thread, LDAP_INT_THREAD_ATTR_DEFAULT,
+               start_routine, arg );
+
+       if( detach ) {
+               pthread_detach( thread );
+       }
+#endif
+
+       return rtn;
+}
+
+void 
+ldap_pvt_thread_exit( void *retval )
+{
+       pthread_exit( retval );
+}
+
+int 
+ldap_pvt_thread_join( ldap_pvt_thread_t thread, void **thread_return )
+{
+#if !defined( HAVE_PTHREADS_FINAL )
+       void *dummy;
+       if (thread_return==NULL)
+         thread_return=&dummy;
+#endif 
+#ifdef HAVE_PTHREADS_OS390
+       int st = pthread_join( thread, thread_return ); 
+       if ( st == -1 ) st = errno;
+       return st;
+#else
+       return pthread_join( thread, thread_return );
+#endif
+}
+
+int 
+ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo )
+{
+#ifdef HAVE_PTHREAD_KILL
+#ifdef HAVE_PTHREADS_OS390
+       int st = pthread_kill( thread, signo );
+       if ( st == -1 ) st = errno;
+       return st;
+#else
+       return pthread_kill( thread, signo );
+#endif
+#else
+       /* pthread package with DCE */
+       if (kill( getpid(), signo )<0)
+               return errno;
+       return 0;
+#endif
+}
+
+int 
+ldap_pvt_thread_yield( void )
+{
+#ifdef _POSIX_THREAD_IS_GNU_PTH
+       sched_yield();
+       return 0;
+
+#elif HAVE_SCHED_YIELD
+       return sched_yield();
+
+#elif HAVE_PTHREAD_YIELD
+#if HAVE_PTHREADS_OS390
+       pthread_yield(NULL);
+#else
+       pthread_yield();
+#endif
+       return 0;
+
+#elif HAVE_THR_YIELD
+       return thr_yield();
+
+#else
+       return 0;
+#endif   
+}
+
+int 
+ldap_pvt_thread_cond_init( ldap_pvt_thread_cond_t *cond )
+{
+       return pthread_cond_init( cond, LDAP_INT_THREAD_CONDATTR_DEFAULT );
+}
+
+int 
+ldap_pvt_thread_cond_destroy( ldap_pvt_thread_cond_t *cond )
+{
+       return pthread_cond_destroy( cond );
+}
+       
+int 
+ldap_pvt_thread_cond_signal( ldap_pvt_thread_cond_t *cond )
+{
+       return pthread_cond_signal( cond );
+}
+
+int
+ldap_pvt_thread_cond_broadcast( ldap_pvt_thread_cond_t *cond )
+{
+       return pthread_cond_broadcast( cond );
+}
+
+int 
+ldap_pvt_thread_cond_wait( ldap_pvt_thread_cond_t *cond, 
+                     ldap_pvt_thread_mutex_t *mutex )
+{
+       return pthread_cond_wait( cond, mutex );
+}
+
+int 
+ldap_pvt_thread_mutex_init( ldap_pvt_thread_mutex_t *mutex )
+{
+       return pthread_mutex_init( mutex, LDAP_INT_THREAD_MUTEXATTR_DEFAULT );
+}
+
+int 
+ldap_pvt_thread_mutex_destroy( ldap_pvt_thread_mutex_t *mutex )
+{
+       return pthread_mutex_destroy( mutex );
+}
+
+int 
+ldap_pvt_thread_mutex_lock( ldap_pvt_thread_mutex_t *mutex )
+{
+       return pthread_mutex_lock( mutex );
+}
+
+int 
+ldap_pvt_thread_mutex_trylock( ldap_pvt_thread_mutex_t *mutex )
+{
+       return pthread_mutex_trylock( mutex );
+}
+
+int 
+ldap_pvt_thread_mutex_unlock( ldap_pvt_thread_mutex_t *mutex )
+{
+       return pthread_mutex_unlock( mutex );
+}
+
+#ifdef LDAP_THREAD_HAVE_RDWR
+#ifdef HAVE_PTHREAD_RWLOCK_DESTROY
+int 
+ldap_pvt_thread_rdwr_init( ldap_pvt_thread_rdwr_t *rw )
+{
+       return pthread_rwlock_init( rw, NULL );
+}
+
+int 
+ldap_pvt_thread_rdwr_destroy( ldap_pvt_thread_rdwr_t *rw )
+{
+       return pthread_rwlock_destroy( rw );
+}
+
+int ldap_pvt_thread_rdwr_rlock( ldap_pvt_thread_rdwr_t *rw )
+{
+       return pthread_rwlock_rdlock( rw );
+}
+
+int ldap_pvt_thread_rdwr_rtrylock( ldap_pvt_thread_rdwr_t *rw )
+{
+       return pthread_rwlock_tryrdlock( rw );
+}
+
+int ldap_pvt_thread_rdwr_runlock( ldap_pvt_thread_rdwr_t *rw )
+{
+       return pthread_rwlock_unlock( rw );
+}
+
+int ldap_pvt_thread_rdwr_wlock( ldap_pvt_thread_rdwr_t *rw )
+{
+       return pthread_rwlock_wrlock( rw );
+}
+
+int ldap_pvt_thread_rdwr_wtrylock( ldap_pvt_thread_rdwr_t *rw )
+{
+       return pthread_rwlock_trywrlock( rw );
+}
+
+int ldap_pvt_thread_rdwr_wunlock( ldap_pvt_thread_rdwr_t *rw )
+{
+       return pthread_rwlock_unlock( rw );
+}
+
+#endif /* HAVE_PTHREAD_RDLOCK_DESTROY */
+#endif /* LDAP_THREAD_HAVE_RDWR */
+#endif /* HAVE_PTHREADS */
+
index 6d15e4629e8a3f6881c4893eedc2c9eee6f79b57..112a54a9b43cfa9a4a2e7ca88dcc8f773f456490 100644 (file)
@@ -1,52 +1,37 @@
 /* ldbm.c - ldap dbm compatibility routines */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
 
-#include <stdio.h>
-#include "ldbm.h"
-
-#ifdef LDBM_USE_GDBM
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-/*****************************************************************
- *                                                               *
- * use gdbm                                                     *
- *                                                               *
- *****************************************************************/
+/* Patched for Berkeley DB version 2.0; /KSp; 98/02/23
+ *   - DB version 2.6.4b   ; 1998/12/28, /KSp
+ *   - DB_DBT_MALLOC       ; 1998/03/22, /KSp
+ *   - basic implementation; 1998/02/23, /KSp
+ */
 
-LDBM
-ldbm_open( char *name, int rw, int mode, int dbcachesize )
-{
-       LDBM            db;
-       struct stat     st;
+#include "portable.h"
 
-       if ( (db =  gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
-               return( NULL );
-       }
-       if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
-               dbcachesize = (dbcachesize / st.st_blksize);
-               gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
-       }
+#ifdef SLAPD_LDBM
 
-       return( db );
-}
+#include <stdio.h>
 
-void
-ldbm_close( LDBM ldbm )
-{
-       gdbm_close( ldbm );
-}
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/errno.h>
 
-void
-ldbm_sync( LDBM ldbm )
-{
-       gdbm_sync( ldbm );
-}
+#include "ldbm.h"
+#include "ldap_pvt_thread.h"
 
 void
 ldbm_datum_free( LDBM ldbm, Datum data )
 {
-       free( data.dptr );
+       if ( data.dptr ) {
+               free( data.dptr );
+               memset( &data, '\0', sizeof( Datum ));
+               data.dptr = NULL;
+       }
 }
 
 Datum
@@ -54,6 +39,8 @@ ldbm_datum_dup( LDBM ldbm, Datum data )
 {
        Datum   dup;
 
+       ldbm_datum_init( dup );
+
        if ( data.dsize == 0 ) {
                dup.dsize = 0;
                dup.dptr = NULL;
@@ -61,58 +48,250 @@ ldbm_datum_dup( LDBM ldbm, Datum data )
                return( dup );
        }
        dup.dsize = data.dsize;
-       if ( dup.dptr = (char *) malloc( data.dsize ) )
-               memcpy( dup.dptr, data.dptr, data.dsize );
+
+       if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL ) {
+               AC_MEMCPY( dup.dptr, data.dptr, data.dsize );
+       }
 
        return( dup );
 }
 
-Datum
-ldbm_fetch( LDBM ldbm, Datum key )
+static int ldbm_initialized = 0;
+
+#if defined( USE_BERKELEY_CDB )
+       /* not currently supported */
+#define LDBM_RWLOCK_INIT  ((void) 0)
+#define LDBM_RWLOCK_DESTROY ((void) 0)
+#define LDBM_WLOCK             ((void) 0)
+#define LDBM_WUNLOCK   ((void) 0)
+#define LDBM_RLOCK             ((void) 0)
+#define LDBM_RUNLOCK   ((void) 0)
+
+#elif defined( HAVE_BERKELEY_DB_THREAD )
+static ldap_pvt_thread_rdwr_t ldbm_big_rdwr;
+#define LDBM_RWLOCK_INIT (ldap_pvt_thread_rdwr_init( &ldbm_big_rdwr ))
+#define LDBM_RWLOCK_DESTROY (ldap_pvt_thread_rdwr_destroy( &ldbm_big_rdwr ))
+#define LDBM_WLOCK             (ldap_pvt_thread_rdwr_wlock(&ldbm_big_rdwr))
+#define LDBM_WUNLOCK   (ldap_pvt_thread_rdwr_wunlock(&ldbm_big_rdwr))
+#define LDBM_RLOCK             (ldap_pvt_thread_rdwr_rlock(&ldbm_big_rdwr))
+#define LDBM_RUNLOCK   (ldap_pvt_thread_rdwr_runlock(&ldbm_big_rdwr))
+
+#else
+static ldap_pvt_thread_mutex_t ldbm_big_mutex;
+#define LDBM_RWLOCK_INIT (ldap_pvt_thread_mutex_init( &ldbm_big_mutex ))
+#define LDBM_RWLOCK_DESTROY (ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex ))
+#define LDBM_WLOCK             (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))
+#define LDBM_WUNLOCK   (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))
+#define LDBM_RLOCK             LDBM_WLOCK
+#define LDBM_RUNLOCK   LDBM_WUNLOCK
+#endif
+
+#if !defined( HAVE_BERKELEY_DB ) || (DB_VERSION_MAJOR < 3)
+       /*  a dbEnv for BERKELEYv2  */
+DB_ENV *ldbm_Env = NULL;       /* real or fake, depending on db and version */
+#endif
+
+/*******************************************************************
+ *                                                                 *
+ *  Create some special functions to initialize Berkeley DB for    *
+ *  versions greater than 2.                                       *
+ *                                                                 *
+ *******************************************************************/
+#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2)
+
+void *
+ldbm_malloc( size_t size )
 {
-       return( gdbm_fetch( ldbm, key ) );
+       /* likely should use ber_mem* routines */
+       return( calloc( 1, size ) );
 }
 
-int
-ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
+#ifdef LDAP_SYSLOG
+#include <ac/syslog.h>
+#endif
+
+static void
+ldbm_db_errcall( const char *prefix, char *message )
 {
-       int     rc;
+#ifdef LDAP_SYSLOG
+       syslog( LOG_INFO, "ldbm: %s %s", prefix, message );
+#endif
+}
 
-       rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
-       if ( flags & LDBM_SYNC )
-               gdbm_sync( ldbm );
-       return( rc );
+int ldbm_initialize( const char* home )
+{
+#if DB_VERSION_MAJOR < 3
+       int     err;
+       u_int32_t       envFlags;
+#endif
+
+       if(ldbm_initialized++) return 1;
+
+       {
+               char *version;
+               int major, minor, patch;
+               version = db_version( &major, &minor, &patch );
+
+               if( major != DB_VERSION_MAJOR ||
+                       minor < DB_VERSION_MINOR )
+               {
+#ifdef LDAP_SYSLOG
+                       syslog( LOG_INFO,
+                               "ldbm_initialize(): version mismatch\nexpected: %s\ngot: %s\n",
+                               DB_VERSION_STRING, version );
+#endif
+                       return 1;
+               }
+       }
+
+#if DB_VERSION_MAJOR < 3
+       ldbm_Env = calloc( 1, sizeof( DB_ENV ));
+
+       if( ldbm_Env == NULL ) return 1;
+
+       ldbm_Env->db_errcall    = ldbm_db_errcall;
+       ldbm_Env->db_errpfx             = "==>";
+
+       envFlags = DB_CREATE | DB_USE_ENVIRON;
+
+       /* add optional flags */
+#ifdef DB_PRIVATE
+       envFlags |= DB_PRIVATE;
+#endif
+#ifdef HAVE_BERKELEY_DB_THREAD
+       envFlags |= DB_THREAD; 
+#endif
+
+       err = db_appinit( home, NULL, ldbm_Env, envFlags );
+
+       if ( err ) {
+#ifdef LDAP_SYSLOG
+               syslog( LOG_INFO, "ldbm_initialize(): "
+                       "FATAL error (%d) in db_appinit()\n", err );
+#endif
+               return( 1 );
+       }
+#endif
+
+       LDBM_RWLOCK_INIT;
+
+       return 0;
 }
 
-int
-ldbm_delete( LDBM ldbm, Datum key )
+int ldbm_shutdown( void )
 {
-       int     rc;
+       if( !ldbm_initialized ) return 1;
 
-       rc = gdbm_delete( ldbm, key );
-       gdbm_sync( ldbm );
-       return( rc );
+#if DB_VERSION_MAJOR < 3
+       db_appexit( ldbm_Env );
+#endif
+
+       LDBM_RWLOCK_DESTROY;
+       return 0;
 }
 
-Datum
-ldbm_firstkey( LDBM ldbm )
+#else  /* some DB other than Berkeley V2 or greater */
+
+int ldbm_initialize( const char * home )
 {
-       return( gdbm_firstkey( ldbm ) );
+       if(ldbm_initialized++) return 1;
+
+       LDBM_RWLOCK_INIT;
+
+       return 0;
 }
 
-Datum
-ldbm_nextkey( LDBM ldbm, Datum key )
+int ldbm_shutdown( void )
 {
-       return( gdbm_nextkey( ldbm, key ) );
+       if( !ldbm_initialized ) return 1;
+
+       LDBM_RWLOCK_DESTROY;
+
+       return 0;
 }
 
-int
-ldbm_errno( LDBM ldbm )
+#endif /* HAVE_BERKELEY_DB */
+
+#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 3)
+
+DB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok)
 {
-       return( (int) gdbm_errno );
+       DB_ENV *env = NULL;    
+       int     err;
+       u_int32_t       envFlags;
+
+       err = db_env_create( &env, 0 );
+
+       if ( err ) {
+#ifdef LDAP_SYSLOG
+               syslog( LOG_INFO, "ldbm_initialize_env(): "
+                       "FATAL error in db_env_create() : %s (%d)\n",
+                       db_strerror( err ), err );
+#endif
+               return NULL;
+       }
+
+#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR >= 3
+       /* This interface appeared in 3.3 */
+       env->set_alloc( env, ldbm_malloc, NULL, NULL );
+#endif
+
+       env->set_errcall( env, ldbm_db_errcall );
+       env->set_errpfx( env, "==>" );
+       if (dbcachesize) {
+               env->set_cachesize( env, 0, dbcachesize, 0 );
+       }
+
+       envFlags = DB_CREATE | DB_INIT_MPOOL | DB_USE_ENVIRON;
+#ifdef DB_PRIVATE
+       envFlags |= DB_PRIVATE;
+#endif
+#ifdef DB_MPOOL_PRIVATE
+       envFlags |= DB_MPOOL_PRIVATE;
+#endif
+#ifdef HAVE_BERKELEY_DB_THREAD
+       envFlags |= DB_THREAD;
+#endif
+
+#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 0
+       err = env->open( env, home, envFlags, 0 );
+#else
+       /* 3.0.x requires an extra argument */
+       err = env->open( env, home, NULL, envFlags, 0 );
+#endif
+
+       if ( err != 0 ) {
+#ifdef LDAP_SYSLOG
+               syslog( LOG_INFO, "ldbm_initialize_env(): "
+                       "FATAL error in dbEnv->open() : %s (%d)\n",
+                       db_strerror( err ), err );
+#endif
+               env->close( env, 0 );
+               return NULL;
+       }
+
+       *envdirok = 1;
+       return env;
+}
+
+void ldbm_shutdown_env(DB_ENV *env)
+{
+       env->close( env, 0 );
 }
 
 #else
+
+DB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok)
+{
+       return ldbm_Env;
+}
+
+void ldbm_shutdown_env(DB_ENV *env)
+{
+}
+
+#endif
+
 #if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )
 
 /*****************************************************************
@@ -122,9 +301,78 @@ ldbm_errno( LDBM ldbm )
  *****************************************************************/
 
 LDBM
-ldbm_open( char *name, int rw, int mode, int dbcachesize )
+ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize )
 {
-       LDBM            ret;
+       LDBM            ret = NULL;
+#ifdef HAVE_EBCDIC
+       char n2[2048];
+#endif
+
+#if DB_VERSION_MAJOR >= 3
+       int err;
+
+       LDBM_WLOCK;
+
+       err = db_create( &ret, env, 0 );
+       if ( err != 0 ) {
+               (void)ret->close(ret, 0);
+               LDBM_WUNLOCK;
+
+               return NULL;
+       }
+
+#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 3
+       ret->set_malloc( ret, ldbm_malloc );
+#endif
+
+       ret->set_pagesize( ret, DEFAULT_DB_PAGE_SIZE );
+
+       /* likely should use ber_mem* routines */
+
+#ifdef HAVE_EBCDIC
+       strncpy(n2, name, sizeof(n2)-1);
+       n2[sizeof(n2)-1] = '\0';
+       __atoe(n2);
+       name = n2;
+#endif
+       err = ret->open( ret, name, NULL, DB_TYPE, rw, mode);
+
+       if ( err != 0 ) {
+               int tmp = errno;
+               (void)ret->close(ret, 0);
+               errno = tmp;
+
+               LDBM_WUNLOCK;
+               return NULL;
+       }
+
+       LDBM_WUNLOCK;
+#elif DB_VERSION_MAJOR >= 2
+       DB_INFO dbinfo;
+
+       memset( &dbinfo, '\0', sizeof( dbinfo ));
+
+#if    DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 4
+       /*
+        * BerkeleyDB 2.4 do not allow db_cachesize
+        * to be specified if an DB_ENV is.
+        */
+#else
+       /* set db_cachesize of MPOOL is NOT being used. */
+       if (( ldbm_Env == NULL ) || ( ldbm_Env->mp_info == NULL )) {
+               dbinfo.db_cachesize = dbcachesize;
+       }
+#endif
+
+       dbinfo.db_pagesize      = DEFAULT_DB_PAGE_SIZE;
+       dbinfo.db_malloc        = ldbm_malloc;
+
+       LDBM_WLOCK;
+       (void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret );
+       LDBM_WUNLOCK;
+
+#else
        void            *info;
        BTREEINFO       binfo;
        HASHINFO        hinfo;
@@ -140,44 +388,33 @@ ldbm_open( char *name, int rw, int mode, int dbcachesize )
        } else {
                info = NULL;
        }
+
+       LDBM_WLOCK;
        ret = dbopen( name, rw, mode, DB_TYPE, info );
-       return( ret );
+       LDBM_WUNLOCK;
+#endif
+
+       return ret;
 }
 
 void
 ldbm_close( LDBM ldbm )
 {
-       (*ldbm->close)( ldbm );
+       LDBM_WLOCK;
+#if DB_VERSION_MAJOR >= 2
+       ldbm->close( ldbm, 0 );
+#else
+       ldbm->close( ldbm );
+#endif
+       LDBM_WUNLOCK;
 }
 
 void
 ldbm_sync( LDBM ldbm )
 {
+       LDBM_WLOCK;
        (*ldbm->sync)( ldbm, 0 );
-}
-
-void
-ldbm_datum_free( LDBM ldbm, Datum data )
-{
-       free( data.dptr );
-}
-
-Datum
-ldbm_datum_dup( LDBM ldbm, Datum data )
-{
-       Datum   dup;
-
-       if ( data.dsize == 0 ) {
-               dup.dsize = 0;
-               dup.dptr = NULL;
-
-               return( dup );
-       }
-       dup.dsize = data.dsize;
-       if ( dup.dptr = (char *) malloc( data.dsize ) )
-               memcpy( dup.dptr, data.dptr, data.dsize );
-
-       return( dup );
+       LDBM_WUNLOCK;
 }
 
 Datum
@@ -186,12 +423,30 @@ ldbm_fetch( LDBM ldbm, Datum key )
        Datum   data;
        int     rc;
 
-       if ( (rc = (*ldbm->get)( ldbm, &key, &data, 0 )) == 0 ) {
+       LDBM_RLOCK;
+
+#if DB_VERSION_MAJOR >= 2
+       ldbm_datum_init( data );
+
+       data.flags = DB_DBT_MALLOC;
+
+       if ( (rc = ldbm->get( ldbm, NULL, &key, &data, 0 )) != 0 ) {
+               ldbm_datum_free( ldbm, data );
+               data.dptr = NULL;
+               data.dsize = 0;
+       }
+#else
+       if ( (rc = ldbm->get( ldbm, &key, &data, 0 )) == 0 ) {
+               /* Berkeley DB 1.85 don't malloc the data for us */
+               /* duplicate it for to ensure reentrancy */
                data = ldbm_datum_dup( ldbm, data );
        } else {
                data.dptr = NULL;
                data.dsize = 0;
        }
+#endif
+
+       LDBM_RUNLOCK;
 
        return( data );
 }
@@ -201,9 +456,20 @@ ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
 {
        int     rc;
 
-       rc = (*ldbm->put)( ldbm, &key, &data, flags & ~LDBM_SYNC );
+       LDBM_WLOCK;
+
+#if DB_VERSION_MAJOR >= 2
+       rc = ldbm->put( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC );
+       rc = (-1) * rc;
+#else
+       rc = ldbm->put( ldbm, &key, &data, flags & ~LDBM_SYNC );
+#endif
+
        if ( flags & LDBM_SYNC )
-               (*ldbm->sync)( ldbm, 0 );
+               ldbm->sync( ldbm, 0 );
+
+       LDBM_WUNLOCK;
+
        return( rc );
 }
 
@@ -212,38 +478,107 @@ ldbm_delete( LDBM ldbm, Datum key )
 {
        int     rc;
 
-       rc = (*ldbm->del)( ldbm, &key, 0 );
-       (*ldbm->sync)( ldbm, 0 );
+       LDBM_WLOCK;
+
+#if DB_VERSION_MAJOR >= 2
+       rc = ldbm->del( ldbm, NULL, &key, 0 );
+       rc = (-1) * rc;
+#else
+       rc = ldbm->del( ldbm, &key, 0 );
+#endif
+       ldbm->sync( ldbm, 0 );
+
+       LDBM_WUNLOCK;
+
        return( rc );
 }
 
 Datum
-ldbm_firstkey( LDBM ldbm )
+ldbm_firstkey( LDBM ldbm, LDBMCursor **dbch )
 {
        Datum   key, data;
        int     rc;
 
-       if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_FIRST )) == 0 ) {
+#if DB_VERSION_MAJOR >= 2
+       LDBMCursor  *dbci;
+
+       ldbm_datum_init( key );
+       ldbm_datum_init( data );
+
+       key.flags = data.flags = DB_DBT_MALLOC;
+
+       LDBM_RLOCK;
+
+       /* acquire a cursor for the DB */
+# if DB_VERSION_MAJOR >= 3 || (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 5)
+       rc = ldbm->cursor( ldbm, NULL, &dbci, 0 );
+# else
+       rc = ldbm->cursor( ldbm, NULL, &dbci );
+# endif
+
+       if( rc ) {
+               key.dptr = NULL;
+       } else {
+               *dbch = dbci;
+               if ( dbci->c_get( dbci, &key, &data, DB_NEXT ) == 0 ) {
+                       ldbm_datum_free( ldbm, data );
+               } else {
+                       key.dptr = NULL;
+                       key.dsize = 0;
+               }
+       }
+
+       LDBM_RUNLOCK;
+
+#else
+       LDBM_RLOCK;
+
+       rc = ldbm->seq( ldbm, &key, &data, R_FIRST );
+
+       if ( rc == 0 ) {
                key = ldbm_datum_dup( ldbm, key );
        } else {
                key.dptr = NULL;
                key.dsize = 0;
        }
+
+       LDBM_RUNLOCK;
+#endif
+
        return( key );
 }
 
 Datum
-ldbm_nextkey( LDBM ldbm, Datum key )
+ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
 {
-       Datum   data;
        int     rc;
+       Datum   data;
+
+       LDBM_RLOCK;
+
+#if DB_VERSION_MAJOR >= 2
+       ldbm_datum_init( data );
+
+       ldbm_datum_free( ldbm, key );
+       key.flags = data.flags = DB_DBT_MALLOC;
 
-       if ( (rc = (*ldbm->seq)( ldbm, &key, &data, R_NEXT )) == 0 ) {
+       rc = dbcp->c_get( dbcp, &key, &data, DB_NEXT );
+       if ( rc == 0 ) {
+               ldbm_datum_free( ldbm, data );
+       } else
+#else
+       rc = ldbm->seq( ldbm, &key, &data, R_NEXT );
+
+       if ( rc == 0 ) {
                key = ldbm_datum_dup( ldbm, key );
-       } else {
+       } else
+#endif
+       {
                key.dptr = NULL;
                key.dsize = 0;
        }
+
+       LDBM_RUNLOCK;
        return( key );
 }
 
@@ -253,96 +588,576 @@ ldbm_errno( LDBM ldbm )
        return( errno );
 }
 
-#else
+/******************************************************************
+ *                                                                *
+ *         END Berkeley section                                   *
+ *                                                                *
+ ******************************************************************/
 
-#ifdef LDBM_USE_NDBM
+#elif defined( HAVE_GDBM )
+
+#ifdef HAVE_ST_BLKSIZE
+#include <sys/stat.h>
+#endif
 
 /*****************************************************************
  *                                                               *
- * if no gdbm, fall back to using ndbm, the standard unix thing  *
+ * use gdbm                                                      *
  *                                                               *
  *****************************************************************/
 
-/* ARGSUSED */
 LDBM
-ldbm_open( char *name, int rw, int mode, int dbcachesize )
+ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize )
 {
-       return( dbm_open( name, rw, mode ) );
+       LDBM            db;
+#ifdef HAVE_ST_BLKSIZE
+               struct stat     st;
+#endif
+#ifdef HAVE_EBCDIC
+       char n2[2048];
+
+       strncpy(n2, name, sizeof(n2)-1);
+       n2[sizeof(n2)-1] = '\0';
+       __atoe(n2);
+       name = n2;
+#endif
+
+       LDBM_WLOCK;
+
+       if ( (db = gdbm_open( name, 0, rw | GDBM_FAST, mode, 0 )) == NULL ) {
+               LDBM_WUNLOCK;
+               return( NULL );
+       }
+
+#ifdef HAVE_ST_BLKSIZE
+       if ( dbcachesize > 0 && stat( name, &st ) == 0 ) {
+               dbcachesize /= st.st_blksize;
+               if( dbcachesize == 0 ) dbcachesize = 1;
+               gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
+       }
+#else
+       if ( dbcachesize > 0 ) {
+               dbcachesize /= 4096;
+               if( dbcachesize == 0 ) dbcachesize = 1;
+               gdbm_setopt( db, GDBM_CACHESIZE, &dbcachesize, sizeof(int) );
+       }
+#endif
+
+       LDBM_WUNLOCK;
+
+       return( db );
 }
 
 void
 ldbm_close( LDBM ldbm )
 {
-       dbm_close( ldbm );
+       LDBM_WLOCK;
+       gdbm_close( ldbm );
+       LDBM_WUNLOCK;
 }
 
-/* ARGSUSED */
 void
 ldbm_sync( LDBM ldbm )
 {
-       return;
+       LDBM_WLOCK;
+       gdbm_sync( ldbm );
+       LDBM_WUNLOCK;
+}
+
+Datum
+ldbm_fetch( LDBM ldbm, Datum key )
+{
+       Datum d;
+
+       LDBM_RLOCK;
+       d = gdbm_fetch( ldbm, key );
+       LDBM_RUNLOCK;
+
+       return d;
+}
+
+int
+ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
+{
+       int     rc;
+
+       LDBM_WLOCK;
+       rc = gdbm_store( ldbm, key, data, flags & ~LDBM_SYNC );
+       if ( flags & LDBM_SYNC )
+               gdbm_sync( ldbm );
+       LDBM_WUNLOCK;
+
+       return( rc );
+}
+
+int
+ldbm_delete( LDBM ldbm, Datum key )
+{
+       int     rc;
+
+       LDBM_WLOCK;
+       rc = gdbm_delete( ldbm, key );
+       gdbm_sync( ldbm );
+       LDBM_WUNLOCK;
+
+       return( rc );
+}
+
+Datum
+ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
+{
+       Datum d;
+
+       LDBM_RLOCK;
+       d = gdbm_firstkey( ldbm );
+       LDBM_RUNLOCK;
+
+       if ( d.dptr != NULL ) {
+               *dbcp = (Datum *) malloc( sizeof( Datum ) );
+               **dbcp = ldbm_datum_dup( ldbm, d );
+       }
+
+       return d;
+}
+
+Datum
+ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
+{
+       Datum d;
+
+       LDBM_RLOCK;
+       d = gdbm_nextkey( ldbm, *dbcp );
+       LDBM_RUNLOCK;
+
+       ldbm_datum_free( ldbm, *dbcp );
+
+       if ( d.dptr != NULL ) {
+               *dbcp = ldbm_datum_dup( ldbm, d );
+       } else {
+               free( dbcp );
+       }
+
+       return d;
+}
+
+int
+ldbm_errno( LDBM ldbm )
+{
+       int err;
+
+       LDBM_WLOCK;
+       err = gdbm_errno;
+       LDBM_WUNLOCK;
+
+       return( err );
+}
+
+#elif HAVE_MDBM
+
+/* MMAPED DBM HASHING DATABASE */
+
+#include <ac/string.h>
+
+/* #define MDBM_DEBUG */
+
+#ifdef MDBM_DEBUG
+#include <stdio.h>
+#endif
+
+#define NO_NULL_KEY
+/* #define MDBM_CHAIN */
+
+#ifdef MDBM_CHAIN
+
+/* Use chaining */
+
+#define mdbm_store     mdbm_chain_store
+#define mdbm_fetch     mdbm_chain_fetch
+#define mdbm_delete    mdbm_chain_delete
+#define mdbm_first     mdbm_chain_first
+#define mdbm_next      mdbm_chain_next
+
+#endif
+
+#define MDBM_PG_SZ     (4*1024)
+
+/*****************************************************************
+ *                                                               *
+ * use mdbm                                                      *
+ *                                                               *
+ *****************************************************************/
+
+LDBM
+ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize )
+{
+       LDBM            db;
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout,
+                "==>(mdbm)ldbm_open(name=%s,rw=%x,mode=%x,cachesize=%d)\n",
+                name ? name : "NULL", rw, mode, dbcachesize );
+       fflush( stdout );
+#endif
+
+       LDBM_WLOCK;     /* We need locking here, this is the only non-thread
+               * safe function we have.  */
+
+       if ( (db =  mdbm_open( name, rw, mode, MDBM_PG_SZ )) == NULL ) {
+               LDBM_WUNLOCK;
+#ifdef MDBM_DEBUG
+               fprintf( stdout, "<==(mdbm)ldbm_open(db=NULL)\n" );
+               fflush( stdout );
+#endif
+               return( NULL );
+       }
+
+#ifdef MDBM_CHAIN
+       (void)mdbm_set_chain(db);
+#endif
+
+       LDBM_WUNLOCK;
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout, "<==(mdbm)ldbm_open(db=%p)\n", db );
+       fflush( stdout );
+#endif
+
+       return( db );
 }
 
 void
-ldbm_datum_free( LDBM ldbm, Datum data )
+ldbm_close( LDBM ldbm )
 {
-       return;
+       /* Open and close are not reentrant so we need to use locks here */
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout,
+                "==>(mdbm)ldbm_close(db=%p)\n", ldbm );
+       fflush( stdout );
+#endif
+
+       LDBM_WLOCK;
+       mdbm_close( ldbm );
+       LDBM_WUNLOCK;
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout, "<==(mdbm)ldbm_close()\n" );
+       fflush( stdout );
+#endif
 }
 
+void
+ldbm_sync( LDBM ldbm )
+{
+       /* XXX: Not sure if this is re-entrant need to check code, if so
+        * you can leave LOCKS out.
+        */
+
+       LDBM_WLOCK;
+       mdbm_sync( ldbm );
+       LDBM_WUNLOCK;
+}
+
+#define MAX_MDBM_RETRY 5
+
 Datum
-ldbm_datum_dup( LDBM ldbm, Datum data )
+ldbm_fetch( LDBM ldbm, Datum key )
 {
-       Datum   dup;
+       Datum   d;
+       kvpair  k;
+       int     retry = 0;
 
-       if ( data.dsize == 0 ) {
-               dup.dsize = 0;
-               dup.dptr = NULL;
+       /* This hack is needed because MDBM does not take keys
+        * which begin with NULL when working in the chaining
+        * mode.
+        */
 
-               return( dup );
+#ifdef NO_NULL_KEY
+       k.key.dsize = key.dsize + 1;                    
+       k.key.dptr = malloc(k.key.dsize);
+       *(k.key.dptr) = 'l';
+       AC_MEMCPY( (void *)(k.key.dptr + 1), key.dptr, key.dsize );     
+#else
+       k.key = key;
+#endif 
+
+       k.val.dptr = NULL;
+       k.val.dsize = 0;
+
+       /* LDBM_RLOCK; */
+       do {
+               d = mdbm_fetch( ldbm, k );
+
+               if ( d.dsize > 0 ) {
+                       if ( k.val.dptr != NULL ) {
+                               free( k.val.dptr );
+                       }
+
+                       if ( (k.val.dptr = malloc( d.dsize )) != NULL ) {
+                               k.val.dsize = d.dsize;
+                               d = mdbm_fetch( ldbm, k );
+
+                       } else { 
+                               d.dsize = 0;
+                               break;
+                       }
+               }/* if ( d.dsize > 0 ) */
+       } while ((d.dsize > k.val.dsize) && (++retry < MAX_MDBM_RETRY));
+       /* LDBM_RUNLOCK; */
+
+#ifdef NO_NULL_KEY
+       free(k.key.dptr);
+#endif
+
+       return d;
+}
+
+int
+ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
+{
+       int     rc;
+       Datum   int_key;        /* Internal key */
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout,
+                "==>(mdbm)ldbm_store(db=%p, key(dptr=%p,sz=%d), data(dptr=%p,sz=%d), flags=%x)\n",
+                ldbm, key.dptr, key.dsize, data.dptr, data.dsize, flags );
+       fflush( stdout );
+#endif
+
+       /* LDBM_WLOCK; */
+
+#ifdef NO_NULL_KEY
+       int_key.dsize = key.dsize + 1;
+       int_key.dptr = malloc( int_key.dsize );
+       *(int_key.dptr) = 'l';  /* Must not be NULL !*/
+       AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );
+#else
+       int_key = key;
+#endif
+
+       rc = mdbm_store( ldbm, int_key, data, flags );
+       if ( flags & LDBM_SYNC ) {
+               mdbm_sync( ldbm );
        }
-       dup.dsize = data.dsize;
-       if ( dup.dptr = (char *) malloc( data.dsize ) )
-               memcpy( dup.dptr, data.dptr, data.dsize );
 
-       return( dup );
+       /* LDBM_WUNLOCK; */
+
+#ifdef MDBM_DEBUG
+       fprintf( stdout, "<==(mdbm)ldbm_store(rc=%d)\n", rc );
+       fflush( stdout );
+#endif
+
+#ifdef NO_NULL_KEY
+       free(int_key.dptr);
+#endif
+
+       return( rc );
+}
+
+int
+ldbm_delete( LDBM ldbm, Datum key )
+{
+       int     rc;
+       Datum   int_key;
+
+       /* LDBM_WLOCK; */
+
+#ifdef NO_NULL_KEY
+       int_key.dsize = key.dsize + 1;
+       int_key.dptr = malloc(int_key.dsize);
+       *(int_key.dptr) = 'l';
+       AC_MEMCPY( (void *)(int_key.dptr + 1), key.dptr, key.dsize );   
+#else
+       int_key = key;
+#endif
+       
+       rc = mdbm_delete( ldbm, int_key );
+
+       /* LDBM_WUNLOCK; */
+#ifdef NO_NULL_KEY
+       free(int_key.dptr);
+#endif
+
+       return( rc );
+}
+
+static Datum
+ldbm_get_next( LDBM ldbm, kvpair (*fptr)(MDBM *, kvpair) ) 
+{
+       kvpair  out;
+       kvpair  in;
+       Datum   ret;
+       size_t  sz = MDBM_PAGE_SIZE(ldbm);
+#ifdef NO_NULL_KEY
+       int     delta = 1;
+#else
+       int     delta = 0;
+#endif
+
+       /* LDBM_RLOCK; */
+
+       in.key.dsize = sz;      /* Assume first key in one pg */
+       in.key.dptr = malloc(sz);
+       
+       in.val.dptr = NULL;     /* Don't need data just key */ 
+       in.val.dsize = 0;
+
+       ret.dptr = NULL;
+       ret.dsize = NULL;
+
+       out = fptr( ldbm, in );
+
+       if (out.key.dsize > 0) {
+               ret.dsize = out.key.dsize - delta;
+
+               if ((ret.dptr = (char *)malloc(ret.dsize)) == NULL) { 
+                       ret.dsize = 0;
+                       ret.dptr = NULL;
+
+               } else {
+                       AC_MEMCPY(ret.dptr, (void *)(out.key.dptr + delta),
+                               ret.dsize );
+           }
+       }
+
+       /* LDBM_RUNLOCK; */
+       
+       free(in.key.dptr);
+       return ret;
+}
+
+Datum
+ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
+{
+       return ldbm_get_next( ldbm, mdbm_first );
+}
+
+Datum
+ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
+{
+       /* XXX:
+        * don't know if this will affect the LDAP server operation 
+        * but mdbm cannot take and input key.
+        */
+
+       return ldbm_get_next( ldbm, mdbm_next );
+}
+
+int
+ldbm_errno( LDBM ldbm )
+{
+       /* XXX: best we can do with current  mdbm interface */
+       return( errno );
+}
+
+#elif defined( HAVE_NDBM )
+
+/*****************************************************************
+ *                                                               *
+ * if no gdbm or mdbm, fall back to using ndbm, the standard unix thing  *
+ *                                                               *
+ *****************************************************************/
+
+/* ARGSUSED */
+LDBM
+ldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize )
+{
+       LDBM ldbm;
+
+       LDBM_WLOCK;
+       ldbm = dbm_open( name, rw, mode );
+       LDBM_WUNLOCK;
+
+       return( ldbm );
+}
+
+void
+ldbm_close( LDBM ldbm )
+{
+       LDBM_WLOCK;
+       dbm_close( ldbm );
+       LDBM_WUNLOCK;
+}
+
+/* ARGSUSED */
+void
+ldbm_sync( LDBM ldbm )
+{
+       return;
 }
 
 Datum
 ldbm_fetch( LDBM ldbm, Datum key )
 {
-       return( ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) ) );
+       Datum d;
+
+       LDBM_RLOCK;
+       d = ldbm_datum_dup( ldbm, dbm_fetch( ldbm, key ) );
+       LDBM_RUNLOCK;
+
+       return d;
 }
 
 int
 ldbm_store( LDBM ldbm, Datum key, Datum data, int flags )
 {
-       return( dbm_store( ldbm, key, data, flags ) );
+       int rc;
+
+       LDBM_WLOCK;
+       rc = dbm_store( ldbm, key, data, flags );
+       LDBM_WUNLOCK;
+
+       return rc;
 }
 
 int
 ldbm_delete( LDBM ldbm, Datum key )
 {
-       return( dbm_delete( ldbm, key ) );
+       int rc;
+
+       LDBM_WLOCK;
+       rc = dbm_delete( ldbm, key );
+       LDBM_WUNLOCK;
+
+       return rc;
 }
 
 Datum
-ldbm_firstkey( LDBM ldbm )
+ldbm_firstkey( LDBM ldbm, LDBMCursor **dbcp )
 {
-       return( dbm_firstkey( ldbm ) );
+       Datum d;
+
+       LDBM_RLOCK;
+       d = dbm_firstkey( ldbm );
+       LDBM_RUNLOCK;
+
+       return d;
 }
 
 Datum
-ldbm_nextkey( LDBM ldbm, Datum key )
+ldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp )
 {
-       return( dbm_nextkey( ldbm ) );
+       Datum d;
+
+       LDBM_RLOCK;
+       d = dbm_nextkey( ldbm );
+       LDBM_RUNLOCK;
+
+       return d;
 }
 
 int
 ldbm_errno( LDBM ldbm )
 {
-       return( dbm_error( ldbm ) );
+       int err;
+
+       LDBM_WLOCK;
+       err = dbm_error( ldbm );
+       LDBM_WUNLOCK;
+
+       return err;
 }
 
 #endif /* ndbm */
-#endif /* db */
-#endif /* gdbm */
+#endif /* ldbm */
index 5316d023aeb252fdbc19b5eb0cae7476039d55d4..ef2e3614a0b31f3ac7d4e1b22059486e376f5791 100644 (file)
@@ -14,6 +14,7 @@ SRCS  = ucstr.c
 OBJS   = ucdata.o ure.o urestubs.o ucstr.o
 
 XLIB = $(LIBRARY)
+XLIBS = $(LDAP_LIBLUTIL_A)
 PROGRAMS = ucgendat
 
 LDAP_INCDIR= ../../include       
index beb4184f03f55a5339dab12854dda44596018b22..151e0ac1057f3c260aff7b1f42eac2a51a84bc25 100644 (file)
@@ -30,6 +30,7 @@
 #include "ldap_config.h"
 
 #include <stdio.h>
+#include <ac/bytes.h>
 #include <ac/stdlib.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
  **************************************************************************/
 
 typedef struct {
-    unsigned short bom;
-    unsigned short cnt;
+    ac_uint2 bom;
+    ac_uint2 cnt;
     union {
-        unsigned long bytes;
-        unsigned short len[2];
+        ac_uint4 bytes;
+        ac_uint2 len[2]; 
     } size;
 } _ucheader_t;
 
index 2daee8a4c339656ccbde77a93be410a5e3f55262..11f32f9cb2b1173d21af17b9d48a17d7ee3a1a12 100644 (file)
@@ -30,6 +30,7 @@
 #include "ldap_config.h"
 
 #include <stdio.h>
+#include <ac/bytes.h>
 #include <ac/stdlib.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
@@ -804,8 +805,8 @@ read_cdata(FILE *in)
     char line[512], *s, *e;
 
     lineno = skip = 0;
-    while (!feof(in)) {
-               if( fscanf(in, "%[^\n]\n", line) != 1) break;
+    while (fgets(line, sizeof(line), in)) {
+       if( (s=strchr(line, '\n')) ) *s = '\0';
         lineno++;
 
         /*
@@ -1163,8 +1164,8 @@ read_compexdata(FILE *in)
 
     (void) memset((char *) compexs, 0, sizeof(unsigned long) << 11);
 
-    while (!feof(in)) {
-               if( fscanf(in, "%[^\n]\n", line) != 1) break;
+    while (fgets(line, sizeof(line), in)) {
+       if( (s=strchr(line, '\n')) ) *s = '\0';
         /*
          * Skip blank lines and lines that start with a '#'.
          */
@@ -1216,7 +1217,8 @@ static void
 write_cdata(char *opath)
 {
     FILE *out;
-    unsigned long i, idx, bytes, nprops;
+       ac_uint4 bytes;
+    unsigned long i, idx, nprops;
     unsigned short casecnt[2];
     char path[BUFSIZ];
 
@@ -1229,7 +1231,7 @@ write_cdata(char *opath)
     /*
      * Open the ctype.dat file.
      */
-    sprintf(path, "%s%sctype.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "ctype.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1268,7 +1270,7 @@ write_cdata(char *opath)
     /*
      * Write the header.
      */
-    fwrite((char *) hdr, sizeof(unsigned short), 2, out);
+    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
 
     /*
      * Write the byte count.
@@ -1300,7 +1302,7 @@ write_cdata(char *opath)
     /*
      * Open the case.dat file.
      */
-    sprintf(path, "%s%scase.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "case.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1355,7 +1357,7 @@ write_cdata(char *opath)
     /*
      * Open the comp.dat file.
      */
-    sprintf(path, "%s%scomp.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "comp.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
        return;
     
@@ -1393,7 +1395,7 @@ write_cdata(char *opath)
     /*
      * Open the decomp.dat file.
      */
-    sprintf(path, "%s%sdecomp.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "decomp.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1447,7 +1449,7 @@ write_cdata(char *opath)
     /*
      * Open the kdecomp.dat file.
      */
-    sprintf(path, "%s%skdecomp.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "kdecomp.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1507,7 +1509,7 @@ write_cdata(char *opath)
     /*
      * Open the cmbcl.dat file.
      */
-    sprintf(path, "%s%scmbcl.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "cmbcl.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1545,7 +1547,7 @@ write_cdata(char *opath)
     /*
      * Open the num.dat file.
      */
-    sprintf(path, "%s%snum.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "num.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1598,10 +1600,7 @@ main(int argc, char *argv[])
     FILE *in;
     char *prog, *opath;
 
-    if ((prog = strrchr(argv[0], *LDAP_DIRSEP)) != 0)
-      prog++;
-    else
-      prog = argv[0];
+    prog = lutil_progname( "ucgendat", argc, argv );
 
     opath = 0;
     in = stdin;
diff --git a/libraries/liblutil/Makefile.in b/libraries/liblutil/Makefile.in
new file mode 100644 (file)
index 0000000..ba9f3ec
--- /dev/null
@@ -0,0 +1,36 @@
+# $OpenLDAP$
+## Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+## COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+##
+## Makefile for -llutil
+##
+
+LIBRARY        = liblutil.a
+
+NT_SRCS = ntservice.c
+NT_OBJS = ntservice.o slapdmsg.res
+
+UNIX_SRCS = detach.c
+UNIX_OBJS = detach.o
+
+SRCS   = base64.c csn.c entropy.c sasl.c signal.c hash.c \
+       md5.c passwd.c sha1.c getpass.c lockf.c utils.c uuid.c sockpair.c \
+       @LIBSRCS@ $(@PLAT@_SRCS)
+
+OBJS   = base64.o csn.o entropy.o sasl.o signal.o hash.o \
+       md5.o passwd.o sha1.o getpass.o lockf.o utils.o uuid.o sockpair.o \
+       @LIBOBJS@ $(@PLAT@_OBJS)
+
+LDAP_INCDIR= ../../include       
+LDAP_LIBDIR= ../../libraries
+
+# These rules are for a Mingw32 build, specifically.
+# It's ok for them to be here because the clean rule is harmless, and
+# slapdmsg.res won't get built unless it's declared in OBJS.
+
+slapdmsg.res: slapdmsg.rc slapdmsg.bin
+       windres $< -O coff -o $@
+
+clean-local:
+       $(RM) *.res
+
diff --git a/libraries/liblutil/debug.c b/libraries/liblutil/debug.c
deleted file mode 100644 (file)
index 1d47361..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/* $OpenLDAP$ */
-/*
- * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-
-#include <ac/stdarg.h>
-#include <ac/stdlib.h>
-#include <ac/string.h>
-#include <ac/time.h>
-
-#ifdef LDAP_SYSLOG
-#include <ac/syslog.h>
-#endif
-
-#include "ldap_log.h"
-#include "ldap_defaults.h"
-#include "lber.h"
-
-struct DEBUGLEVEL
-{
-       char *subsystem;
-       int  level;
-};
-
-static struct DEBUGLEVEL **levelArray;
-static long   numLevels = 0;
-
-static FILE *log_file = NULL;
-static int global_level = 0;
-
-#ifdef LDAP_SYSLOG
-static int use_syslog = 0;
-
-static int debug2syslog(int l) {
-       switch (l) {
-       case LDAP_LEVEL_EMERG:  return LOG_EMERG;
-       case LDAP_LEVEL_ALERT:  return LOG_ALERT;
-       case LDAP_LEVEL_CRIT:   return LOG_CRIT;
-       case LDAP_LEVEL_ERR:    return LOG_ERR;
-       case LDAP_LEVEL_WARNING:        return LOG_WARNING;
-       case LDAP_LEVEL_NOTICE: return LOG_NOTICE;
-       case LDAP_LEVEL_INFO:   return LOG_INFO;
-       }
-       return LOG_DEBUG;
-}
-#endif
-
-static char *lutil_levels[] = {"emergency", "alert", "critical",
-                          "error", "warning", "notice",
-                          "information", "entry", "args",
-                          "results", "detail1", "detail2",
-                          NULL};
-
-int lutil_mnem2level( const char *level )
-{
-    int i;
-    for( i = 0; lutil_levels[i] != NULL; i++ )
-    {
-       if ( !strcasecmp( level, lutil_levels[i] ) )
-       {
-           return i;
-       }
-    }
-    return 0;
-}
-
-static void addSubsys( const char *subsys, int level )
-{
-       int i, j;
-
-       if ( !strcasecmp( subsys, "global") ) global_level = level;
-
-       for( i = 0; i < numLevels; i++ )
-       {
-               if ( levelArray[i] == NULL )
-               {
-                       levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
-                       levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
-                       strcpy ( levelArray[i]->subsystem, subsys );
-                       levelArray[i]->level = level;
-                       return;
-               }
-               if( !strcasecmp( subsys, levelArray[i]->subsystem ) )
-               {
-                       levelArray[i]->level = level;
-                       return;
-               }
-       }
-       levelArray = (struct DEBUGLEVEL**)ber_memrealloc( levelArray, sizeof( struct DEBUGLEVEL* ) * (numLevels + 10) );
-       for( j = numLevels; j < (numLevels + 10); j++ )
-       {
-               levelArray[j] = NULL;
-       }
-       numLevels += 10;
-       levelArray[i] = (struct DEBUGLEVEL*)ber_memalloc( sizeof( struct DEBUGLEVEL ) );
-       levelArray[i]->subsystem = (char*)ber_memalloc( strlen( subsys ) + 1 );
-       strcpy( levelArray[i]->subsystem, subsys );
-       levelArray[i]->level = level;
-       return;
-}
-
-void lutil_set_debug_level( const char* subsys, int level )
-{
-    addSubsys( subsys, level );
-}
-
-int lutil_debug_file( FILE *file )
-{
-       log_file = file;
-       ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file );
-
-       return 0;
-}
-
-void lutil_log_int(
-       FILE* file,
-       const char *subsys, int level,
-       const char *fmt, va_list vl )
-{
-#ifdef HAVE_WINSOCK
-       time_t now;
-       struct tm *today;
-#endif
-       int i;
-
-       if ( levelArray == NULL ) return; /* logging isn't set up */
-
-       /*
-        * Look for the subsystem in the level array.  When we find it,
-        * break out of the loop.
-        */
-       for( i = 0; i < numLevels; i++ ) {
-               if ( levelArray[i] == NULL ) break; 
-               if ( ! strcasecmp( levelArray[i]->subsystem, subsys ) ) break;
-       }
-
-       /*
-        * If we didn't find the subsystem, or the set level is less than
-        * the requested output level, don't output it.
-        */
-       if ( (level > global_level) &&
-               ((i > numLevels ) || (levelArray[i] == NULL) || ( level > levelArray[i]->level )) )
-       {
-               return;
-       }
-
-#ifdef LDAP_SYSLOG
-       /* we're configured to use syslog */
-       if( use_syslog ) {
-               vsyslog( debug2syslog(level), fmt, vl );
-               return;
-       }
-#endif
-
-#if 0
-#ifdef HAVE_WINSOCK
-       if( log_file == NULL ) {
-               log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
-
-               if ( log_file == NULL )
-                       log_file = fopen( "openldap.log", "w" );
-
-               if ( log_file == NULL )
-                       return;
-
-               ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
-       }
-#endif
-#endif
-
-       if( file == NULL ) {
-               /*
-                * Use stderr unless file was specified via:
-                *   ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, file)
-                */
-               file = stderr;
-       }
-
-#ifdef HAVE_WINSOCK
-       /*
-        * Stick the time in the buffer to output when using Winsock
-        * as NT can't pipe to a timestamp program like Unix can.
-        * This, of course, makes some logs hard to read.
-     */
-       time( &now );
-       today = localtime( &now );
-       fprintf( file, "%4d%02d%02d:%02d:%02d:%02d ",
-               today->tm_year + 1900, today->tm_mon + 1,
-               today->tm_mday, today->tm_hour,
-               today->tm_min, today->tm_sec );
-#endif
-
-       /*
-        * format the output data.
-        */
-       vfprintf( file, fmt, vl );
-}
-
-/*
- * The primary logging routine.         Takes the subsystem being logged from, the
- * level of the log output and the format and data.  Send this on to the
- * internal routine with the print file, if any.
- */
-void lutil_log( const char *subsys, int level, const char *fmt, ... )
-{
-       FILE* outfile = NULL;
-       va_list vl;
-       va_start( vl, fmt );
-       ber_get_option( NULL, LBER_OPT_LOG_PRINT_FILE, &outfile );
-       lutil_log_int( outfile, subsys, level, fmt, vl );
-       va_end( vl );
-}
-
-void lutil_log_initialize(int argc, char **argv)
-{
-    int i;
-    /*
-     * Start by setting the hook for the libraries to use this logging
-     * routine.
-     */
-    ber_set_option( NULL, LBER_OPT_LOG_PROC, (void*)lutil_log_int );
-
-    if ( argc == 0 ) return;
-    /*
-     * Now go through the command line options to set the debugging
-     * levels
-     */
-    for( i = 0; i < argc; i++ )
-    {
-       char *next = argv[i];
-       if ( i < argc-1 && next[0] == '-' && next[1] == 'd' )
-       {
-           char subsys[64];
-           int level;
-           char *optarg = argv[i+1];
-           char *index = strchr( optarg, '=' );
-           if ( index != NULL )
-           {
-               *index = 0;
-               strcpy ( subsys, optarg );
-               level = atoi( index+1 );
-               if ( level <= 0 ) level = lutil_mnem2level( index + 1 );
-               lutil_set_debug_level( subsys, level );
-               *index = '=';
-           }
-           else
-           {
-               global_level = atoi( optarg );
-               /* 
-                * if a negative number was used, make the global level the
-                * maximum sane level.
-                */
-               if ( global_level < 0 ) global_level = 65535;
-           }
-       }
-    }
-}
-
-void (lutil_debug)( int debug, int level, const char *fmt, ... )
-{
-       char buffer[4096];
-       va_list vl;
-
-       if ( !(level & debug ) )
-               return;
-
-#ifdef HAVE_WINSOCK
-       if( log_file == NULL ) {
-               log_file = fopen( LDAP_RUNDIR LDAP_DIRSEP "openldap.log", "w" );
-
-               if ( log_file == NULL )
-                       log_file = fopen( "openldap.log", "w" );
-
-               if ( log_file == NULL )
-                       return;
-
-               ber_set_option( NULL, LBER_OPT_LOG_PRINT_FILE, log_file );
-       }
-#endif
-       va_start( vl, fmt );
-
-#ifdef HAVE_VSNPRINTF
-       vsnprintf( buffer, sizeof(buffer), fmt, vl );
-#else
-       vsprintf( buffer, fmt, vl );
-#endif
-       buffer[sizeof(buffer)-1] = '\0';
-
-       if( log_file != NULL ) {
-               fputs( buffer, log_file );
-               fflush( log_file );
-       }
-
-    fputs( buffer, stderr );
-       va_end( vl );
-}
diff --git a/libraries/liblutil/getopt.c b/libraries/liblutil/getopt.c
new file mode 100644 (file)
index 0000000..137944a
--- /dev/null
@@ -0,0 +1,126 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/*
+       getopt.c
+
+       modified public-domain AT&T getopt(3)
+       modified by Kurt Zeilenga for inclusion into OpenLDAP
+*/
+
+#include "portable.h"
+
+#ifndef HAVE_GETOPT
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "lutil.h"
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+int opterr = 1;
+int optind = 1;
+int optopt;
+char * optarg;
+
+#ifdef HAVE_EBCDIC
+extern int _trans_argv;
+#endif
+
+static void ERR (char * const argv[], const char * s, char c)
+{
+#ifdef DF_TRACE_DEBUG
+printf("DF_TRACE_DEBUG:        static void ERR () in getopt.c\n");
+#endif
+       if (opterr)
+       {
+               char *ptr, outbuf[4096];
+
+               ptr = lutil_strncopy(outbuf, argv[0], sizeof(outbuf) - 2);
+               ptr = lutil_strncopy(ptr, s, sizeof(outbuf)-2 -(ptr-outbuf));
+               *ptr++ = c;
+               *ptr++ = '\n';
+#ifdef HAVE_EBCDIC
+               __atoe_l(outbuf, ptr - outbuf);
+#endif
+               (void) write(STDERR_FILENO,outbuf,ptr - outbuf);
+       }
+}
+
+int getopt (int argc, char * const argv [], const char * opts)
+{
+       static int sp = 1, error = (int) '?';
+       static char sw = '-', eos = '\0', arg = ':';
+       register char c, * cp;
+
+#ifdef DF_TRACE_DEBUG
+printf("DF_TRACE_DEBUG:        int getopt () in getopt.c\n");
+#endif
+
+#ifdef HAVE_EBCDIC
+       if (_trans_argv) {
+               int i;
+               for (i=0; i<argc; i++) __etoa(argv[i]);
+               _trans_argv = 0;
+       }
+#endif
+       if (sp == 1)
+       {
+               if (optind >= argc || argv[optind][0] != sw
+               || argv[optind][1] == eos)
+                       return EOF;
+               else if (strcmp(argv[optind],"--") == 0)
+               {
+                       optind++;
+                       return EOF;
+               }
+       }
+       c = argv[optind][sp];
+       optopt = (int) c;
+       if (c == arg || (cp = strchr(opts,c)) == NULL)
+       {
+               ERR(argv,": illegal option--",c);
+               if (argv[optind][++sp] == eos)
+               {
+                       optind++;
+                       sp = 1;
+               }
+               return error;
+       }
+       else if (*++cp == arg)
+       {
+               if (argv[optind][sp + 1] != eos)
+                       optarg = &argv[optind++][sp + 1];
+               else if (++optind >= argc)
+               {
+                       ERR(argv,": option requires an argument--",c);
+                       sp = 1;
+                       return error;
+               }
+               else
+                       optarg = argv[optind++];
+               sp = 1;
+       }
+       else
+       {
+               if (argv[optind][++sp] == eos)
+               {
+                       sp = 1;
+                       optind++;
+               }
+               optarg = NULL;
+       }
+       return (int) c;
+}
+#endif /* HAVE_GETOPT */
diff --git a/libraries/liblutil/liblutil.dsp b/libraries/liblutil/liblutil.dsp
new file mode 100644 (file)
index 0000000..436a698
--- /dev/null
@@ -0,0 +1,297 @@
+# Microsoft Developer Studio Project File - Name="liblutil" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=liblutil - Win32 Single Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "liblutil.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "liblutil.mak" CFG="liblutil - Win32 Single Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "liblutil - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "liblutil - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "liblutil - Win32 Single Debug" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE "liblutil - Win32 Single Release" (based on\
+ "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF  "$(CFG)" == "liblutil - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\Release"
+# PROP Intermediate_Dir "..\..\Release\liblutil"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\Release\olutil32.lib"
+
+!ELSEIF  "$(CFG)" == "liblutil - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\Debug"
+# PROP Intermediate_Dir "..\..\Debug\liblutil"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\Debug\olutil32.lib"
+
+!ELSEIF  "$(CFG)" == "liblutil - Win32 Single Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "liblutil"
+# PROP BASE Intermediate_Dir "liblutil"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "..\..\SDebug"
+# PROP Intermediate_Dir "..\..\SDebug\liblutil"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /MTd /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /Z7 /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\Debug\olutil32.lib"
+# ADD LIB32 /nologo /out:"..\..\SDebug\olutil32.lib"
+
+!ELSEIF  "$(CFG)" == "liblutil - Win32 Single Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "libluti0"
+# PROP BASE Intermediate_Dir "libluti0"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "..\..\SRelease"
+# PROP Intermediate_Dir "..\..\SRelease\liblutil"
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"..\Release\olutil32.lib"
+# ADD LIB32 /nologo /out:"..\..\SRelease\olutil32.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "liblutil - Win32 Release"
+# Name "liblutil - Win32 Debug"
+# Name "liblutil - Win32 Single Debug"
+# Name "liblutil - Win32 Single Release"
+# Begin Source File
+
+SOURCE=.\authpasswd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\ac\bytes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\csn.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\entropy.c
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\getopt-compat.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\getopt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\getpass.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\ldap_cdefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\lockf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil_hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil_ldap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil_lockf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil_md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\lutil_sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ntservice.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\passwd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\portable.h
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\queue-compat.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\sasl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\slapdmsg.mc
+
+!IF  "$(CFG)" == "liblutil - Win32 Release"
+
+# Begin Custom Build - Building slapd message file
+IntDir=.\..\..\Release\liblutil
+InputPath=.\slapdmsg.mc
+
+"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+       mkdir $(IntDir) 
+       mc -v slapdmsg.mc -r $(IntDir) 
+       rc /v /r $(IntDir)\slapdmsg.rc 
+       
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "liblutil - Win32 Debug"
+
+# Begin Custom Build - Building slapd message file
+IntDir=.\..\..\Debug\liblutil
+InputPath=.\slapdmsg.mc
+
+"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+       mkdir $(IntDir) 
+       mc -v slapdmsg.mc -r $(IntDir) 
+       rc /v /r $(IntDir)\slapdmsg.rc 
+       
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "liblutil - Win32 Single Debug"
+
+# Begin Custom Build - Building slapd message file
+IntDir=.\..\..\SDebug\liblutil
+InputPath=.\slapdmsg.mc
+
+"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+       mkdir $(IntDir) 
+       mc -v slapdmsg.mc -r $(IntDir) 
+       rc /v /r $(IntDir)\slapdmsg.rc 
+       
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "liblutil - Win32 Single Release"
+
+# Begin Custom Build - Building slapd message file
+IntDir=.\..\..\SRelease\liblutil
+InputPath=.\slapdmsg.mc
+
+"slapdmsg.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+       mkdir $(IntDir) 
+       mc -v slapdmsg.mc -r $(IntDir) 
+       rc /v /r $(IntDir)\slapdmsg.rc 
+       
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sockpair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\uuid.c
+# End Source File
+# End Target
+# End Project
diff --git a/libraries/liblutil/ntservice.c b/libraries/liblutil/ntservice.c
new file mode 100644 (file)
index 0000000..9bd27b7
--- /dev/null
@@ -0,0 +1,513 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+/*
+ * NT Service manager utilities for OpenLDAP services
+ *     these should NOT be slapd specific, but are
+ */
+
+#include "portable.h"
+
+#ifdef HAVE_NT_SERVICE_MANAGER
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+
+#include <stdio.h>
+
+#include <windows.h>
+#include <winsvc.h>
+
+#include <ldap.h>
+
+/*
+ * The whole debug implementation is a bit of a hack.
+ * We have to define this LDAP_SLAPD_V macro here since the slap.h
+ * header file isn't included (and really shouldn't be).
+ * TODO: re-implement debug functions so that the debug level can
+ * be passed around instead of having to count on the existence of
+ * ldap_debug, slap_debug, etc.
+ */
+#define ldap_debug slap_debug
+LDAP_SLAPD_V (int) slap_debug;
+
+#include "ldap_log.h"
+#include "ldap_pvt_thread.h"
+
+
+#include "ldap_defaults.h"
+
+#include "slapdmsg.h"
+
+#define SCM_NOTIFICATION_INTERVAL      5000
+#define THIRTY_SECONDS                         (30 * 1000)
+
+int      is_NT_Service = 1;    /* assume this is an NT service until determined that */
+                                                       /* startup was from the command line */
+
+SERVICE_STATUS                 SLAPDServiceStatus;
+SERVICE_STATUS_HANDLE  hSLAPDServiceStatus;
+
+ldap_pvt_thread_cond_t started_event,          stopped_event;
+ldap_pvt_thread_t              start_status_tid,       stop_status_tid;
+
+void (*stopfunc)(int);
+
+static char *GetLastErrorString( void );
+
+int srv_install(LPCTSTR lpszServiceName, LPCTSTR lpszDisplayName,
+               LPCTSTR lpszBinaryPathName, BOOL auto_start)
+{
+       HKEY            hKey;
+       DWORD           dwValue, dwDisposition;
+       SC_HANDLE       schSCManager, schService;
+
+       fprintf( stderr, "The install path is %s.\n", lpszBinaryPathName );
+       if ((schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE ) ) != NULL )
+       {
+               if ((schService = CreateService( 
+                                                       schSCManager, 
+                                                       lpszServiceName, 
+                                                       lpszDisplayName, 
+                                                       SERVICE_ALL_ACCESS, 
+                                                       SERVICE_WIN32_OWN_PROCESS, 
+                                                       auto_start ? SERVICE_AUTO_START : SERVICE_DEMAND_START, 
+                                                       SERVICE_ERROR_NORMAL, 
+                                                       lpszBinaryPathName, 
+                                                       NULL, NULL, NULL, NULL, NULL)) != NULL)
+               {
+                       char regpath[132];
+                       CloseServiceHandle(schService);
+                       CloseServiceHandle(schSCManager);
+
+                       snprintf( regpath, sizeof regpath,
+                               "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
+                               lpszServiceName );
+                       /* Create the registry key for event logging to the Windows NT event log. */
+                       if ( RegCreateKeyEx(HKEY_LOCAL_MACHINE, 
+                               regpath, 0, 
+                               "REG_SZ", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, 
+                               &dwDisposition) != ERROR_SUCCESS)
+                       {
+                               fprintf( stderr, "RegCreateKeyEx() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() );
+                               RegCloseKey(hKey);
+                               return(0);
+                       }
+                       if ( RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ, lpszBinaryPathName, strlen(lpszBinaryPathName) + 1) != ERROR_SUCCESS)
+                       {
+                               fprintf( stderr, "RegSetValueEx(EventMessageFile) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() );
+                               RegCloseKey(hKey);
+                               return(0);
+                       }
+
+                       dwValue = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
+                       if ( RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD)) != ERROR_SUCCESS) 
+                       {
+                               fprintf( stderr, "RegCreateKeyEx(TypesSupported) failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() );
+                               RegCloseKey(hKey);
+                               return(0);
+                       }
+                       RegCloseKey(hKey);
+                       return(1);
+               }
+               else
+               {
+                       fprintf( stderr, "CreateService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() );
+                       CloseServiceHandle(schSCManager);
+                       return(0);
+               }
+       }
+       else
+               fprintf( stderr, "OpenSCManager() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() );
+       return(0);
+}
+
+
+int srv_remove(LPCTSTR lpszServiceName, LPCTSTR lpszBinaryPathName)
+{
+       SC_HANDLE schSCManager, schService;
+
+       fprintf( stderr, "The installed path is %s.\n", lpszBinaryPathName );
+       if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE)) != NULL ) 
+       {
+               if ((schService = OpenService(schSCManager, lpszServiceName, DELETE)) != NULL) 
+               {
+                       if ( DeleteService(schService) == TRUE) 
+                       {
+                               CloseServiceHandle(schService);
+                               CloseServiceHandle(schSCManager);
+                               return(1);
+                       } else {
+                               fprintf( stderr, "DeleteService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() );
+                               fprintf( stderr, "The %s service has not been removed.\n", lpszBinaryPathName);
+                               CloseServiceHandle(schService);
+                               CloseServiceHandle(schSCManager);
+                               return(0);
+                       }
+               } else {
+                       fprintf( stderr, "OpenService() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() );
+                       CloseServiceHandle(schSCManager);
+                       return(0);
+               }
+       }
+       else
+               fprintf( stderr, "OpenSCManager() failed. GetLastError=%lu (%s)\n", GetLastError(), GetLastErrorString() );
+       return(0);
+}
+
+
+DWORD
+svc_installed (LPTSTR lpszServiceName, LPTSTR lpszBinaryPathName)
+{
+       char buf[256];
+       HKEY key;
+       DWORD rc;
+       DWORD type;
+       long len;
+
+       strcpy(buf, TEXT("SYSTEM\\CurrentControlSet\\Services\\"));
+       strcat(buf, lpszServiceName);
+       if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
+               return(-1);
+
+       rc = 0;
+       if (lpszBinaryPathName) {
+               len = sizeof(buf);
+               if (RegQueryValueEx(key, "ImagePath", NULL, &type, buf, &len) == ERROR_SUCCESS) {
+                       if (strcmp(lpszBinaryPathName, buf))
+                               rc = -1;
+               }
+       }
+       RegCloseKey(key);
+       return(rc);
+}
+
+
+DWORD
+svc_running (LPTSTR lpszServiceName)
+{
+       SC_HANDLE service;
+       SC_HANDLE scm;
+       DWORD rc;
+       SERVICE_STATUS ss;
+
+       if (!(scm = OpenSCManager(NULL, NULL, GENERIC_READ)))
+               return(GetLastError());
+
+       rc = 1;
+       service = OpenService(scm, lpszServiceName, SERVICE_QUERY_STATUS);
+       if (service) {
+               if (!QueryServiceStatus(service, &ss))
+                       rc = GetLastError();
+               else if (ss.dwCurrentState != SERVICE_STOPPED)
+                       rc = 0;
+               CloseServiceHandle(service);
+       }
+       CloseServiceHandle(scm);
+       return(rc);
+}
+
+
+static void *start_status_routine( void *ptr )
+{
+       DWORD   wait_result;
+       int             done = 0;
+
+       while ( !done )
+       {
+               wait_result = WaitForSingleObject( started_event, SCM_NOTIFICATION_INTERVAL );
+               switch ( wait_result )
+               {
+                       case WAIT_ABANDONED:
+                       case WAIT_OBJECT_0:
+                               /* the object that we were waiting for has been destroyed (ABANDONED) or
+                                * signalled (TIMEOUT_0). We can assume that the startup process is
+                                * complete and tell the Service Control Manager that we are now runnng */
+                               SLAPDServiceStatus.dwCurrentState       = SERVICE_RUNNING;
+                               SLAPDServiceStatus.dwWin32ExitCode      = NO_ERROR;
+                               SLAPDServiceStatus.dwCheckPoint++;
+                               SLAPDServiceStatus.dwWaitHint           = 1000;
+                               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+                               done = 1;
+                               break;
+                       case WAIT_TIMEOUT:
+                               /* We've waited for the required time, so send an update to the Service Control 
+                                * Manager saying to wait again. */
+                               SLAPDServiceStatus.dwCheckPoint++;
+                               SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2;
+                               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+                               break;
+                       case WAIT_FAILED:
+                               /* theres been some problem with WaitForSingleObject so tell the Service
+                                * Control Manager to wait 30 seconds before deploying its assasin and 
+                                * then leave the thread. */
+                               SLAPDServiceStatus.dwCheckPoint++;
+                               SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+                               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+                               done = 1;
+                               break;
+               }
+       }
+       ldap_pvt_thread_exit(NULL);
+       return NULL;
+}
+
+
+
+static void *stop_status_routine( void *ptr )
+{
+       DWORD   wait_result;
+       int             done = 0;
+
+       while ( !done )
+       {
+               wait_result = WaitForSingleObject( stopped_event, SCM_NOTIFICATION_INTERVAL );
+               switch ( wait_result )
+               {
+                       case WAIT_ABANDONED:
+                       case WAIT_OBJECT_0:
+                               /* the object that we were waiting for has been destroyed (ABANDONED) or
+                                * signalled (TIMEOUT_0). The shutting down process is therefore complete 
+                                * and the final SERVICE_STOPPED message will be sent to the service control
+                                * manager prior to the process terminating. */
+                               done = 1;
+                               break;
+                       case WAIT_TIMEOUT:
+                               /* We've waited for the required time, so send an update to the Service Control 
+                                * Manager saying to wait again. */
+                               SLAPDServiceStatus.dwCheckPoint++;
+                               SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL * 2;
+                               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+                               break;
+                       case WAIT_FAILED:
+                               /* theres been some problem with WaitForSingleObject so tell the Service
+                                * Control Manager to wait 30 seconds before deploying its assasin and 
+                                * then leave the thread. */
+                               SLAPDServiceStatus.dwCheckPoint++;
+                               SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+                               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+                               done = 1;
+                               break;
+               }
+       }
+       ldap_pvt_thread_exit(NULL);
+       return NULL;
+}
+
+
+
+void WINAPI SLAPDServiceCtrlHandler( IN DWORD Opcode)
+{
+       switch (Opcode)
+       {
+       case SERVICE_CONTROL_STOP:
+       case SERVICE_CONTROL_SHUTDOWN:
+
+               Debug( LDAP_DEBUG_TRACE, "Service Shutdown ordered\n", 0, 0, 0 );
+               SLAPDServiceStatus.dwCurrentState       = SERVICE_STOP_PENDING;
+               SLAPDServiceStatus.dwCheckPoint++;
+               SLAPDServiceStatus.dwWaitHint           = SCM_NOTIFICATION_INTERVAL * 2;
+               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+
+               ldap_pvt_thread_cond_init( &stopped_event );
+               if ( stopped_event == NULL )
+               {
+                       /* the event was not created. We will ask the service control manager for 30
+                        * seconds to shutdown */
+                       SLAPDServiceStatus.dwCheckPoint++;
+                       SLAPDServiceStatus.dwWaitHint           = THIRTY_SECONDS;
+                       SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+               }
+               else
+               {
+                       /* start a thread to report the progress to the service control manager 
+                        * until the stopped_event is fired. */
+                       if ( ldap_pvt_thread_create( &stop_status_tid, 0, stop_status_routine, NULL ) == 0 )
+                       {
+                               
+                       }
+                       else {
+                               /* failed to create the thread that tells the Service Control Manager that the
+                                * service stopping is proceeding. 
+                                * tell the Service Control Manager to wait another 30 seconds before deploying its
+                                * assasin.  */
+                               SLAPDServiceStatus.dwCheckPoint++;
+                               SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+                               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+                       }
+               }
+               stopfunc( -1 );
+               break;
+
+       case SERVICE_CONTROL_INTERROGATE:
+               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+               break;
+       }
+       return;
+}
+
+void *getRegParam( char *svc, char *value )
+{
+       HKEY hkey;
+       char path[255];
+       DWORD vType;
+       static char vValue[1024];
+       DWORD valLen = sizeof( vValue );
+
+       if ( svc != NULL )
+               snprintf ( path, sizeof path, "SOFTWARE\\%s", svc );
+       else
+               snprintf ( path, sizeof path, "SOFTWARE\\OpenLDAP\\Parameters" );
+       
+       if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &hkey ) != ERROR_SUCCESS )
+       {
+               /*Debug( LDAP_DEBUG_ANY, "RegOpenKeyEx() %s\n", GetLastErrorString(), 0, 0); */
+               return NULL;
+       }
+
+       if ( RegQueryValueEx( hkey, value, NULL, &vType, vValue, &valLen ) != ERROR_SUCCESS )
+       {
+               /*Debug( LDAP_DEBUG_ANY, "RegQueryValueEx() %s\n", GetLastErrorString(), 0, 0 );*/
+               RegCloseKey( hkey );
+               return NULL;
+       }
+       RegCloseKey( hkey );
+       
+       switch ( vType )
+       {
+       case REG_BINARY:
+       case REG_DWORD:
+               return (void*)&vValue;
+       case REG_SZ:
+               return (void*)&vValue;
+       }
+       return (void*)NULL;
+}
+
+void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, char *urls )
+{
+       char *Inserts[5];
+       WORD i = 0, j;
+       HANDLE hEventLog;
+       
+       hEventLog = RegisterEventSource( NULL, svc );
+
+       Inserts[i] = (char *)malloc( 20 );
+       itoa( slap_debug, Inserts[i++], 10 );
+       Inserts[i++] = strdup( configfile );
+       Inserts[i++] = strdup( urls ? urls : "ldap:///" );
+       Inserts[i++] = strdup( is_NT_Service ? "svc" : "cmd" );
+
+       ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
+               MSG_SLAPD_STARTED, NULL, i, 0, (LPCSTR *) Inserts, NULL );
+
+       for ( j = 0; j < i; j++ )
+               ldap_memfree( Inserts[j] );
+       DeregisterEventSource( hEventLog );
+}
+
+
+
+void LogSlapdStoppedEvent( char *svc )
+{
+       HANDLE hEventLog;
+       
+       hEventLog = RegisterEventSource( NULL, svc );
+       ReportEvent( hEventLog, EVENTLOG_INFORMATION_TYPE, 0,
+               MSG_SLAPD_STOPPED, NULL, 0, 0, NULL, NULL );
+       DeregisterEventSource( hEventLog );
+}
+
+
+void CommenceStartupProcessing( LPCTSTR lpszServiceName,
+                                                          void (*stopper)(int) )
+{
+       hSLAPDServiceStatus = RegisterServiceCtrlHandler( lpszServiceName, (LPHANDLER_FUNCTION)SLAPDServiceCtrlHandler);
+
+       stopfunc = stopper;
+
+       /* initialize the Service Status structure */
+       SLAPDServiceStatus.dwServiceType                                = SERVICE_WIN32_OWN_PROCESS;
+       SLAPDServiceStatus.dwCurrentState                               = SERVICE_START_PENDING;
+       SLAPDServiceStatus.dwControlsAccepted                   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+       SLAPDServiceStatus.dwWin32ExitCode                              = NO_ERROR;
+       SLAPDServiceStatus.dwServiceSpecificExitCode    = 0;
+       SLAPDServiceStatus.dwCheckPoint                                 = 1;
+       SLAPDServiceStatus.dwWaitHint                                   = SCM_NOTIFICATION_INTERVAL * 2;
+
+       SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+
+       /* start up a thread to keep sending SERVICE_START_PENDING to the Service Control Manager
+        * until the slapd listener is completed and listening. Only then should we send 
+        * SERVICE_RUNNING to the Service Control Manager. */
+       ldap_pvt_thread_cond_init( &started_event );
+       if ( started_event == NULL)
+       {
+               /* failed to create the event to determine when the startup process is complete so
+                * tell the Service Control Manager to wait another 30 seconds before deploying its
+                * assasin  */
+               SLAPDServiceStatus.dwCheckPoint++;
+               SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+       }
+       else
+       {
+               /* start a thread to report the progress to the service control manager 
+                * until the started_event is fired.  */
+               if ( ldap_pvt_thread_create( &start_status_tid, 0, start_status_routine, NULL ) == 0 )
+               {
+                       
+               }
+               else {
+                       /* failed to create the thread that tells the Service Control Manager that the
+                        * service startup is proceeding. 
+                        * tell the Service Control Manager to wait another 30 seconds before deploying its
+                        * assasin.  */
+                       SLAPDServiceStatus.dwCheckPoint++;
+                       SLAPDServiceStatus.dwWaitHint = THIRTY_SECONDS;
+                       SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+               }
+       }
+}
+
+void ReportSlapdShutdownComplete(  )
+{
+       if ( is_NT_Service )
+       {
+               /* stop sending SERVICE_STOP_PENDING messages to the Service Control Manager */
+               ldap_pvt_thread_cond_signal( &stopped_event );
+               ldap_pvt_thread_cond_destroy( &stopped_event );
+
+               /* wait for the thread sending the SERVICE_STOP_PENDING messages to the Service Control Manager to die.
+                * if the wait fails then put ourselves to sleep for half the Service Control Manager update interval */
+               if (ldap_pvt_thread_join( stop_status_tid, (void *) NULL ) == -1)
+                       ldap_pvt_thread_sleep( SCM_NOTIFICATION_INTERVAL / 2 );
+
+               SLAPDServiceStatus.dwCurrentState = SERVICE_STOPPED;
+               SLAPDServiceStatus.dwCheckPoint++;
+               SLAPDServiceStatus.dwWaitHint = SCM_NOTIFICATION_INTERVAL;
+               SetServiceStatus(hSLAPDServiceStatus, &SLAPDServiceStatus);
+       }
+}
+
+static char *GetErrorString( int err )
+{
+       static char msgBuf[1024];
+
+       FormatMessage(
+               FORMAT_MESSAGE_FROM_SYSTEM,
+               NULL,
+               err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+               msgBuf, 1024, NULL );
+
+       return msgBuf;
+}
+
+static char *GetLastErrorString( void )
+{
+       return GetErrorString( GetLastError() );
+}
+#endif
diff --git a/libraries/liblutil/sasl.c b/libraries/liblutil/sasl.c
new file mode 100644 (file)
index 0000000..a1308a8
--- /dev/null
@@ -0,0 +1,206 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 2000-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#ifdef HAVE_CYRUS_SASL
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#ifdef HAVE_SASL_SASL_H
+#include <sasl/sasl.h>
+#else
+#include <sasl.h>
+#endif
+
+#include <ldap.h>
+#include "lutil_ldap.h"
+
+
+typedef struct lutil_sasl_defaults_s {
+       char *mech;
+       char *realm;
+       char *authcid;
+       char *passwd;
+       char *authzid;
+} lutilSASLdefaults;
+
+
+void *
+lutil_sasl_defaults(
+       LDAP *ld,
+       char *mech,
+       char *realm,
+       char *authcid,
+       char *passwd,
+       char *authzid )
+{
+       lutilSASLdefaults *defaults;
+       
+       defaults = ber_memalloc( sizeof( lutilSASLdefaults ) );
+
+       if( defaults == NULL ) return NULL;
+
+       defaults->mech = mech;
+       defaults->realm = realm;
+       defaults->authcid = authcid;
+       defaults->passwd = passwd;
+       defaults->authzid = authzid;
+
+       if( defaults->mech == NULL ) {
+               ldap_get_option( ld, LDAP_OPT_X_SASL_MECH, &defaults->mech );
+       }
+       if( defaults->realm == NULL ) {
+               ldap_get_option( ld, LDAP_OPT_X_SASL_REALM, &defaults->realm );
+       }
+       if( defaults->authcid == NULL ) {
+               ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHCID, &defaults->authcid );
+       }
+       if( defaults->authzid == NULL ) {
+               ldap_get_option( ld, LDAP_OPT_X_SASL_AUTHZID, &defaults->authzid );
+       }
+
+       return defaults;
+}
+
+static int interaction(
+       unsigned flags,
+       sasl_interact_t *interact,
+       lutilSASLdefaults *defaults )
+{
+       const char *dflt = interact->defresult;
+       char input[1024];
+
+       int noecho=0;
+       int challenge=0;
+
+       switch( interact->id ) {
+       case SASL_CB_GETREALM:
+               if( defaults ) dflt = defaults->realm;
+               break;
+       case SASL_CB_AUTHNAME:
+               if( defaults ) dflt = defaults->authcid;
+               break;
+       case SASL_CB_PASS:
+               if( defaults ) dflt = defaults->passwd;
+               noecho = 1;
+               break;
+       case SASL_CB_USER:
+               if( defaults ) dflt = defaults->authzid;
+               break;
+       case SASL_CB_NOECHOPROMPT:
+               noecho = 1;
+               challenge = 1;
+               break;
+       case SASL_CB_ECHOPROMPT:
+               challenge = 1;
+               break;
+       }
+
+       if( dflt && !*dflt ) dflt = NULL;
+
+       if( flags != LDAP_SASL_INTERACTIVE &&
+               ( dflt || interact->id == SASL_CB_USER ) )
+       {
+               goto use_default;
+       }
+
+       if( flags == LDAP_SASL_QUIET ) {
+               /* don't prompt */
+               return LDAP_OTHER;
+       }
+
+       if( challenge ) {
+               if( interact->challenge ) {
+                       fprintf( stderr, "Challenge: %s\n", interact->challenge );
+               }
+       }
+
+       if( dflt ) {
+               fprintf( stderr, "Default: %s\n", dflt );
+       }
+
+       snprintf( input, sizeof input, "%s: ",
+               interact->prompt ? interact->prompt : "Interact" );
+
+       if( noecho ) {
+               interact->result = (char *) getpassphrase( input );
+               interact->len = interact->result
+                       ? strlen( interact->result ) : 0;
+
+       } else {
+               /* prompt user */
+               fputs( input, stderr );
+
+               /* get input */
+               interact->result = fgets( input, sizeof(input), stdin );
+
+               if( interact->result == NULL ) {
+                       interact->len = 0;
+                       return LDAP_UNAVAILABLE;
+               }
+
+               /* len of input */
+               interact->len = strlen(input); 
+
+               if( interact->len > 0 && input[interact->len - 1] == '\n' ) {
+                       /* input includes '\n', trim it */
+                       interact->len--;
+                       input[interact->len] = '\0';
+               }
+       }
+
+
+       if( interact->len > 0 ) {
+               /* duplicate */
+               char *p = (char *)interact->result;
+               interact->result = strdup( p );
+
+               /* zap */
+               memset( p, '\0', interact->len );
+
+       } else {
+use_default:
+               /* input must be empty */
+               interact->result = strdup( (dflt && *dflt) ? dflt : "" );
+               interact->len = interact->result
+                       ? strlen( interact->result ) : 0;
+       }
+
+       if( defaults && defaults->passwd && interact->id == SASL_CB_PASS ) {
+               /* zap password after first use */
+               memset( defaults->passwd, '\0', strlen(defaults->passwd) );
+               defaults->passwd = NULL;
+       }
+
+       return LDAP_SUCCESS;
+}
+
+int lutil_sasl_interact(
+       LDAP *ld,
+       unsigned flags,
+       void *defaults,
+       void *in )
+{
+       sasl_interact_t *interact = in;
+
+       if( flags == LDAP_SASL_INTERACTIVE ) {
+               fputs( "SASL Interaction\n", stderr );
+       }
+
+       while( interact->id != SASL_CB_LIST_END ) {
+               int rc = interaction( flags, interact, defaults );
+
+               if( rc )  return rc;
+               interact++;
+       }
+       
+       return LDAP_SUCCESS;
+}
+#endif
diff --git a/libraries/liblutil/stdio.c b/libraries/liblutil/stdio.c
new file mode 100644 (file)
index 0000000..adf4187
--- /dev/null
@@ -0,0 +1,228 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdarg.h>
+#include <ac/string.h>
+
+#include <lutil.h>
+
+#ifndef HAVE_VSNPRINTF
+/* Write at most n characters to the buffer in str, return the
+ * number of chars written or -1 if the buffer would have been
+ * overflowed.
+ *
+ * This is portable to any POSIX-compliant system. We use pipe()
+ * to create a valid file descriptor, and then fdopen() it to get
+ * a valid FILE pointer. The user's buffer and size are assigned
+ * to the FILE pointer using setvbuf. Then we close the read side
+ * of the pipe to invalidate the descriptor.
+ *
+ * If the write arguments all fit into size n, the write will
+ * return successfully. If the write is too large, the stdio
+ * buffer will need to be flushed to the underlying file descriptor.
+ * The flush will fail because it is attempting to write to a
+ * broken pipe, and the write will be terminated.
+ * -- hyc, 2002-07-19
+ */
+#ifndef HAVE_EBCDIC
+/* This emulation uses vfprintf; on OS/390 we're also emulating
+ * that function so it's more efficient just to have a separate
+ * version of vsnprintf there.
+ */
+#include <ac/signal.h>
+int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
+{
+       int fds[2], res;
+       FILE *f;
+       RETSIGTYPE (*sig)();
+
+       if (pipe( fds )) return -1;
+
+       f = fdopen( fds[1], "w" );
+       if ( !f ) {
+               close( fds[1] );
+               close( fds[0] );
+               return -1;
+       }
+       setvbuf( f, str, _IOFBF, n );
+       sig = signal( SIGPIPE, SIG_IGN );
+       close( fds[0] );
+
+       res = vfprintf( f, fmt, ap );
+
+       fclose( f );
+       signal( SIGPIPE, sig );
+       return res;
+}
+#endif
+
+int snprintf( char *str, size_t n, const char *fmt, ... )
+{
+       va_list ap;
+       int res;
+
+       va_start( ap, fmt );
+       res = vsnprintf( str, n, fmt, ap );
+       va_end( ap );
+       return res;
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#ifdef HAVE_EBCDIC
+/* stdio replacements with ASCII/EBCDIC translation for OS/390.
+ * The OS/390 port depends on the CONVLIT compiler option being
+ * used to force character and string literals to be compiled in
+ * ISO8859-1, and the __LIBASCII cpp symbol to be defined to use the
+ * OS/390 ASCII-compatibility library. This library only supplies
+ * an ASCII version of sprintf, so other needed functions are
+ * provided here.
+ *
+ * All of the internal character manipulation is done in ASCII,
+ * but file I/O is EBCDIC, so we catch any stdio reading/writing
+ * of files here and do the translations.
+ */
+
+#undef fputs
+#undef fgets
+
+char *lutil_fgets( char *s, int n, FILE *fp )
+{
+       s = (char *)fgets( s, n, fp );
+       if ( s ) __etoa( s );
+       return s;
+}
+
+int lutil_fputs( const char *str, FILE *fp )
+{
+       char buf[8192];
+
+       strncpy( buf, str, sizeof(buf) );
+       __atoe( buf );
+       return fputs( buf, fp );
+}
+
+/* The __LIBASCII doesn't include a working vsprintf, so we make do
+ * using just sprintf. This is a very simplistic parser that looks for
+ * format strings and uses sprintf to process them one at a time.
+ * Literal text is just copied straight to the destination.
+ * The result is appended to the destination string. The parser
+ * recognizes field-width specifiers and the 'l' qualifier; it
+ * may need to be extended to recognize other qualifiers but so
+ * far this seems to be enough.
+ */
+int vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
+{
+       char *ptr, *pct, *s2, *f2, *end;
+       char fm2[64];
+       int len, rem;
+
+       ptr = (char *)fmt;
+       s2 = str;
+       fm2[0] = '%';
+       if (n)
+               end = str + n;
+       else
+               end = NULL;
+
+       for (pct = strchr(ptr, '%'); pct; pct = strchr(ptr, '%')) {
+               len = pct-ptr;
+               if (end) {
+                       rem = end-s2;
+                       if (rem < 1) return -1;
+                       if (rem < len) len = rem;
+               }
+               s2 = lutil_strncopy( s2, ptr, len );
+               /* Did we cheat the length above? If so, bail out */
+               if (len < pct-ptr) return -1;
+               for (pct++, f2 = fm2+1; isdigit(*pct);) *f2++ = *pct++;
+               if (*pct == 'l') *f2++ = *pct++;
+               if (*pct == '%') *s2++ = '%';
+               else {
+                       *f2++ = *pct;
+                       *f2 = '\0';
+                       if (*pct == 's') {
+                               char *ss = va_arg(ap, char *);
+                               /* Attempt to limit sprintf output. This
+                                * may be thrown off if field widths were
+                                * specified for this string.
+                                *
+                                * If it looks like the string is too
+                                * long for the remaining buffer, bypass
+                                * sprintf and just copy what fits, then
+                                * quit.
+                                */
+                               if (end && strlen(ss) > (rem=end-s2)) {
+                                       strncpy(s2, ss, rem);
+                                       return -1;
+                               } else {
+                                       s2 += sprintf(s2, fm2, ss);
+                               }
+                       } else
+                               s2 += sprintf(s2, fm2, va_arg(ap, int));
+               }
+               ptr = pct + 1;
+       }
+       if (end) {
+               rem = end-s2;
+               if (rem > 0) {
+                       len = strlen(ptr);
+                       s2 = lutil_strncopy( s2, ptr, rem );
+                       rem -= len;
+               }
+               if (rem < 0) return -1;
+       } else {
+               s2 = lutil_strcopy( s2, ptr );
+       }
+       return s2 - str;
+}
+
+int lutil_vsprintf( char *str, const char *fmt, va_list ap )
+{
+       return vsnprintf( str, 0, fmt, ap );
+}
+
+/* The fixed buffer size here is a problem, we don't know how
+ * to flush the buffer and keep printing if the msg is too big. 
+ * Hopefully we never try to write something bigger than this
+ * in a log msg...
+ */
+int lutil_vfprintf( FILE *fp, const char *fmt, va_list ap )
+{
+       char buf[8192];
+       int res;
+
+       vsnprintf( buf, sizeof(buf), fmt, ap );
+       __atoe( buf );
+       res = fputs( buf, fp );
+       if (res == EOF) res = -1;
+       return res;
+}
+
+int lutil_printf( const char *fmt, ... )
+{
+       va_list ap;
+       int res;
+
+       va_start( ap, fmt );
+       res = lutil_vfprintf( stdout, fmt, ap );
+       va_end( ap );
+       return res;
+}
+
+int lutil_fprintf( FILE *fp, const char *fmt, ... )
+{
+       va_list ap;
+       int res;
+
+       va_start( ap, fmt );
+       res = lutil_vfprintf( fp, fmt, ap );
+       va_end( ap );
+       return res;
+}
+#endif
diff --git a/libraries/liblutil/utils.c b/libraries/liblutil/utils.c
new file mode 100644 (file)
index 0000000..973406f
--- /dev/null
@@ -0,0 +1,109 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/unistd.h>
+#include <ac/time.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <lutil.h>
+#include <ldap_defaults.h>
+
+#ifdef HAVE_EBCDIC
+int _trans_argv = 1;
+#endif
+
+char* lutil_progname( const char* name, int argc, char *argv[] )
+{
+       char *progname;
+
+       if(argc == 0) {
+               return (char *)name;
+       }
+
+#ifdef HAVE_EBCDIC
+       if (_trans_argv) {
+               int i;
+               for (i=0; i<argc; i++) __etoa(argv[i]);
+               _trans_argv = 0;
+       }
+#endif
+       progname = strrchr ( argv[0], *LDAP_DIRSEP );
+       progname = progname ? &progname[1] : argv[0];
+
+       return progname;
+}
+
+size_t lutil_gentime( char *s, size_t max, const struct tm *tm )
+{
+       size_t ret;
+#ifdef HAVE_EBCDIC
+/* We've been compiling in ASCII so far, but we want EBCDIC now since
+ * strftime only understands EBCDIC input.
+ */
+#pragma convlit(suspend)
+#endif
+       ret = strftime( s, max, "%Y%m%d%H%M%SZ", tm );
+#ifdef HAVE_EBCDIC
+#pragma convlit(resume)
+       __etoa( s );
+#endif
+       return ret;
+}
+
+/* strcopy is like strcpy except it returns a pointer to the trailing NUL of
+ * the result string. This allows fast construction of catenated strings
+ * without the overhead of strlen/strcat.
+ */
+char *
+lutil_strcopy(
+       char *a,
+       const char *b
+)
+{
+       if (!a || !b)
+               return a;
+       
+       while ((*a++ = *b++)) ;
+       return a-1;
+}
+
+/* strncopy is like strcpy except it returns a pointer to the trailing NUL of
+ * the result string. This allows fast construction of catenated strings
+ * without the overhead of strlen/strcat.
+ */
+char *
+lutil_strncopy(
+       char *a,
+       const char *b,
+       size_t n
+)
+{
+       if (!a || !b || n == 0)
+               return a;
+       
+       while ((*a++ = *b++) && n-- > 0) ;
+       return a-1;
+}
+
+#ifndef HAVE_MKSTEMP
+int mkstemp( char * template )
+{
+#ifdef HAVE_MKTEMP
+       return open ( mktemp ( template ), O_RDWR|O_CREAT|O_EXCL, 0600 );
+#else
+       return -1;
+#endif
+}
+#endif
index 8db54af13711b89701804bb6fdcf5a214cf20012..19389dff45ffa80718476d90d4242bae0487310e 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <portable.h>
 
+#include <stdio.h>
+
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #endif
@@ -541,6 +543,7 @@ rewrite_xmap_apply(
                        break;
                }
 
+#ifdef HAVE_PW_GECOS
                if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) {
                        int l = strlen( pwd->pw_gecos );
                        
@@ -555,7 +558,9 @@ rewrite_xmap_apply(
                                break;
                        }
                        val->bv_len = l;
-               } else {
+               } else
+#endif /* HAVE_PW_GECOS */
+               {
                        val->bv_val = strdup( key->bv_val );
                        val->bv_len = key->bv_len;
                }
index bc83e0594e575a6a0cc61c4ce12ec07ef05e0452..42b0180ba38e7740c1db2a31270a71cbb956fcc4 100644 (file)
@@ -24,6 +24,8 @@
 
 #include <portable.h>
 
+#include <stdio.h>
+
 #include "rewrite-int.h"
 
 static int
diff --git a/libraries/librewrite/rewrite.c b/libraries/librewrite/rewrite.c
new file mode 100644 (file)
index 0000000..ac301b7
--- /dev/null
@@ -0,0 +1,144 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
+ * All rights reserved.
+ *
+ * Permission is granted to anyone to use this software for any purpose
+ * on any computer system, and to alter it and redistribute it, subject
+ * to the following restrictions:
+ *
+ * 1. The author is not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ *
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission.  Since few users ever read sources,
+ * credits should appear in the documentation.
+ *
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.  Since few users
+ * ever read sources, credits should appear in the documentation.
+ * 
+ * 4. This notice may not be removed or altered.
+ *
+ ******************************************************************************/
+
+#include <portable.h>
+
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/syslog.h>
+#include <ac/regex.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <stdio.h>
+
+#include <rewrite.h>
+
+int ldap_debug;
+int ldap_syslog;
+int ldap_syslog_level;
+
+char *
+apply( 
+               FILE *fin, 
+               const char *rewriteContext,
+               const char *arg
+)
+{
+       struct rewrite_info *info;
+       char *string, *sep, *result = NULL;
+       int rc;
+       void *cookie = &info;
+
+       info = rewrite_info_init(REWRITE_MODE_ERR);
+
+       if ( rewrite_read( fin, info ) != 0 ) {
+               exit( EXIT_FAILURE );
+       }
+
+       rewrite_param_set( info, "prog", "rewrite" );
+
+       rewrite_session_init( info, cookie );
+
+       string = strdup( arg );
+       for ( sep = strchr( rewriteContext, ',' );
+                       rewriteContext != NULL;
+                       rewriteContext = sep,
+                       sep ? sep = strchr( rewriteContext, ',' ) : NULL ) {
+               if ( sep != NULL ) {
+                       sep[ 0 ] = '\0';
+                       sep++;
+               }
+               /* rc = rewrite( info, rewriteContext, string, &result ); */
+               rc = rewrite_session( info, rewriteContext, string,
+                               cookie, &result );
+               
+               fprintf( stdout, "%s -> %s\n", string, 
+                               ( result ? result : "unwilling to perform" ) );
+               if ( result == NULL ) {
+                       break;
+               }
+               free( string );
+               string = result;
+       }
+
+       rewrite_session_delete( info, cookie );
+
+       return result;
+}
+
+int
+main( int argc, char *argv[] )
+{
+       FILE *fin = NULL;
+       char *rewriteContext = REWRITE_DEFAULT_CONTEXT;
+
+       while ( 1 ) {
+               int opt = getopt( argc, argv, "f:hr:" );
+
+               if ( opt == EOF ) {
+                       break;
+               }
+
+               switch ( opt ) {
+               case 'f':
+                       fin = fopen( optarg, "r" );
+                       if ( fin == NULL ) {
+                               fprintf( stderr, "unable to open file '%s'\n",
+                                               optarg );
+                               exit( EXIT_FAILURE );
+                       }
+                       break;
+                       
+               case 'h':
+                       fprintf( stderr, 
+       "usage: rewrite [options] string\n"
+       "\n"
+       "\t\t-f file\t\tconfiguration file\n"
+       "\t\t-r rule[s]\tlist of comma-separated rules\n"
+       "\n"
+       "\tsyntax:\n"
+       "\t\trewriteEngine\t{on|off}\n"
+       "\t\trewriteContext\tcontextName [alias aliasedContextName]\n"
+       "\t\trewriteRule\tpattern subst [flags]\n"
+       "\n" 
+                               );
+                       exit( EXIT_SUCCESS );
+                       
+               case 'r':
+                       rewriteContext = strdup( optarg );
+                       break;
+               }
+       }
+       
+       if ( optind >= argc ) {
+               return -1;
+       }
+
+       apply( ( fin ? fin : stdin ), rewriteContext, argv[ optind ] );
+
+       return 0;
+}
+