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