1 /*++
2 /* NAME
3 /* mail_conf_nint 3
4 /* SUMMARY
5 /* integer-valued configuration parameter support
6 /* SYNOPSIS
7 /* #include <mail_conf.h>
8 /*
9 /* int get_mail_conf_nint(name, defval, min, max);
10 /* const char *name;
11 /* const char *defval;
12 /* int min;
13 /* int max;
14 /*
15 /* int get_mail_conf_nint_fn(name, defval, min, max);
16 /* const char *name;
17 /* char *(*defval)();
18 /* int min;
19 /* int max;
20 /*
21 /* void set_mail_conf_nint(name, value)
22 /* const char *name;
23 /* const char *value;
24 /*
25 /* void set_mail_conf_nint_int(name, value)
26 /* const char *name;
27 /* int value;
28 /*
29 /* void get_mail_conf_nint_table(table)
30 /* const CONFIG_NINT_TABLE *table;
31 /*
32 /* void get_mail_conf_nint_fn_table(table)
33 /* const CONFIG_NINT_TABLE *table;
34 /* AUXILIARY FUNCTIONS
35 /* int get_mail_conf_nint2(name1, name2, defval, min, max);
36 /* const char *name1;
37 /* const char *name2;
38 /* int defval;
39 /* int min;
40 /* int max;
41 /* DESCRIPTION
42 /* This module implements configuration parameter support
43 /* for integer values. Unlike mail_conf_int, the default
44 /* is a string, which can be subjected to macro expansion.
45 /*
46 /* get_mail_conf_nint() looks up the named entry in the global
47 /* configuration dictionary. The default value is returned
48 /* when no value was found.
49 /* \fImin\fR is zero or specifies a lower limit on the integer
50 /* value or string length; \fImax\fR is zero or specifies an
51 /* upper limit on the integer value or string length.
52 /*
53 /* get_mail_conf_nint_fn() is similar but specifies a function that
54 /* provides the default value. The function is called only
55 /* when the default value is needed.
56 /*
57 /* set_mail_conf_nint() updates the named entry in the global
58 /* configuration dictionary. This has no effect on values that
59 /* have been looked up earlier via the get_mail_conf_XXX() routines.
60 /*
61 /* get_mail_conf_nint_table() and get_mail_conf_nint_fn_table() initialize
62 /* lists of variables, as directed by their table arguments. A table
63 /* must be terminated by a null entry.
64 /*
65 /* get_mail_conf_nint2() concatenates the two names and is otherwise
66 /* identical to get_mail_conf_nint().
67 /* DIAGNOSTICS
68 /* Fatal errors: malformed numerical value.
69 /* SEE ALSO
70 /* config(3) general configuration
71 /* mail_conf_str(3) string-valued configuration parameters
72 /* LICENSE
73 /* .ad
74 /* .fi
75 /* The Secure Mailer license must be distributed with this software.
76 /* AUTHOR(S)
77 /* Wietse Venema
78 /* IBM T.J. Watson Research
79 /* P.O. Box 704
80 /* Yorktown Heights, NY 10598, USA
81 /*
82 /* Wietse Venema
83 /* Google, Inc.
84 /* 111 8th Avenue
85 /* New York, NY 10011, USA
86 /*--*/
87
88 /* System library. */
89
90 #include <sys_defs.h>
91 #include <stdlib.h>
92 #include <stdio.h> /* BUFSIZ */
93 #include <errno.h>
94
95 /* Utility library. */
96
97 #include <msg.h>
98 #include <mymalloc.h>
99 #include <dict.h>
100 #include <stringops.h>
101
102 /* Global library. */
103
104 #include "mail_conf.h"
105
106 /* convert_mail_conf_nint - look up and convert integer parameter value */
107
convert_mail_conf_nint(const char * name,int * intval)108 static int convert_mail_conf_nint(const char *name, int *intval)
109 {
110 const char *strval;
111 char *end;
112 long longval;
113
114 if ((strval = mail_conf_lookup_eval(name)) != 0) {
115 errno = 0;
116 *intval = longval = strtol(strval, &end, 10);
117 if (*strval == 0 || *end != 0 || errno == ERANGE || longval != *intval)
118 msg_fatal("bad numerical configuration: %s = %s", name, strval);
119 return (1);
120 }
121 return (0);
122 }
123
124 /* check_mail_conf_nint - validate integer value */
125
check_mail_conf_nint(const char * name,int intval,int min,int max)126 static void check_mail_conf_nint(const char *name, int intval, int min, int max)
127 {
128 if (min && intval < min)
129 msg_fatal("invalid %s parameter value %d < %d", name, intval, min);
130 if (max && intval > max)
131 msg_fatal("invalid %s parameter value %d > %d", name, intval, max);
132 }
133
134 /* get_mail_conf_nint - evaluate integer-valued configuration variable */
135
get_mail_conf_nint(const char * name,const char * defval,int min,int max)136 int get_mail_conf_nint(const char *name, const char *defval, int min, int max)
137 {
138 int intval;
139
140 if (convert_mail_conf_nint(name, &intval) == 0)
141 set_mail_conf_nint(name, defval);
142 if (convert_mail_conf_nint(name, &intval) == 0)
143 msg_panic("get_mail_conf_nint: parameter not found: %s", name);
144 check_mail_conf_nint(name, intval, min, max);
145 return (intval);
146 }
147
148 /* get_mail_conf_nint2 - evaluate integer-valued configuration variable */
149
get_mail_conf_nint2(const char * name1,const char * name2,int defval,int min,int max)150 int get_mail_conf_nint2(const char *name1, const char *name2, int defval,
151 int min, int max)
152 {
153 int intval;
154 char *name;
155
156 name = concatenate(name1, name2, (char *) 0);
157 if (convert_mail_conf_nint(name, &intval) == 0)
158 set_mail_conf_nint_int(name, defval);
159 if (convert_mail_conf_nint(name, &intval) == 0)
160 msg_panic("get_mail_conf_nint2: parameter not found: %s", name);
161 check_mail_conf_nint(name, intval, min, max);
162 myfree(name);
163 return (intval);
164 }
165
166 /* get_mail_conf_nint_fn - evaluate integer-valued configuration variable */
167
168 typedef const char *(*stupid_indent_int) (void);
169
get_mail_conf_nint_fn(const char * name,stupid_indent_int defval,int min,int max)170 int get_mail_conf_nint_fn(const char *name, stupid_indent_int defval,
171 int min, int max)
172 {
173 int intval;
174
175 if (convert_mail_conf_nint(name, &intval) == 0)
176 set_mail_conf_nint(name, defval());
177 if (convert_mail_conf_nint(name, &intval) == 0)
178 msg_panic("get_mail_conf_nint_fn: parameter not found: %s", name);
179 check_mail_conf_nint(name, intval, min, max);
180 return (intval);
181 }
182
183 /* set_mail_conf_nint - update integer-valued configuration dictionary entry */
184
set_mail_conf_nint(const char * name,const char * value)185 void set_mail_conf_nint(const char *name, const char *value)
186 {
187 mail_conf_update(name, value);
188 }
189
190 /* set_mail_conf_nint_int - update integer-valued configuration dictionary entry */
191
set_mail_conf_nint_int(const char * name,int value)192 void set_mail_conf_nint_int(const char *name, int value)
193 {
194 const char myname[] = "set_mail_conf_nint_int";
195 char buf[BUFSIZ]; /* yeah! crappy code! */
196
197 #ifndef NO_SNPRINTF
198 ssize_t ret;
199
200 ret = snprintf(buf, sizeof(buf), "%d", value);
201 if (ret < 0)
202 msg_panic("%s: output error for %%d", myname);
203 if (ret >= sizeof(buf))
204 msg_panic("%s: output for %%d exceeds space %ld",
205 myname, (long) sizeof(buf));
206 #else
207 sprintf(buf, "%d", value); /* yeah! more crappy code! */
208 #endif
209 mail_conf_update(name, buf);
210 }
211
212 /* get_mail_conf_nint_table - look up table of integers */
213
get_mail_conf_nint_table(const CONFIG_NINT_TABLE * table)214 void get_mail_conf_nint_table(const CONFIG_NINT_TABLE *table)
215 {
216 while (table->name) {
217 table->target[0] = get_mail_conf_nint(table->name, table->defval,
218 table->min, table->max);
219 table++;
220 }
221 }
222
223 /* get_mail_conf_nint_fn_table - look up integers, defaults are functions */
224
get_mail_conf_nint_fn_table(const CONFIG_NINT_FN_TABLE * table)225 void get_mail_conf_nint_fn_table(const CONFIG_NINT_FN_TABLE *table)
226 {
227 while (table->name) {
228 table->target[0] = get_mail_conf_nint_fn(table->name, table->defval,
229 table->min, table->max);
230 table++;
231 }
232 }
233