/*
 * Copyright (c) 2006 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: t-conf-7.c,v 1.2 2006/12/24 00:20:24 ca Exp $")

#if SM_LIBCONF_ALONE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sm-conf.h"
#else /* SM_LIBCONF_ALONE */
#include "sm/io.h"
#include "sm/string.h"
#include "sm/net.h"
#include "sm/units.h"
#include "sm/sm-conf.h"
#define SM_CONF_BYTE_DEF 1
#define SM_CONF_KBYTE_DEF 1
#include "sm/sm-conf-byte.h"
#include "sm/sm-conf-prt.h"
#include <stdio.h>
#endif /* SM_LIBCONF_ALONE */

/*
**  Just a test program to play around with libconf.
**  testing inheritance
*/

#define SSSE_CFL_STARTTLS	0x00800000u /* offer STARTTLS */
#define SSSE_CFL_AUTH		0x01000000u /* offer AUTH */
#define SSSE_CFL_DELAY_CHKS	0x00000002u /* delay checks */

/* server features (per session) */
struct ss_srv_feat_S {
	char		*sssf_name;
	uint32_t	 sssf_flags;
};
typedef struct ss_srv_feat_S ss_srv_feat_T, *ss_srv_feat_P;

typedef struct ss_cnf_S		ss_cnf_T, *ss_cnf_P;
struct ss_cnf_S
{
	uint32_t        ss_cnf_cflags;
	ss_srv_feat_T   ss_cnf_srv_feat;
};

sm_conf_definition_T const ss_se_flag_names[] = {
{ SM_CONF_DEF_MAGIC,
	"starttls",		sm_conf_type_choice_value,
	SSSE_CFL_STARTTLS,
	0, NULL, 0, NULL, NULL, NULL,
	"offer STARTTLS" },
{ SM_CONF_DEF_MAGIC,
	"auth",		sm_conf_type_choice_value,
	SSSE_CFL_AUTH,
	0, NULL, 0, NULL, NULL, NULL,
	"offer AUTH" },
{ SM_CONF_DEF_MAGIC,
	"delay_checks",		sm_conf_type_choice_value,
	SSSE_CFL_DELAY_CHKS,
	0, NULL, 0, NULL, NULL, NULL,
	"delay returning results from access check until RCPT stage" },
{ SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL }
};

sm_conf_definition_T ss_srv_feat_defs[] = {
{ SM_CONF_DEF_MAGIC, "name",		sm_conf_type_section_title,
	offsetof(ss_srv_feat_T, sssf_name),	0,
	NULL,	0 /*SM_CONF_FLAG_STRICTLY_REQUIRED*/,
	NULL, NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC, "flags",		sm_conf_type_choice,
	offsetof(ss_srv_feat_T, sssf_flags),	sizeof(uint32_t),
	NULL,
	SM_CONF_FLAG_STRICTLY_REQUIRED|SM_CONF_FLAG_MULTIPLE|
		SM_CONF_FLAG_DEFAULT_FROM_ENVIRONMENT|
		SM_CONF_FLAG_SECTION_DEFAULT_FROM_ANONYMOUS,
	ss_se_flag_names,
	NULL,	NULL,
	"flags to influence behavior per session"	},
{ SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL }
};

sm_conf_definition_T ss_defs[] = {
{ SM_CONF_DEF_MAGIC, "server_features",		sm_conf_type_section,
	offsetof(ss_cnf_T, ss_cnf_srv_feat), sizeof(ss_srv_feat_T),
	NULL,
	SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_SECTION_DEFAULT_FROM_ANONYMOUS,
	ss_srv_feat_defs,
	NULL,  NULL,
	"server feature declarations"	},
{ SM_CONF_DEF_MAGIC, "flags",		sm_conf_type_choice,
	offsetof(ss_cnf_T, ss_cnf_cflags),	sizeof(uint32_t),
	NULL,
	SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_NUMERIC|SM_CONF_FLAG_SECTION_DEFAULT_FROM_ANONYMOUS,
	ss_se_flag_names,
	NULL,	NULL,
	"global flags to influence behavior"	},
{ SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL }
};

static ss_cnf_T s;

static int
process(char const *name, FILE *fp, const char *ssname)
{
	sm_conf_T		*stream;
	/* uint u,n; */
	int			err;
	char buf[SM_CONF_ERROR_BUFFER_SIZE];
	char const *e = NULL;

	if (((stream = sm_conf_new(name ? name : "*stdin*"))) == NULL)
	{
		fprintf(stderr, "error -- sm_conf_new() returns NULL!\n");
		return 1;
	}
	if ((err = sm_conf_read_FILE(stream, name, fp)) != 0)
	{
		fprintf(stderr, "%s: %s\n",
			name ? name : "*stdin*",
			sm_conf_strerror(err, buf, sizeof buf));
		while ((e = sm_conf_syntax_error(stream, e)) != NULL)
			fprintf(stderr, "%s\n", e);
		sm_conf_destroy(stream);
		return 2;
	}

	if ((err = sm_conf_scan(stream, ss_defs, 0, &s)) != 0)
	{

		fprintf(stderr, "(while scanning) %s: %s\n",
			name ? name : "*stdin*",
			sm_conf_strerror(err, buf, sizeof buf));
		while ((e = sm_conf_syntax_error(stream, e)) != NULL)
			fprintf(stderr, "%s\n", e);
		sm_conf_destroy(stream);
		return 3;
	}

	(void) sm_conf_prt_conf(ss_defs, &s, smioerr);
/*
	n = s.ss_cnf_srv_feats.sssfs_n;
	fprintf(stderr, "n=%u\n", n);
	for (u = 0; u < n; u++)
	{
		fprintf(stderr, "name[%u]=%s\n", u,
			s.ss_cnf_srv_feats.sssfs_feat[u].sssf_name);
		fprintf(stderr, "flags[%u]=%#010x\n", u,
			s.ss_cnf_srv_feats.sssfs_feat[u].sssf_flags);
	}
*/

#if 0
	sm_conf_destroy(stream);
#endif /* 0 */

	return 0;
}

int
main(int ac, char **av)
{
	int ai, c, ret, done;
	char *ssname;

	done = 0;
	ssname = NULL;
	while ((c = getopt(ac, av, "f:N:")) != -1)
	{
		switch (c)
		{
		  case 'f':
			ret = process(optarg, NULL, ssname);
			if (ret != 0)
				return ret;
			done = 1;
			break;
		  case 'N':
			ssname = strdup(optarg);
			if (ssname == NULL)
				return ENOMEM;
			break;
		}
	}
	ac -= optind;
	av += optind;

	if (ac == 0)
		return process("*stdin*", stdin, ssname);

	for (ai = 0; ai < ac; ai++)
	{
		int ret = process(av[ai], NULL, ssname);
		if (ret != 0)
			return ret;
	}
	return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1