+ return -1;
+}
+
+static int
+at_insert(
+ AttributeType *sat,
+ const char **err
+)
+{
+ AttributeType **atp;
+ struct aindexrec *air;
+ char **names;
+
+ atp = &attr_list;
+ while ( *atp != NULL ) {
+ atp = &(*atp)->sat_next;
+ }
+ *atp = sat;
+
+ if ( sat->sat_oid ) {
+ air = (struct aindexrec *)
+ ch_calloc( 1, sizeof(struct aindexrec) );
+ 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_oid;
+ ldap_memfree(air);
+ return SLAP_SCHERR_DUP_ATTR;
+ }
+ /* FIX: temporal consistency check */
+ at_find(air->air_name);
+ }
+ if ( (names = sat->sat_names) ) {
+ while ( *names ) {
+ air = (struct aindexrec *)
+ ch_calloc( 1, sizeof(struct aindexrec) );
+ air->air_name = ch_strdup(*names);
+ air->air_at = sat;
+ if ( avl_insert( &attr_index, (caddr_t) air,
+ (AVL_CMP) attr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = *names;
+ ldap_memfree(air);
+ return SLAP_SCHERR_DUP_ATTR;
+ }
+ /* FIX: temporal consistency check */
+ at_find(air->air_name);
+ names++;
+ }
+ }
+
+ return 0;
+}
+
+int
+at_add(
+ LDAP_ATTRIBUTE_TYPE *at,
+ const char **err
+)
+{
+ AttributeType *sat;
+ AttributeType *sat1;
+ MatchingRule *mr;
+ Syntax *syn;
+ int code;
+ char *errattr;
+
+ if ( at->at_names && at->at_names[0] ) {
+ errattr = at->at_names[0];
+ } else if ( at->at_oid ) {
+ errattr = at->at_oid;
+ } else {
+ errattr = "";
+ return SLAP_SCHERR_ATTR_INCOMPLETE;
+ }
+ sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
+ memcpy( &sat->sat_atype, at, sizeof(LDAP_ATTRIBUTE_TYPE));
+ if ( at->at_sup_oid ) {
+ if ( (sat1 = at_find(at->at_sup_oid)) ) {
+ sat->sat_sup = sat1;
+ if ( at_append_to_list(sat, &sat1->sat_subtypes) ) {
+ *err = errattr;
+ return SLAP_SCHERR_OUTOFMEM;
+ }
+ } else {
+ *err = at->at_sup_oid;
+ return SLAP_SCHERR_ATTR_NOT_FOUND;
+ }
+ }
+
+ if ( at->at_syntax_oid ) {
+ if ( (syn = syn_find(sat->sat_syntax_oid)) ) {
+ sat->sat_syntax = syn;
+ } else {
+ *err = sat->sat_syntax_oid;
+ return SLAP_SCHERR_SYN_NOT_FOUND;
+ }
+ if ( !strcmp(at->at_syntax_oid,
+ "1.3.6.1.4.1.1466.115.121.1.15") ) {
+ if ( at->at_equality_oid &&
+ !strcmp(at->at_equality_oid, "2.5.13.5") ) {
+ sat->sat_syntax_compat = SYNTAX_CES;
+ } else {
+ sat->sat_syntax_compat = SYNTAX_CIS;
+ }
+ } else if ( !strcmp(at->at_syntax_oid,
+ "1.3.6.1.4.1.1466.115.121.1.50") ) {
+ sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_TEL;
+ } else if ( !strcmp(at->at_syntax_oid,
+ "1.3.6.1.4.1.1466.115.121.1.12") ) {
+ sat->sat_syntax_compat = SYNTAX_CIS | SYNTAX_DN;
+ } else if ( !strcmp(at->at_syntax_oid, "1.3.6.1.4.1.1466.115.121.1.5") ) {
+ sat->sat_syntax_compat = SYNTAX_BIN;
+ } else {
+ sat->sat_syntax_compat = DEFAULT_SYNTAX;
+ }
+ } else {
+ sat->sat_syntax_compat = DEFAULT_SYNTAX;
+ }
+
+ if ( sat->sat_equality_oid ) {
+ if ( (mr = mr_find(sat->sat_equality_oid)) ) {
+ sat->sat_equality = mr;
+ } else {
+ *err = sat->sat_equality_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+ }
+ if ( sat->sat_ordering_oid ) {
+ if ( (mr = mr_find(sat->sat_ordering_oid)) ) {
+ sat->sat_ordering = mr;
+ } else {
+ *err = sat->sat_ordering_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+ }
+ if ( sat->sat_substr_oid ) {
+ if ( (mr = mr_find(sat->sat_substr_oid)) ) {
+ sat->sat_substr = mr;
+ } else {
+ *err = sat->sat_substr_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+ }
+
+ /*
+ * Now inherit definitions from superiors. We only check the
+ * direct superior since that one has already inherited from
+ * its own superiorss
+ */
+ if ( sat->sat_sup ) {
+ if ( !sat->sat_syntax ) {
+ sat->sat_syntax = sat->sat_sup->sat_syntax;
+ sat->sat_syntax_len = sat->sat_sup->sat_syntax_len;
+ }
+ if ( !sat->sat_equality ) {
+ sat->sat_equality = sat->sat_sup->sat_equality;
+ }
+ if ( !sat->sat_ordering ) {
+ sat->sat_ordering = sat->sat_sup->sat_ordering;
+ }
+ if ( !sat->sat_substr ) {
+ sat->sat_substr = sat->sat_sup->sat_substr;
+ }
+ }
+ code = at_insert(sat,err);
+ return code;
+}
+
+
+char *
+at_canonical_name( char * a_type )
+{
+ AttributeType *atp;
+
+ if ( (atp=at_find(a_type)) == NULL ) {
+
+ return a_type;
+
+ } else if ( atp->sat_names
+ && atp->sat_names[0]
+ && (*(atp->sat_names[0]) != '\0') ) {
+
+ return atp->sat_names[0];
+
+ } else if (atp->sat_oid && (*atp->sat_oid != '\0')) {
+
+ return atp->sat_oid;
+
+ } else {
+
+ return a_type;
+
+ }
+
+}/* char * at_canonica_name() */
+
+
+#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
+at_index_printnode( struct aindexrec *air )
+{
+
+ printf( "%s = %s\n", air->air_name, ldap_attributetype2str(&air->air_at->sat_atype) );