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 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 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 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 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 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 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 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 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 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