From a97e3e94e665df092cc512cd5a3f9c5ceac820ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julio=20S=C3=A1nchez=20Fern=C3=A1ndez?=
 <jsanchez@openldap.org>
Date: Fri, 28 May 1999 18:56:47 +0000
Subject: [PATCH] Provide (and use) #define shortcuts Really kill global_oc &
 global_at Publish schema through LDAP (really, it's there at last :-)

---
 include/ldapconfig.h.edit   |   2 +-
 servers/slapd/attr.c        |  37 +++++++++--
 servers/slapd/proto-slap.h  |   3 +-
 servers/slapd/root_dse.c    |   2 +-
 servers/slapd/schema.c      | 129 ++++++++++++++++++++++++++++--------
 servers/slapd/schemaparse.c |   2 -
 servers/slapd/search.c      |   2 +-
 servers/slapd/slap.h        |  22 ++++++
 8 files changed, 160 insertions(+), 39 deletions(-)

diff --git a/include/ldapconfig.h.edit b/include/ldapconfig.h.edit
index cfeb1a98f9..e99dbac074 100644
--- a/include/ldapconfig.h.edit
+++ b/include/ldapconfig.h.edit
@@ -226,6 +226,6 @@ Please try again later.\r\n"
 	/* dn of the special "config" entry */
 #define SLAPD_CONFIG_DN			"CN=CONFIG"
 	/* dn of the special "schema" entry */
-/* #define SLAPD_SCHEMA_DN			"CN=SCHEMA" */
+#define SLAPD_SCHEMA_DN			"CN=SCHEMA"
 
 #endif /* _LDAP_CONFIG_H */
diff --git a/servers/slapd/attr.c b/servers/slapd/attr.c
index 3254b3d0aa..799a8a194d 100644
--- a/servers/slapd/attr.c
+++ b/servers/slapd/attr.c
@@ -20,6 +20,7 @@
 
 #include <sys/stat.h>
 
+#include "ldapconfig.h"
 #include "slap.h"
 
 #ifdef LDAP_DEBUG
@@ -488,22 +489,22 @@ at_insert(
 	}
 	*atp = sat;
 
-	if ( sat->sat_atype.at_oid ) {
+	if ( sat->sat_oid ) {
 		air = (struct aindexrec *)
 			ch_calloc( 1, sizeof(struct aindexrec) );
-		air->air_name = sat->sat_atype.at_oid;
+		air->air_name = sat->sat_oid;
 		air->air_at = sat;
 		if ( avl_insert( &attr_index, (caddr_t) air,
 				 (AVL_CMP) attr_index_cmp,
 				 (AVL_DUP) avl_dup_error ) ) {
-			*err = sat->sat_atype.at_oid;
+			*err = sat->sat_oid;
 			ldap_memfree(air);
 			return SLAP_SCHERR_DUP_ATTR;
 		}
 		/* FIX: temporal consistency check */
 		at_find(air->air_name);
 	}
-	if ( (names = sat->sat_atype.at_names) ) {
+	if ( (names = sat->sat_names) ) {
 		while ( *names ) {
 			air = (struct aindexrec *)
 				ch_calloc( 1, sizeof(struct aindexrec) );
@@ -578,6 +579,34 @@ at_add(
 	return code;
 }
 
+#if defined( SLAPD_SCHEMA_DN )
+
+int
+at_schema_info( Entry *e )
+{
+	struct berval	val;
+	struct berval	*vals[2];
+	AttributeType	*at;
+
+	vals[0] = &val;
+	vals[1] = NULL;
+
+	for ( at = attr_list; at; at = at->sat_next ) {
+		val.bv_val = ldap_attributetype2str( &at->sat_atype );
+		if ( val.bv_val ) {
+			val.bv_len = strlen( val.bv_val );
+			Debug( LDAP_DEBUG_TRACE, "Merging at [%d] %s\n",
+			       val.bv_len, val.bv_val, 0 );
+			attr_merge( e, "attributeTypes", vals );
+			ldap_memfree( val.bv_val );
+		} else {
+			return -1;
+		}
+	}
+	return 0;
+}
+#endif
+
 #ifdef LDAP_DEBUG
 
 static int
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index ccc7cc5742..a079c81c33 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -51,6 +51,7 @@ int at_find_in_list LDAP_P(( AttributeType *sat, AttributeType **list ));
 int at_append_to_list LDAP_P(( AttributeType *sat, AttributeType ***listp ));
 int at_delete_from_list LDAP_P(( int pos, AttributeType ***listp ));
 int at_fake_if_needed LDAP_P(( char *name ));
+int at_schema_info LDAP_P(( Entry *e ));
 
 /*
  * ava.c
@@ -237,6 +238,7 @@ void send_ldap_search_result LDAP_P(( Connection *conn, Operation *op, int err,
 int oc_schema_check LDAP_P(( Entry *e ));
 ObjectClass *oc_find LDAP_P((char *ocname));
 int oc_add LDAP_P((LDAP_OBJECT_CLASS *oc, char **err));
+void schema_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
 
 
 /*
@@ -322,7 +324,6 @@ extern ldap_pvt_thread_mutex_t	crypt_mutex;
 extern ldap_pvt_thread_mutex_t	gmtime_mutex;
 
 extern struct acl		*global_acl;
-extern ObjectClass		*global_oc;
 
 extern int	slap_init LDAP_P((int mode, char* name));
 extern int	slap_startup LDAP_P((int dbnum));
diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c
index 2c13df0ed7..c2aa8f9caa 100644
--- a/servers/slapd/root_dse.c
+++ b/servers/slapd/root_dse.c
@@ -46,7 +46,7 @@ root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
 
 #if defined( SLAPD_SCHEMA_DN )
 	val.bv_val = ch_strdup( SLAPD_SCHEMA_DN );
-	val.bv_len = strlen( va.bv_val );
+	val.bv_len = strlen( val.bv_val );
 	attr_merge( e, "subschemaSubentry", vals );
 	ldap_memfree( val.bv_val );
 #endif
diff --git a/servers/slapd/schema.c b/servers/slapd/schema.c
index a5b0a0519b..25056be2d0 100644
--- a/servers/slapd/schema.c
+++ b/servers/slapd/schema.c
@@ -7,6 +7,7 @@
 #include <ac/string.h>
 #include <ac/socket.h>
 
+#include "ldapconfig.h"
 #include "slap.h"
 
 static char *	oc_check_required(Entry *e, char *ocname);
@@ -88,11 +89,11 @@ oc_check_required( Entry *e, char *ocname )
 		at = oc->soc_required[i];
 		/* see if it's in the entry */
 		for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
-			if ( at->sat_atype.at_oid &&
-			     strcmp( a->a_type, at->sat_atype.at_oid ) == 0 ) {
+			if ( at->sat_oid &&
+			     strcmp( a->a_type, at->sat_oid ) == 0 ) {
 				break;
 			}
-			pp = at->sat_atype.at_names;
+			pp = at->sat_names;
 			if ( pp  == NULL ) {
 				/* Empty name list => not found */
 				a = NULL;
@@ -110,11 +111,10 @@ oc_check_required( Entry *e, char *ocname )
 		}
 		/* not there => schema violation */
 		if ( a == NULL ) {
-			if ( at->sat_atype.at_names &&
-			     at->sat_atype.at_names[0] ) {
-				return at->sat_atype.at_names[0];
+			if ( at->sat_names && at->sat_names[0] ) {
+				return at->sat_names[0];
 			} else {
-				return at->sat_atype.at_oid;
+				return at->sat_oid;
 			}
 		}
 	}
@@ -164,11 +164,11 @@ oc_check_allowed( char *type, struct berval **ocl )
 			for ( j = 0; oc->soc_required != NULL && 
 				oc->soc_required[j] != NULL; j++ ) {
 				at = oc->soc_required[j];
-				if ( at->sat_atype.at_oid &&
-				     strcmp(at->sat_atype.at_oid, type ) == 0 ) {
+				if ( at->sat_oid &&
+				     strcmp(at->sat_oid, type ) == 0 ) {
 					return( 0 );
 				}
-				pp = at->sat_atype.at_names;
+				pp = at->sat_names;
 				if ( pp == NULL )
 					continue;
 				while ( *pp ) {
@@ -182,11 +182,11 @@ oc_check_allowed( char *type, struct berval **ocl )
 			for ( j = 0; oc->soc_allowed != NULL && 
 				oc->soc_allowed[j] != NULL; j++ ) {
 				at = oc->soc_allowed[j];
-				if ( at->sat_atype.at_oid &&
-				     strcmp(at->sat_atype.at_oid, type ) == 0 ) {
+				if ( at->sat_oid &&
+				     strcmp(at->sat_oid, type ) == 0 ) {
 					return( 0 );
 				}
-				pp = at->sat_atype.at_names;
+				pp = at->sat_names;
 				if ( pp == NULL )
 					continue;
 				while ( *pp ) {
@@ -215,7 +215,7 @@ struct oindexrec {
 };
 
 static Avlnode	*oc_index = NULL;
-static AttributeType *oc_list = NULL;
+static ObjectClass *oc_list = NULL;
 
 static int
 oc_index_cmp(
@@ -360,16 +360,15 @@ oc_add_sups(
 			if ( add_sups )
 				soc->soc_sups[nsups] = soc1;
 
-			code = oc_add_sups(soc,soc1->soc_oclass.oc_sup_oids,
-					   err);
+			code = oc_add_sups(soc,soc1->soc_sup_oids, err);
 			if ( code )
 				return code;
 			
 			if ( code = oc_create_required(soc,
-				soc1->soc_oclass.oc_at_oids_must,err) )
+				soc1->soc_at_oids_must,err) )
 				return code;
 			if ( code = oc_create_allowed(soc,
-				soc1->soc_oclass.oc_at_oids_may,err) )
+				soc1->soc_at_oids_may,err) )
 				return code;
 			nsups++;
 			sups1++;
@@ -388,28 +387,28 @@ oc_insert(
 	struct oindexrec	*oir;
 	char			**names;
 
-	ocp = &global_oc;
+	ocp = &oc_list;
 	while ( *ocp != NULL ) {
 		ocp = &(*ocp)->soc_next;
 	}
 	*ocp = soc;
 
-	if ( soc->soc_oclass.oc_oid ) {
+	if ( soc->soc_oid ) {
 		oir = (struct oindexrec *)
 			ch_calloc( 1, sizeof(struct oindexrec) );
-		oir->oir_name = soc->soc_oclass.oc_oid;
+		oir->oir_name = soc->soc_oid;
 		oir->oir_oc = soc;
 		if ( avl_insert( &oc_index, (caddr_t) oir,
 				 (AVL_CMP) oc_index_cmp,
 				 (AVL_DUP) avl_dup_error ) ) {
-			*err = soc->soc_oclass.oc_oid;
+			*err = soc->soc_oid;
 			ldap_memfree(oir);
 			return SLAP_SCHERR_DUP_CLASS;
 		}
 		/* FIX: temporal consistency check */
 		oc_find(oir->oir_name);
 	}
-	if ( (names = soc->soc_oclass.oc_names) ) {
+	if ( (names = soc->soc_names) ) {
 		while ( *names ) {
 			oir = (struct oindexrec *)
 				ch_calloc( 1, sizeof(struct oindexrec) );
@@ -441,16 +440,88 @@ oc_add(
 
 	soc = (ObjectClass *) ch_calloc( 1, sizeof(ObjectClass) );
 	memcpy( &soc->soc_oclass, oc, sizeof(LDAP_OBJECT_CLASS));
-	if ( code = oc_add_sups(soc,soc->soc_oclass.oc_sup_oids,err) )
+	if ( code = oc_add_sups(soc,soc->soc_sup_oids,err) )
 		return code;
-	if ( code = oc_create_required(soc,soc->soc_oclass.oc_at_oids_must,err) )
+	if ( code = oc_create_required(soc,soc->soc_at_oids_must,err) )
 		return code;
-	if ( code = oc_create_allowed(soc,soc->soc_oclass.oc_at_oids_may,err) )
+	if ( code = oc_create_allowed(soc,soc->soc_at_oids_may,err) )
 		return code;
 	code = oc_insert(soc,err);
 	return code;
 }
 
+#if defined( SLAPD_SCHEMA_DN )
+
+static int
+oc_schema_info( Entry *e )
+{
+	struct berval	val;
+	struct berval	*vals[2];
+	ObjectClass	*oc;
+
+	vals[0] = &val;
+	vals[1] = NULL;
+
+	for ( oc = oc_list; oc; oc = oc->soc_next ) {
+		val.bv_val = ldap_objectclass2str( &oc->soc_oclass );
+		if ( val.bv_val ) {
+			val.bv_len = strlen( val.bv_val );
+			Debug( LDAP_DEBUG_TRACE, "Merging oc [%d] %s\n",
+			       val.bv_len, val.bv_val, 0 );
+			attr_merge( e, "objectclasses", vals );
+			ldap_memfree( val.bv_val );
+		} else {
+			return -1;
+		}
+	}
+	return 0;
+}
+
+void
+schema_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
+{
+	Entry		*e;
+	struct berval	val;
+	struct berval	*vals[2];
+
+	vals[0] = &val;
+	vals[1] = NULL;
+
+	e = (Entry *) ch_calloc( 1, sizeof(Entry) );
+
+	e->e_attrs = NULL;
+	e->e_dn = ch_strdup( SLAPD_SCHEMA_DN );
+	e->e_ndn = dn_normalize_case( ch_strdup( SLAPD_SCHEMA_DN ));
+	e->e_private = NULL;
+
+	val.bv_val = ch_strdup( "top" );
+	val.bv_len = strlen( val.bv_val );
+	attr_merge( e, "objectclass", vals );
+	ldap_memfree( val.bv_val );
+
+	val.bv_val = ch_strdup( "subschema" );
+	val.bv_len = strlen( val.bv_val );
+	attr_merge( e, "objectclass", vals );
+	ldap_memfree( val.bv_val );
+
+	if ( at_schema_info( e ) ) {
+		/* Out of memory, do something about it */
+		entry_free( e );
+		return;
+	}
+	if ( oc_schema_info( e ) ) {
+		/* Out of memory, do something about it */
+		entry_free( e );
+		return;
+	}
+	
+	send_search_entry( &backends[0], conn, op, e, attrs, attrsonly );
+	send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+
+	entry_free( e );
+}
+#endif
+
 #ifdef LDAP_DEBUG
 
 static void
@@ -458,10 +529,10 @@ oc_print( ObjectClass *oc )
 {
 	int	i;
 
-	if ( oc->soc_oclass.oc_names && oc->soc_oclass.oc_names[0] ) {
-		printf( "objectclass %s\n", oc->soc_oclass.oc_names[0] );
+	if ( oc->soc_names && oc->soc_names[0] ) {
+		printf( "objectclass %s\n", oc->soc_names[0] );
 	} else {
-		printf( "objectclass %s\n", oc->soc_oclass.oc_oid );
+		printf( "objectclass %s\n", oc->soc_oid );
 	}
 	if ( oc->soc_required != NULL ) {
 		printf( "\trequires %s", oc->soc_required[0] );
diff --git a/servers/slapd/schemaparse.c b/servers/slapd/schemaparse.c
index 83865d488b..e68d0dcaec 100644
--- a/servers/slapd/schemaparse.c
+++ b/servers/slapd/schemaparse.c
@@ -10,10 +10,8 @@
 #include "slap.h"
 #include "ldap_schema.h"
 
-ObjectClass 		*global_oc;
 static Avlnode		*object_classes = NULL;
 
-AttributeType		*global_at;
 int	global_schemacheck = 1; /* schemacheck on is default */
 
 static void		oc_usage_old(void);
diff --git a/servers/slapd/search.c b/servers/slapd/search.c
index 715376341b..bb0ee0f6b2 100644
--- a/servers/slapd/search.c
+++ b/servers/slapd/search.c
@@ -122,7 +122,7 @@ do_search(
 #endif
 #if defined( SLAPD_SCHEMA_DN )
 		if ( strcmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
-			schema_info( conn, op );
+			schema_info( conn, op, attrs, attrsonly );
 			goto return_results;
 		}
 #endif
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index fb857e8da4..8f5f692519 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -234,6 +234,20 @@ typedef struct slap_attribute_type {
 	int				sat_syntax_compat;
 	struct slap_attribute_type	*sat_next;
 } AttributeType;
+#define sat_oid			sat_atype.at_oid
+#define sat_names		sat_atype.at_names
+#define sat_desc		sat_atype.at_desc
+#define sat_obsolete		sat_atype.at_obsolete
+#define sat_sup_oid		sat_atype.at_sup_oid
+#define sat_equality_oid	sat_atype.at_equality_oid
+#define sat_ordering_oid	sat_atype.at_ordering_oid
+#define sat_substr_oid		sat_atype.at_substr_oid
+#define sat_syntax_oid		sat_atype.at_syntax_oid
+#define sat_syntax_len		sat_atype.at_syntax_len
+#define sat_single_value	sat_atype.at_single_value
+#define sat_collective		sat_atype.at_collective
+#define sat_no_user_mods	sat_atype.at_no_user_mods
+#define sat_usage		sat_atype.at_usage
 
 typedef struct slap_object_class {
 	LDAP_OBJECT_CLASS		soc_oclass;
@@ -242,6 +256,14 @@ typedef struct slap_object_class {
 	AttributeType			**soc_allowed;
 	struct slap_object_class	*soc_next;
 } ObjectClass;
+#define soc_oid			soc_oclass.oc_oid
+#define soc_names		soc_oclass.oc_names
+#define soc_desc		soc_oclass.oc_desc
+#define soc_obsolete		soc_oclass.oc_obsolete
+#define soc_sup_oids		soc_oclass.oc_sup_oids
+#define soc_kind		soc_oclass.oc_kind
+#define soc_at_oids_must	soc_oclass.oc_at_oids_must
+#define soc_at_oids_may		soc_oclass.oc_at_oids_may
 
 /*
  * Backend-info
-- 
GitLab