static int
create_baseObject(
	BackendDB	*be,
	const char	*fname,
	int		lineno )
{
	backsql_info 	*bi = (backsql_info *)be->be_private;
	LDAPRDN		rdn;
	char		*p;
	int		rc, iAVA;
	char		buf[1024];

	snprintf( buf, sizeof(buf),
			"dn: %s\n"
			"objectClass: extensibleObject\n"
			"description: builtin baseObject for back-sql\n"
			"description: all entries mapped "
				"in table \"ldap_entries\" "
				"must have "
				"\"" BACKSQL_BASEOBJECT_IDSTR "\" "
				"in the \"parent\" column",
			be->be_suffix[0].bv_val );

	bi->sql_baseObject = str2entry( buf );
	if ( bi->sql_baseObject == NULL ) {
		Debug( LDAP_DEBUG_TRACE,
			"<==backsql_db_config (%s line %d): "
			"unable to parse baseObject entry\n",
			fname, lineno, 0 );
		return 1;
	}

	if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) {
		return 0;
	}

	rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **)&p,
			LDAP_DN_FORMAT_LDAP );
	if ( rc != LDAP_SUCCESS ) {
		snprintf( buf, sizeof(buf),
			"unable to extract RDN "
			"from baseObject DN \"%s\" (%d: %s)",
			be->be_suffix[ 0 ].bv_val,
			rc, ldap_err2string( rc ) );
		Debug( LDAP_DEBUG_TRACE,
			"<==backsql_db_config (%s line %d): %s\n",
			fname, lineno, buf );
		return 1;
	}

	for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
		LDAPAVA				*ava = rdn[ iAVA ];
		AttributeDescription		*ad = NULL;
		slap_syntax_transform_func	*transf = NULL;
		struct berval			bv = BER_BVNULL;
		const char			*text = NULL;

		assert( ava != NULL );

		rc = slap_bv2ad( &ava->la_attr, &ad, &text );
		if ( rc != LDAP_SUCCESS ) {
			snprintf( buf, sizeof(buf),
				"AttributeDescription of naming "
				"attribute #%d from baseObject "
				"DN \"%s\": %d: %s",
				iAVA, be->be_suffix[ 0 ].bv_val,
				rc, ldap_err2string( rc ) );
			Debug( LDAP_DEBUG_TRACE,
				"<==backsql_db_config (%s line %d): %s\n",
				fname, lineno, buf );
			return 1;
		}
		
		transf = ad->ad_type->sat_syntax->ssyn_pretty;
		if ( transf ) {
			/*
	 		 * transform value by pretty function
			 *	if value is empty, use empty_bv
			 */
			rc = ( *transf )( ad->ad_type->sat_syntax,
				ava->la_value.bv_len
					? &ava->la_value
					: (struct berval *) &slap_empty_bv,
				&bv, NULL );
	
			if ( rc != LDAP_SUCCESS ) {
				snprintf( buf, sizeof(buf),
					"prettying of attribute #%d "
					"from baseObject "
					"DN \"%s\" failed: %d: %s",
					iAVA, be->be_suffix[ 0 ].bv_val,
					rc, ldap_err2string( rc ) );
				Debug( LDAP_DEBUG_TRACE,
					"<==backsql_db_config (%s line %d): "
					"%s\n",
					fname, lineno, buf );
				return 1;
			}
		}

		if ( !BER_BVISNULL( &bv ) ) {
			if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) {
				ber_memfree( ava->la_value.bv_val );
			}
			ava->la_value = bv;
			ava->la_flags |= LDAP_AVA_FREE_VALUE;
		}

		attr_merge_normalize_one( bi->sql_baseObject,
				ad, &ava->la_value, NULL );
	}

	ldap_rdnfree( rdn );

	return 0;
}
Exemple #2
0
int
read_and_send_results(
    Operation	*op,
    SlapReply	*rs,
    FILE	*fp )
{
	int	bsize, len;
	char	*buf, *bp;
	char	line[BUFSIZ];
	char	ebuf[128];

	/* read in the result and send it along */
	buf = (char *) ch_malloc( BUFSIZ );
	buf[0] = '\0';
	bsize = BUFSIZ;
	bp = buf;
	while ( !feof(fp) ) {
		errno = 0;
		if ( fgets( line, sizeof(line), fp ) == NULL ) {
			if ( errno == EINTR ) continue;

			Debug( LDAP_DEBUG_ANY, "shell: fgets failed: %s (%d)\n",
				AC_STRERROR_R(errno, ebuf, sizeof ebuf), errno, 0 ); 
			break;
		}

		Debug( LDAP_DEBUG_SHELL, "shell search reading line (%s)\n",
		    line, 0, 0 );

		/* ignore lines beginning with # (LDIFv1 comments) */
		if ( *line == '#' ) {
			continue;
		}

		/* ignore lines beginning with DEBUG: */
		if ( strncasecmp( line, "DEBUG:", 6 ) == 0 ) {
			continue;
		}

		len = strlen( line );
		while ( bp + len + 1 - buf > bsize ) {
			size_t offset = bp - buf;
			bsize += BUFSIZ;
			buf = (char *) ch_realloc( buf, bsize );
			bp = &buf[offset];
		}
		strcpy( bp, line );
		bp += len;

		/* line marked the end of an entry or result */
		if ( *line == '\n' ) {
			if ( strncasecmp( buf, "RESULT", 6 ) == 0 ) {
				break;
			}

			if ( (rs->sr_entry = str2entry( buf )) == NULL ) {
				Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n",
				    buf, 0, 0 );
			} else {
				rs->sr_attrs = op->oq_search.rs_attrs;
				rs->sr_flags = REP_ENTRY_MODIFIABLE;
				send_search_entry( op, rs );
				entry_free( rs->sr_entry );
				rs->sr_attrs = NULL;
			}

			bp = buf;
		}
	}
	(void) str2result( buf, &rs->sr_err, (char **)&rs->sr_matched, (char **)&rs->sr_text );

	/* otherwise, front end will send this result */
	if ( rs->sr_err != 0 || op->o_tag != LDAP_REQ_BIND ) {
		send_ldap_result( op, rs );
	}

	free( buf );

	return( rs->sr_err );
}
/*
 * Read the entries specified in fname and merge the attributes
 * to the user defined baseObject entry. Note that if we find any errors
 * what so ever, we will discard the entire entries, print an
 * error message and return.
 */
static int
read_baseObject( 
	BackendDB	*be,
	const char	*fname )
{
	backsql_info 	*bi = (backsql_info *)be->be_private;
	LDIFFP		*fp;
	int		rc = 0, lineno = 0, lmax = 0;
	char		*buf = NULL;

	assert( fname != NULL );

	fp = ldif_open( fname, "r" );
	if ( fp == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"could not open back-sql baseObject "
			"attr file \"%s\" - absolute path?\n",
			fname, 0, 0 );
		perror( fname );
		return LDAP_OTHER;
	}

	bi->sql_baseObject = entry_alloc();
	if ( bi->sql_baseObject == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			"read_baseObject_file: entry_alloc failed", 0, 0, 0 );
		ldif_close( fp );
		return LDAP_NO_MEMORY;
	}
	bi->sql_baseObject->e_name = be->be_suffix[0];
	bi->sql_baseObject->e_nname = be->be_nsuffix[0];
	bi->sql_baseObject->e_attrs = NULL;

	while ( ldif_read_record( fp, &lineno, &buf, &lmax ) ) {
		Entry		*e = str2entry( buf );
		Attribute	*a;

		if( e == NULL ) {
			fprintf( stderr, "back-sql baseObject: "
					"could not parse entry (line=%d)\n",
					lineno );
			rc = LDAP_OTHER;
			break;
		}

		/* make sure the DN is the database's suffix */
		if ( !be_issuffix( be, &e->e_nname ) ) {
			fprintf( stderr,
				"back-sql: invalid baseObject - "
				"dn=\"%s\" (line=%d)\n",
				e->e_name.bv_val, lineno );
			entry_free( e );
			rc = EXIT_FAILURE;
			break;
		}

		/*
		 * we found a valid entry, so walk thru all the attributes in the
		 * entry, and add each attribute type and description to baseObject
		 */
		for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
			if ( attr_merge( bi->sql_baseObject, a->a_desc,
						a->a_vals,
						( a->a_nvals == a->a_vals ) ?
						NULL : a->a_nvals ) )
			{
				rc = LDAP_OTHER;
				break;
			}
		}

		entry_free( e );
		if ( rc ) {
			break;
		}
	}

	if ( rc ) {
		entry_free( bi->sql_baseObject );
		bi->sql_baseObject = NULL;
	}

	ch_free( buf );

	ldif_close( fp );

	Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n",
			fname, 0, 0 );

	return rc;
}
Exemple #4
0
/*
 * call from within ldap_back_db_open()
 */
int
ldap_back_monitor_db_open( BackendDB *be )
{
	ldapinfo_t		*li = (ldapinfo_t *) be->be_private;
	char			buf[ BACKMONITOR_BUFSIZE ];
	Entry			*e = NULL;
	monitor_callback_t	*cb = NULL;
	struct berval		suffix, *filter, *base;
	char			*ptr;
	time_t			now;
	char			timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
	struct berval 		timestamp;
	int			rc = 0;
	BackendInfo		*mi;
	monitor_extra_t		*mbe;

	if ( !SLAP_DBMONITORING( be ) ) {
		return 0;
	}

	/* check if monitor is configured and usable */
	mi = backend_info( "monitor" );
	if ( !mi || !mi->bi_extra ) {
		SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING;
		return 0;
 	}
 	mbe = mi->bi_extra;

	/* don't bother if monitor is not configured */
	if ( !mbe->is_configured() ) {
		static int warning = 0;

		if ( warning++ == 0 ) {
			Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: "
				"monitoring disabled; "
				"configure monitor database to enable\n",
				0, 0, 0 );
		}

		return 0;
	}

	/* set up the fake subsystem that is used to create
	 * the volatile connection entries */
	li->li_monitor_info.lmi_mss.mss_name = "back-ldap";
	li->li_monitor_info.lmi_mss.mss_flags = MONITOR_F_VOLATILE_CH;
	li->li_monitor_info.lmi_mss.mss_create = ldap_back_monitor_conn_create;

	li->li_monitor_info.lmi_li = li;
	li->li_monitor_info.lmi_scope = LDAP_SCOPE_SUBORDINATE;
	base = &li->li_monitor_info.lmi_base;
	BER_BVSTR( base, "cn=databases,cn=monitor" );
	filter = &li->li_monitor_info.lmi_filter;
	BER_BVZERO( filter );

	suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] );
	if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) {
		suffix = be->be_nsuffix[ 0 ];

	} else {
		ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix );
	}
	
	filter->bv_len = STRLENOF( "(&" )
		+ li->li_monitor_info.lmi_more_filter.bv_len
		+ STRLENOF( "(monitoredInfo=" )
		+ strlen( be->bd_info->bi_type )
		+ STRLENOF( ")(!(monitorOverlay=" )
		+ strlen( be->bd_info->bi_type )
		+ STRLENOF( "))(namingContexts:distinguishedNameMatch:=" )
		+ suffix.bv_len + STRLENOF( "))" );
	ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 );
	ptr = lutil_strcopy( ptr, "(&" );
	ptr = lutil_strncopy( ptr, li->li_monitor_info.lmi_more_filter.bv_val,
		li->li_monitor_info.lmi_more_filter.bv_len );
	ptr = lutil_strcopy( ptr, "(monitoredInfo=" );
	ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
	ptr = lutil_strcopy( ptr, ")(!(monitorOverlay=" );
	ptr = lutil_strcopy( ptr, be->bd_info->bi_type );
	ptr = lutil_strcopy( ptr, "))(namingContexts:distinguishedNameMatch:=" );
	ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len );
	ptr = lutil_strcopy( ptr, "))" );
	ptr[ 0 ] = '\0';
	assert( ptr == &filter->bv_val[ filter->bv_len ] );

	if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) {
		ch_free( suffix.bv_val );
	}

	now = slap_get_time();
	timestamp.bv_val = timebuf;
	timestamp.bv_len = sizeof( timebuf );
	slap_timestamp( &now, &timestamp );

	/* caller (e.g. an overlay based on back-ldap) may want to use
	 * a different RDN... */
	if ( BER_BVISNULL( &li->li_monitor_info.lmi_rdn ) ) {
		ber_str2bv( "cn=Connections", 0, 1, &li->li_monitor_info.lmi_rdn );
	}

	ptr = ber_bvchr( &li->li_monitor_info.lmi_rdn, '=' );
	assert( ptr != NULL );
	ptr[ 0 ] = '\0';
	ptr++;

	snprintf( buf, sizeof( buf ),
		"dn: %s=%s\n"
		"objectClass: monitorContainer\n"
		"%s: %s\n"
		"creatorsName: %s\n"
		"createTimestamp: %s\n"
		"modifiersName: %s\n"
		"modifyTimestamp: %s\n",
		li->li_monitor_info.lmi_rdn.bv_val,
			ptr,
		li->li_monitor_info.lmi_rdn.bv_val,
			ptr,
		BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val,
		timestamp.bv_val,
		BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val,
		timestamp.bv_val );
	e = str2entry( buf );
	if ( e == NULL ) {
		rc = -1;
		goto cleanup;
	}

	ptr[ -1 ] = '=';

	/* add labeledURI and special, modifiable URI value */
	if ( li->li_uri != NULL ) {
		struct berval	bv;
		LDAPURLDesc	*ludlist = NULL;
		int		rc;

		rc = ldap_url_parselist_ext( &ludlist,
			li->li_uri, NULL,
			LDAP_PVT_URL_PARSE_NOEMPTY_HOST
				| LDAP_PVT_URL_PARSE_DEF_PORT );
		if ( rc != LDAP_URL_SUCCESS ) {
			Debug( LDAP_DEBUG_ANY,
				"ldap_back_monitor_db_open: "
				"unable to parse URI list (ignored)\n",
				0, 0, 0 );
		} else {
			for ( ; ludlist != NULL; ) {
				LDAPURLDesc	*next = ludlist->lud_next;

				bv.bv_val = ldap_url_desc2str( ludlist );
				assert( bv.bv_val != NULL );
				ldap_free_urldesc( ludlist );
				bv.bv_len = strlen( bv.bv_val );
				attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI,
					&bv, NULL );
				ch_free( bv.bv_val );

				ludlist = next;
			}
		}
		
		ber_str2bv( li->li_uri, 0, 0, &bv );
		attr_merge_normalize_one( e, ad_olmDbURIList,
			&bv, NULL );
	}

	ber_dupbv( &li->li_monitor_info.lmi_nrdn, &e->e_nname );

	cb = ch_calloc( sizeof( monitor_callback_t ), 1 );
	cb->mc_update = ldap_back_monitor_update;
	cb->mc_modify = ldap_back_monitor_modify;
	cb->mc_free = ldap_back_monitor_free;
	cb->mc_private = (void *)li;

	rc = mbe->register_entry_parent( e, cb,
		(monitor_subsys_t *)&li->li_monitor_info,
		MONITOR_F_VOLATILE_CH,
		base, LDAP_SCOPE_SUBORDINATE, filter );

cleanup:;
	if ( rc != 0 ) {
		if ( cb != NULL ) {
			ch_free( cb );
			cb = NULL;
		}

		if ( e != NULL ) {
			entry_free( e );
			e = NULL;
		}

		if ( !BER_BVISNULL( filter ) ) {
			ch_free( filter->bv_val );
			BER_BVZERO( filter );
		}
	}

	/* store for cleanup */
	li->li_monitor_info.lmi_cb = (void *)cb;

	if ( e != NULL ) {
		entry_free( e );
	}

	return rc;
}
int
monitor_subsys_database_init(
	BackendDB	*be
)
{
	struct monitorinfo	*mi;
	Entry			*e, *e_database, *e_tmp;
	int			i;
	struct monitorentrypriv	*mp;
	AttributeDescription 	*ad_nc = slap_schema.si_ad_namingContexts;
	AttributeDescription 	*ad_mc = slap_schema.si_ad_monitorContext;
	AttributeDescription 	*ad_seeAlso = NULL;
	const char		*text = NULL;

	assert( be != NULL );
	assert( monitor_ad_desc != NULL );

	mi = ( struct monitorinfo * )be->be_private;

	if ( monitor_cache_get( mi, 
				&monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn, 
				&e_database ) ) {
#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, CRIT,
			"monitor_subsys_database_init: "
			"unable to get entry '%s'\n",
			monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_database_init: "
			"unable to get entry '%s'\n%s%s",
			monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val, 
			"", "" );
#endif
		return( -1 );
	}

	if ( slap_str2ad( "seeAlso", &ad_seeAlso, &text ) != LDAP_SUCCESS ) {
#ifdef NEW_LOGGING
		LDAP_LOG( OPERATION, CRIT,
			"monitor_subsys_database_init: "
			"unable to find 'seeAlso' attribute description\n",
			0, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY,
			"monitor_subsys_database_init: "
			"unable to find 'seeAlso' attribute description\n",
			0, 0, 0 );
#endif
		return( -1 );
	}

	e_tmp = NULL;
	for ( i = nBackendDB; i--; ) {
		char buf[1024];
		int j;

		be = &backendDB[i];

		/* Subordinates are not exposed as their own naming context */
		if ( SLAP_GLUE_SUBORDINATE( be ) ) {
			continue;
		}

		snprintf( buf, sizeof( buf ),
				"dn: cn=Database %d,%s\n"
				SLAPD_MONITOR_OBJECTCLASSES
				"cn: Database %d\n"
				"description: %s",
				i,
				monitor_subsys[SLAPD_MONITOR_DATABASE].mss_dn.bv_val,
				i,
				be->bd_info->bi_type );
		
		e = str2entry( buf );
		if ( e == NULL ) {
#ifdef NEW_LOGGING
			LDAP_LOG( OPERATION, CRIT,
				"monitor_subsys_database_init: "
				"unable to create entry 'cn=Database %d,%s'\n",
				i, monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val, 0 );
#else
			Debug( LDAP_DEBUG_ANY,
				"monitor_subsys_database_init: "
				"unable to create entry 'cn=Database %d,%s'\n%s",
				i, 
				monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val,
				"" );
#endif
			return( -1 );
		}
		
		if ( be->be_flags & SLAP_BFLAG_MONITOR ) {
			attr_merge( e, ad_mc, be->be_suffix );
			attr_merge( e_database, ad_mc, be->be_suffix );
		} else {
			attr_merge( e, ad_nc, be->be_suffix );
			attr_merge( e_database, ad_nc, be->be_suffix );
		}

		for ( j = nBackendInfo; j--; ) {
			if ( backendInfo[ j ].bi_type == be->bd_info->bi_type ) {
				struct berval 		bv;

				snprintf( buf, sizeof( buf ), 
					"cn=Backend %d,%s", 
					j, monitor_subsys[SLAPD_MONITOR_BACKEND].mss_dn.bv_val );
				bv.bv_val = buf;
				bv.bv_len = strlen( buf );
				attr_merge_one( e, ad_seeAlso, &bv );
				break;
			}
		}
		/* we must find it! */
		assert( j >= 0 );

		mp = ( struct monitorentrypriv * )ch_calloc( sizeof( struct monitorentrypriv ), 1 );
		e->e_private = ( void * )mp;
		mp->mp_next = e_tmp;
		mp->mp_children = NULL;
		mp->mp_info = &monitor_subsys[SLAPD_MONITOR_DATABASE];
		mp->mp_flags = monitor_subsys[SLAPD_MONITOR_DATABASE].mss_flags
			| MONITOR_F_SUB;

		if ( monitor_cache_add( mi, e ) ) {
#ifdef NEW_LOGGING
			LDAP_LOG( OPERATION, CRIT,
				"monitor_subsys_database_init: "
				"unable to add entry 'cn=Database %d,%s'\n",
				i, monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val, 0 );
#else
			Debug( LDAP_DEBUG_ANY,
				"monitor_subsys_database_init: "
				"unable to add entry 'cn=Database %d,%s'\n",
				i, 
				monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val,
				0 );
#endif
			return( -1 );
		}

#if defined(LDAP_SLAPI)
		monitor_back_add_plugin( be, e );
#endif /* defined(LDAP_SLAPI) */

		e_tmp = e;
	}
	
	mp = ( struct monitorentrypriv * )e_database->e_private;
	mp->mp_children = e_tmp;

	monitor_cache_release( mi, e_database );

	return( 0 );
}
Exemple #6
0
/**********************************************************
 *
 * Search
 *
 **********************************************************/
int
perl_back_search(
	Operation *op,
	SlapReply *rs )
{
	PerlBackend *perl_back = (PerlBackend *)op->o_bd->be_private;
	int count ;
	AttributeName *an;
	Entry	*e;
	char *buf;
	int i;

	PERL_SET_CONTEXT( PERL_INTERPRETER );
	ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );	

	{
		dSP; ENTER; SAVETMPS;

		PUSHMARK(sp) ;
		XPUSHs( perl_back->pb_obj_ref );
		XPUSHs(sv_2mortal(newSVpv( op->o_req_ndn.bv_val , op->o_req_ndn.bv_len)));
		XPUSHs(sv_2mortal(newSViv( op->ors_scope )));
		XPUSHs(sv_2mortal(newSViv( op->ors_deref )));
		XPUSHs(sv_2mortal(newSViv( op->ors_slimit )));
		XPUSHs(sv_2mortal(newSViv( op->ors_tlimit )));
		XPUSHs(sv_2mortal(newSVpv( op->ors_filterstr.bv_val , op->ors_filterstr.bv_len)));
		XPUSHs(sv_2mortal(newSViv( op->ors_attrsonly )));

		for ( an = op->ors_attrs; an && an->an_name.bv_val; an++ ) {
			XPUSHs(sv_2mortal(newSVpv( an->an_name.bv_val , an->an_name.bv_len)));
		}
		PUTBACK;

		count = call_method("search", G_ARRAY );

		SPAGAIN;

		if (count < 1) {
			croak("Big trouble in back_search\n") ;
		}

		if ( count > 1 ) {
							 
			for ( i = 1; i < count; i++ ) {

				buf = POPp;

				if ( (e = str2entry( buf )) == NULL ) {
					Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n", buf, 0, 0 );

				} else {
					int send_entry;

					if (perl_back->pb_filter_search_results)
						send_entry = (test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE);
					else
						send_entry = 1;

					if (send_entry) {
						rs->sr_entry = e;
						rs->sr_attrs = op->ors_attrs;
						rs->sr_flags = REP_ENTRY_MODIFIABLE;
						rs->sr_err = LDAP_SUCCESS;
						rs->sr_err = send_search_entry( op, rs );
						rs->sr_flags = 0;
						rs->sr_attrs = NULL;
						rs->sr_entry = NULL;
						if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED || rs->sr_err == LDAP_BUSY ) {
							goto done;
						}
					}

					entry_free( e );
				}
			}
		}

		/*
		 * We grab the return code last because the stack comes
		 * from perl in reverse order. 
		 *
		 * ex perl: return ( 0, $res_1, $res_2 );
		 *
		 * ex stack: <$res_2> <$res_1> <0>
		 */

		rs->sr_err = POPi;

done:;
		PUTBACK; FREETMPS; LEAVE;
	}

	ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );	

	send_ldap_result( op, rs );

	return 0;
}
/* returns entry with reader/writer lock */
Entry *
id2entry_rw( Backend *be, ID id, int rw )
{
	struct ldbminfo	*li = (struct ldbminfo *) be->be_private;
	DBCache	*db;
	Datum		key, data;
	Entry		*e;
#ifndef WORDS_BIGENDIAN
	ID		id2;
#endif

	ldbm_datum_init( key );
	ldbm_datum_init( data );

#ifdef NEW_LOGGING
	LDAP_LOG( INDEX, ENTRY, 
		   "id2entry_rw: %s (%ld)\n", rw ? "write" : "read", id, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "=> id2entry_%s( %ld )\n",
		rw ? "w" : "r", id, 0 );
#endif


	if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, DETAIL1, 
			   "id2entry_rw: %s (%ld) 0x%lx (cache).\n",
			   rw ? "write" : "read", id, (unsigned long)e  );
#else
		Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
			rw ? "w" : "r", id, (unsigned long) e );
#endif

		return( e );
	}

	if ( (db = ldbm_cache_open( be, "id2entry", LDBM_SUFFIX, LDBM_WRCREAT ))
		== NULL ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			   "id2entry_rw: could not open id2entry%s\n", LDBM_SUFFIX, 0, 0 );
#else
		Debug( LDAP_DEBUG_ANY, "Could not open id2entry%s\n",
		    LDBM_SUFFIX, 0, 0 );
#endif

		return( NULL );
	}

#ifdef WORDS_BIGENDIAN
	key.dptr = (char *) &id;
#else
	id2 = htonl(id);
	key.dptr = (char *) &id2;
#endif
	key.dsize = sizeof(ID);

	data = ldbm_cache_fetch( db, key );

	if ( data.dptr == NULL ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			   "id2entry_rw: (%ld) not found\n", id, 0, 0 );
#else
		Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) not found\n",
			rw ? "w" : "r", id, 0 );
#endif

		ldbm_cache_close( be, db );
		return( NULL );
	}

	e = str2entry( data.dptr );
	ldbm_datum_free( db->dbc_db, data );
	ldbm_cache_close( be, db );

	if ( e == NULL ) {
#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			   "id2entry_rw: %s of %ld failed\n", rw ? "write" : "read", id, 0);
#else
		Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (failed)\n",
			rw ? "w" : "r", id, 0 );
#endif

		return( NULL );
	}

	e->e_id = id;

	if( cache_add_entry_rw( &li->li_cache, e, rw ) != 0 ) {
		entry_free( e );

		/* XXX this is a kludge.
		 * maybe the entry got added underneath us
		 * There are many underlying race condtions in the cache/disk code.
		 */
		if ( (e = cache_find_entry_id( &li->li_cache, id, rw )) != NULL ) {
#ifdef NEW_LOGGING
			LDAP_LOG( INDEX, DETAIL1, 
				   "id2entry_rw: %s of %ld 0x%lx (cache)\n",
				   rw ? "write" : "read", id, (unsigned long)e  );
#else
			Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (cache)\n",
				rw ? "w" : "r", id, (unsigned long) e );
#endif

			return( e );
		}

#ifdef NEW_LOGGING
		LDAP_LOG( INDEX, ERR, 
			   "id2entry_rw: %s of %ld (cache add failed)\n",
			   rw ? "write" : "read", id, 0 );
#else
		Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) (cache add failed)\n",
			rw ? "w" : "r", id, 0 );
#endif

		return NULL;
	}

#ifdef NEW_LOGGING
	LDAP_LOG( INDEX, ENTRY, 
		   "id2entry_rw: %s of %ld 0x%lx (disk)\n",
		   rw ? "write" : "read", id, (unsigned long)e  );
#else
	Debug( LDAP_DEBUG_TRACE, "<= id2entry_%s( %ld ) 0x%lx (disk)\n",
		rw ? "w" : "r", id, (unsigned long) e );
#endif

	/* marks the entry as committed, so it will get added to the cache
	 * when the lock is released */
	cache_entry_commit( e );

	return( e );
}