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 111static 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 124void 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 134static 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 155int 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 171int 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 189void 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 196void 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 218void 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 234int 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