/*
* Copyright (c) 2004, 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-1.c,v 1.23 2007/06/10 16:05:07 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/io.h"
#include "sm/sm-conf.h"
#include "sm/sm-conf-prt.h"
#define SM_CONF_LOG_DEF 1
#include "sm/logcnfdef.h"
#include <stdio.h>
#endif /* SM_LIBCONF_ALONE */
/*
** Just a test program to play around with libconf.
*/
typedef struct
{
char const *s_socket;
uchar s_socket_isset;
ipv4_T s_ipv4;
uchar s_ipv4_isset;
uint32_t s_flags;
uchar s_flags_isset;
uint32_t s_cflags;
uchar s_cflags_isset;
unsigned int s_int_u32;
uchar s_int_u32_isset;
unsigned int s_type;
uchar s_type_isset;
unsigned short s_limit; /* between 2 and 12 */
uchar s_limit_isset;
unsigned long s_duration;
uchar s_duration_isset;
uchar s_char;
uchar s_char_isset;
sm_logspec_T s_log;
uchar s_log_isset;
char s_pi[13];
unsigned int s_pi_n;
char s_seq[5];
unsigned int s_seq_n;
} structure;
sm_conf_definition_T const flag_names[] =
{
{ SM_CONF_DEF_MAGIC, "Flag1", sm_conf_type_choice_value, 0x01,
0, NULL, 0, NULL, NULL, NULL, "first flag" },
{ SM_CONF_DEF_MAGIC, "Flag2", sm_conf_type_choice_value, 0x02,
0, NULL, 0, NULL, NULL, NULL, "second flag" },
/* Sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
sm_conf_definition_T const cflag_names[] =
{
{ SM_CONF_DEF_MAGIC, "cflag1", sm_conf_type_choice_value, 0x01,
0, "cflag2", 0, NULL, NULL, NULL, "first cflag" },
{ SM_CONF_DEF_MAGIC, "cflag2", sm_conf_type_choice_value, 0x02,
0, "cflag2", 0, NULL, NULL, NULL, "second cflag" },
/* Sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
sm_conf_definition_T const alias_options[] =
{
{ SM_CONF_DEF_MAGIC, "none", sm_conf_type_choice_value, 0x00,
0, NULL, 0, NULL, NULL, NULL, "no flag" },
{ SM_CONF_DEF_MAGIC, "localpart", sm_conf_type_choice_value, 0x04,
0, NULL, 0, NULL, NULL, NULL, "apply aliases to local part" },
{ SM_CONF_DEF_MAGIC, "localdomains", sm_conf_type_choice_value, 0x08,
0, NULL, 0, NULL, NULL, NULL, "apply aliases to local domains" },
{ SM_CONF_DEF_MAGIC, "all", sm_conf_type_choice_value, 0x10,
0, NULL, 0, NULL, NULL, NULL, "apply aliases to all domains" },
/* Sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
sm_conf_definition_T const limit_constraints[] =
{
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_u32_minimum, 2 },
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_u32_maximum, 12 },
/* Sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
sm_conf_definition_T const duration_suffixes[] =
{
{ SM_CONF_DEF_MAGIC, "s", sm_conf_type_u32_suffix, 1, 60 },
{ SM_CONF_DEF_MAGIC, "m", sm_conf_type_u32_suffix, 60, 60 },
{ SM_CONF_DEF_MAGIC, "h", sm_conf_type_u32_suffix, 60 * 60, 24 },
{ SM_CONF_DEF_MAGIC, "d", sm_conf_type_u32_suffix, 60 * 60 * 24, 7 },
{ SM_CONF_DEF_MAGIC, "w", sm_conf_type_u32_suffix, 60 * 60 * 24 * 7, 365 },
{ SM_CONF_DEF_MAGIC, "y", sm_conf_type_u32_suffix, 60 * 60 * 24 * 365 },
/* Sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
qmgr_definitions[] = {
{ SM_CONF_DEF_MAGIC, "type",
sm_conf_type_u32,
offsetof(structure, s_type),
sizeof(unsigned int),
NULL,
SM_CONF_FLAG_STRICTLY_REQUIRED
},
{ SM_CONF_DEF_MAGIC, "value",
sm_conf_type_u32,
offsetof(structure, s_int_u32),
sizeof(unsigned int),
NULL
},
{ SM_CONF_DEF_MAGIC, "limit",
sm_conf_type_u32,
offsetof(structure, s_limit),
sizeof(unsigned short),
NULL,
0,
limit_constraints
},
/* A number with suffix multipliers. */
{ SM_CONF_DEF_MAGIC, "duration",
sm_conf_type_u32,
offsetof(structure, s_duration),
sizeof(unsigned long),
"0",
0,
duration_suffixes
},
{ SM_CONF_DEF_MAGIC, "log", sm_conf_type_section,
offsetof(structure, s_log), 0,
NULL, SM_CONF_FLAG_KEEP_DEFAULT, sm_log_spec_defs,
NULL, NULL,
"Specify syslog configuration instead of logging to files" },
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
#define SS_PR_CNF "protected_recipients"
#define SS_PR_A_SENDER "sender"
#define SS_PR_A_CLTADDR "client_ip"
#define SS_PR_USE_LOOKUP "use_lookup"
#define SS_PR_MATCH_DET "implicitly_match_detail"
sm_conf_definition_T const
ss_protrcpt_allow_names[] =
{
{ SM_CONF_DEF_MAGIC,
SS_PR_A_SENDER, sm_conf_type_choice_value,
0x0100,
0, NULL, 0, NULL, NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
SS_PR_A_CLTADDR, sm_conf_type_choice_value,
0x0200,
0, NULL, 0, NULL, NULL, NULL, NULL },
/* Sentinel */
{ SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL }
};
sm_conf_definition_T const
ss_protrcpt_match_names[] =
{
{ SM_CONF_DEF_MAGIC,
"exact", sm_conf_type_choice_value,
0x0000,
0, NULL, 0, NULL, NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
SS_PR_USE_LOOKUP, sm_conf_type_choice_value,
0x0400,
0, NULL, 0, NULL, NULL, NULL, NULL },
{ SM_CONF_DEF_MAGIC,
SS_PR_MATCH_DET, sm_conf_type_choice_value,
0x0800,
0, NULL, 0, NULL, NULL, NULL, NULL },
/* Sentinel */
{ SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL }
};
static sm_conf_definition_T
ss_protrcpt_defs[] =
{
{ SM_CONF_DEF_MAGIC, "allow_by", sm_conf_type_choice,
offsetof(structure, s_flags), sizeof(uint32_t),
NULL, SM_CONF_FLAG_STRICTLY_REQUIRED|SM_CONF_FLAG_MULTIPLE,
ss_protrcpt_allow_names,
NULL, NULL,
"allow by" },
{ SM_CONF_DEF_MAGIC, "match_type", sm_conf_type_choice,
offsetof(structure, s_flags), sizeof(uint32_t),
NULL, SM_CONF_FLAG_OR, ss_protrcpt_match_names, NULL, NULL,
"match type" },
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
pi_definitions[] =
{
/* numbers: char */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_u32,
offsetof(structure, s_pi), sizeof(char), NULL, 0, NULL
},
/* counter: unsigned int */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_array_n,
offsetof(structure, s_pi_n), sizeof(unsigned int), NULL, 0, NULL
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
sm_conf_definition_T const seq_names[] =
{
{ SM_CONF_DEF_MAGIC, "dnsbl", sm_conf_type_choice_value, 0x01 },
{ SM_CONF_DEF_MAGIC, "grey", sm_conf_type_choice_value, 0x02 },
{ SM_CONF_DEF_MAGIC, "access", sm_conf_type_choice_value, 0x04 },
/* Sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
seq_defs[] =
{
/* values: choise */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_choice,
offsetof(structure, s_seq), sizeof(char), NULL, 0, seq_names
},
/* counter: unsigned int */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_array_n,
offsetof(structure, s_seq_n), sizeof(unsigned int), NULL, 0, NULL
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
sm_conf_definition_T
definitions[] =
{
{ SM_CONF_DEF_MAGIC, "qmgr",
sm_conf_type_section,
0,
sizeof(structure),
NULL, SM_CONF_FLAG_ALLOW_ANY, qmgr_definitions
},
{ SM_CONF_DEF_MAGIC, "socket", sm_conf_type_string,
offsetof(structure, s_socket), 0,
"path/to/socket",
0,
NULL, NULL, NULL,
"socket path"
#if SM_LIBCONF_ISSET
, offsetof(structure, s_socket_isset)
#endif
},
{ SM_CONF_DEF_MAGIC, "delim",
sm_conf_type_char,
offsetof(structure, s_char),
0,
"+",
0,
NULL, NULL, NULL,
"delimiter"
#if SM_LIBCONF_ISSET
, offsetof(structure, s_char_isset)
#endif
},
{ SM_CONF_DEF_MAGIC, "nameserver",
sm_conf_type_ipv4,
offsetof(structure, s_ipv4),
sizeof(ipv4_T),
"127.0.0.1",
0,
NULL, NULL, NULL,
"nameserver IPv4"
#if SM_LIBCONF_ISSET
, offsetof(structure, s_ipv4_isset)
#endif
},
{ SM_CONF_DEF_MAGIC, "flags",
sm_conf_type_choice,
offsetof(structure, s_flags),
sizeof(uint32_t),
NULL,
SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_KEEP_DEFAULT,
flag_names,
NULL, NULL,
"flags what else"
#if SM_LIBCONF_ISSET
, offsetof(structure, s_flags_isset)
#endif
},
{ SM_CONF_DEF_MAGIC, "cflags",
sm_conf_type_choice,
offsetof(structure, s_cflags),
sizeof(uint32_t),
"cflag2",
SM_CONF_FLAG_MULTIPLE,
cflag_names
},
{ SM_CONF_DEF_MAGIC, "sequence",
sm_conf_type_array,
0,
4,
NULL,
SM_CONF_FLAG_FLAT,
seq_defs
},
{ SM_CONF_DEF_MAGIC, "pi",
sm_conf_type_array,
0, /* offset (n/a; see contents) */
12, /* size: maximum number of elements */
NULL,
SM_CONF_FLAG_FLAT,
pi_definitions,
NULL, NULL, "digits of pi"
},
{ SM_CONF_DEF_MAGIC, "aliases",
sm_conf_type_choice,
offsetof(structure, s_flags),
sizeof(uint32_t),
NULL,
SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_KEEP_DEFAULT,
alias_options
},
{ SM_CONF_DEF_MAGIC, SS_PR_CNF, sm_conf_type_section,
0, sizeof(uint32_t),
NULL, SM_CONF_FLAG_KEEP_DEFAULT, ss_protrcpt_defs,
NULL, NULL,
"how to protect recipient addresses" },
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static structure s;
static void
print_structure(structure *st)
{
sm_ret_T ret;
sm_str_P ipv4s;
unsigned int i;
ipv4s = sm_str_new(NULL, 20, 32);
if (ipv4s == NULL)
{
printf("out of memory\n");
return;
}
printf("int_u32: %u\n", st->s_int_u32);
printf("limit: %hu\n", st->s_limit);
printf("duration: %lu\n", st->s_duration);
printf("socket: \"%s\"\n", st->s_socket);
printf("flags: %X\n", st->s_flags);
printf("cflags: %X\n", st->s_cflags);
printf("char: %c\n", st->s_char);
ret = sm_inet_ipv4str(st->s_ipv4, ipv4s);
if (ret != SM_SUCCESS)
{
printf("sm_inet_ipv4str=0x%x\n", ret);
return;
}
printf("nameserver: %s\n", sm_str_getdata(ipv4s));
printf("pi: [%lu]", (unsigned long)st->s_pi_n);
for (i = 0; i < st->s_pi_n; i++)
printf(" %d", (int)st->s_pi[i]);
putchar('\n');
printf("seq: [%lu]", (unsigned long)st->s_seq_n);
for (i = 0; i < st->s_seq_n; i++)
printf(" %d", (int)st->s_seq[i]);
putchar('\n');
printf("int_u32: %c\n", st->s_int_u32_isset + '0');
printf("limit: %c\n", st->s_limit_isset + '0');
printf("duration: %c\n", st->s_duration_isset + '0');
printf("socket: %c\n", st->s_socket_isset + '0');
printf("flags: %c\n", st->s_flags_isset + '0');
printf("cflags: %c\n", st->s_cflags_isset + '0');
printf("char: %c\n", st->s_char_isset + '0');
printf("ns: %c\n", st->s_ipv4_isset + '0');
}
static int
process(char const *confname, FILE *fp, bool show, bool prt, const char *option, const char *opt)
{
sm_conf_T *smc;
int err;
char const *name, *kw;
size_t name_n, kw_n;
#if 0
sm_conf_iterator_T service_iter;
#endif /* 0 */
sm_conf_node_T *node, *root;
char buf[SM_CONF_ERROR_BUFFER_SIZE];
char const *e = NULL;
if (((smc = sm_conf_new(confname ? confname : "*stdin*"))) == NULL)
{
fprintf(stderr, "error -- sm_conf_new() returns NULL!\n");
return 1;
}
if ((err = sm_conf_read_FILE(smc, confname, fp)) != 0)
{
fprintf(stderr, "%s: %s\n",
confname ? confname : "*stdin*",
sm_conf_strerror(err, buf, sizeof buf));
while ((e = sm_conf_syntax_error(smc, e)) != NULL)
fprintf(stderr, "%s\n", e);
sm_conf_destroy(smc);
return 2;
}
/* s.s_flags = 0x7; */
s.s_cflags = 0x3;
err = sm_conf_scan(smc, definitions,
SM_CONF_FLAG_ALLOW_ANY|SM_CONF_FLAG_KEEP_DEFAULT, &s);
if (err != 0)
{
#if 0
fprintf(stderr, "%s: %d\n", confname ? confname : "*stdin*", err);
#endif /* 0 */
fprintf(stderr, "(while scanning) %s: %s\n",
confname ? confname : "*stdin*",
sm_conf_strerror(err, buf, sizeof buf));
while ((e = sm_conf_syntax_error(smc, e)) != NULL)
fprintf(stderr, "%s\n", e);
sm_conf_destroy(smc);
return 3;
}
if (show)
print_structure(&s);
if (prt)
{
sm_str_P text;
text = sm_str_new(NULL, 256, 8192);
sm_io_fprintf(smioout, "prt_conf1:\n");
(void) sm_conf_prt_cnfs(definitions, &s, 0, smioout, 0, NULL,
text);
sm_io_flush(smioout);
}
#if 0
service_iter = NULL;
while ((err = sm_conf_scan_next(smc, "",
definitions, 0,
&service_name, &service_name_n,
&s, &service_iter)) == 0)
{
node = (sm_conf_node_T *) service_iter;
err = sm_conf_section_keyword(smc, node, &kw, &kw_n);
if (kw == NULL)
printf("kw=(none)\n");
else
printf("kw=%*s\n", (int) kw_n, kw);
if (service_name == NULL)
printf("name=(none)\n");
else
printf("name=%*s\n", (int) service_name_n,
service_name);
}
#endif /* 0 */
root = sm_conf_root(smc);
node = NULL;
while ((node = sm_conf_section_next_subsection(smc, root,
NULL, 0,
NULL, 0,
node)) != NULL)
{
err = sm_conf_section_keyword(smc, node, &kw, &kw_n);
if (kw == NULL)
printf("kw=(none)\n");
else
printf("kw=%*s\n", (int) kw_n, kw);
err = sm_conf_section_name(smc, node, &name, &name_n);
if (name == NULL)
printf("name=(none)\n");
else
printf("name=%*s\n", (int) name_n, name);
printf("type=%d\n", sm_conf_node_type(smc, node));
err = sm_conf_get_relative(smc, node, NULL,
sm_conf_type_section, qmgr_definitions,
SM_CONF_FLAG_ALLOW_ANY, &s, sizeof(s));
if (err != 0)
{
fprintf(stderr, "%s: %#x\n",
confname ? confname : "*stdin*", err);
#if 0
fprintf(stderr, "%s: %s\n",
confname ? confname : "*stdin*",
sm_conf_strerror(err, buf, sizeof buf));
while ((e = sm_conf_syntax_error(smc, e)) != NULL)
fprintf(stderr, "%s\n", e);
#endif /* 0 */
}
}
if (option != NULL && *option != '\0')
{
uint v;
err = sm_conf_get(smc, option, sm_conf_type_u32, NULL, 0,
(void *) &v, sizeof(v));
fprintf(stdout, "option=%s, conf_get=%d, text=%s, val=%u\n",
option != NULL ? option : "(null)", err,
err == 0 ? "OK" : sm_conf_strerror(err, buf,
sizeof buf),
v);
}
if (opt != NULL && *opt != '\0')
{
char *v;
err = sm_conf_get(smc, opt, sm_conf_type_string, NULL, 0,
(void *) &v, 0);
fprintf(stdout, "opt=%s, conf_get=%d, text=%s, val=\"%s\"\n",
opt != NULL ? opt : "(null)", err,
err == 0 ? "OK" : sm_conf_strerror(err, buf,
sizeof buf),
err == 0 ? v : "(some error)");
}
#if 0
sm_conf_destroy(smc);
#endif /* 0 */
return 0;
}
int
main(int ac, char **av)
{
int ai, c, ret;
bool prt, done;
char *option, *opt;
done = false;
prt = false;
option = NULL;
opt = NULL;
while ((c = getopt(ac, av, "df:l:O:o:sv:")) != -1)
{
switch (c)
{
case 'd':
sm_conf_prt_dflt(definitions, SMC_FLD_FLAGS, smioout);
sm_io_flush(smioout);
return 0;
case 'f':
ret = process(optarg, NULL, 0, prt, option, opt);
if (ret != 0)
return ret;
done = true;
break;
case 'l':
s.s_limit = atoi(optarg);
break;
case 'O':
opt = strdup(optarg);
break;
case 'o':
option = strdup(optarg);
break;
case 's':
prt = true;
break;
case 'v':
s.s_int_u32 = atoi(optarg);
break;
}
}
ac -= optind;
av += optind;
if (done)
{
print_structure(&s);
if (prt)
{
sm_io_fprintf(smioout, "prt_conf:\n");
(void) sm_conf_prt_cnfs(definitions, &s, 0,
smioout, 0, NULL, NULL);
sm_io_flush(smioout);
}
return 0;
}
if (ac == 0)
return process("*stdin*", stdin, 1, prt, option, opt);
for (ai = 0; ai < ac; ai++)
{
int ret;
ret = process(av[ai], NULL, 1, prt, option, opt);
if (ret != 0)
return ret;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1