/*
* 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 <string.h>
#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
};
syntax highlighted by Code2HTML, v. 0.9.1