X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/cd8cb71deb2d653228cc037cf91ecab980acdcd0..HEAD:/src/src/readconf.c diff --git a/src/src/readconf.c b/src/src/readconf.c index 8ee6e9fe0..940c5d4d3 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) The Exim Maintainers 2020 - 2023 */ +/* Copyright (c) The Exim Maintainers 2020 - 2024 */ /* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* SPDX-License-Identifier: GPL-2.0-or-later */ @@ -66,6 +66,9 @@ static optionlist optionlist_config[] = { { "acl_smtp_starttls", opt_stringptr, {&acl_smtp_starttls} }, #endif { "acl_smtp_vrfy", opt_stringptr, {&acl_smtp_vrfy} }, +#ifndef DISABLE_WELLKNOWN + { "acl_smtp_wellknown", opt_stringptr, {&acl_smtp_wellknown} }, +#endif { "add_environment", opt_stringptr, {&add_environment} }, { "admin_groups", opt_gidlist, {&admin_groups} }, { "allow_domain_literals", opt_bool, {&allow_domain_literals} }, @@ -293,7 +296,7 @@ static optionlist optionlist_config[] = { { "received_header_text", opt_stringptr, {&received_header_text} }, { "received_headers_max", opt_int, {&received_headers_max} }, { "recipient_unqualified_hosts", opt_stringptr, {&recipient_unqualified_hosts} }, - { "recipients_max", opt_int, {&recipients_max} }, + { "recipients_max", opt_stringptr, {&recipients_max} }, { "recipients_max_reject", opt_bool, {&recipients_max_reject} }, #ifdef LOOKUP_REDIS { "redis_servers", opt_stringptr, {&redis_servers} }, @@ -402,6 +405,9 @@ static optionlist optionlist_config[] = { { "uucp_from_pattern", opt_stringptr, {&uucp_from_pattern} }, { "uucp_from_sender", opt_stringptr, {&uucp_from_sender} }, { "warn_message_file", opt_stringptr, {&warn_message_file} }, +#ifndef DISABLE_WELLKNOWN + { "wellknown_advertise_hosts",opt_stringptr, {&wellknown_advertise_hosts} }, +#endif { "write_rejectlog", opt_bool, {&write_rejectlog} }, }; @@ -592,46 +598,104 @@ static int syslog_list_size = sizeof(syslog_list)/sizeof(syslog_fac_item); pointer variables in the options table or in option tables for various drivers. For debugging output, it is useful to be able to find the name of the option which is currently being processed. This function finds it, if it exists, by -searching the table(s). +searching the table(s) for a value with the given content. Arguments: a value that is presumed to be in the table above Returns: the option name, or an empty string */ -uschar * -readconf_find_option(void *p) +const uschar * +readconf_find_option(void * listptr) { -for (int i = 0; i < nelem(optionlist_config); i++) - if (p == optionlist_config[i].v.value) return US optionlist_config[i].name; +uschar * list = * USS listptr; +const uschar * name = NULL, * drname = NULL; + +for (optionlist * o = optionlist_config; /* main-config options */ + o < optionlist_config + optionlist_config_size; o++) + if (listptr == o->v.value) + return US o->name; for (router_instance * r = routers; r; r = r->next) + if (router_name && Ustrcmp(r->name, router_name) == 0) { - router_info *ri = r->info; - for (int i = 0; i < *ri->options_count; i++) - { - if ((ri->options[i].type & opt_mask) != opt_stringptr) continue; - if (p == CS (r->options_block) + ri->options[i].v.offset) - return US ri->options[i].name; - } + const router_info * ri = r->info; + + /* Check for a listptr match first */ + + for (optionlist * o = optionlist_routers; /* generic options */ + o < optionlist_routers + optionlist_routers_size; o++) + if ( (o->type & opt_mask) == opt_stringptr + && listptr == CS r + o->v.offset) + return US o->name; + + for (optionlist * o = ri->options; /* private options */ + o < ri->options + *ri->options_count; o++) + if ( (o->type & opt_mask) == opt_stringptr + && listptr == CS (r->options_block) + o->v.offset) + return US o->name; + + /* Check for a list addr match, unless null */ + + if (!list) continue; + + for (optionlist * o = optionlist_routers; /* generic options */ + o < optionlist_routers + optionlist_routers_size; o++) + if ( (o->type & opt_mask) == opt_stringptr + && list == * USS(CS r + o->v.offset)) + if (name) return string_sprintf("DUP: %s %s vs. %s %s", + drname, name, r->name, o->name); + else { name = US o->name; drname = r->name; } + + for (optionlist * o = ri->options; /* private options */ + o < ri->options + *ri->options_count; o++) + if ( (o->type & opt_mask) == opt_stringptr + && list == * USS(CS (r->options_block) + o->v.offset)) + if (name) return string_sprintf("DUP: %s %s vs. %s %s", + drname, name, r->name, o->name); + else { name = US o->name; drname = r->name; } } for (transport_instance * t = transports; t; t = t->next) + if (transport_name && Ustrcmp(t->name, transport_name) == 0) { - transport_info *ti = t->info; - for (int i = 0; i < *ti->options_count; i++) - { - optionlist * op = &ti->options[i]; - if ((op->type & opt_mask) != opt_stringptr) continue; - if (p == ( op->type & opt_public - ? CS t - : CS t->options_block - ) - + op->v.offset) - return US op->name; - } + const transport_info * ti = t->info; + + /* Check for a listptr match first */ + + for (optionlist * o = optionlist_transports; /* generic options */ + o < optionlist_transports + optionlist_transports_size; o++) + if ( (o->type & opt_mask) == opt_stringptr + && listptr == CS t + o->v.offset) + return US o->name; + + for (optionlist * o = ti->options; /* private options */ + o < ti->options + *ti->options_count; o++) + if ( (o->type & opt_mask) == opt_stringptr + && listptr == CS t->options_block + o->v.offset) + return US o->name; + + /* Check for a list addr match, unless null */ + + if (!list) continue; + + for (optionlist * o = optionlist_transports; /* generic options */ + o < optionlist_transports + optionlist_transports_size; o++) + if ( (o->type & opt_mask) == opt_stringptr + && list == * USS(CS t + o->v.offset)) + if (name) return string_sprintf("DUP: %s %s vs. %s %s", + drname, name, t->name, o->name); + else { name = US o->name; drname = t->name; } + + for (optionlist * o = ti->options; /* private options */ + o < ti->options + *ti->options_count; o++) + if ( (o->type & opt_mask) == opt_stringptr + && list == * USS(CS t->options_block + o->v.offset)) + if (name) return string_sprintf("DUP: %s %s vs. %s %s", + drname, name, t->name, o->name); + else { name = US o->name; drname = t->name; } } -return US""; +return name ? name : US""; } @@ -1050,7 +1114,7 @@ for (;;) (Ustrncmp(ss+8, "_if_exists", 10) == 0 && isspace(ss[18])))) { uschar *t; - int include_if_exists = isspace(ss[8])? 0 : 10; + int include_if_exists = isspace(ss[8]) ? 0 : 10; config_file_item *save; struct stat statbuf; @@ -1644,8 +1708,7 @@ uschar name2[EXIM_DRIVERNAME_MAX]; /* There may be leading spaces; thereafter, we expect an option name starting with a letter. */ -while (isspace(*s)) s++; -if (!isalpha(*s)) +if (!isalpha( Uskip_whitespace(&s) )) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "option setting expected: %s", s); /* Read the name of the option, and skip any subsequent white space. If @@ -1660,7 +1723,7 @@ for (int n = 0; n < 2; n++) s++; } name[ptr] = 0; - while (isspace(*s)) s++; + Uskip_whitespace(&s); if (Ustrcmp(name, "hide") != 0) break; issecure = opt_secure; ptr = 0; @@ -1720,7 +1783,7 @@ else if (*s && (offset != 0 || *s != '=')) /* Skip white space after = */ -if (*s == '=') while (isspace((*(++s)))); +if (*s == '=') while (isspace(*++s)); /* If there is a data block and the opt_public flag is not set, change the data block pointer to the private options block. */ @@ -2202,8 +2265,7 @@ switch (type) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "absolute value of integer \"%s\" is too large (overflow)", s); - while (isspace(*endptr)) endptr++; - if (*endptr) + if (Uskip_whitespace(&endptr)) extra_chars_error(endptr, inttype, US"integer value for ", name); value = (int)lvalue; @@ -2251,8 +2313,7 @@ switch (type) if (errno == ERANGE) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "absolute value of integer \"%s\" is too large (overflow)", s); - while (isspace(*endptr)) endptr++; - if (*endptr != 0) + if (Uskip_whitespace(&endptr)) extra_chars_error(endptr, inttype, US"integer value for ", name); if (data_block) @@ -2347,7 +2408,7 @@ switch (type) list[count+1] = value; if (snext == NULL) break; s = snext + 1; - while (isspace(*s)) s++; + Uskip_whitespace(&s); } if (count > list[0] - 2) @@ -3210,7 +3271,7 @@ if (config_file) if (os_getcwd(buf, PATH_MAX) == NULL) { perror("exim: getcwd"); - exit(EXIT_FAILURE); + exim_exit(EXIT_FAILURE); } g = string_cat(NULL, buf); @@ -3240,7 +3301,7 @@ to a safe place. Later we change to $spool_directory. */ if (Uchdir("/") < 0) { perror("exim: chdir `/': "); - exit(EXIT_FAILURE); + exim_exit(EXIT_FAILURE); } /* Check the status of the file we have opened, if we have retained root @@ -3570,8 +3631,7 @@ if (host_number_string) "failed to expand localhost_number \"%s\": %s", host_number_string, expand_string_message); n = Ustrtol(s, &end, 0); - while (isspace(*end)) end++; - if (*end) + if (Uskip_whitespace(&end)) log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "localhost_number value is not a number: %s", s); if (n > LOCALHOST_MAX) @@ -4019,10 +4079,9 @@ Returns: time in seconds or fixed point number * 1000 */ static int -retry_arg(const uschar **paddr, int type) +retry_arg(const uschar ** paddr, int type) { -const uschar *p = *paddr; -const uschar *pp; +const uschar * p = *paddr, * pp; if (*p++ != ',') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "comma expected"); @@ -4030,7 +4089,7 @@ Uskip_whitespace(&p); pp = p; while (isalnum(*p) || (type == 1 && *p == '.')) p++; -if (*p != 0 && !isspace(*p) && *p != ',' && *p != ';') +if (*p && !isspace(*p) && *p != ',' && *p != ';') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "comma or semicolon expected"); *paddr = p; @@ -4433,10 +4492,8 @@ for (const config_line_item * i = config_lines; i; i = i->next) r = store_mark(); /* skip over to the first non-space */ - for (current = string_copy(i->line); *current && isspace(*current); ++current) - ; - - if (!*current) + current = string_copy(i->line); + if (!Uskip_whitespace(¤t)) continue; /* Collapse runs of spaces. We stop this if we encounter one of the @@ -4444,11 +4501,10 @@ for (const config_line_item * i = config_lines; i; i = i->next) for (p = current; *p; p++) if (isspace(*p)) { - uschar *next; + uschar * next = p; if (*p != ' ') *p = ' '; - for (next = p; isspace(*next); ++next) - ; + Uskip_whitespace(&p); if (next - p > 1) memmove(p+1, next, Ustrlen(next)+1);