|
|
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);
}