--- /dev/null
+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
--- /dev/null
+/* 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;
+}
--- /dev/null
+# $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
+
--- /dev/null
+# $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)
--- /dev/null
+# $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)
+
--- /dev/null
+/* $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 );
+}
/* 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.
* 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
* 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 */
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 */
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;
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 */
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 );
#endif
#include "lber-int.h"
+#include "ldap_log.h"
ber_slen_t
ber_read(
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",
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" );
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;
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 "
*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",
--- /dev/null
+/* $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 */
--- /dev/null
+# 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
--- /dev/null
+/* $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 */
+
/* 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
{
Datum dup;
+ ldbm_datum_init( 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 );
+
+ 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 )
/*****************************************************************
*****************************************************************/
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;
} 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
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 );
}
{
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 );
}
{
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 );
}
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 */
OBJS = ucdata.o ure.o urestubs.o ucstr.o
XLIB = $(LIBRARY)
+XLIBS = $(LDAP_LIBLUTIL_A)
PROGRAMS = ucgendat
LDAP_INCDIR= ../../include
#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;
#include "ldap_config.h"
#include <stdio.h>
+#include <ac/bytes.h>
#include <ac/stdlib.h>
#include <ac/string.h>
#include <ac/unistd.h>
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++;
/*
(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 '#'.
*/
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];
/*
* 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;
/*
* Write the header.
*/
- fwrite((char *) hdr, sizeof(unsigned short), 2, out);
+ fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
/*
* Write the byte count.
/*
* 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;
/*
* 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;
/*
* 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;
/*
* 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;
/*
* 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;
/*
* 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;
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;
--- /dev/null
+# $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
+
+++ /dev/null
-/* $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 );
-}
--- /dev/null
+/* $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 */
--- /dev/null
+# 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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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
#include <portable.h>
+#include <stdio.h>
+
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
break;
}
+#ifdef HAVE_PW_GECOS
if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) {
int l = strlen( pwd->pw_gecos );
break;
}
val->bv_len = l;
- } else {
+ } else
+#endif /* HAVE_PW_GECOS */
+ {
val->bv_val = strdup( key->bv_val );
val->bv_len = key->bv_len;
}
#include <portable.h>
+#include <stdio.h>
+
#include "rewrite-int.h"
static int
--- /dev/null
+/******************************************************************************
+ *
+ * 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;
+}
+