1 /* cfg.h -- general-purpose configuration file parser 2 Copyright (C) 2007-2021 Free Software Foundation, Inc. 3 4 GNU Mailutils is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License as 6 published by the Free Software Foundation; either version 3, or (at 7 your option) any later version. 8 9 GNU Mailutils is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef _MAILUTILS_CFG_H 19 #define _MAILUTILS_CFG_H 20 21 #include <mailutils/types.h> 22 #include <mailutils/list.h> 23 #include <mailutils/debug.h> 24 #include <mailutils/opool.h> 25 #include <mailutils/util.h> 26 #include <mailutils/locus.h> 27 #include <sys/socket.h> 28 #include <netinet/in.h> 29 #include <arpa/inet.h> 30 31 #ifdef __cplusplus 32 extern "C" { 33 #endif 34 35 typedef struct mu_cfg_node mu_cfg_node_t; 36 typedef struct mu_cfg_tree mu_cfg_tree_t; 37 38 #define MU_CFG_STRING 0 39 #define MU_CFG_LIST 1 40 #define MU_CFG_ARRAY 2 41 42 typedef struct mu_config_value mu_config_value_t; 43 44 struct mu_config_value 45 { 46 int type; 47 union 48 { 49 mu_list_t list; 50 const char *string; 51 struct 52 { 53 size_t c; 54 mu_config_value_t *v; 55 } arg; 56 } v; 57 }; 58 59 enum mu_cfg_node_type 60 { 61 mu_cfg_node_undefined, 62 mu_cfg_node_statement, 63 mu_cfg_node_param 64 }; 65 66 struct mu_cfg_node 67 { 68 struct mu_locus_range locus; 69 enum mu_cfg_node_type type; 70 char *tag; 71 mu_config_value_t *label; 72 mu_list_t nodes; /* a list of mu_cfg_node_t */ 73 struct mu_cfg_node *parent; /* parent node */ 74 }; 75 76 struct mu_cfg_parse_hints 77 { 78 int flags; 79 char *site_file; 80 char *custom_file; 81 char *program; 82 }; 83 84 /* Bit constants for the flags field of struct mu_cfg_parse_hints */ 85 /* Parse site-wide configuration file hints.site_file */ 86 #define MU_CFHINT_SITE_FILE 0x0001 87 /* Parse custom configuration file hints.custom_file */ 88 #define MU_CFHINT_CUSTOM_FILE 0x0002 89 /* The hints.program field is set. The "program PROGNAME" section 90 will be processed, if PROGNAME is the same as hints.program. 91 If include statement is used with the directory name DIR as its 92 argument, the file DIR/PROGNAME will be looked up and read in, 93 if it exists. */ 94 #define MU_CFHINT_PROGRAM 0x0004 95 96 /* If MU_CFHINT_PROGRAM is set, look for the file ~/.PROGNAME after parsing 97 site-wide configuration */ 98 #define MU_CFHINT_PER_USER_FILE 0x0008 99 100 /* Don't allow to overide configuration settings from the command line. */ 101 #define MU_CFHINT_NO_CONFIG_OVERRIDE 0x0010 102 103 /* Verbosely log files being processed */ 104 #define MU_CF_VERBOSE 0x0100 105 /* Dump the pare tree on stderr */ 106 #define MU_CF_DUMP 0x0200 107 108 /* Format location of the statement */ 109 #define MU_CF_FMT_LOCUS 0x1000 110 /* Print only value */ 111 #define MU_CF_FMT_VALUE_ONLY 0x2000 112 /* Print full parameter path */ 113 #define MU_CF_FMT_PARAM_PATH 0x4000 114 115 struct mu_cfg_tree 116 { 117 mu_list_t nodes; /* a list of mu_cfg_node_t */ 118 mu_opool_t pool; 119 }; 120 121 int mu_cfg_parse (mu_cfg_tree_t **ptree); 122 int mu_cfg_tree_union (mu_cfg_tree_t **pa, mu_cfg_tree_t **pb); 123 int mu_cfg_tree_postprocess (mu_cfg_tree_t *tree, 124 struct mu_cfg_parse_hints *hints); 125 126 mu_opool_t mu_cfg_lexer_pool (void); 127 128 #define MU_CFG_ITER_OK 0 129 #define MU_CFG_ITER_SKIP 1 130 #define MU_CFG_ITER_STOP 2 131 132 typedef int (*mu_cfg_iter_func_t) (const mu_cfg_node_t *node, void *data); 133 134 struct mu_cfg_iter_closure 135 { 136 mu_cfg_iter_func_t beg; 137 mu_cfg_iter_func_t end; 138 void *data; 139 }; 140 141 void mu_cfg_destroy_tree (mu_cfg_tree_t **tree); 142 143 int mu_cfg_preorder (mu_list_t nodelist, struct mu_cfg_iter_closure *); 144 145 146 #define MU_CFG_LIST_MASK 0x8000 147 #define MU_CFG_LIST_OF(t) ((t) | MU_CFG_LIST_MASK) 148 #define MU_CFG_TYPE(t) ((t) & ~MU_CFG_LIST_MASK) 149 #define MU_CFG_IS_LIST(t) ((t) & MU_CFG_LIST_MASK) 150 151 typedef int (*mu_cfg_callback_t) (void *, mu_config_value_t *); 152 153 enum mu_cfg_param_type 154 { 155 mu_cfg_section = mu_c_void + 1, 156 mu_cfg_callback 157 }; 158 159 struct mu_cfg_param 160 { 161 const char *ident; 162 int type; /* One of enum mu_c_type or mu_cfg_param_type values */ 163 void *data; 164 size_t offset; 165 mu_cfg_callback_t callback; 166 const char *docstring; 167 const char *argname; 168 }; 169 170 enum mu_cfg_section_stage 171 { 172 mu_cfg_section_start, 173 mu_cfg_section_end 174 }; 175 176 typedef int (*mu_cfg_section_fp) (enum mu_cfg_section_stage stage, 177 const mu_cfg_node_t *node, 178 const char *label, 179 void **section_data_ptr, 180 void *call_data, 181 mu_cfg_tree_t *tree); 182 183 struct mu_cfg_section 184 { 185 const char *ident; /* Section identifier */ 186 char *label; /* Label description */ 187 mu_cfg_section_fp parser; /* Parser function */ 188 void *data; /* Data pointer */ 189 size_t offset; /* Offset within target (see below) */ 190 mu_list_t /* of mu_cfg_cont */ children; 191 char *docstring; /* Documentation string */ 192 void *target; /* Actual pointer to the data. It is 193 recomputed each time the section is 194 reduced. */ 195 }; 196 197 enum mu_cfg_cont_type 198 { 199 mu_cfg_cont_section, 200 mu_cfg_cont_param 201 }; 202 203 struct mu_cfg_cont 204 { 205 enum mu_cfg_cont_type type; 206 mu_refcount_t refcount; 207 union 208 { 209 const char *ident; 210 struct mu_cfg_section section; 211 struct mu_cfg_param param; 212 } v; 213 }; 214 215 #define MU_CFG_PATH_DELIM '.' 216 #define MU_CFG_PATH_DELIM_STR "." 217 218 int mu_config_create_container (struct mu_cfg_cont **pcont, 219 enum mu_cfg_cont_type type); 220 int mu_config_clone_container (struct mu_cfg_cont *cont); 221 struct mu_cfg_cont *mu_config_clone_root_container (void); 222 223 void mu_config_destroy_container (struct mu_cfg_cont **pcont); 224 225 int mu_cfg_section_add_container (struct mu_cfg_section *sect, 226 struct mu_cfg_cont *cont); 227 int mu_cfg_section_add_params (struct mu_cfg_section *sect, 228 struct mu_cfg_param *param); 229 230 231 int mu_create_canned_section (char *name, struct mu_cfg_section **psection); 232 int mu_create_canned_param (char *name, struct mu_cfg_param **pparam); 233 struct mu_cfg_cont *mu_get_canned_container (const char *name); 234 235 int mu_cfg_create_node_list (mu_list_t *plist); 236 237 int mu_cfg_scan_tree (mu_cfg_tree_t *tree, struct mu_cfg_section *sections, 238 void *target, void *call_data); 239 240 int mu_cfg_find_section (struct mu_cfg_section *root_sec, 241 const char *path, struct mu_cfg_section **retval); 242 243 int mu_config_container_register_section (struct mu_cfg_cont **proot, 244 const char *parent_path, 245 const char *ident, 246 const char *label, 247 mu_cfg_section_fp parser, 248 struct mu_cfg_param *param, 249 struct mu_cfg_section **psection); 250 int mu_config_root_register_section (const char *parent_path, 251 const char *ident, 252 const char *label, 253 mu_cfg_section_fp parser, 254 struct mu_cfg_param *param); 255 256 int mu_config_register_plain_section (const char *parent_path, 257 const char *ident, 258 struct mu_cfg_param *params); 259 260 261 extern int mu_cfg_parser_verbose; 262 extern size_t mu_cfg_error_count; 263 264 void mu_cfg_format_docstring (mu_stream_t stream, const char *docstring, 265 int level); 266 void mu_cfg_format_parse_tree (mu_stream_t stream, struct mu_cfg_tree *tree, 267 int flags); 268 void mu_cfg_format_node (mu_stream_t stream, const mu_cfg_node_t *node, 269 int flags); 270 271 void mu_cfg_format_container (mu_stream_t stream, struct mu_cfg_cont *cont); 272 void mu_format_config_tree (mu_stream_t stream, 273 struct mu_cfg_param *progparam); 274 int mu_cfg_tree_reduce (mu_cfg_tree_t *parse_tree, 275 struct mu_cfg_parse_hints *hints, 276 struct mu_cfg_param *progparam, 277 void *target_ptr); 278 int mu_cfg_assert_value_type (mu_config_value_t *val, int type); 279 int mu_cfg_string_value_cb (mu_config_value_t *val, 280 int (*fun) (const char *, void *), 281 void *data); 282 283 int mu_cfg_parse_file (mu_cfg_tree_t **return_tree, const char *file, 284 int flags); 285 286 287 int mu_cfg_tree_create (struct mu_cfg_tree **ptree); 288 mu_cfg_node_t *mu_cfg_tree_create_node (struct mu_cfg_tree *tree, 289 enum mu_cfg_node_type type, 290 const struct mu_locus_range *loc, 291 const char *tag, 292 const char *label, 293 mu_list_t nodelist); 294 void mu_cfg_tree_add_node (mu_cfg_tree_t *tree, mu_cfg_node_t *node); 295 void mu_cfg_tree_add_nodelist (mu_cfg_tree_t *tree, mu_list_t nodelist); 296 297 int mu_cfg_find_node (mu_cfg_tree_t *tree, const char *path, 298 mu_cfg_node_t **pnode); 299 int mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode); 300 301 int mu_cfg_parse_config (mu_cfg_tree_t **ptree, 302 struct mu_cfg_parse_hints *hints); 303 304 int mu_cfg_field_map (struct mu_config_value const *val, mu_assoc_t *passoc, 305 char **err_term); 306 307 308 #ifdef __cplusplus 309 } 310 #endif 311 312 #endif 313