/* * Copyright (c) 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: t-conf-3.c,v 1.7 2006/12/24 00:20:24 ca Exp $") #if SM_LIBCONF_ALONE #include #include #include #include "sm-conf.h" #else /* SM_LIBCONF_ALONE */ #include "sm/io.h" #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 "sm/sm-conf-prt.h" #include #endif /* SM_LIBCONF_ALONE */ /* ** Just a test program to play around with libconf. ** testing an array */ #define SSSE_CFL_STARTTLS 0x00800000u /* offer STARTTLS */ #define SSSE_CFL_AUTH 0x01000000u /* offer AUTH */ #define SSSE_CFL_DELAY_CHKS 0x00000002u /* delay checks */ #define SM_SRV_FEAT_MAGIC SM_MAGIC('S', 'R', 'V', 'F') #define SM_CNF_MAGIC SM_MAGIC('S', 'C', 'N', 'F') /* session features */ struct ss_srv_feat_S { /* how to do this? it's allocated by libconf... sm_magic_T sm_magic; */ char *sssf_name; uint32_t sssf_flags; uint32_t sssf_max_ta; #if SM_LIBCONF_ISSET uchar sssf_isset_name; uchar sssf_isset_flags; uchar sssf_max_ta_isset; #endif }; typedef struct ss_srv_feat_S ss_srv_feat_T, *ss_srv_feat_P; /* array of session features */ struct ss_srv_feats_S { ss_srv_feat_T *sssfs_feat; uint sssfs_n; }; typedef struct ss_srv_feats_S ss_srv_feats_T, *ss_srv_feats_P; typedef struct ss_cnf_S ss_cnf_T, *ss_cnf_P; struct ss_cnf_S { sm_magic_T sm_magic; uint32_t ss_cnf_cflags; uint32_t ss_cnf_max_ta; ss_srv_feats_T ss_cnf_srv_feats; #if SM_LIBCONF_ISSET uchar sssf_isset_cflags; uchar ss_cnf_max_ta_isset; #endif }; sm_conf_definition_T const ss_se_flag_names[] = { { SM_CONF_DEF_MAGIC, "u|", sm_conf_type_u32_suffix, 1, 1, NULL, 0, NULL, NULL, NULL, "" }, { SM_CONF_DEF_MAGIC, "|", sm_conf_type_u32_suffix, 1, 1, NULL, 0, NULL, NULL, NULL, "" }, { SM_CONF_DEF_MAGIC, "u", sm_conf_type_u32_suffix, 1, 1, NULL, 0, NULL, NULL, NULL, "" }, { SM_CONF_DEF_MAGIC, "starttls", sm_conf_type_choice_value, SSSE_CFL_STARTTLS, 0, "starttls", 0, NULL, NULL, NULL, "offer STARTTLS" }, { SM_CONF_DEF_MAGIC, "auth", sm_conf_type_choice_value, SSSE_CFL_AUTH, 0, "auth", 0, NULL, NULL, NULL, "offer AUTH" }, { SM_CONF_DEF_MAGIC, "delay_checks", sm_conf_type_choice_value, SSSE_CFL_DELAY_CHKS, 0, NULL, 0, NULL, NULL, NULL, "delay returning results from access check until RCPT stage" }, { SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL } }; sm_conf_definition_T ss_srv_feat_defs[] = { { SM_CONF_DEF_MAGIC, "name", sm_conf_type_section_title, offsetof(ss_srv_feat_T, sssf_name), 0, NULL, 0 /*SM_CONF_FLAG_STRICTLY_REQUIRED*/, NULL, NULL, NULL, NULL #if SM_LIBCONF_ISSET , offsetof(ss_srv_feat_T, sssf_isset_name) #endif }, { SM_CONF_DEF_MAGIC, "flags", sm_conf_type_choice, offsetof(ss_srv_feat_T, sssf_flags), sizeof(uint32_t), SM_XSTR(SSSE_CFL_STARTTLS) "|" SM_XSTR(SSSE_CFL_AUTH) /* "0x00800000|0x01000000" "{starttls,auth}"*/ /*NULL */ , SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_OR|SM_CONF_FLAG_PLURAL| SM_CONF_FLAG_NUMERIC|SM_CONF_FLAG_DEFAULT_FROM_ENVIRONMENT| SM_CONF_FLAG_SECTION_DEFAULT_FROM_ANONYMOUS, ss_se_flag_names, NULL, NULL, "flags to influence behavior per session" #if SM_LIBCONF_ISSET , offsetof(ss_srv_feat_T, sssf_isset_flags) #endif }, { SM_CONF_DEF_MAGIC, "max_ta", sm_conf_type_u32, offsetof(ss_srv_feat_T, sssf_max_ta), sizeof(uint32_t), NULL, SM_CONF_FLAG_DEFAULT_FROM_ENVIRONMENT| SM_CONF_FLAG_SECTION_DEFAULT_FROM_ANONYMOUS, NULL, NULL, NULL, "max ta" #if SM_LIBCONF_ISSET , offsetof(ss_srv_feat_T, sssf_max_ta_isset) #endif }, { SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL } }; sm_conf_definition_T ss_srv_feat_definitions[] = { { SM_CONF_DEF_MAGIC, "", sm_conf_type_section, offsetof(ss_cnf_T, ss_cnf_srv_feats.sssfs_feat), sizeof(ss_srv_feat_T), NULL, /*SM_CONF_FLAG_SECTION_MUST_BE_NAMED|*/SM_CONF_FLAG_DEFAULT_FROM_ENVIRONMENT, ss_srv_feat_defs, NULL, NULL, "session features" }, { SM_CONF_DEF_MAGIC, "n", sm_conf_type_array_n, offsetof(ss_cnf_T, ss_cnf_srv_feats.sssfs_n), sizeof(uint), NULL, 0, ss_srv_feat_defs, NULL, NULL, "number of session features (implicit)" }, { SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL } }; sm_conf_definition_T ss_defs[] = { { SM_CONF_DEF_MAGIC, "session_features", sm_conf_type_array, 0, /* offset */ 0, /* size (# of elements) */ NULL, /* default */ SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_DEFAULT_FROM_ENVIRONMENT|SM_CONF_FLAG_SECTION_DEFAULT_FROM_ANONYMOUS, ss_srv_feat_definitions, NULL, NULL, "session feature declarations" }, { SM_CONF_DEF_MAGIC, "flags", sm_conf_type_choice, offsetof(ss_cnf_T, ss_cnf_cflags), sizeof(uint32_t), SM_XSTR(SSSE_CFL_STARTTLS) "|" SM_XSTR(SSSE_CFL_AUTH), SM_CONF_FLAG_MULTIPLE|SM_CONF_FLAG_OR|SM_CONF_FLAG_PLURAL|SM_CONF_FLAG_NUMERIC, ss_se_flag_names, NULL, NULL, "global flags to influence behavior" #if SM_LIBCONF_ISSET , offsetof(ss_cnf_T, sssf_isset_cflags) #endif #if SM_LIBCONF_MAGIC , SM_CNF_MAGIC #endif }, { SM_CONF_DEF_MAGIC, "max_ta", sm_conf_type_u32, offsetof(ss_cnf_T, ss_cnf_max_ta), sizeof(uint32_t), "99", 0, NULL, NULL, NULL, "global max ta" #if SM_LIBCONF_ISSET , offsetof(ss_cnf_T, ss_cnf_max_ta_isset) #endif #if SM_LIBCONF_MAGIC , SM_CNF_MAGIC #endif }, { SM_CONF_DEF_MAGIC, NULL, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL } }; static ss_cnf_T s; static int process(char const *name, FILE *fp, const char *ssname) { sm_conf_T *stream; uint u,n; int err; char buf[SM_CONF_ERROR_BUFFER_SIZE]; char const *e = NULL; s.sm_magic = SM_CNF_MAGIC; 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, ss_defs, 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; } (void) sm_conf_prt_conf(ss_defs, &s, smioerr); n = s.ss_cnf_srv_feats.sssfs_n; #if SM_LIBCONF_ISSET fprintf(stderr, "isset_cflags=%hd\n", s.sssf_isset_cflags); #endif fprintf(stderr, "n=%u\n", n); for (u = 0; u < n; u++) { fprintf(stderr, "name[%u]=%s\n", u, s.ss_cnf_srv_feats.sssfs_feat[u].sssf_name); fprintf(stderr, "flags[%u]=0x%08x\n", u, s.ss_cnf_srv_feats.sssfs_feat[u].sssf_flags); fprintf(stderr, "isset_flags[%u]=%hd\n", u, s.ss_cnf_srv_feats.sssfs_feat[u].sssf_isset_flags); fprintf(stderr, "isset_name[%u]=%hd\n", u, s.ss_cnf_srv_feats.sssfs_feat[u].sssf_isset_name); fprintf(stderr, "isset_max_ta[%u]=%hd\n", u, s.ss_cnf_srv_feats.sssfs_feat[u].sssf_max_ta_isset); } #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; }