Postfix3.3.1
cfg_parser.c
[詳解]
1 /*++
2 /* NAME
3 /* cfg_parser 3
4 /* SUMMARY
5 /* configuration parser utilities
6 /* SYNOPSIS
7 /* #include "cfg_parser.h"
8 /*
9 /* CFG_PARSER *cfg_parser_alloc(pname)
10 /* const char *pname;
11 /*
12 /* CFG_PARSER *cfg_parser_free(parser)
13 /* CFG_PARSER *parser;
14 /*
15 /* char *cfg_get_str(parser, name, defval, min, max)
16 /* const CFG_PARSER *parser;
17 /* const char *name;
18 /* const char *defval;
19 /* int min;
20 /* int max;
21 /*
22 /* int cfg_get_int(parser, name, defval, min, max)
23 /* const CFG_PARSER *parser;
24 /* const char *name;
25 /* int defval;
26 /* int min;
27 /* int max;
28 /*
29 /* int cfg_get_bool(parser, name, defval)
30 /* const CFG_PARSER *parser;
31 /* const char *name;
32 /* int defval;
33 /*
34 /* DICT_OWNER cfg_get_owner(parser)
35 /* const CFG_PARSER *parser;
36 /* DESCRIPTION
37 /* This module implements utilities for parsing parameters defined
38 /* either as "\fIname\fR = \fBvalue\fR" in a file pointed to by
39 /* \fIpname\fR (the old MySQL style), or as "\fIpname\fR_\fIname\fR =
40 /* \fBvalue\fR" in main.cf (the old LDAP style). It unifies the
41 /* two styles and provides support for range checking.
42 /*
43 /* \fIcfg_parser_alloc\fR initializes the parser. The result
44 /* is NULL if a configuration file could not be opened.
45 /*
46 /* \fIcfg_parser_free\fR releases the parser.
47 /*
48 /* \fIcfg_get_str\fR looks up a string.
49 /*
50 /* \fIcfg_get_int\fR looks up an integer.
51 /*
52 /* \fIcfg_get_bool\fR looks up a boolean value.
53 /*
54 /* \fIdefval\fR is returned when no value was found. \fImin\fR is
55 /* zero or specifies a lower limit on the integer value or string
56 /* length; \fImax\fR is zero or specifies an upper limit on the
57 /* integer value or string length.
58 /*
59 /* Conveniently, \fIcfg_get_str\fR returns \fBNULL\fR if
60 /* \fIdefval\fR is \fBNULL\fR and no value was found. The returned
61 /* string has to be freed by the caller if not \fBNULL\fR.
62 /*
63 /* cfg_get_owner() looks up the configuration file owner.
64 /* DIAGNOSTICS
65 /* Fatal errors: bad string length, malformed numerical value, malformed
66 /* boolean value.
67 /* SEE ALSO
68 /* mail_conf_str(3) string-valued global configuration parameter support
69 /* mail_conf_int(3) integer-valued configuration parameter support
70 /* mail_conf_bool(3) boolean-valued configuration parameter support
71 /* LICENSE
72 /* .ad
73 /* .fi
74 /* The Secure Mailer license must be distributed with this software.
75 /* AUTHOR(S)
76 /* Wietse Venema
77 /* IBM T.J. Watson Research
78 /* P.O. Box 704
79 /* Yorktown Heights, NY 10598, USA
80 /*
81 /* Liviu Daia
82 /* Institute of Mathematics of the Romanian Academy
83 /* P.O. BOX 1-764
84 /* RO-014700 Bucharest, ROMANIA
85 /*--*/
86 
87 /* System library. */
88 
89 #include "sys_defs.h"
90 
91 #include <stdlib.h>
92 #include <errno.h>
93 #include <string.h>
94 
95 #ifdef STRCASECMP_IN_STRINGS_H
96 #include <strings.h>
97 #endif
98 
99 /* Utility library. */
100 
101 #include "msg.h"
102 #include "mymalloc.h"
103 #include "vstring.h"
104 #include "dict.h"
105 
106 /* Global library. */
107 
108 #include "mail_conf.h"
109 
110 /* Application-specific. */
111 
112 #include "cfg_parser.h"
113 
114 /* get string from file */
115 
116 static char *get_dict_str(const struct CFG_PARSER *parser,
117  const char *name, const char *defval,
118  int min, int max)
119 {
120  const char *strval;
121  int len;
122 
123  if ((strval = dict_lookup(parser->name, name)) == 0)
124  strval = defval;
125 
126  len = strlen(strval);
127  if (min && len < min)
128  msg_fatal("%s: bad string length %d < %d: %s = %s",
129  parser->name, len, min, name, strval);
130  if (max && len > max)
131  msg_fatal("%s: bad string length %d > %d: %s = %s",
132  parser->name, len, max, name, strval);
133  return (mystrdup(strval));
134 }
135 
136 /* get string from main.cf */
137 
138 static char *get_main_str(const struct CFG_PARSER *parser,
139  const char *name, const char *defval,
140  int min, int max)
141 {
142  static VSTRING *buf = 0;
143 
144  if (buf == 0)
145  buf = vstring_alloc(15);
146  vstring_sprintf(buf, "%s_%s", parser->name, name);
147  return (get_mail_conf_str(vstring_str(buf), defval, min, max));
148 }
149 
150 /* get integer from file */
151 
152 static int get_dict_int(const struct CFG_PARSER *parser,
153  const char *name, int defval, int min, int max)
154 {
155  const char *strval;
156  char *end;
157  int intval;
158  long longval;
159 
160  if ((strval = dict_lookup(parser->name, name)) != 0) {
161  errno = 0;
162  intval = longval = strtol(strval, &end, 10);
163  if (*strval == 0 || *end != 0 || errno == ERANGE || longval != intval)
164  msg_fatal("%s: bad numerical configuration: %s = %s",
165  parser->name, name, strval);
166  } else
167  intval = defval;
168  if (min && intval < min)
169  msg_fatal("%s: invalid %s parameter value %d < %d",
170  parser->name, name, intval, min);
171  if (max && intval > max)
172  msg_fatal("%s: invalid %s parameter value %d > %d",
173  parser->name, name, intval, max);
174  return (intval);
175 }
176 
177 /* get integer from main.cf */
178 
179 static int get_main_int(const struct CFG_PARSER *parser,
180  const char *name, int defval, int min, int max)
181 {
182  static VSTRING *buf = 0;
183 
184  if (buf == 0)
185  buf = vstring_alloc(15);
186  vstring_sprintf(buf, "%s_%s", parser->name, name);
187  return (get_mail_conf_int(vstring_str(buf), defval, min, max));
188 }
189 
190 /* get boolean option from file */
191 
192 static int get_dict_bool(const struct CFG_PARSER *parser,
193  const char *name, int defval)
194 {
195  const char *strval;
196  int intval;
197 
198  if ((strval = dict_lookup(parser->name, name)) != 0) {
199  if (strcasecmp(strval, CONFIG_BOOL_YES) == 0) {
200  intval = 1;
201  } else if (strcasecmp(strval, CONFIG_BOOL_NO) == 0) {
202  intval = 0;
203  } else {
204  msg_fatal("%s: bad boolean configuration: %s = %s",
205  parser->name, name, strval);
206  }
207  } else
208  intval = defval;
209  return (intval);
210 }
211 
212 /* get boolean option from main.cf */
213 
214 static int get_main_bool(const struct CFG_PARSER *parser,
215  const char *name, int defval)
216 {
217  static VSTRING *buf = 0;
218 
219  if (buf == 0)
220  buf = vstring_alloc(15);
221  vstring_sprintf(buf, "%s_%s", parser->name, name);
222  return (get_mail_conf_bool(vstring_str(buf), defval));
223 }
224 
225 /* initialize parser */
226 
227 CFG_PARSER *cfg_parser_alloc(const char *pname)
228 {
229  const char *myname = "cfg_parser_alloc";
230  CFG_PARSER *parser;
231  DICT *dict;
232 
233  if (pname == 0 || *pname == 0)
234  msg_fatal("%s: null parser name", myname);
235  parser = (CFG_PARSER *) mymalloc(sizeof(*parser));
236  parser->name = mystrdup(pname);
237  if (*parser->name == '/' || *parser->name == '.') {
238  if (dict_load_file_xt(parser->name, parser->name) == 0) {
239  myfree(parser->name);
240  myfree((void *) parser);
241  return (0);
242  }
243  parser->get_str = get_dict_str;
244  parser->get_int = get_dict_int;
245  parser->get_bool = get_dict_bool;
246  dict = dict_handle(parser->name);
247  } else {
248  parser->get_str = get_main_str;
249  parser->get_int = get_main_int;
250  parser->get_bool = get_main_bool;
251  dict = dict_handle(CONFIG_DICT); /* XXX Use proper API */
252  }
253  if (dict == 0)
254  msg_panic("%s: dict_handle failed", myname);
255  parser->owner = dict->owner;
256  return (parser);
257 }
258 
259 /* get string */
260 
261 char *cfg_get_str(const CFG_PARSER *parser, const char *name,
262  const char *defval, int min, int max)
263 {
264  const char *myname = "cfg_get_str";
265  char *strval;
266 
267  strval = parser->get_str(parser, name, (defval ? defval : ""), min, max);
268  if (defval == 0 && *strval == 0) {
269  /* the caller wants NULL instead of "" */
270  myfree(strval);
271  strval = 0;
272  }
273  if (msg_verbose)
274  msg_info("%s: %s: %s = %s", myname, parser->name, name,
275  (strval ? strval : "<NULL>"));
276  return (strval);
277 }
278 
279 /* get integer */
280 
281 int cfg_get_int(const CFG_PARSER *parser, const char *name, int defval,
282  int min, int max)
283 {
284  const char *myname = "cfg_get_int";
285  int intval;
286 
287  intval = parser->get_int(parser, name, defval, min, max);
288  if (msg_verbose)
289  msg_info("%s: %s: %s = %d", myname, parser->name, name, intval);
290  return (intval);
291 }
292 
293 /* get boolean option */
294 
295 int cfg_get_bool(const CFG_PARSER *parser, const char *name, int defval)
296 {
297  const char *myname = "cfg_get_bool";
298  int intval;
299 
300  intval = parser->get_bool(parser, name, defval);
301  if (msg_verbose)
302  msg_info("%s: %s: %s = %s", myname, parser->name, name,
303  (intval ? "on" : "off"));
304  return (intval);
305 }
306 
307 /* release parser */
308 
310 {
311  const char *myname = "cfg_parser_free";
312 
313  if (parser->name == 0 || *parser->name == 0)
314  msg_panic("%s: null parser name", myname);
315  if (*parser->name == '/' || *parser->name == '.') {
316  if (dict_handle(parser->name))
317  dict_unregister(parser->name);
318  }
319  myfree(parser->name);
320  myfree((void *) parser);
321  return (0);
322 }
int msg_verbose
Definition: msg.c:177
#define CONFIG_BOOL_NO
Definition: mail_conf.h:31
void myfree(void *ptr)
Definition: mymalloc.c:207
char * mystrdup(const char *str)
Definition: mymalloc.c:225
int dict_load_file_xt(const char *dict_name, const char *path)
Definition: dict.c:441
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define vstring_str(vp)
Definition: vstring.h:71
int get_mail_conf_bool(const char *, int)
#define CONFIG_DICT
Definition: mail_conf.h:17
int cfg_get_int(const CFG_PARSER *parser, const char *name, int defval, int min, int max)
Definition: cfg_parser.c:281
int get_mail_conf_int(const char *, int, int, int)
void dict_unregister(const char *dict_name)
Definition: dict.c:354
DICT_OWNER owner
Definition: cfg_parser.h:28
Definition: dict.h:78
const char * dict_lookup(const char *dict_name, const char *member)
Definition: dict.c:382
DICT * dict_handle(const char *dict_name)
Definition: dict.c:333
int(* get_int)(const struct CFG_PARSER *, const char *, int, int, int)
Definition: cfg_parser.h:26
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
char * name
Definition: cfg_parser.h:23
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
char * cfg_get_str(const CFG_PARSER *parser, const char *name, const char *defval, int min, int max)
Definition: cfg_parser.c:261
#define CONFIG_BOOL_YES
Definition: mail_conf.h:30
CFG_PARSER * cfg_parser_free(CFG_PARSER *parser)
Definition: cfg_parser.c:309
int strcasecmp(const char *s1, const char *s2)
Definition: strcasecmp.c:41
CFG_PARSER * cfg_parser_alloc(const char *pname)
Definition: cfg_parser.c:227
char * get_mail_conf_str(const char *, const char *, int, int)
int(* get_bool)(const struct CFG_PARSER *, const char *, int)
Definition: cfg_parser.h:27
int cfg_get_bool(const CFG_PARSER *parser, const char *name, int defval)
Definition: cfg_parser.c:295
char *(* get_str)(const struct CFG_PARSER *, const char *, const char *, int, int)
Definition: cfg_parser.h:24
DICT_OWNER owner
Definition: dict.h:93
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
void msg_info(const char *fmt,...)
Definition: msg.c:199