/* * Copyright (c) 2004, 2005 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-type-u32.c,v 1.19 2005/05/24 17:57:28 ca Exp $") #if SM_LIBCONF_ALONE #include #include #include #include #include "sm-conf.h" #else /* SM_LIBCONF_ALONE */ #include "sm/limits.h" #include "sm/error.h" #include "sm/ctype.h" #include "sm/memops.h" #include "sm/string.h" #include "sm/sm-conf.h" #endif /* SM_LIBCONF_ALONE */ #include "sm-conf-node.h" #include "sm-conf-state.h" #include "sm-conf-type.h" #include "sm-conf-util.h" #include "sm-conf-u32.h" /* flag */ sm_conf_type_T const sm_conf_type_u32_suffix_data, sm_conf_type_u32_maximum_data, sm_conf_type_u32_minimum_data; /* return the first definition of type */ static sm_conf_definition_T const * first_typed(sm_conf_definition_T const *def, sm_conf_type_T const *type) { if (def != NULL) { SM_IS_CONF_DEF(def); while (def->scd_name != NULL) { if (def->scd_type == type) return def; def++; } } return NULL; } static int u32_write( sm_conf_T *smc, sm_conf_node_T const *node, sm_conf_definition_T const *def, void *data, unsigned long val) { char loc[SM_CONF_ERROR_BUFFER_SIZE]; unsigned long limit_min; unsigned long limit_max; sm_conf_definition_T const *limit_def; SM_IS_CONF_DEF(def); limit_min = 0; limit_max = 0; if (def->scd_size == 1) { *(unsigned char *)data = val; limit_max = UCHAR_MAX; } else if (def->scd_size == sizeof(unsigned short)) { *(unsigned short *)data = val; limit_max = USHRT_MAX; } else if (def->scd_size == sizeof(unsigned int)) { *(unsigned int *)data = val; limit_max = UINT_MAX; } else if (def->scd_size == sizeof(unsigned long)) { *(unsigned long *)data = val; } else { sm_conf_error_add(smc, "%s: %s%sunexpected size %lu", sm_conf_node_location(smc, node, loc, sizeof loc), def->scd_name, def->scd_name[0] == '\0' ? "" : ": ", (unsigned long)def->scd_size); return SM_CONF_ERR_INVALID; } limit_def = first_typed(def->scd_contents, sm_conf_type_u32_maximum); if ( limit_def != NULL && (limit_max == 0 || limit_def->scd_offset < limit_max)) limit_max = limit_def->scd_offset; limit_def = first_typed(def->scd_contents, sm_conf_type_u32_minimum); if (limit_def != NULL) limit_min = limit_def->scd_offset; if (limit_max > 0 && val > limit_max) { sm_conf_error_add(smc, "%s: overflow error in %s '%lu'", sm_conf_node_location(smc, node, loc, sizeof loc), def->scd_name[0] == '\0' ? "value" : def->scd_name, val); return SM_CONF_ERR_TYPE; } if (val < limit_min) { sm_conf_error_add(smc, "%s: %s %lu must be at least %lu", sm_conf_node_location(smc, node, loc, sizeof loc), def->scd_name[0] == '\0' ? "value" : def->scd_name, val, limit_min); return SM_CONF_ERR_TYPE; } return 0; } static int sm_conf_type_u32_node_to_value( sm_conf_T *smc, sm_conf_definition_T const *def, sm_conf_node_T *node, void *data) { char const *text; size_t text_n; int err; unsigned long val; SM_IS_CONF_DEF(def); err = sm_conf_node_to_value(smc, "number", node, &text, &text_n); if (err != 0) return err; err = sm_conf_u32_scan(smc, node, def, text, text_n, &val); if (err != 0) return err; if (data != NULL) err = u32_write(smc, node, def, data, val); return err; } static int sm_conf_type_u32_value_check( sm_conf_T *smc, sm_conf_definition_T const *def, void const *data) { SM_IS_CONF_DEF(def); /* if we have a check function, use it. */ if (def->scd_check != NULL) return (* def->scd_check)(smc, def->scd_check_data, def, data); return 0; } static int sm_conf_type_u32_value_null( sm_conf_T *smc, sm_conf_definition_T const *def, void *data) { unsigned long val; int err; if (data != NULL) { SM_IS_CONF_DEF(def); val = 0; /* is there a default? if NULL: don't set value to 0 */ if (def->scd_default != NULL) { err = sm_conf_u32_scan(smc, NULL, def, def->scd_default, strlen(def->scd_default), &val); if (err != 0) return err; err = u32_write(smc, NULL, def, data, val); if (err != 0) return err; } } return 0; } sm_conf_type_T const sm_conf_type_u32_data = { sm_conf_type_u32_node_to_value, sm_conf_type_u32_value_check, sm_conf_type_u32_value_null };