/*
* 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: smconf.c,v 1.31 2007/06/10 16:14:42 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/memops.h"
#include "sm/io.h"
#include "sm/qmgrcomm.h"
#include "sm/sm-conf.h"
#include "sm/sm-conf-prt.h"
#define SM_QMGRCNFDEF 1
#define SM_SCCNFDEF 1
#define SM_SMARCNFDEF 1
#define SM_MAPCNFDEF 1
#define SM_SSCNFDEF 1
#define SM_CONF_TIME_DEF 1
#define SM_CONF_LOG_DEF 1
#define SM_CONF_BYTE_DEF 1
#define SM_CONF_KBYTE_DEF 1
#define SM_GREYCNFDEF 1
#include "sm/qmgrcnf.h"
#include "sm/sccnf.h"
#include "sm/mapcnf.h"
#include "sm/smarcnf.h"
#include "sm/sscnf.h"
#include "sm/greycnf.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"
static int Verbose = 0;
static bool Quiet = false;
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;
char *smc_hostname;
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, "hostname", sm_conf_type_string,
offsetof(sm_cnf_T, smc_hostname), 0, NULL,
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|SM_CONF_FLAG_MULTIPLE, 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|SM_CONF_FLAG_MULTIPLE, 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 },
};
#define SM_SHOWTREE 0x01
#define SM_SHOWALL 0x02
#define SM_ALLOW_ANY_SECTION 0x04
/*
** SM_READCONF -- Read configuration file
**
** Parameters:
** fn -- filename of configuration file
** flags -- show tree/all?
** name -- name of subsection (can be NULL)
**
** Returns:
** 0 on success, everything else is an error
*/
static sm_ret_T
sm_readconf(const char *fn, uint flags, const char *name)
{
int err;
uint pflags;
sm_conf_T *smc;
FILE *fp;
sm_cnf_T sm_cnf;
sm_conf_node_T *root, *node;
fp = NULL;
sm_memzero(&sm_cnf, sizeof(sm_cnf));
sm_cnf.smc_qmgr_cnf.sm_magic = SM_QMGR_CNF_MAGIC;
sm_cnf.smc_sc_cnf.sm_magic = SM_SC_CNF_MAGIC;
sm_cnf.smc_smar_cnf.sm_magic = SM_SMAR_CNF_MAGIC;
sm_cnf.smc_ss_cnf.sm_magic = SM_SS_CNF_MAGIC;
smc = sm_conf_new(fn);
if (smc == NULL)
{
err = errno;
sm_io_fprintf(smioerr,
"sev=ERROR, func=sm_readconf, file=%s, sm_conf_new=NULL, errno=%d\n",
fn, err);
return ENOMEM;
}
err = sm_conf_read_FILE(smc, fn, fp);
if (err != 0)
{
sm_prt_conferr(fn, smc, err, smioerr);
sm_conf_destroy(smc);
smc = NULL;
return err;
}
pflags = SM_CONF_FLAG_KEEP_DEFAULT;
if (SM_IS_FLAG(flags, SM_ALLOW_ANY_SECTION))
pflags |= SM_CONF_FLAG_ALLOW_ANY_SECTION;
err = sm_conf_scan(smc, smx_defs, pflags, &sm_cnf);
if (err != 0)
{
sm_prt_conferr(fn, smc, err, smioerr);
return err;
}
else if (Quiet)
/* do nothing */ ;
else if (SM_IS_FLAG(flags, SM_SHOWTREE))
{
root = sm_conf_root(smc);
if (root != NULL)
{
node = root;
if (name != NULL)
{
node = sm_conf_section_next_subsection(smc,
root, name, strlen(name),
NULL, 0, NULL);
}
if (node != NULL)
{
sm_conf_dump_root(smc, node, smioout);
sm_io_flush(smioout);
}
}
}
else
{
if (!SM_IS_FLAG(flags, SM_SHOWALL))
sm_io_fprintf(smioout, "QMGR {\n");
qmgr_prt_cnf(&(sm_cnf.smc_qmgr_cnf), smioout,
SM_IS_FLAG(flags, SM_SHOWALL));
if (!SM_IS_FLAG(flags, SM_SHOWALL))
sm_io_fprintf(smioout, "}\nSMTPS {\n");
ss_prt_cnf(&(sm_cnf.smc_ss_cnf), smioout,
SM_IS_FLAG(flags, SM_SHOWALL));
if (!SM_IS_FLAG(flags, SM_SHOWALL))
sm_io_fprintf(smioout, "}\nSMTPC {\n");
sc_prt_cnf(&(sm_cnf.smc_sc_cnf), smioout,
SM_IS_FLAG(flags, SM_SHOWALL));
if (!SM_IS_FLAG(flags, SM_SHOWALL))
sm_io_fprintf(smioout, "}\nSMAR {\n");
smar_prt_cnf(&(sm_cnf.smc_smar_cnf), smioout,
SM_IS_FLAG(flags, SM_SHOWALL));
if (!SM_IS_FLAG(flags, SM_SHOWALL))
sm_io_fprintf(smioout, "}\n");
sm_io_flush(smioout);
}
return SM_SUCCESS;
}
/*
** USAGE -- Show usage
**
** Parameters:
** prg -- program name
**
** Returns:
** none
*/
static void
usage(const char *prg)
{
sm_io_fprintf(smioerr, "%s: usage: %s [options] configuration-file\n"
"options:\n"
"-a show complete configuration data after parsing\n"
"-q quiet: do not show configuration file, just perform checks\n"
"-s name look for section name\n"
"-t show parsed tree\n"
"-u do not complain about unknown sections\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 ret, ai, r;
uint flags;
char *name, *prg;
prg = argv[0];
ret = 0; /* make compiler happy */
flags = 0;
name = NULL;
while ((r = getopt(argc, argv, "aqs:tuV")) != -1)
{
switch (r)
{
case 'a':
flags |= SM_SHOWALL;
break;
case 'q':
Quiet = true;
break;
case 's':
name = optarg;
break;
case 't':
flags |= SM_SHOWTREE;
break;
case 'u':
flags |= SM_ALLOW_ANY_SECTION;
break;
case 'V':
Verbose++;
break;
default:
usage(prg);
return 1;
}
}
argc -= optind;
argv += optind;
if (Verbose == 3)
{
showcopt();
return 0;
}
for (ai = 0; ai < argc; ai++)
{
ret = sm_readconf(argv[ai], flags, name);
if (ret != 0)
break;
}
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1