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