/* * 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-argv.c,v 1.9 2005/05/24 17:57:28 ca Exp $") #if SM_LIBCONF_ALONE #include #include "sm-conf.h" #else /* SM_LIBCONF_ALONE */ #include "sm/string.h" #include "sm/memops.h" #include "sm/sm-conf.h" #endif /* SM_LIBCONF_ALONE */ #include "sm-conf-type.h" #include "sm-conf-state.h" static int sm_conf_type_argv_node_to_value( sm_conf_T *smc, sm_conf_definition_T const *def, sm_conf_node_T *node, void *out) { size_t argv_n; int err; char loc[SM_CONF_ERROR_BUFFER_SIZE]; char const * const *argv, * const *p; SM_IS_CONF_DEF(def); if (sm_conf_node_type(smc, node) == SM_CONF_NODE_SECTION) { sm_conf_error_add(smc, "%s: %s%sexpected string or array, got section", sm_conf_node_location(smc, node, loc, sizeof loc), def->scd_name, def->scd_name[0] == '\0' ? "" : ": "); return SM_CONF_ERR_TYPE; } err = sm_conf_node_argv(smc, (sm_conf_node_T *)node, &argv); if (err) { char errbuf[SM_CONF_ERROR_BUFFER_SIZE]; sm_conf_error_add(smc, "%s: %s%s%s", sm_conf_node_location(smc, node, loc, sizeof loc), def->scd_name, def->scd_name[0] == '\0' ? "" : ": ", sm_conf_strerror(err, errbuf, sizeof errbuf)); return err; } if (argv == NULL) argv_n = 0; else { for (p = argv; *p != NULL; p++) ; argv_n = p - argv; } if (def->scd_size > 0) { if (argv_n > def->scd_size) { sm_conf_error_add(smc, "%s: %s%soverflow -- " "too many elements in list", sm_conf_node_location(smc, node, loc, sizeof loc), def->scd_name, def->scd_name[0] == '\0' ? "" : ": "); return SM_CONF_ERR_TYPE; } if (out != NULL) { if (argv_n > 0) sm_memcpy(out, argv, argv_n * sizeof(char **)); while (argv_n < def->scd_size) ((char const **)out)[argv_n++] = NULL; } } else { if (out != NULL) *(char const * const **)out = argv; } return err; } static int sm_conf_type_argv_value_check( sm_conf_T *smc, sm_conf_definition_T const *def, void const *data) { SM_IS_CONF_DEF(def); SM_REQUIRE(smc != NULL); if (data == NULL) return 0; /* 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_argv_value_null( sm_conf_T *smc, sm_conf_definition_T const *def, void *out) { char const * const *default_av; size_t i; if (out == NULL) return 0; SM_IS_CONF_DEF(def); default_av = (char const * const *)def->scd_default; if (def->scd_size == 0) *(char const * const **)out = default_av; else { /* copy entries from the default until we hit NULL */ i = 0; if (default_av != NULL) while (i < def->scd_size && default_av[i] != NULL) { ((char const **)out)[i] = default_av[i]; i++; } while (i < def->scd_size) { ((char const **)out)[i] = NULL; i++; } } return 0; } sm_conf_type_T const sm_conf_type_argv_data = { sm_conf_type_argv_node_to_value, sm_conf_type_argv_value_check, sm_conf_type_argv_value_null };