/* * 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 #include #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 . ** ** The up to bytes pointed to by may be ** a prefix. All definition records in with type ** name possible prefixes. Find the longest prefix ** that occurs at the start of 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 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 ** 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 in bytes. ** ** Returns: ** NULL on failure, otherwise a pointer to the ** first record on or after whose type is ** and whose name is [0...-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; }