/*
 * 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: t-conf-2.c,v 1.6 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/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 <stdio.h>
#endif /* SM_LIBCONF_ALONE */

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

typedef struct
{
	unsigned short  ss_port;
	char           *ss_name;
	unsigned int    ss_msgsize;
} ss;

#define SS_MSGSIZE	5 UNIT_MBYTES

typedef struct
{
	unsigned short  sc_port;
	char           *sc_name;
} sc;

typedef struct
{
	ss		 s_ss;
	sc		 s_sc;
} structure;

static sm_conf_definition_T smtps_defs[] =
{
	{ SM_CONF_DEF_MAGIC, "port",
		sm_conf_type_u32,
		offsetof(ss, ss_port),
		sizeof(unsigned short),
		"25"
	},

	{ SM_CONF_DEF_MAGIC, "message_size",
		sm_conf_type_u32,
		offsetof(ss, ss_msgsize),
		sizeof(unsigned int),
		SM_XSTR(SS_MSGSIZE), 0, sm_conf_byte_suffixes
	},

	/* sentinel */
	{ SM_CONF_DEF_MAGIC, NULL }
};

static sm_conf_definition_T smtpc_defs[] =
{
	{ SM_CONF_DEF_MAGIC, "port",
		sm_conf_type_u32,
		offsetof(sc, sc_port),
		sizeof(unsigned short),
		"25"
	},

	/* sentinel */
	{ SM_CONF_DEF_MAGIC, NULL }
};



sm_conf_definition_T definitions[] =
{
	{ SM_CONF_DEF_MAGIC, "smtps",
		sm_conf_type_section,
		offsetof(structure, s_ss),
		sizeof(ss),
		NULL,
		SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_PARSE_ONLY,
		smtps_defs
	},

	{ SM_CONF_DEF_MAGIC, "smtpc",
		sm_conf_type_section,
		offsetof(structure, s_sc),
		sizeof(sc),
		NULL,
		SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_PARSE_ONLY,
		smtpc_defs
	},

	/* sentinel */
	{ SM_CONF_DEF_MAGIC, NULL }
};

static structure s;

static int
process(char const *name, FILE *fp, const char *ssname)
{
	sm_conf_T		*stream;
	int			err;
	char const *service_name;
	size_t service_name_n;
	sm_conf_iterator_T service_iter;
	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, definitions, 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;
	}

	service_iter = NULL;
	s.s_ss.ss_msgsize = 2 UNIT_MBYTES;
	while ((err = sm_conf_scan_next(stream, "smtps",
				smtps_defs, 0,
				&service_name, &service_name_n,
				&(s.s_ss), &service_iter)) == 0)
	{
		const char *n;

		n = service_name;
		if (ssname == NULL)
		{
			printf("len=%d\n", service_name_n);
			if (service_name_n == 0)
			{
				printf("smtps= %s\n", n == NULL ? "(NoName)" : n);
				printf("smtps.port= %hu\n", s.s_ss.ss_port);
				printf("smtps.msgsize= %u\n", s.s_ss.ss_msgsize);
				break;
			}
		}
		else if (strlen(ssname) == service_name_n &&
			 strncmp(ssname, service_name,  service_name_n) == 0)
		{
			printf("smtps= %s\n", n == NULL ? "(NoName)" : n);
			printf("smtps.port= %hu\n", s.s_ss.ss_port);
			printf("smtps.msgsize= %u\n", s.s_ss.ss_msgsize);
			break;
		}
	}


	service_iter = NULL;
	while ((err = sm_conf_scan_next(stream, "smtpc",
				smtpc_defs, 0,
				&service_name, &service_name_n,
				&(s.s_sc), &service_iter)) == 0)
	{
		const char *n;

		n = service_name;
		if (ssname == NULL)
		{
			printf("len=%d\n", service_name_n);
			if (service_name_n == 0)
			{
				printf("smtpc= %s\n", n == NULL ? "(NoName)" : n);
				printf("smtpc.port= %hu\n", s.s_sc.sc_port);
				break;
			}
		}
		else if (strlen(ssname) == service_name_n &&
			 strncmp(ssname, service_name,  service_name_n) == 0)
		{
			printf("smtpc= %s\n", n == NULL ? "(NoName)" : n);
			printf("smtpc.port= %hu\n", s.s_sc.sc_port);
			break;
		}
	}


#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