1 /* $NetBSD: mail_conf_nint.c,v 1.2 2020/03/18 19:05:16 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* mail_conf_nint 3 6 /* SUMMARY 7 /* integer-valued configuration parameter support 8 /* SYNOPSIS 9 /* #include <mail_conf.h> 10 /* 11 /* int get_mail_conf_nint(name, defval, min, max); 12 /* const char *name; 13 /* const char *defval; 14 /* int min; 15 /* int max; 16 /* 17 /* int get_mail_conf_nint_fn(name, defval, min, max); 18 /* const char *name; 19 /* char *(*defval)(); 20 /* int min; 21 /* int max; 22 /* 23 /* void set_mail_conf_nint(name, value) 24 /* const char *name; 25 /* const char *value; 26 /* 27 /* void set_mail_conf_nint_int(name, value) 28 /* const char *name; 29 /* int value; 30 /* 31 /* void get_mail_conf_nint_table(table) 32 /* const CONFIG_NINT_TABLE *table; 33 /* 34 /* void get_mail_conf_nint_fn_table(table) 35 /* const CONFIG_NINT_TABLE *table; 36 /* AUXILIARY FUNCTIONS 37 /* int get_mail_conf_nint2(name1, name2, defval, min, max); 38 /* const char *name1; 39 /* const char *name2; 40 /* int defval; 41 /* int min; 42 /* int max; 43 /* DESCRIPTION 44 /* This module implements configuration parameter support 45 /* for integer values. Unlike mail_conf_int, the default 46 /* is a string, which can be subjected to macro expansion. 47 /* 48 /* get_mail_conf_nint() looks up the named entry in the global 49 /* configuration dictionary. The default value is returned 50 /* when no value was found. 51 /* \fImin\fR is zero or specifies a lower limit on the integer 52 /* value or string length; \fImax\fR is zero or specifies an 53 /* upper limit on the integer value or string length. 54 /* 55 /* get_mail_conf_nint_fn() is similar but specifies a function that 56 /* provides the default value. The function is called only 57 /* when the default value is needed. 58 /* 59 /* set_mail_conf_nint() updates the named entry in the global 60 /* configuration dictionary. This has no effect on values that 61 /* have been looked up earlier via the get_mail_conf_XXX() routines. 62 /* 63 /* get_mail_conf_nint_table() and get_mail_conf_nint_fn_table() initialize 64 /* lists of variables, as directed by their table arguments. A table 65 /* must be terminated by a null entry. 66 /* 67 /* get_mail_conf_nint2() concatenates the two names and is otherwise 68 /* identical to get_mail_conf_nint(). 69 /* DIAGNOSTICS 70 /* Fatal errors: malformed numerical value. 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 <errno.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 "mail_conf.h" 107 108 /* convert_mail_conf_nint - look up and convert integer parameter value */ 109 110 static int convert_mail_conf_nint(const char *name, int *intval) 111 { 112 const char *strval; 113 char *end; 114 long longval; 115 116 if ((strval = mail_conf_lookup_eval(name)) != 0) { 117 errno = 0; 118 *intval = longval = strtol(strval, &end, 10); 119 if (*strval == 0 || *end != 0 || errno == ERANGE || longval != *intval) 120 msg_fatal("bad numerical configuration: %s = %s", name, strval); 121 return (1); 122 } 123 return (0); 124 } 125 126 /* check_mail_conf_nint - validate integer value */ 127 128 static void check_mail_conf_nint(const char *name, int intval, int min, int max) 129 { 130 if (min && intval < min) 131 msg_fatal("invalid %s parameter value %d < %d", name, intval, min); 132 if (max && intval > max) 133 msg_fatal("invalid %s parameter value %d > %d", name, intval, max); 134 } 135 136 /* get_mail_conf_nint - evaluate integer-valued configuration variable */ 137 138 int get_mail_conf_nint(const char *name, const char *defval, int min, int max) 139 { 140 int intval; 141 142 if (convert_mail_conf_nint(name, &intval) == 0) 143 set_mail_conf_nint(name, defval); 144 if (convert_mail_conf_nint(name, &intval) == 0) 145 msg_panic("get_mail_conf_nint: parameter not found: %s", name); 146 check_mail_conf_nint(name, intval, min, max); 147 return (intval); 148 } 149 150 /* get_mail_conf_nint2 - evaluate integer-valued configuration variable */ 151 152 int get_mail_conf_nint2(const char *name1, const char *name2, int defval, 153 int min, int max) 154 { 155 int intval; 156 char *name; 157 158 name = concatenate(name1, name2, (char *) 0); 159 if (convert_mail_conf_nint(name, &intval) == 0) 160 set_mail_conf_nint_int(name, defval); 161 if (convert_mail_conf_nint(name, &intval) == 0) 162 msg_panic("get_mail_conf_nint2: parameter not found: %s", name); 163 check_mail_conf_nint(name, intval, min, max); 164 myfree(name); 165 return (intval); 166 } 167 168 /* get_mail_conf_nint_fn - evaluate integer-valued configuration variable */ 169 170 typedef const char *(*stupid_indent_int) (void); 171 172 int get_mail_conf_nint_fn(const char *name, stupid_indent_int defval, 173 int min, int max) 174 { 175 int intval; 176 177 if (convert_mail_conf_nint(name, &intval) == 0) 178 set_mail_conf_nint(name, defval()); 179 if (convert_mail_conf_nint(name, &intval) == 0) 180 msg_panic("get_mail_conf_nint_fn: parameter not found: %s", name); 181 check_mail_conf_nint(name, intval, min, max); 182 return (intval); 183 } 184 185 /* set_mail_conf_nint - update integer-valued configuration dictionary entry */ 186 187 void set_mail_conf_nint(const char *name, const char *value) 188 { 189 mail_conf_update(name, value); 190 } 191 192 /* set_mail_conf_nint_int - update integer-valued configuration dictionary entry */ 193 194 void set_mail_conf_nint_int(const char *name, int value) 195 { 196 const char myname[] = "set_mail_conf_nint_int"; 197 char buf[BUFSIZ]; /* yeah! crappy code! */ 198 199 #ifndef NO_SNPRINTF 200 ssize_t ret; 201 202 ret = snprintf(buf, sizeof(buf), "%d", value); 203 if (ret < 0) 204 msg_panic("%s: output error for %%d", myname); 205 if (ret >= sizeof(buf)) 206 msg_panic("%s: output for %%d exceeds space %ld", 207 myname, (long) sizeof(buf)); 208 #else 209 sprintf(buf, "%d", value); /* yeah! more crappy code! */ 210 #endif 211 mail_conf_update(name, buf); 212 } 213 214 /* get_mail_conf_nint_table - look up table of integers */ 215 216 void get_mail_conf_nint_table(const CONFIG_NINT_TABLE *table) 217 { 218 while (table->name) { 219 table->target[0] = get_mail_conf_nint(table->name, table->defval, 220 table->min, table->max); 221 table++; 222 } 223 } 224 225 /* get_mail_conf_nint_fn_table - look up integers, defaults are functions */ 226 227 void get_mail_conf_nint_fn_table(const CONFIG_NINT_FN_TABLE *table) 228 { 229 while (table->name) { 230 table->target[0] = get_mail_conf_nint_fn(table->name, table->defval, 231 table->min, table->max); 232 table++; 233 } 234 } 235