Postfix3.3.1
attr_override.c
[詳解]
1 /*++
2 /* NAME
3 /* attr_override 3
4 /* SUMMARY
5 /* apply name=value settings from string
6 /* SYNOPSIS
7 /* #include <attr_override.h>
8 /*
9 /* void attr_override(bp, delimiters, parens, ... CA_ATTR_OVER_END);
10 /* char *bp;
11 /* const char *delimiters;
12 /* const char *parens;
13 /* DESCRIPTION
14 /* This routine updates the values of known in-memory variables
15 /* based on the name=value specifications from an input string.
16 /* The input format supports parentheses around name=value to
17 /* allow whitespace around "=" and within values.
18 /*
19 /* This may be used, for example, with client endpoint
20 /* specifications or with policy tables to allow selective
21 /* overrides of global main.cf parameter settings (timeouts,
22 /* fall-back policies, etc.).
23 /*
24 /* Arguments:
25 /* .IP bp
26 /* Pointer to input string. The input is modified.
27 /* .IP "delimiters, parens"
28 /* See mystrtok(3) for description. Typical values are
29 /* CHARS_COMMA_SP and CHARS_BRACE, respectively.
30 /* .PP
31 /* The parens argument is followed by a list of macros
32 /* with arguments. Each macro may appear only once. The list
33 /* must be terminated with CA_ATTR_OVER_END which has no argument.
34 /* The following describes the expected values.
35 /* .IP "CA_ATTR_OVER_STR_TABLE(const ATTR_OVER_STR *)"
36 /* The macro argument specifies a null-terminated table with
37 /* attribute names, assignment targets, and range limits which
38 /* should be the same as for the corresponding main.cf parameters.
39 /* .IP "CA_ATTR_OVER_TIME_TABLE(const ATTR_OVER_TIME *)"
40 /* The macro argument specifies a null-terminated table with
41 /* attribute names, their default time units (leading digits
42 /* are skipped), assignment targets, and range limits which
43 /* should be the same as for the corresponding main.cf parameters.
44 /* .IP "CA_ATTR_OVER_INT_TABLE(const ATTR_OVER_INT *)"
45 /* The macro argument specifies a null-terminated table with
46 /* attribute names, assignment targets, and range limits which
47 /* should be the same as for the corresponding main.cf parameters.
48 /* SEE ALSO
49 /* mystrtok(3), safe tokenizer
50 /* extpar(3), extract text from parentheses
51 /* split_nameval(3), name-value splitter
52 /* DIAGNOSTICS
53 /* Panic: interface violations.
54 /*
55 /* Fatal errors: memory allocation problem, syntax error,
56 /* out-of-range error.
57 /* LICENSE
58 /* .ad
59 /* .fi
60 /* The Secure Mailer license must be distributed with this software.
61 /* AUTHOR(S)
62 /* Wietse Venema
63 /* IBM T.J. Watson Research
64 /* P.O. Box 704
65 /* Yorktown Heights, NY 10598, USA
66 /*--*/
67 
68  /*
69  * System library.
70  */
71 #include <sys_defs.h>
72 #include <errno.h>
73 #include <string.h>
74 #include <stdlib.h> /* strtol() */
75 
76  /*
77  * Utility library.
78  */
79 #include <msg.h>
80 #include <stringops.h>
81 
82  /*
83  * Global library.
84  */
85 #include <mail_conf.h>
86 #include <conv_time.h>
87 #include <attr_override.h>
88 
89 /* attr_override - apply settings from list of attribute=value pairs */
90 
91 void attr_override(char *cp, const char *sep, const char *parens,...)
92 {
93  static const char myname[] = "attr_override";
94  va_list ap;
95  int idx;
96  char *nameval;
97  const ATTR_OVER_INT *int_table = 0;
98  const ATTR_OVER_STR *str_table = 0;
99  const ATTR_OVER_TIME *time_table = 0;
100 
101  /*
102  * Get the lookup tables and assignment targets.
103  */
104  va_start(ap, parens);
105  while ((idx = va_arg(ap, int)) != ATTR_OVER_END) {
106  switch (idx) {
107  case ATTR_OVER_INT_TABLE:
108  if (int_table)
109  msg_panic("%s: multiple ATTR_OVER_INT_TABLE", myname);
110  int_table = va_arg(ap, const ATTR_OVER_INT *);
111  break;
112  case ATTR_OVER_STR_TABLE:
113  if (str_table)
114  msg_panic("%s: multiple ATTR_OVER_STR_TABLE", myname);
115  str_table = va_arg(ap, const ATTR_OVER_STR *);
116  break;
118  if (time_table)
119  msg_panic("%s: multiple ATTR_OVER_TIME_TABLE", myname);
120  time_table = va_arg(ap, const ATTR_OVER_TIME *);
121  break;
122  default:
123  msg_panic("%s: unknown argument type: %d", myname, idx);
124  }
125  }
126  va_end(ap);
127 
128  /*
129  * Process each attribute=value override in the input string.
130  */
131  while ((nameval = mystrtokq(&cp, sep, parens)) != 0) {
132  int found = 0;
133  char *key;
134  char *value;
135  const char *err;
136  const ATTR_OVER_INT *ip;
137  const ATTR_OVER_STR *sp;
138  const ATTR_OVER_TIME *tp;
139  int int_val;
140  int def_unit;
141  char *end;
142  long longval;
143 
144  /*
145  * Split into name and value.
146  */
147  /* { name = value } */
148  if (*nameval == parens[0]
149  && (err = extpar(&nameval, parens, EXTPAR_FLAG_NONE)) != 0)
150  msg_fatal("%s in \"%s\"", err, nameval);
151  if ((err = split_nameval(nameval, &key, &value)) != 0)
152  msg_fatal("malformed option: %s: \"...%s...\"", err, nameval);
153 
154  /*
155  * Look up the name and apply the value.
156  */
157  for (sp = str_table; sp != 0 && found == 0 && sp->name != 0; sp++) {
158  if (strcmp(sp->name, key) != 0)
159  continue;
160  check_mail_conf_str(sp->name, value, sp->min, sp->max);
161  sp->target[0] = value;
162  found = 1;
163  }
164  for (ip = int_table; ip != 0 && found == 0 && ip->name != 0; ip++) {
165  if (strcmp(ip->name, key) != 0)
166  continue;
167  /* XXX Duplicated from mail_conf_int(3). */
168  errno = 0;
169  int_val = longval = strtol(value, &end, 10);
170  if (*value == 0 || *end != 0 || errno == ERANGE
171  || longval != int_val)
172  msg_fatal("bad numerical configuration: %s = %s", key, value);
173  check_mail_conf_int(key, int_val, ip->min, ip->max);
174  ip->target[0] = int_val;
175  found = 1;
176  }
177  for (tp = time_table; tp != 0 && found == 0 && tp->name != 0; tp++) {
178  if (strcmp(tp->name, key) != 0)
179  continue;
180  def_unit = tp->defval[strspn(tp->defval, "0123456789")];
181  if (conv_time(value, &int_val, def_unit) == 0)
182  msg_fatal("%s: bad time value or unit: %s", key, value);
183  check_mail_conf_time(key, int_val, tp->min, tp->max);
184  tp->target[0] = int_val;
185  found = 1;
186  }
187  if (found == 0)
188  msg_fatal("unknown option: \"%s = %s\"", key, value);
189  }
190 }
char * extpar(char **bp, const char *parens, int flags)
Definition: extpar.c:77
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define EXTPAR_FLAG_NONE
Definition: stringops.h:56
const char * name
Definition: attr_override.h:29
void attr_override(char *cp, const char *sep, const char *parens,...)
Definition: attr_override.c:91
int conv_time(const char *strval, int *timval, int def_unit)
Definition: conv_time.c:67
char * mystrtokq(char **src, const char *sep, const char *parens)
Definition: mystrtok.c:80
#define ATTR_OVER_STR_TABLE
Definition: attr_override.h:45
const char * name
Definition: attr_override.h:37
const char * split_nameval(char *buf, char **name, char **value)
Definition: split_nameval.c:61
const char * name
Definition: attr_override.h:22
void check_mail_conf_str(const char *, const char *, int, int)
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
const char * defval
Definition: attr_override.h:30
void check_mail_conf_int(const char *, int, int, int)
#define ATTR_OVER_TIME_TABLE
Definition: attr_override.h:46
void check_mail_conf_time(const char *, int, int, int)
#define ATTR_OVER_END
Definition: attr_override.h:44
CONST_CHAR_STAR * target
Definition: attr_override.h:23
#define ATTR_OVER_INT_TABLE
Definition: attr_override.h:47