masqmail
diff src/conf.c @ 392:c5fd796ea06e
Heavy refactoring in parts of conf.c.
init_conf()
parse_boolean()
parse_list_file()
Re-arrangement of code.
parse_address_glob_list()
Removed unneccessary parameter.
parse_list()
parse_interface():
Use strtok()/strchr() instead of doing is all by hand.
Removed limitation of fixed size buffer.
eat_comments()
Use a state machine.
eat_line_trailing()
eat_spaces()
read_lval()
Better structured code.
read_conf()
read_route()
Removed magic numbers.
Made all list type in the config files accept pathname entries,
except for `permanent_routes' and `query_routes.' for which this
is impossible.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Sat, 18 Feb 2012 18:07:55 +0100 |
parents | a408411ff8df |
children | 5e728dd64c1b |
line diff
1.1 --- a/src/conf.c Sat Feb 18 17:53:04 2012 +0100 1.2 +++ b/src/conf.c Sat Feb 18 18:07:55 2012 +0100 1.3 @@ -31,23 +31,21 @@ 1.4 struct passwd *passwd; 1.5 struct group *group; 1.6 1.7 + if (!(passwd = getpwnam(DEF_MAIL_USER))) { 1.8 + fprintf(stderr, "user %s not found! (terminating)\n", 1.9 + DEF_MAIL_USER); 1.10 + exit(1); 1.11 + } 1.12 + if (!(group = getgrnam(DEF_MAIL_GROUP))) { 1.13 + fprintf(stderr, "group %s not found! (terminating)\n", 1.14 + DEF_MAIL_GROUP); 1.15 + exit(1); 1.16 + } 1.17 memset(&conf, 0, sizeof(masqmail_conf)); 1.18 - 1.19 conf.orig_uid = getuid(); 1.20 conf.orig_gid = getgid(); 1.21 - 1.22 - if ((passwd = getpwnam(DEF_MAIL_USER))) 1.23 - conf.mail_uid = passwd->pw_uid; 1.24 - else { 1.25 - fprintf(stderr, "user %s not found! (terminating)\n", DEF_MAIL_USER); 1.26 - exit(1); 1.27 - } 1.28 - if ((group = getgrnam(DEF_MAIL_GROUP))) 1.29 - conf.mail_gid = group->gr_gid; 1.30 - else { 1.31 - fprintf(stderr, "group %s not found! (terminating)\n", DEF_MAIL_GROUP); 1.32 - exit(1); 1.33 - } 1.34 + conf.mail_uid = passwd->pw_uid; 1.35 + conf.mail_gid = group->gr_gid; 1.36 } 1.37 1.38 static gchar *true_strings[] = { 1.39 @@ -64,96 +62,83 @@ 1.40 gchar **str; 1.41 1.42 DEBUG(9) fprintf(stderr, "parse_boolean: %s\n", rval); 1.43 - 1.44 - str = true_strings; 1.45 - while (*str) { 1.46 - if (strncasecmp(*str, rval, strlen(*str)) == 0) 1.47 + for (str = true_strings; *str; str++) { 1.48 + if (strncasecmp(*str, rval, strlen(*str))==0) { 1.49 return TRUE; 1.50 - str++; 1.51 + } 1.52 } 1.53 - 1.54 - str = false_strings; 1.55 - while (*str) { 1.56 - if (strncasecmp(*str, rval, strlen(*str)) == 0) 1.57 + for (str = false_strings; *str; str++) { 1.58 + if (strncasecmp(*str, rval, strlen(*str))==0) { 1.59 return FALSE; 1.60 - str++; 1.61 + } 1.62 } 1.63 - 1.64 fprintf(stderr, "cannot parse value '%s'\n", rval); 1.65 exit(1); 1.66 } 1.67 1.68 -/* make a list from each line in a file */ 1.69 +/* 1.70 +** make a list from the lines of a file 1.71 +*/ 1.72 static GList* 1.73 -parse_list_file(gchar *fname) 1.74 +parse_list_file(const gchar *fname) 1.75 { 1.76 GList *list = NULL; 1.77 FILE *fptr; 1.78 + gchar buf[256]; 1.79 1.80 - if ((fptr = fopen(fname, "rt")) == NULL) { 1.81 - logwrite(LOG_ALERT, "could not open %s for reading: %s\n", fname, strerror(errno)); 1.82 + if (!(fptr = fopen(fname, "rt"))) { 1.83 + logwrite(LOG_ALERT, "could not open %s for reading: %s\n", 1.84 + fname, strerror(errno)); 1.85 exit(1); 1.86 } 1.87 - 1.88 - gchar buf[256]; 1.89 - 1.90 - while (!feof(fptr)) { 1.91 - fgets(buf, 255, fptr); 1.92 - if (buf[0] && (buf[0] != '#') && (buf[0] != '\n')) { 1.93 - g_strchomp(buf); 1.94 - DEBUG(9) fprintf(stderr,"parse_list_file: item = %s\n", buf); 1.95 - list = g_list_append(list, g_strdup(buf)); 1.96 + while (!fgets(buf, sizeof buf, fptr)) { 1.97 + g_strstrip(buf); 1.98 + if (!*buf || *buf == '#') { 1.99 + continue; 1.100 } 1.101 + DEBUG(9) fprintf(stderr, "parse_list_file: item = %s\n", buf); 1.102 + list = g_list_append(list, g_strdup(buf)); 1.103 } 1.104 fclose(fptr); 1.105 1.106 return list; 1.107 } 1.108 1.109 -/* given a semicolon separated string, this function makes a GList out of it. */ 1.110 -GList* 1.111 +/* 1.112 +** given a semicolon separated string, this function makes a GList out of it. 1.113 +*/ 1.114 +static GList* 1.115 parse_list(gchar *line, gboolean read_file) 1.116 { 1.117 GList *list = NULL; 1.118 - gchar buf[256]; 1.119 - gchar *p, *q; 1.120 + gchar *tok; 1.121 1.122 - DEBUG(9) fprintf(stderr, "parsing list %s, file?:%d\n", line, read_file); 1.123 - 1.124 - p = line; 1.125 - while (*p != '\0') { 1.126 - q = buf; 1.127 - 1.128 - while (*p && (*p != ';') && (q < buf + 255)) 1.129 - *(q++) = *(p++); 1.130 - *q = '\0'; 1.131 - 1.132 - if ((buf[0] == '/') && (read_file)) 1.133 + DEBUG(9) fprintf(stderr, "parsing list %s, file?:%d\n", 1.134 + line, read_file); 1.135 + for (tok = strtok(strdup(line), ";"); tok; tok = strtok(NULL, ";")) { 1.136 + DEBUG(9) fprintf(stderr, "item = %s\n", tok); 1.137 + if (read_file && *tok == '/') { 1.138 /* item is a filename, include its contents */ 1.139 - list = g_list_concat(list, parse_list_file(buf)); 1.140 - else 1.141 + list = g_list_concat(list, parse_list_file(tok)); 1.142 + } else { 1.143 /* just a normal item */ 1.144 - list = g_list_append(list, g_strdup(buf)); 1.145 - 1.146 - DEBUG(9) fprintf(stderr, "item = %s\n", buf); 1.147 - 1.148 - if (*p) 1.149 - p++; 1.150 + list = g_list_append(list, g_strdup(tok)); 1.151 + } 1.152 } 1.153 return list; 1.154 } 1.155 1.156 /* 1.157 ** Split the addrs at '@' into local_part and domain. Without an '@' 1.158 -** everything is local_part. Create address structs, which are put into a 1.159 -** list and returned. This funktion is used for lists of addrs containing 1.160 -** globbing chars (* and ?). We don't need valid RFC821 addresses here, 1.161 -** just patterns to match against. 1.162 +** everything is local_part. Create and return a list of address structs. 1.163 +** This funktion is used for lists of addrs containing globbing chars 1.164 +** (* and ?). We don't need valid RFC821 addresses here, just patterns 1.165 +** to match against. 1.166 */ 1.167 static GList* 1.168 -parse_address_glob_list(gchar *line, gboolean read_file) 1.169 +parse_address_glob_list(gchar *line) 1.170 { 1.171 - GList *plain_list = parse_list(line, read_file); 1.172 + GList *plain_list = parse_list(line, TRUE); 1.173 GList *node; 1.174 GList *list = NULL; 1.175 1.176 @@ -181,7 +166,8 @@ 1.177 addr->domain = "*"; 1.178 } 1.179 list = g_list_append(list, addr); 1.180 - DEBUG(6) debugf("parse_address_glob_list: read pattern `%s' `%s'\n", 1.181 + DEBUG(6) debugf("parse_address_glob_list: " 1.182 + "read pattern `%s' `%s'\n", 1.183 addr->local_part, addr->domain); 1.184 g_free(item); 1.185 } 1.186 @@ -195,20 +181,20 @@ 1.187 GList *list; 1.188 GList *list_node; 1.189 GList *res_list = NULL; 1.190 + gchar *item; 1.191 1.192 - list = parse_list(line, FALSE); 1.193 + list = parse_list(line, TRUE); 1.194 if (!list) { 1.195 return NULL; 1.196 } 1.197 - 1.198 foreach(list, list_node) { 1.199 - gchar *item = (gchar *) (list_node->data); 1.200 - if (strcmp(item, "byname") == 0) { 1.201 + item = (gchar *) list_node->data; 1.202 + if (strcmp(item, "byname")==0) { 1.203 res_list = g_list_append(res_list, resolve_byname); 1.204 #ifdef ENABLE_RESOLVER 1.205 - } else if (strcmp(item, "dns_a") == 0) { 1.206 + } else if (strcmp(item, "dns_a")==0) { 1.207 res_list = g_list_append(res_list, resolve_dns_a); 1.208 - } else if (strcmp(item, "dns_mx") == 0) { 1.209 + } else if (strcmp(item, "dns_mx")==0) { 1.210 res_list = g_list_append(res_list, resolve_dns_mx); 1.211 #endif 1.212 } else { 1.213 @@ -224,28 +210,17 @@ 1.214 static interface* 1.215 parse_interface(gchar *line, gint def_port) 1.216 { 1.217 - gchar buf[256]; 1.218 - gchar *p, *q; 1.219 - interface *iface; 1.220 + gchar *cp; 1.221 + interface *iface = g_malloc(sizeof(interface)); 1.222 1.223 DEBUG(9) fprintf(stderr, "parse_interface: %s\n", line); 1.224 - 1.225 - p = line; 1.226 - q = buf; 1.227 - while ((*p != '\0') && (*p != ':') && (q < buf + 255)) 1.228 - *(q++) = *(p++); 1.229 - *q = '\0'; 1.230 - 1.231 - iface = g_malloc(sizeof(interface)); 1.232 - iface->address = g_strdup(buf); 1.233 - 1.234 - if (*p) { 1.235 - p++; 1.236 - iface->port = atoi(p); 1.237 - } else 1.238 - iface->port = def_port; 1.239 - DEBUG(9) fprintf(stderr,"rval=%s, address:port=%s:%i\n",line, iface->address, iface->port); 1.240 - 1.241 + if ((cp = strchr(line, ':'))) { 1.242 + *cp = '\0'; 1.243 + } 1.244 + iface->address = g_strdup(line); 1.245 + iface->port = (cp) ? atoi(++cp) : def_port; 1.246 + DEBUG(9) fprintf(stderr,"found: address:port=%s:%u\n", 1.247 + iface->address, iface->port); 1.248 return iface; 1.249 } 1.250 1.251 @@ -253,30 +228,48 @@ 1.252 eat_comments(FILE *in) 1.253 { 1.254 gint c; 1.255 + int incomment = 0; 1.256 1.257 - for (c = fgetc(in); (c == '#' || isspace(c)) && c != EOF; 1.258 - c = fgetc(in)) { 1.259 - if (c == '#') { 1.260 - gint c; 1.261 - for (c = fgetc(in); (c != '\n') && (c != EOF); c = fgetc(in)); 1.262 + while ((c = fgetc(in)) != EOF) { 1.263 + if (incomment) { 1.264 + /* eat until end of line */ 1.265 + if (c == '\n') { 1.266 + incomment = 0; 1.267 + continue; 1.268 + } else { 1.269 + continue; 1.270 + } 1.271 + } else { 1.272 + /* eat whitespace and watch for comments */ 1.273 + if (isspace(c)) { 1.274 + continue; 1.275 + } else if (c == '#') { 1.276 + incomment = 1; 1.277 + continue; 1.278 + } else { 1.279 + /* found something (that's not our business) */ 1.280 + ungetc(c, in); 1.281 + return TRUE; 1.282 + } 1.283 } 1.284 } 1.285 - if (c == EOF) 1.286 - return FALSE; 1.287 - ungetc(c, in); 1.288 - return TRUE; 1.289 + return FALSE; 1.290 } 1.291 1.292 -/* after parsing, eat trailing character until LF */ 1.293 +/* 1.294 +** after parsing, eat trailing characters until and including the Newline 1.295 +*/ 1.296 static gboolean 1.297 eat_line_trailing(FILE *in) 1.298 { 1.299 gint c; 1.300 1.301 - for (c = fgetc(in); c != EOF && c != '\n'; c = fgetc(in)); 1.302 - if (c == EOF) 1.303 - return FALSE; 1.304 - return TRUE; 1.305 + while ((c = fgetc(in)) != EOF) { 1.306 + if (c == '\n') { 1.307 + return TRUE; 1.308 + } 1.309 + } 1.310 + return FALSE; 1.311 } 1.312 1.313 static gboolean 1.314 @@ -284,13 +277,13 @@ 1.315 { 1.316 gint c; 1.317 1.318 - for (c = fgetc(in); c != EOF && isspace(c); c = fgetc(in)) { 1.319 - /* empty */ 1.320 + while ((c = fgetc(in)) != EOF) { 1.321 + if (!isspace(c)) { 1.322 + ungetc(c, in); 1.323 + return TRUE; 1.324 + } 1.325 } 1.326 - if (c == EOF) 1.327 - return FALSE; 1.328 - ungetc(c, in); 1.329 - return TRUE; 1.330 + return FALSE; 1.331 } 1.332 1.333 static gboolean 1.334 @@ -300,34 +293,31 @@ 1.335 gchar *ptr = buf; 1.336 1.337 DEBUG(9) fprintf(stderr, "read_lval()\n"); 1.338 - 1.339 - if (!eat_spaces(in)) 1.340 + if (!eat_spaces(in)) { 1.341 return FALSE; 1.342 + } 1.343 1.344 c = fgetc(in); 1.345 DEBUG(9) fprintf(stderr, "read_lval() 2\n"); 1.346 - while ((isalnum(c) || c == '_' || c == '-' || c == '.') 1.347 - && (ptr < buf + size - 1) 1.348 - && (c != EOF)) { 1.349 - *ptr = c; 1.350 - ptr++; 1.351 - c = fgetc(in); 1.352 + while (1) { 1.353 + if ((c = fgetc(in)) == EOF) { 1.354 + fprintf(stderr, "unexpected EOF after %s\n", buf); 1.355 + return FALSE; 1.356 + } 1.357 + if (ptr >= buf+size-1) { 1.358 + fprintf(stderr, "lval too long\n"); 1.359 + break; 1.360 + } 1.361 + if (!isalnum(c) && c != '_' && c != '-' && c != '.') { 1.362 + break; 1.363 + } 1.364 + *ptr++ = c; 1.365 } 1.366 *ptr = '\0'; 1.367 ungetc(c, in); 1.368 - 1.369 - if (c == EOF) { 1.370 - fprintf(stderr, "unexpected EOF after %s\n", buf); 1.371 - return FALSE; 1.372 - } else if (ptr >= buf + size - 1) { 1.373 - fprintf(stderr, "lval too long\n"); 1.374 - } 1.375 - 1.376 eat_spaces(in); 1.377 - 1.378 DEBUG(9) fprintf(stderr, "lval = %s\n", buf); 1.379 - 1.380 - return buf[0] != '\0'; 1.381 + return *buf != '\0'; 1.382 } 1.383 1.384 static gboolean 1.385 @@ -337,9 +327,9 @@ 1.386 gchar *ptr = buf; 1.387 1.388 DEBUG(9) fprintf(stderr, "read_rval()\n"); 1.389 - 1.390 - if (!eat_spaces(in)) 1.391 + if (!eat_spaces(in)) { 1.392 return FALSE; 1.393 + } 1.394 1.395 c = fgetc(in); 1.396 if (c != '\"') { 1.397 @@ -426,7 +416,7 @@ 1.398 } 1.399 1.400 gchar lval[256], rval[2048]; 1.401 - while (read_statement(in, lval, 256, rval, 2048)) { 1.402 + while (read_statement(in, lval, sizeof lval, rval, sizeof rval)) { 1.403 DEBUG(9) fprintf(stderr,"read_conf(): lval=%s\n", lval); 1.404 if (strcmp(lval, "debug_level") == 0) 1.405 conf.debug_level = atoi(rval); 1.406 @@ -459,7 +449,7 @@ 1.407 fclose(fptr); 1.408 } 1.409 } else if (strcmp(lval, "local_hosts") == 0) 1.410 - conf.local_hosts = parse_list(rval, FALSE); 1.411 + conf.local_hosts = parse_list(rval, TRUE); 1.412 else if (strcmp(lval, "local_addresses") == 0) 1.413 conf.local_addresses = parse_list(rval, TRUE); 1.414 else if (strcmp(lval, "not_local_addresses") == 0) 1.415 @@ -494,7 +484,7 @@ 1.416 conf.pipe_fromhack = parse_boolean(rval); 1.417 } else if (strcmp(lval, "listen_addresses") == 0) { 1.418 GList *node; 1.419 - GList *tmp_list = parse_list(rval, FALSE); 1.420 + GList *tmp_list = parse_list(rval, TRUE); 1.421 1.422 conf.listen_addresses = NULL; 1.423 foreach(tmp_list, node) { 1.424 @@ -517,7 +507,7 @@ 1.425 else if (strcmp(lval, "warnmsg_file") == 0) 1.426 conf.warnmsg_file = g_strdup(rval); 1.427 else if (strcmp(lval, "warn_intervals") == 0) 1.428 - conf.warn_intervals = parse_list(rval, FALSE); 1.429 + conf.warn_intervals = parse_list(rval, TRUE); 1.430 else if (strcmp(lval, "max_defer_time") == 0) { 1.431 gint ival = time_interval(rval); 1.432 if (ival < 0) 1.433 @@ -553,7 +543,7 @@ 1.434 conf.mbox_default = g_strdup("mbox"); 1.435 1.436 if (conf.warn_intervals == NULL) 1.437 - conf.warn_intervals = parse_list("1h;4h;8h;1d;2d;3d", FALSE); 1.438 + conf.warn_intervals = parse_list("1h;4h;8h;1d;2d;3d", TRUE); 1.439 1.440 if (!conf.local_hosts) { 1.441 char *shortname = strdup(conf.host_name); 1.442 @@ -561,9 +551,10 @@ 1.443 if (p) { 1.444 *p = '\0'; 1.445 } 1.446 - /* we don't care if shortname and conf.host_name are the same */ 1.447 - char *local_hosts_str = g_strdup_printf("localhost;%s;%s", shortname, conf.host_name); 1.448 - conf.local_hosts = parse_list(local_hosts_str, FALSE); 1.449 + /* don't care if shortname and conf.host_name are the same */ 1.450 + char *local_hosts_str = g_strdup_printf("localhost;%s;%s", 1.451 + shortname, conf.host_name); 1.452 + conf.local_hosts = parse_list(local_hosts_str, TRUE); 1.453 free(shortname); 1.454 free(local_hosts_str); 1.455 } 1.456 @@ -599,7 +590,7 @@ 1.457 } 1.458 1.459 gchar lval[256], rval[2048]; 1.460 - while (read_statement(in, lval, 256, rval, 2048)) { 1.461 + while (read_statement(in, lval, sizeof lval, rval, sizeof rval)) { 1.462 if (strcmp(lval, "mail_host") == 0) 1.463 route->mail_host = parse_interface(rval, 25); 1.464 else if (strcmp(lval, "helo_name") == 0) 1.465 @@ -616,13 +607,13 @@ 1.466 route->do_pipelining = parse_boolean(rval); 1.467 1.468 else if (strcmp(lval, "allowed_senders") == 0) 1.469 - route->allowed_senders = parse_address_glob_list(rval, TRUE); 1.470 + route->allowed_senders = parse_address_glob_list(rval); 1.471 else if (strcmp(lval, "denied_senders") == 0) 1.472 - route->denied_senders = parse_address_glob_list(rval, TRUE); 1.473 + route->denied_senders = parse_address_glob_list(rval); 1.474 else if (strcmp(lval, "allowed_recipients") == 0) 1.475 - route->allowed_recipients = parse_address_glob_list(rval, TRUE); 1.476 + route->allowed_recipients = parse_address_glob_list(rval); 1.477 else if (strcmp(lval, "denied_recipients") == 0) 1.478 - route->denied_recipients = parse_address_glob_list(rval, TRUE); 1.479 + route->denied_recipients = parse_address_glob_list(rval); 1.480 1.481 else if (strcmp(lval, "set_h_from_domain") == 0) 1.482 route->set_h_from_domain = g_strdup(rval);