/*
 * Copyright (c) 2004-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: dumpdef.c,v 1.26 2007/06/10 16:14:42 ca Exp $")

/* show configuration definition */

#include "sm/string.h"
#include "sm/memops.h"
#include "sm/io.h"
#include "sm/sysexits.h"
#include "sm/qmgrcomm.h"
#include "sm/sm-conf.h"
#include "sm/sm-conf-prt.h"
#include "sm-conf-type.h"

#define SM_QMGRCNFDEF 1
#define SM_SCCNFDEF 1
#define SM_SMARCNFDEF 1
#define SM_MAPCNFDEF 1
#define SM_SSCNFDEF 1
#define SM_CONF_LOG_DEF 1
#define SM_CONF_TIME_DEF 1
#define SM_CONF_BYTE_DEF 1
#define SM_CONF_KBYTE_DEF 1
#define SM_GREYCNFDEF 1

#define SM_NOMCPDEFS 0

#include "sm/scdef.h"
#include "sm/ssdef.h"

#include "sm/qmgrcnf.h"
#include "sm/sccnf.h"
#include "sm/mapcnf.h"
#include "sm/greycnf.h"
#include "sm/smarcnf.h"
#include "sm/sscnf.h"

#include "sm/qmgrcnfdef.h"
#include "sm/sccnfdef.h"
#include "sm/mapcnfdef.h"
#include "sm/greycnfdef.h"
#include "sm/smarcnfdef.h"
#include "sm/sscnfdef.h"

typedef struct sm_cnf_S		sm_cnf_T, *sm_cnf_P;
struct sm_cnf_S
{
	char		*smc_smtpcsock;
	char		*smc_smtpssock;
	char		*smc_smarsock;
	char		*smc_cdb_base;
	qmgr_cnf_T	 smc_qmgr_cnf;
	sc_cnf_T	 smc_sc_cnf;
	smar_cnf_T	 smc_smar_cnf;
	ss_cnf_T	 smc_ss_cnf;
};

sm_conf_definition_T
smx_defs[] =
{

{ SM_CONF_DEF_MAGIC,
  "SMTPC_socket",	sm_conf_type_string,
	offsetof(sm_cnf_T, smc_smtpcsock), 0,
	smsmtpcsock, 0,
	NULL, NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
  "SMTPS_socket",	sm_conf_type_string,
	offsetof(sm_cnf_T, smc_smtpssock), 0,
	smsmtpssock, 0,
	NULL, NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
  "SMAR_socket",	sm_conf_type_string,
	offsetof(sm_cnf_T, smc_smarsock), 0,
	smarsock, 0,
	NULL, NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
  "CDB_base_directory",	sm_conf_type_string,
	offsetof(sm_cnf_T, smc_cdb_base), 0,
	"", 0,
	NULL, NULL, NULL, NULL },

{ SM_CONF_DEF_MAGIC,
  "smar", sm_conf_type_section,
	offsetof(sm_cnf_T, smc_smar_cnf),
	0, /* sizeof(smar_cnf_T), */
	NULL, SM_CONF_FLAG_KEEP_DEFAULT, smar_defs,
	NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
  "smtpc", sm_conf_type_section,
	offsetof(sm_cnf_T, smc_sc_cnf),
	0, /* sizeof(sc_cnf_T), */
	NULL, SM_CONF_FLAG_KEEP_DEFAULT, sc_defs,
	NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
  "smtps", sm_conf_type_section,
	offsetof(sm_cnf_T, smc_ss_cnf),
	0, /* sizeof(ss_cnf_T), */
	NULL, SM_CONF_FLAG_KEEP_DEFAULT, ss_defs,
	NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
  "qmgr", sm_conf_type_section,
	offsetof(sm_cnf_T, smc_qmgr_cnf),
	0, /* sizeof(qmgr_cnf_T), */
	NULL, SM_CONF_FLAG_KEEP_DEFAULT, qmgr_defs,
	NULL, NULL, NULL },

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

static int Verbose = 0;

#if 0
struct sm_conf_definition_S
{
	sm_magic_T			 sm_magic;
	char const			*scd_name;
	const sm_conf_type_T		*scd_type;
	ptrdiff_t			 scd_offset;
	size_t				 scd_size;
	char const			*scd_default;
	unsigned int			 scd_flags;
	sm_conf_definition_T const	*scd_contents;
	sm_conf_definition_check_T	*scd_check;
	void				*scd_check_data;
	char const			*scd_description;
};
	int (* sctp_node_to_value)(
		sm_conf_T			*_handle,
		sm_conf_definition_T const	*_def,
		sm_conf_node_T const		*_node,
		void				*_value);
	int (* sctp_value_check)(
		sm_conf_T			*_handle,
		sm_conf_definition_T const	*_def,
		void const			*_value);
	int (* sctp_value_copy)(
		sm_conf_T			*_handle,
		sm_conf_definition_T const	*_def,
		void				*_to,
		void const			*_from);
	int (* sctp_value_null)(
		sm_conf_T			*_handle,
		sm_conf_definition_T const	*_def,
		void				*_value);
#endif /* 0 */

#if 0
static int show_defs(sm_conf_definition_T *defs, sm_file_T *fp, int indent);

static int
show_def(sm_conf_definition_T *def, sm_file_T *fp, int indent)
{
	sm_conf_type_T *scdtype;

	SM_IS_CONF_DEF(def);
	scdtype = def->scd_type;
	if (scdtype != NULL)
	{
		if (def->scd_description != NULL &&
		    *(def->scd_description) != '\0')
		{
			prt_fmtted(fp, indent, "# ", def->scd_description);
		}
		if (scdtype == sm_conf_type_section)
		{
			sm_io_fprintf(fp, "\n%*s%s {\n"
				, indent, ""
				, def->scd_name);
			show_defs(def->scd_contents, fp, indent + 2);
			sm_io_fprintf(fp, "%*s}\n"
				, indent, "");
		}
		else if (scdtype == sm_conf_type_string)
			sm_io_fprintf(fp, "%*s%s=\"%s\";\n"
				, indent, ""
				, def->scd_name
				, def->scd_default);
		else
			sm_io_fprintf(fp, "%*s%s=%s;\n"
				, indent, ""
				, def->scd_name
				, def->scd_default);
	}
	return 0;
}

static int
show_defs(sm_conf_definition_T *defs, sm_file_T *fp, int indent)
{
	sm_conf_definition_T *def;

	while ((def = defs++) != NULL && def->scd_name != NULL)
	{
		SM_IS_CONF_DEF(def);
		show_def(def, fp, indent + 2);
#if 0
		sm_io_fprintf(fp, "name=\"%s\"\n", def->scd_name);
		scdtype = def->scd_type;
		if (scdtype != NULL && scdtype->sctp_node_to_value != NULL)
		{
			r = (*scdtype->sctp_node_to_value)(
					stream,
					def,
					NULL,
					(void *)def->scd_default);
			r = (*scdtype->sctp_value_null)(
					stream,
					def,
					((char *)&sm_cnf) + def->scd_offset);
			sm_io_fprintf(fp, "r=%d, def=%s\n", r, def->scd_default);
			if (sm_conf_type_section,
			sm_io_fprintf(fp, "def=%s\n", def->scd_default);

		}
#endif /* 0 */

	}
	return 0;
}
#endif /* 0 */

#define SM_DUMP_CONF	0x01
#define SM_DUMP_TREE	0x02
#define SM_DUMP_PREFIX	0x04

static int
dump_defs(sm_conf_definition_T *defs, unsigned int flags, sm_file_T *fp, const char *name)
{
	sm_conf_T *stream;
	sm_conf_node_T *node;
	int err;
	sm_cnf_T sm_cnf;

	sm_memzero(&sm_cnf, sizeof(sm_cnf));
	if ((stream = sm_conf_new(name)) == NULL)
		return 1;

	if ((err = sm_conf_read_FILE(stream, name, NULL)) != 0)
	{
		char buf[SM_CONF_ERROR_BUFFER_SIZE];
		char const *e = NULL;

		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;
	}

	node = sm_conf_root(stream);

#if 0
	show_defs(defs, fp, 0);
#else /* 0 */
	if (flags != 0)
	{
		err = sm_conf_scan(stream, smx_defs,
			SM_CONF_FLAG_ALLOW_ANY,
			&sm_cnf);
		if (err == 0)
		{
			sm_str_P p;

			p = NULL;
			if (SM_IS_FLAG(flags, SM_DUMP_PREFIX))
				p = sm_str_new(NULL, 256, 1024);
			else if (SM_IS_FLAG(flags, SM_DUMP_CONF))
				(void) sm_conf_prt_cnfs(defs, &sm_cnf, 0, fp,
						0, p, NULL);
			if (SM_IS_FLAG(flags, SM_DUMP_TREE))
				sm_conf_dump_root(stream, node, fp);
			SM_STR_FREE(p);
		}
		else
		{
			sm_prt_conferr("oops", stream, err, smioerr);
		}
	}
	else
		sm_conf_prt_dflt(defs, 0, fp);
#endif /* 0 */

	sm_io_flush(fp);
	return 0;
}

/*
**  USAGE -- Show usage
**
**	Parameters:
**		prg -- program name
**
**	Returns:
**		none
*/

static void
usage(const char *prg)
{
	fprintf(stderr, "%s: usage: %s [options] configuration-file\n"
		"options:\n"
		"-c       show configuration\n"
		"-p       use prefix notation\n"
		"-t       show parsed tree\n"
		"-V       increase verbosity\n"
		, prg, prg);
}

/*
**  SHOWCOPT -- show compile time options
**
**	Parameters:
**		none
**
**	Returns:
**		none
*/

static void
showcopt(void)
{
	sm_io_fprintf(smioout, "compile time options:\n"
#if MTA_USE_TLS
			"MTA_USE_TLS\n"
#endif
#if MTA_USE_SASL
			"MTA_USE_SASL\n"
#endif
#if MTA_USE_PMILTER
			"MTA_USE_PMILTER\n"
#endif
#if QMGR_TEST
			"QMGR_TEST\n"
#endif
		);
	sm_io_flush(smioout);
}

int
main(int argc, char **argv)
{
	int r;
	unsigned int flags;

	flags = 0;
	while ((r = getopt(argc, argv, "cptV")) != -1)
	{
		switch (r)
		{
		  case 'c':
			flags |= SM_DUMP_CONF;
			break;
		  case 'p':
			flags |= SM_DUMP_PREFIX;
			break;
		  case 't':
			flags |= SM_DUMP_TREE;
			break;
		  case 'V':
			Verbose++;
			break;
		  default:
			usage(argv[0]);
			return EX_USAGE;
		}
	}

	argc -= optind;
	argv += optind;

	if (Verbose == 3)
	{
		showcopt();
		return 0;
	}

	if (argc > 0)
		r = dump_defs(smx_defs, flags, smioout, argv[0]);
	return r;
}


syntax highlighted by Code2HTML, v. 0.9.1