/*
* Copyright (c) 2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: sm-conf-util.c,v 1.10 2004/08/02 22:33:52 ca Exp $")
#if SM_LIBCONF_ALONE
#include <ctype.h>
#include <errno.h>
#include "sm-conf.h"
#else /* SM_LIBCONF_ALONE */
#include "sm/ctype.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/sm-conf.h"
#endif /* SM_LIBCONF_ALONE */
#include "sm-conf-util.h"
#include "sm-conf-state.h"
#if SM_LIBCONF_ALONE
/* strncasecmp that doesn't stop at \0 */
bool sm_memncaseeq(
char const *a,
size_t a_size,
char const *b,
size_t b_size)
{
size_t i;
if (a_size != b_size)
return false;
for (i = 0; i < a_size; i++, a++, b++)
{
if (isascii(*a) && isascii(*b))
{
if (tolower(*a) != tolower(*b))
return false;
}
else
{
if ((unsigned char)*a != (unsigned char)*b)
return false;
}
}
return true;
}
#endif /* SM_LIBCONF_ALONE */
/*
** SM_CONF_SUBDEF_PREFIX -- return the longest matching prefix in <name>.
**
** The up to <name_n> bytes pointed to by <name> may be
** a prefix. All definition records in <def> with type
** <type> name possible prefixes. Find the longest prefix
** that occurs at the start of <name> and return it and its length.
**
** Parameters:
** def -- the resource list of the containing type;
** terminated by a record with NULL name.
** type -- the type of prefix we're looking at.
** Resources in the definition list that don't
** have type <type> are ignored.
** name -- string we're trying to match a suffix in
** name_n -- # of bytes we can access, at most.
** len -- out: how many bytes did we actually match?
**
** Returns:
** NULL if no suffix was found, otherwise a pointer
** to the matching definition record.
**
** Last code review:
** Last code change: 2004-07-12 15:42:47 jutta
*/
sm_conf_definition_T const *
sm_conf_subdef_prefix(
sm_conf_definition_T const *def,
sm_conf_type_T const *type,
char const *name,
size_t name_n,
size_t *len)
{
sm_conf_definition_T const *best_def = NULL;
size_t best_len = 0;
if (name_n != 0 && def != NULL)
{
size_t n;
SM_IS_CONF_DEF(def);
while (def->scd_name != NULL)
{
n = strlen(def->scd_name);
if (n <= name_n
&& sm_memncaseeq(
def->scd_name, strlen(def->scd_name),
name, n)
&& def->scd_type == type)
{
if ( best_def == NULL
|| best_len < n)
{
best_def = def;
best_len = n;
}
}
def++;
}
}
*len = best_len;
return best_def;
}
/*
** SM_CONF_SUBDEF -- return a subdefinition with a name and type
**
** Parameters:
** def -- NULL or start of a sentinel-terminated array
** of subdefinitions. Those with type <type>
** are the possible values
**
** type -- if non-NULL, only entries of this type are
** taken into account
** name -- if non-NULL, name we're looking for
** name_n -- length of <name> in bytes.
**
** Returns:
** NULL on failure, otherwise a pointer to the
** first record on or after <def> whose type is <type>
** and whose name is <name>[0...<name_n>-1].
*/
sm_conf_definition_T const *
sm_conf_subdef(
sm_conf_definition_T const *def,
sm_conf_type_T const *type,
char const *name,
size_t name_n)
{
if (def != NULL)
{
SM_IS_CONF_DEF(def);
while (def->scd_name != NULL)
{
if ( (name == NULL || sm_memncaseeq(
def->scd_name, strlen(def->scd_name),
name, name_n))
&& (type == NULL || def->scd_type == type))
return def;
def++;
}
}
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1