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