/* * 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: sm-conf-prtdef.c,v 1.12 2007/06/10 16:03:55 ca Exp $") #include "sm/string.h" #include "sm/sm-conf.h" #include "sm/sm-conf-prt.h" #include "sm-conf-type.h" #include "sm/io.h" #include "sm/util.h" #include "prtcnf.h" /* show configuration definition */ /* ** SM_CONF_PRT_DEF -- print defaults for one node ** ** Parameters: ** def -- configuration definition. ** flags -- flags ** fp -- file for output ** indent -- current indentation ** text -- if not NULL: print this if something is printed ** in this invocation ** ** Returns: ** 0: didn't print anything ** >0: something has been printed ** ** Note: this doesn't deal with all types! FIXME! */ static int sm_conf_prt_def(const sm_conf_definition_T *def, uint flags, sm_file_T *fp, int indent, sm_str_P text) { const sm_conf_type_T *scdtype; int ret; sm_file_T *sfp; sm_file_T text_file; SM_IS_CONF_DEF(def); scdtype = def->scd_type; if (scdtype == NULL) return 0; ret = 0; sfp = NULL; #define PRT_COMMENT(fp) \ do \ { \ if (def->scd_description != NULL && \ *(def->scd_description) != '\0') \ { \ prt_fmtted((fp), indent, "# ", def->scd_description); \ } \ } while (0) #define PRT_TEXT \ do \ { \ if (text != NULL && sm_str_getlen(text) > 0) \ { \ sm_io_fprintf(fp, "%S", text); \ sm_str_clr(text); \ } \ } while (0) #define TEXT2FP \ do \ { \ if (text != NULL) \ { \ /* currently doesn't fail; check?? */ \ (void) sm_str2file(text, &text_file); \ sfp = &text_file; \ } \ else \ { \ PRT_TEXT; \ sfp = fp; \ } \ } while (0) if (SM_IS_FLAG(def->scd_flags, SM_CONF_FLAG_DPRCD)) return 0; if (scdtype == sm_conf_type_section) { int r; TEXT2FP; PRT_COMMENT(sfp); sm_io_fprintf(sfp, "\n%*s%s {\n" , indent, "" , def->scd_name); r = sm_conf_prt_defs(def->scd_contents, flags, fp, indent + 2, text); if (r > 0) { sm_io_fprintf(fp, "%*s}\n" , indent, ""); ret += r; } /* ** This doesn't work for nested sections! ** we "just" need to get back to the old text */ if (text != NULL) sm_str_clr(text); } else if (scdtype == sm_conf_type_string && def->scd_default != NULL) { PRT_TEXT; PRT_COMMENT(fp); sm_io_fprintf(fp, "%*s%s=\"%s\";\n" , indent, "" , def->scd_name , def->scd_default); ret = 1; } else if (scdtype == sm_conf_type_union) { const sm_conf_definition_T *union_def; union_def = def->scd_contents; if (union_def != NULL && union_def->scd_type == sm_conf_type_union_type) { int choice_type; bool found; ptrdiff_t offtype; const sm_conf_definition_T *union_choice_def; offtype = union_def->scd_offset; /* fixme: how to find the right size for the type?? */ choice_type = 0; /* default???? */ #if 0 if (def->scd_default != NULL) /* scan default, assign it to choice_type?? */; #endif found = false; union_choice_def = union_def + 1; while (union_choice_def != NULL && union_choice_def->sm_magic == SM_CONF_DEF_MAGIC && union_choice_def->scd_name != NULL && union_choice_def->scd_type == sm_conf_type_union_choice && !found ) { if ((int) union_choice_def->scd_offset == choice_type) found = true; else ++union_choice_def; } if (found) { int r; PRT_TEXT; PRT_COMMENT(fp); sm_io_fprintf(fp, "%*s%s {\n" , indent, "" , def->scd_name); r = sm_conf_prt_defs( union_choice_def->scd_contents, flags, fp, indent + 2, text); sm_io_fprintf(fp, "%*s}\n" , indent, ""); if (r > 0) ret += r; } } } else if (scdtype == sm_conf_type_choice && SM_IS_FLAG(flags, SMC_FLD_FLAGS)) { /* ** When can we actually print this? ** Only if the section doesn't contain a required selection, ** otherwise the created output is not a valid conf file. */ uint32_t u; u = 0xffffffff; /* scan def->scd_default? */ if (u != 0 && (def->scd_flags & SM_CONF_FLAG_MULTIPLE) != 0) { PRT_TEXT; PRT_COMMENT(fp); sm_io_fprintf(fp, "%*s# %s={ # possible values:\n" , indent, "" , def->scd_name); (void) sm_conf_sub2valbit(def->scd_contents, NULL, u, "# flag: ", "\n", indent + 2, fp); sm_io_fprintf(fp, "%*s# }\n", indent, ""); ret = 1; } else if (u != 0 && (def->scd_flags & SM_CONF_FLAG_OR) != 0) { PRT_TEXT; PRT_COMMENT(fp); sm_io_fprintf(fp, "%*s# %s= # select one of:\n" , indent, "" , def->scd_name); (void) sm_conf_sub2valbit(def->scd_contents, NULL, u, "# flag:", "\n", indent + 2, fp); ret = 1; } else if (u != 0) { PRT_TEXT; PRT_COMMENT(fp); sm_io_fprintf(fp, "%*s# %s=\n" , indent, "" , def->scd_name); (void) sm_conf_sub2valeq(def->scd_contents, NULL, u, fp); sm_io_fprintf(fp, "\n"); ret = 1; } } else if (def->scd_default != NULL) { PRT_TEXT; PRT_COMMENT(fp); sm_io_fprintf(fp, "%*s%s=%s;\n" , indent, "" , def->scd_name , def->scd_default); ret = 1; } else { TEXT2FP; PRT_COMMENT(sfp); sm_io_fprintf(sfp, "%*s# %s %s not set by default\n" , indent, "" , def->scd_name , ((def->scd_flags & SM_CONF_FLAG_PLURAL) != 0) ? "are" : "is" ); } return ret; } /* ** SM_CONF_PRT_DEFS -- print default values of configuration definition ** ** Parameters: ** def -- configuration definition. ** fp -- file for output ** indent -- current indentation ** text -- if not NULL: print this if something is printed ** in this invocation ** ** Returns: ** SM_SUCCESS */ int sm_conf_prt_defs(const sm_conf_definition_T *defs, uint flags, sm_file_T *fp, int indent, sm_str_P text) { const sm_conf_definition_T *def; int r, ret; ret = 0; while ((def = defs++) != NULL && def->scd_name != NULL) { SM_IS_CONF_DEF(def); r = sm_conf_prt_def(def, flags, fp, indent, text); if (r > 0) ret += r; } return ret; } /* ** SM_CONF_PRT_DFLT -- print default values of configuration definition ** (wrapper for sm_conf_prt_defs()) ** ** Parameters: ** def -- configuration definition. ** fp -- file for output ** ** Returns: ** SM_SUCCESS or ENOMEM */ sm_ret_T sm_conf_prt_dflt(const sm_conf_definition_T *defs, uint flags, sm_file_T *fp) { int ret; sm_str_P sect_text; sect_text = sm_str_new(NULL, 256, 8 * 1024); if (sect_text == NULL) return sm_err_temp(ENOMEM); ret = sm_conf_prt_defs(defs, flags, fp, 0, sect_text); SM_STR_FREE(sect_text); return ret; }