|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 22873 (0x5959) Types: TextFile Names: »ds_search.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/quipu/ds_search.c«
/* ds_search.c - DSA search of the directory */ #ifndef lint static char *rcsid = "$Header: /f/osi/quipu/RCS/ds_search.c,v 6.0 89/03/18 23:41:23 mrose Rel $"; #endif /* * $Header: /f/osi/quipu/RCS/ds_search.c,v 6.0 89/03/18 23:41:23 mrose Rel $ * * * $Log: ds_search.c,v $ * Revision 6.0 89/03/18 23:41:23 mrose * Release 5.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ #include "quipu/util.h" #include "quipu/entry.h" #include "quipu/list.h" /* to get LSR # defs */ #include "quipu/ds_search.h" #include "config.h" extern LLog * log_dsap; #ifndef NO_STATS extern LLog * log_stat; extern int dn_print (); #endif #define ASPE as->attr_value->avseq_av static EntryInfo *filterentry(); static EntryInfo *filterchildren(); static test_avs(); static apply_search(); static soundex_search (); static substr_search(); static aux_substr_search(); static check_filteritem_presrch (); static check_filter_presrch (); static check_filterop_presrch (); static check_filteritem (); static check_filter (); static check_filterop (); struct ds_search_task * st_done (); static search_refer (); static do_alias (); Entry list_find_entry(); extern Entry database_root; static int size; static time_t srtime; static time_t cnttime; extern time_t time(); static DN binddn; static DN path; extern DN super_user; extern int search_level; Attr_Sequence eis_select (); do_ds_search (arg, error, result, dnbind, target, local, refer) register struct ds_search_arg *arg; struct ds_search_result *result; struct DSError *error; DN dnbind; DN target; struct ds_search_task ** local, ** refer; { extern time_t admin_time; extern int admin_size; if (*local == NULL_ST) { DLOG (log_dsap,LLOG_TRACE,("ds_search")); if (target == NULLDN) target = arg->sra_baseobject; #ifndef NO_STATS dn_decode (target); switch (arg->sra_subset) { case SRA_ONELEVEL: pslog (log_stat,LLOG_NOTICE,"search (onelevel)",dn_print,(caddr_t)target); break; case SRA_WHOLESUBTREE: pslog (log_stat,LLOG_NOTICE,"search (subtree)",dn_print,(caddr_t)target); break; default: pslog (log_stat,LLOG_NOTICE,"search (baseobject)",dn_print,(caddr_t)target); break; } #endif /* Put local stuff straight into result structure (dangerous) */ result->srr_correlated = TRUE; result->srr_un.srr_unit = (struct ds_search_unit *) calloc(1, sizeof(struct ds_search_unit)); *local = st_alloc(); (*local)->st_baseobject = dn_cpy (target); (*local)->st_subset = arg->sra_subset; (*local)->st_alias = NULLDN; if (((*local)->st_size = MIN(admin_size,arg->sra_common.ca_servicecontrol.svc_sizelimit)) == SVC_NOSIZELIMIT) (*local)->st_size = admin_size; if (((*local)->st_time = MIN(admin_time,arg->sra_common.ca_servicecontrol.svc_timelimit)) == SVC_NOTIMELIMIT) (*local)->st_time = admin_time; (*local)->st_cr = NULLCONTINUATIONREF; (*local)->st_next = NULL_ST; result->CSR_entries = NULLENTRYINFO; if (check_filter_presrch (arg->sra_filter,error) != OK) return (DS_ERROR_REMOTE); else { Entry entryptr; if (arg->sra_subset == SRA_BASEOBJECT) entryptr = find_entry ((*local)->st_baseobject,&arg->sra_common,error,dnbind); else entryptr = list_find_entry ((*local)->st_baseobject,&arg->sra_common,error,dnbind); if (entryptr != NULLENTRY) { /* if no error and NOT SVC_OPT_DONTDEREFERENCEALIASES then */ /* the alias will have been derefeferenced -signified by */ /* NO_ERROR !!! */ if (error->dse_type == DSE_NOERROR) { result->CSR_object = NULLDN; result->CSR_common.cr_aliasdereferenced = FALSE; } else { result->CSR_common.cr_aliasdereferenced = TRUE; result->CSR_object = get_copy_dn (entryptr); } /* one final check - will we allow such searched in this DSA ? */ if (arg->sra_subset == SRA_WHOLESUBTREE) { DN dn; int x = 0; for (dn = (*local)->st_baseobject; dn!= NULLDN; dn=dn->dn_parent, x++) ; if ( x < search_level ) { if (dn_cmp (dnbind,super_user) != OK) { /* Too high */ error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNWILLINGTOPERFORM; return (DS_ERROR_REMOTE); } } } return (DS_CONTINUE); /* yup - we will take the search on */ } else { if (error->dse_type == DSE_REFERRAL) return (DS_ERROR_CONNECT); /* can't co-ordinate it */ else return (DS_ERROR_REMOTE); } } } else { DLOG (log_dsap,LLOG_NOTICE,("ds_search continuing")); binddn = dnbind; size = (*local)->st_size; srtime = (*local)->st_time; cnttime = time((time_t *)0); if ((*local)->st_alias == NULLDN) path = (*local)->st_baseobject; else path = (*local)->st_alias; if ((apply_search (arg,error,result,local,refer)) == NOTOK) { st_free (local); st_free (refer); return (DS_ERROR_REMOTE); } if (cnttime < (time((time_t *)0) - srtime)) { st_free (local); st_free (refer); result->CSR_limitproblem = LSR_TIMELIMITEXCEEDED; return (DS_OK); } if (size <= 0) { st_free (local); st_free (refer); if (arg->sra_common.ca_servicecontrol.svc_sizelimit == SVC_NOSIZELIMIT) result->CSR_limitproblem = LSR_ADMINSIZEEXCEEDED; else if (admin_size < arg->sra_common.ca_servicecontrol.svc_sizelimit) result->CSR_limitproblem = LSR_ADMINSIZEEXCEEDED; else result->CSR_limitproblem = LSR_SIZELIMITEXCEEDED; return (DS_OK); } if ((*local)->st_next == NULL_ST) { st_free (local); return (DS_OK); } else { (*local) = st_done(local); (*local)->st_size = size; (*local)->st_time = srtime - (time((time_t *)0) - cnttime); return (DS_CONTINUE); } } } /* * SEARCH TASK HANDLING */ st_comp_free (st) struct ds_search_task *st; { dn_free (st->st_baseobject); dn_free (st->st_alias); crefs_free (st->st_cr); free (st); } st_free (st) struct ds_search_task **st; { for (; (*st) != NULL_ST; (*st) = (*st)->st_next) st_comp_free (*st); } struct ds_search_task * st_done (st) struct ds_search_task **st; { struct ds_search_task *next; next = (*st)->st_next; st_comp_free (*st); return (next); } /* * CHECK FILTER BEFORE SEARCHING */ static check_filter_presrch (fltr,error) register Filter fltr; struct DSError *error; { DLOG (log_dsap,LLOG_DEBUG,("in check filter aux")); switch (fltr->flt_type) { case FILTER_ITEM: return (check_filteritem_presrch (&fltr->FUITEM,error)); case FILTER_AND: case FILTER_OR: return(check_filterop_presrch (fltr->FUFILT,error)); case FILTER_NOT: return(check_filter_presrch (fltr->FUFILT,error)); default: LLOG (log_dsap,LLOG_EXCEPTIONS,("check_filter protocol error")); error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; return (NOTOK); } /* NOTREACHED */ } static check_filterop_presrch (fltr,error) register Filter fltr; struct DSError * error; { register Filter ptr; int i; DLOG (log_dsap,LLOG_DEBUG,("in filter op aux")); for (ptr=fltr; ptr!=NULLFILTER ; ptr=ptr->flt_next) { i = check_filter_presrch (ptr,error); if (i != OK) return (NOTOK); } return (OK); } static check_filteritem_presrch (fitem,error) register struct filter_item *fitem; struct DSError * error; { DLOG (log_dsap,LLOG_DEBUG,("search: check filter item aux")); if (fitem == NULLFITEM) { LLOG (log_dsap,LLOG_EXCEPTIONS,("check_filter_item protocol error (1)")); error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; return (NOTOK); } switch ( fitem->fi_type) { case FILTERITEM_APPROX: ava_decode (&fitem->UNAVA); AttrT_decode (fitem->UNAVA.ava_type); if (fitem->UNAVA.ava_type->at_table == NULLTABLE_ATTR) return (invalid_matching (fitem->UNAVA.ava_type,error)); if ((fitem->UNAVA.ava_type->at_table->oa_syntax== AV_CASEEXACTSTRING) || (fitem->UNAVA.ava_type->at_table->oa_syntax == AV_CASEIGNORESTRING)) { fitem_soundex_key (fitem); break; } else /* approx not suported for this type */ /* so set it to equality */ fitem->fi_type = FILTERITEM_EQUALITY; /* NO break - check equality is OK */ case FILTERITEM_EQUALITY: case FILTERITEM_GREATEROREQUAL: case FILTERITEM_LESSOREQUAL: AttrT_decode(fitem->UNAVA.ava_type); ava_decode (&fitem->UNAVA); if (fitem->UNAVA.ava_type->at_table == NULLTABLE_ATTR) return (invalid_matching (fitem->UNAVA.ava_type,error)); switch (fitem->UNAVA.ava_type->at_table->oa_syntax) { case AV_ACL: case AV_SCHEMA: case AV_UPDATE: /* if matching written, allow the match */ return (invalid_matching (fitem->UNAVA.ava_type,error)); } break; case FILTERITEM_SUBSTRINGS: AttrT_decode (fitem->UNSUB.fi_sub_type); avs_decode (fitem->UNSUB.fi_sub_type, fitem->UNSUB.fi_sub_initial); avs_decode (fitem->UNSUB.fi_sub_type, fitem->UNSUB.fi_sub_any); avs_decode (fitem->UNSUB.fi_sub_type, fitem->UNSUB.fi_sub_final); if (fitem->UNSUB.fi_sub_type->at_table == NULLTABLE_ATTR) return (invalid_matching (fitem->UNSUB.fi_sub_type,error)); switch (fitem->UNSUB.fi_sub_type->at_table->oa_syntax) { case AV_CASEEXACTSTRING: case AV_CASEIGNORESTRING: break; default: return (invalid_matching (fitem->UNSUB.fi_sub_type,error)); } case FILTERITEM_PRESENT: break; default: LLOG (log_dsap,LLOG_EXCEPTIONS,("check_filter_item protocol error (2)")); error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; return (NOTOK); } return (OK); } /* APPLY SEARCH TO ONE LEVEL */ static apply_search (arg,error,result,local,refer) struct ds_search_arg *arg; struct DSError *error; struct ds_search_result *result; struct ds_search_task **local, **refer; { Entry entryptr; EntryInfo *einfo = NULLENTRYINFO; if ((*local)->st_subset == SRA_BASEOBJECT) entryptr = find_entry ((*local)->st_baseobject,&arg->sra_common,error,binddn); else entryptr = list_find_entry ((*local)->st_baseobject,&arg->sra_common,error,binddn); if (entryptr != NULLENTRY) { switch ((*local)->st_subset) { case SRA_BASEOBJECT: einfo = filterentry (arg,entryptr); break; case SRA_ONELEVEL: case SRA_WHOLESUBTREE: einfo = filterchildren (arg,entryptr,local,refer,(*local)->st_subset); break; default: LLOG (log_dsap,LLOG_EXCEPTIONS,("search protocol error")); error->dse_type = DSE_SERVICEERROR; error->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE; return (NOTOK); } if (einfo != NULLENTRYINFO) if (result->CSR_entries == NULLENTRYINFO) result->CSR_entries = einfo; else entryinfo_append (result->CSR_entries,einfo); result->CSR_common.cr_requestor = NULLDN; result->CSR_cr = NULLCONTINUATIONREF; if (size < 0) result->CSR_limitproblem = LSR_SIZELIMITEXCEEDED; else result->CSR_limitproblem = LSR_NOLIMITPROBLEM; return (OK); } if (error->dse_type == DSE_REFERRAL) { /* turn query into a referral */ struct ds_search_task * new_task; new_task = st_alloc(); new_task->st_baseobject = dn_cpy ((*local)->st_baseobject); new_task->st_subset = (*local)->st_subset; new_task->st_alias = dn_cpy ((*local)->st_baseobject); if ((new_task->st_size = MIN(admin_size,arg->sra_common.ca_servicecontrol.svc_sizelimit)) == SVC_NOSIZELIMIT) new_task->st_size = admin_size; if ((new_task->st_time = MIN(admin_time,arg->sra_common.ca_servicecontrol.svc_timelimit)) == SVC_NOTIMELIMIT) new_task->st_time = admin_time; new_task->st_cr = error->ERR_REFERRAL.DSE_ref_candidates; new_task->st_next = *refer; *refer = new_task; return (OK); } return (NOTOK); } /* * SEARCH CHILDREN */ static EntryInfo * filterchildren (arg,entryptr,local,refer,extent) struct ds_search_arg *arg; Entry entryptr; struct ds_search_task **local, **refer; int extent; { register EntryInfo *einfo = NULLENTRYINFO; register EntryInfo *eptr = NULLENTRYINFO; register Entry ptr; DN dnend, dnsave; RDN freeend; struct ds_search_task * new_task; DLOG (log_dsap,LLOG_DEBUG,("search: filter children")); if (entryptr == NULLENTRY) return (NULLENTRYINFO); if (entryptr->e_leaf) return (NULLENTRYINFO); if (check_acl (binddn, ACL_READ, entryptr->e_acl->ac_child, (*local)->st_baseobject) == NOTOK) { return (NULLENTRYINFO); } if (( ptr=entryptr->e_child ) == NULLENTRY) { search_refer (arg,entryptr,local,refer); return (NULLENTRYINFO); } if (path == NULLDN) { path = dn_comp_new(rdn_cpy(entryptr->e_child->e_name)); freeend = path->dn_rdn; dnend = path; } else { for (dnend=path; dnend->dn_parent != NULLDN; dnend=dnend->dn_parent) ; /* NULL */ dnend->dn_parent = dn_comp_new(rdn_cpy(entryptr->e_child->e_name)); freeend = dnend->dn_parent->dn_rdn; dnsave = dnend; dnend = dnend ->dn_parent; } for (; (ptr != NULLENTRY) && (size > 0) ; ptr=ptr->e_sibling) { dnend->dn_rdn = ptr->e_name; if (ptr->e_alias != NULLDN) { do_alias (arg,ptr,local); continue; } else eptr = filterentry (arg,ptr); if (eptr != NULLENTRYINFO) if (einfo == NULLENTRYINFO) einfo = eptr; else entryinfo_append (einfo,eptr); if ( (extent == SRA_WHOLESUBTREE) && (!ptr->e_leaf)) { if (check_acl (binddn, ACL_READ, ptr->e_acl->ac_child, path) == OK) { if (((ptr->e_child != NULLENTRY) && (ptr->e_allchildrenpresent == FALSE)) || (ptr->e_child == NULLENTRY)) search_refer (arg,ptr,local,refer); else { new_task = st_alloc(); new_task->st_baseobject = dn_cpy(path); new_task->st_size = 0; /* fill in later */ new_task->st_time = 0; new_task->st_alias = NULLDN; new_task->st_cr = NULLCONTINUATIONREF; new_task->st_subset = SRA_WHOLESUBTREE; new_task->st_next = (*local)->st_next; (*local)->st_next = new_task; } } } } if (path->dn_parent == NULLDN) { path->dn_rdn = NULLRDN; dn_free (path); path = NULLDN; } else { dnend->dn_rdn = NULLRDN; dn_free (dnend); dnsave->dn_parent = NULLDN; } rdn_free (freeend); return (einfo); } /* * HANDLE ALIASES AND REFERRALS */ static do_alias (arg,eptr,local) struct ds_search_arg *arg; Entry eptr; struct ds_search_task **local; { struct ds_search_task *new_task; if ( (arg->sra_common.ca_servicecontrol.svc_options & SVC_OPT_DONTDEREFERENCEALIAS) != 0) return; DLOG (log_dsap,LLOG_DEBUG,("alias in search path")); new_task = st_alloc(); new_task->st_baseobject = dn_cpy(eptr->e_alias); new_task->st_size = 0; /* fill in later */ new_task->st_time = 0; new_task->st_alias = get_copy_dn (eptr); new_task->st_cr = NULLCONTINUATIONREF; switch ((*local)->st_subset) { case SRA_ONELEVEL: case SRA_BASEOBJECT: new_task->st_subset = SRA_BASEOBJECT; break; case SRA_WHOLESUBTREE: new_task->st_subset = SRA_WHOLESUBTREE; break; } new_task->st_next = (*local)->st_next; (*local)->st_next = new_task; } static search_refer(arg,entryptr,local,refer) struct ds_search_arg *arg; Entry entryptr; struct ds_search_task **local, **refer; { struct ds_search_task *new_task; ContinuationRef ref,cont_ref_new(); DN name; name = get_copy_dn (entryptr); if ((ref = cont_ref_new (name,entryptr)) == NULLCONTINUATIONREF) { dn_free (name); return; /* leaf or invalid reference !!! */ } DLOG (log_dsap,LLOG_DEBUG,("referral in search path")); new_task = st_alloc(); new_task->st_baseobject = name; new_task->st_subset = (*local)->st_subset; new_task->st_alias = NULLDN; if ((new_task->st_size = MIN(admin_size,arg->sra_common.ca_servicecontrol.svc_sizelimit)) == SVC_NOSIZELIMIT) new_task->st_size = admin_size; if ((new_task->st_time = MIN(admin_time,arg->sra_common.ca_servicecontrol.svc_timelimit)) == SVC_NOTIMELIMIT) new_task->st_time = admin_time; new_task->st_cr = ref; new_task->st_next = *refer; *refer = new_task; } /* * SEARCH ENTRY */ static EntryInfo * filterentry (arg,entryptr) struct ds_search_arg *arg; register Entry entryptr; { register EntryInfo * einfo; register Attr_Sequence as; DLOG (log_dsap,LLOG_DEBUG,("search: filter entry")); if (check_filter (arg->sra_filter,entryptr) != OK ) { DLOG (log_dsap,LLOG_DEBUG,("none found")); return (NULLENTRYINFO); } as = eis_select (arg->sra_eis, entryptr, binddn); einfo = entryinfo_alloc (); einfo->ent_dn = dn_cpy (path); einfo->ent_attr = as; einfo->ent_iscopy = entryptr->e_data; einfo->ent_age = (time_t) 0; einfo->ent_next = NULLENTRYINFO; size--; return (einfo); } /* * TEST FILTER AGAINST SINGLE ENTRY */ static check_filter (fltr,entryptr) register Filter fltr; register Entry entryptr; { register int i; DLOG (log_dsap,LLOG_DEBUG,("in check filter")); switch (fltr->flt_type) { case FILTER_ITEM: return (check_filteritem (&fltr->FUITEM,entryptr)); case FILTER_AND: case FILTER_OR: return(check_filterop (fltr->FUFILT,entryptr,fltr->flt_type)); case FILTER_NOT: i = check_filter (fltr->FUFILT,entryptr); if ( i == -2) return (-2); else if (i == OK) return (NOTOK); else return (OK); } /* NOTREACHED */ } static check_filterop (fltr,entryptr,op) register Filter fltr; register Entry entryptr; int op; { register Filter ptr; DLOG (log_dsap,LLOG_DEBUG,("in filter op")); for (ptr=fltr; ptr!=NULLFILTER ; ptr=ptr->flt_next) switch (check_filter (ptr,entryptr)) { case -2: return (-2); case 0: if (op == FILTER_OR) { DLOG (log_dsap,LLOG_DEBUG,("or ok")); return (OK); } break; default: if (op == FILTER_AND) { DLOG (log_dsap,LLOG_DEBUG,("and not")); return (NOTOK); } break; } if (op == FILTER_OR) return (NOTOK); else return (OK); } /* * CHECK FILTER ITEM AGAINST ENTRY */ static check_filteritem (fitem,entryptr) register struct filter_item *fitem; register Entry entryptr; { register Attr_Sequence as; AttributeType at; DLOG (log_dsap,LLOG_DEBUG,("search: check filter item")); switch ( fitem->fi_type) { case FILTERITEM_APPROX: case FILTERITEM_EQUALITY: case FILTERITEM_GREATEROREQUAL: case FILTERITEM_LESSOREQUAL: at = fitem->UNAVA.ava_type; break; case FILTERITEM_SUBSTRINGS: at = fitem->UNSUB.fi_sub_type; break; case FILTERITEM_PRESENT: at = fitem->UNTYPE; break; } if ((as = as_find_type (entryptr->e_attributes, at)) == NULLATTR) return (NOTOK); switch ( fitem->fi_type) { case FILTERITEM_SUBSTRINGS: return (substr_search (fitem,as->attr_value)); case FILTERITEM_APPROX: return (soundex_search (fitem,as->attr_value)); case FILTERITEM_PRESENT: return (OK); default: return (test_avs (fitem,as->attr_value,fitem->fi_type)); } /* NOTREACHED */ } static test_avs (fitem,avs,mode) register struct filter_item *fitem; register AV_Sequence avs; register int mode; { register int i; struct DSError error; for (; avs != NULLAV; avs=avs->avseq_next) { i = AttrV_cmp (avs->avseq_av, fitem->UNAVA.ava_value,&error); switch (i) { case 0: return (OK); case -1: if (mode == FILTERITEM_GREATEROREQUAL) return (OK); break; case 1: if (mode == FILTERITEM_LESSOREQUAL) return (OK); break; default: ds_error_free (&error); /* not interested in errs here */ } } return (NOTOK); } /* * APPROX SEARCH */ static soundex_search (fitem,avs) register struct filter_item *fitem; register AV_Sequence avs; { for (; avs != NULLAV; avs=avs->avseq_next) if (soundex_cmp (avs->avseq_soundex, fitem->fi_soundex) == OK) return (OK); return (NOTOK); } /* * SUBSTRING MATCH */ static substr_search (fitem,avs) register struct filter_item *fitem; register AV_Sequence avs; { extern char chrcnv[]; extern char nochrcnv[]; for (; avs != NULLAV; avs=avs->avseq_next) switch (avs->avseq_av->av_syntax) { case AV_CASEEXACTSTRING: if (aux_substr_search (fitem,avs,nochrcnv) == OK) return (OK); break; case AV_CASEIGNORESTRING: if (aux_substr_search (fitem,avs,chrcnv) == OK) return (OK); break; } return (NOTOK); } static aux_substr_search (fitem,avs,chrmatch) struct filter_item *fitem; AV_Sequence avs; char chrmatch []; { register AV_Sequence loopavs; register char * compstr; char * top; register char * temp; char * temp2; int offset; compstr = avs->avseq_av->av_un.av_str; top = compstr; if (fitem->UNSUB.fi_sub_initial != NULLAV) { temp = fitem->UNSUB.fi_sub_initial->avseq_av->av_un.av_str; do if (chrmatch[*compstr++] != chrmatch[*temp++]) { DLOG (log_dsap,LLOG_DEBUG,("initial failure (%s, %s)",top,fitem->UNSUB.fi_sub_initial->avseq_av->av_un.av_str)); return (NOTOK); } while (*temp != '\0') ; } for (loopavs=fitem->UNSUB.fi_sub_any; loopavs!=NULLAV; loopavs=loopavs->avseq_next, compstr += offset) if ((offset= attr_substr (compstr, loopavs->avseq_av,chrmatch)) == -1) { DLOG (log_dsap,LLOG_DEBUG,("any failure (%s, %s)",top,loopavs->avseq_av->av_un.av_str)); return (NOTOK); } if (fitem->UNSUB.fi_sub_final != NULLAV) { temp = fitem->UNSUB.fi_sub_final->avseq_av->av_un.av_str; temp2 = temp; while (*++compstr != '\0') ; /* NO-OP*/ while (*temp++ != '\0') compstr--; if (compstr < top) { DLOG (log_dsap,LLOG_DEBUG,("final too long failure (%s,%s)",top,temp2)); return (NOTOK); } temp = temp2; while (*compstr != '\0') if (chrmatch[*compstr++] != chrmatch[*temp++]) { /* free (top); */ DLOG (log_dsap,LLOG_DEBUG,("final failure (%s, %s)",top,temp2)); return (NOTOK); } } return (OK); } attr_substr (str1,av,chrmatch) register char * str1; AttributeValue av; char chrmatch[]; { register char * str2; register int count; char * top; int found = 0; int slen; top = str1; str2 = av->av_un.av_str; while (*str1 != '\0') { if (chrmatch[*str1++] == chrmatch[*str2]) { str2++; found = 1; break; } } if ( found == 0 ) return (-1); slen = strlen (str2) + 1; for (count = 1; count < slen ; count ++) { if (*str1 == '\0') return (-1); if (chrmatch[*str1++] != chrmatch[*str2++]) { /* not found here, but may still be in the string !! */ str1 -= count; str2 -= count + 1; while (*str1 != '\0') { if (chrmatch[*str1++] == chrmatch[*str2]) { str2++; break; } } count = 0; /* for loop ++ will make it 1 !!! */ } } return (str1 - top); }