xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/mail_conf_time.c (revision 67b9b338a7386232ac596b5fd0cd5a9cc8a03c71)
1 /*	$NetBSD: mail_conf_time.c,v 1.4 2022/10/08 16:12:45 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	mail_conf_time 3
6 /* SUMMARY
7 /*	time interval configuration parameter support
8 /* SYNOPSIS
9 /*	#include <mail_conf.h>
10 /*
11 /*	int	get_mail_conf_time(name, defval, min, max);
12 /*	const char *name;
13 /*	const char *defval;
14 /*	int	min;
15 /*	int	max;
16 /*
17 /*	void	set_mail_conf_time(name, value)
18 /*	const char *name;
19 /*	const char *value;
20 /*
21 /*	void	set_mail_conf_time_int(name, value)
22 /*	const char *name;
23 /*	int     value;
24 /*
25 /*	void	get_mail_conf_time_table(table)
26 /*	const CONFIG_TIME_TABLE *table;
27 /* AUXILIARY FUNCTIONS
28 /*	int	get_mail_conf_time2(name1, name2, defval, def_unit, min, max);
29 /*	const char *name1;
30 /*	const char *name2;
31 /*	int	defval;
32 /*	int	def_unit;
33 /*	int	min;
34 /*	int	max;
35 /*
36 /*	void	check_mail_conf_time(name, intval, min, max)
37 /*	const char *name;
38 /*	int	intval;
39 /*	int	min;
40 /*	int	max;
41 /* DESCRIPTION
42 /*	This module implements configuration parameter support
43 /*	for time interval values. The conversion routines understand
44 /*	one-letter suffixes to specify an explicit time unit: s
45 /*	(seconds), m (minutes), h (hours), d (days) or w (weeks).
46 /*	Internally, time is represented in seconds.
47 /*
48 /*	get_mail_conf_time() looks up the named entry in the global
49 /*	configuration dictionary. The default value is returned
50 /*	when no value was found. \fIdef_unit\fR supplies the default
51 /*	time unit for numbers specified without explicit unit.
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 /*	set_mail_conf_time() updates the named entry in the global
57 /*	configuration dictionary. This has no effect on values that
58 /*	have been looked up earlier via the get_mail_conf_XXX() routines.
59 /*
60 /*	get_mail_conf_time_table() and get_mail_conf_time_fn_table() initialize
61 /*	lists of variables, as directed by their table arguments. A table
62 /*	must be terminated by a null entry.
63 /*
64 /*	check_mail_conf_time() terminates the program with a fatal
65 /*	runtime error when the time does not meet its requirements.
66 /* DIAGNOSTICS
67 /*	Fatal errors: malformed numerical value, unknown time unit.
68 /* BUGS
69 /*	Values and defaults are given in any unit; upper and lower
70 /*	bounds are given in seconds.
71 /* SEE ALSO
72 /*	config(3) general configuration
73 /*	mail_conf_str(3) string-valued configuration parameters
74 /* LICENSE
75 /* .ad
76 /* .fi
77 /*	The Secure Mailer license must be distributed with this software.
78 /* AUTHOR(S)
79 /*	Wietse Venema
80 /*	IBM T.J. Watson Research
81 /*	P.O. Box 704
82 /*	Yorktown Heights, NY 10598, USA
83 /*
84 /*	Wietse Venema
85 /*	Google, Inc.
86 /*	111 8th Avenue
87 /*	New York, NY 10011, USA
88 /*--*/
89 
90 /* System library. */
91 
92 #include <sys_defs.h>
93 #include <stdlib.h>
94 #include <stdio.h>			/* BUFSIZ */
95 #include <ctype.h>
96 
97 /* Utility library. */
98 
99 #include <msg.h>
100 #include <mymalloc.h>
101 #include <dict.h>
102 #include <stringops.h>
103 
104 /* Global library. */
105 
106 #include "conv_time.h"
107 #include "mail_conf.h"
108 
109 /* convert_mail_conf_time - look up and convert integer parameter value */
110 
convert_mail_conf_time(const char * name,int * intval,int def_unit)111 static int convert_mail_conf_time(const char *name, int *intval, int def_unit)
112 {
113     const char *strval;
114 
115     if ((strval = mail_conf_lookup_eval(name)) == 0)
116 	return (0);
117     if (conv_time(strval, intval, def_unit) == 0)
118 	msg_fatal("parameter %s: bad time value or unit: %s", name, strval);
119     return (1);
120 }
121 
122 /* check_mail_conf_time - validate integer value */
123 
check_mail_conf_time(const char * name,int intval,int min,int max)124 void    check_mail_conf_time(const char *name, int intval, int min, int max)
125 {
126     if (min && intval < min)
127 	msg_fatal("invalid %s: %d (min %d)", name, intval, min);
128     if (max && intval > max)
129 	msg_fatal("invalid %s: %d (max %d)", name, intval, max);
130 }
131 
132 /* get_def_time_unit - extract time unit from default value */
133 
get_def_time_unit(const char * name,const char * defval)134 static int get_def_time_unit(const char *name, const char *defval)
135 {
136     const char *cp;
137 
138     for (cp = mail_conf_eval(defval); /* void */ ; cp++) {
139 	if (*cp == 0)
140 	    msg_panic("parameter %s: missing time unit in default value: %s",
141 		      name, defval);
142 	if (ISALPHA(*cp)) {
143 #if 0
144 	    if (cp[1] != 0)
145 		msg_panic("parameter %s: bad time unit in default value: %s",
146 			  name, defval);
147 #endif
148 	    return (*cp);
149 	}
150     }
151 }
152 
153 /* get_mail_conf_time - evaluate integer-valued configuration variable */
154 
get_mail_conf_time(const char * name,const char * defval,int min,int max)155 int     get_mail_conf_time(const char *name, const char *defval, int min, int max)
156 {
157     int     intval;
158     int     def_unit;
159 
160     def_unit = get_def_time_unit(name, defval);
161     if (convert_mail_conf_time(name, &intval, def_unit) == 0)
162 	set_mail_conf_time(name, defval);
163     if (convert_mail_conf_time(name, &intval, def_unit) == 0)
164 	msg_panic("get_mail_conf_time: parameter not found: %s", name);
165     check_mail_conf_time(name, intval, min, max);
166     return (intval);
167 }
168 
169 /* get_mail_conf_time2 - evaluate integer-valued configuration variable */
170 
get_mail_conf_time2(const char * name1,const char * name2,int defval,int def_unit,int min,int max)171 int     get_mail_conf_time2(const char *name1, const char *name2,
172 			         int defval, int def_unit, int min, int max)
173 {
174     int     intval;
175     char   *name;
176 
177     name = concatenate(name1, name2, (char *) 0);
178     if (convert_mail_conf_time(name, &intval, def_unit) == 0)
179 	set_mail_conf_time_int(name, defval);
180     if (convert_mail_conf_time(name, &intval, def_unit) == 0)
181 	msg_panic("get_mail_conf_time2: parameter not found: %s", name);
182     check_mail_conf_time(name, intval, min, max);
183     myfree(name);
184     return (intval);
185 }
186 
187 /* set_mail_conf_time - update integer-valued configuration dictionary entry */
188 
set_mail_conf_time(const char * name,const char * value)189 void    set_mail_conf_time(const char *name, const char *value)
190 {
191     mail_conf_update(name, value);
192 }
193 
194 /* set_mail_conf_time_int - update integer-valued configuration dictionary entry */
195 
set_mail_conf_time_int(const char * name,int value)196 void    set_mail_conf_time_int(const char *name, int value)
197 {
198     const char myname[] = "set_mail_conf_time_int";
199     char    buf[BUFSIZ];		/* yeah! crappy code! */
200 
201 #ifndef NO_SNPRINTF
202     ssize_t ret;
203 
204     ret = snprintf(buf, sizeof(buf), "%ds", value);
205     if (ret < 0)
206 	msg_panic("%s: output error for %%ds", myname);
207     if (ret >= sizeof(buf))
208 	msg_panic("%s: output for %%ds exceeds space %ld",
209 		  myname, (long) sizeof(buf));
210 #else
211     sprintf(buf, "%ds", value);			/* yeah! more crappy code! */
212 #endif
213     mail_conf_update(name, buf);
214 }
215 
216 /* get_mail_conf_time_table - look up table of integers */
217 
get_mail_conf_time_table(const CONFIG_TIME_TABLE * table)218 void    get_mail_conf_time_table(const CONFIG_TIME_TABLE *table)
219 {
220     while (table->name) {
221 	table->target[0] = get_mail_conf_time(table->name, table->defval,
222 					      table->min, table->max);
223 	table++;
224     }
225 }
226 
227 #ifdef TEST
228 
229  /*
230   * Stand-alone driver program for regression testing.
231   */
232 #include <vstream.h>
233 
main(int unused_argc,char ** unused_argv)234 int     main(int unused_argc, char **unused_argv)
235 {
236     static int seconds;
237     static int minutes;
238     static int hours;
239     static int days;
240     static int weeks;
241     static const CONFIG_TIME_TABLE time_table[] = {
242 	"seconds", "10s", &seconds, 0, 0,
243 	"minutes", "10m", &minutes, 0, 0,
244 	"hours", "10h", &hours, 0, 0,
245 	"days", "10d", &days, 0, 0,
246 	"weeks", "10w", &weeks, 0, 0,
247 	0,
248     };
249 
250     get_mail_conf_time_table(time_table);
251     vstream_printf("10 seconds = %d\n", seconds);
252     vstream_printf("10 minutes = %d\n", minutes);
253     vstream_printf("10 hours = %d\n", hours);
254     vstream_printf("10 days = %d\n", days);
255     vstream_printf("10 weeks = %d\n", weeks);
256     vstream_fflush(VSTREAM_OUT);
257     return (0);
258 }
259 
260 #endif
261