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