/*
 * Copyright (c) 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: t-conf-sock-0.c,v 1.5 2005/09/26 23:26:41 ca Exp $")

#include "sm/string.h"
#include "sm/net.h"
#include "sm/sm-conf.h"
#include "sm/sm-conf-prt.h"
#include "sm/sockcnf.h"
#define SM_SOCKCNFDEF 1
#include "sm/sockcnfdef.h"
#include "sm/io.h"

/*
**  Just a test program to play around with libconf (sm_conf_type_union).
**  Note: it is used by a test program (t-conf-sock-0.sh),
**  so don't break it.
*/

typedef struct
{
	sockspec_T	 s_socket;
} mts_T;

sm_conf_definition_T
mts_def[] =
{
{ SM_CONF_DEF_MAGIC,
  "listen_socket", sm_conf_type_union,
	offsetof(mts_T, s_socket.sckspc_type),
	sizeof(sockspec_T),
	NULL, 0, sock_spec_definitions,
	NULL, NULL, NULL },

	/* Sentinel */
	{ SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL }
};

static mts_T mts;

static void
print_ipv4(ipv4_T ipv4, const char *name)
{
	sm_ret_T ret;
	sm_str_P ipv4s;

	ipv4s = sm_str_new(NULL, 20, 32);
	if (ipv4s == NULL)
	{
		printf("out of memory\n");
		return;
	}
	ret = sm_inet_ipv4str(ipv4, ipv4s);
	if (ret != SM_SUCCESS)
	{
		printf("sm_inet_ipv4str=0x%x\n", ret);
		return;
	}
	printf("%s= %s\n", name, sm_str_getdata(ipv4s));
}

static void
print_mts(mts_T *st)
{
	switch (st->s_socket.sckspc_type)
	{
	  case SOCK_TYPE_UNIX:
		printf("path=\"%s\"\n",
			st->s_socket.sock_unix.unixsckspc_path);
		break;
	  case SOCK_TYPE_INET:
		printf("port=%hd\n",
			st->s_socket.sock_inet.inetsckspc_port);
		print_ipv4(st->s_socket.sock_inet.inetsckspc_addr, "address");
		break;
	  default:
		break;
	}
}

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

	if (((stream = sm_conf_new(name ? name : "*stdin*"))) == NULL)
	{
		sm_io_fprintf(smioerr, "error -- sm_conf_new() returns NULL!\n");
		return 1;
	}
	if ((err = sm_conf_read_FILE(stream, name, fp)) != 0)
	{
		sm_io_fprintf(smioerr, "%s: %s\n",
			name ? name : "*stdin*",
			sm_conf_strerror(err, buf, sizeof buf));

		while ((e = sm_conf_syntax_error(stream, e)) != NULL)
			sm_io_fprintf(smioerr, "%s\n", e);

		sm_conf_destroy(stream);
		return 2;
	}

	if ((err = sm_conf_scan(stream, mts_def, 0, &mts)) != 0)
	{
		sm_io_fprintf(smioerr, "(while scanning) %s: %s\n",
			name ? name : "*stdin*",
			sm_conf_strerror(err, buf, sizeof buf));
		while ((e = sm_conf_syntax_error(stream, e)) != NULL)
			sm_io_fprintf(smioerr, "%s\n", e);
		sm_conf_destroy(stream);
		return 3;
	}
	print_mts(&mts);
	if (show)
	{
		err = sm_conf_prt_conf(mts_def, &mts, smioout);
		sm_io_flush(smioout);
	}

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

	return 0;
}

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

	done = 0;
	show = 0;
	while ((c = getopt(ac, av, "f:s")) != -1)
	{
		switch (c)
		{
		  case 'f':
			ret = process(optarg, NULL, show);
			if (ret != 0)
				return ret;
			done = 1;
			break;
		  case 's':
			show = 1;
		}
	}
	ac -= optind;
	av += optind;
	if (done)
	{
		print_mts(&mts);
		return 0;
	}

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

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


syntax highlighted by Code2HTML, v. 0.9.1