X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Freadconf.c;h=220438ada3504d94d514f6b3921cc2280e3906c9;hb=7546de58d97a3a4d36dc27ab4e8764f77dc4f887;hp=95470763db7dd3081438ee281a877c6200c12d5f;hpb=059ec3d9952740285fb1ebf47961b8aca2eb1b4a;p=exim.git diff --git a/src/src/readconf.c b/src/src/readconf.c index 95470763d..220438ada 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/readconf.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */ +/* $Cambridge: exim/src/src/readconf.c,v 1.12 2005/08/08 10:48:27 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* Copyright (c) University of Cambridge 1995 - 2005 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for reading the configuration file, and for displaying @@ -135,6 +135,9 @@ static optionlist optionlist_config[] = { { "*set_system_filter_user", opt_bool|opt_hidden, &system_filter_uid_set }, { "accept_8bitmime", opt_bool, &accept_8bitmime }, { "acl_not_smtp", opt_stringptr, &acl_not_smtp }, +#ifdef WITH_CONTENT_SCAN + { "acl_not_smtp_mime", opt_stringptr, &acl_not_smtp_mime }, +#endif { "acl_smtp_auth", opt_stringptr, &acl_smtp_auth }, { "acl_smtp_connect", opt_stringptr, &acl_smtp_connect }, { "acl_smtp_data", opt_stringptr, &acl_smtp_data }, @@ -143,6 +146,9 @@ static optionlist optionlist_config[] = { { "acl_smtp_helo", opt_stringptr, &acl_smtp_helo }, { "acl_smtp_mail", opt_stringptr, &acl_smtp_mail }, { "acl_smtp_mailauth", opt_stringptr, &acl_smtp_mailauth }, +#ifdef WITH_CONTENT_SCAN + { "acl_smtp_mime", opt_stringptr, &acl_smtp_mime }, +#endif { "acl_smtp_predata", opt_stringptr, &acl_smtp_predata }, { "acl_smtp_quit", opt_stringptr, &acl_smtp_quit }, { "acl_smtp_rcpt", opt_stringptr, &acl_smtp_rcpt }, @@ -156,7 +162,13 @@ static optionlist optionlist_config[] = { { "allow_utf8_domains", opt_bool, &allow_utf8_domains }, { "auth_advertise_hosts", opt_stringptr, &auth_advertise_hosts }, { "auto_thaw", opt_time, &auto_thaw }, +#ifdef WITH_CONTENT_SCAN + { "av_scanner", opt_stringptr, &av_scanner }, +#endif { "bi_command", opt_stringptr, &bi_command }, +#ifdef EXPERIMENTAL_BRIGHTMAIL + { "bmi_config_file", opt_stringptr, &bmi_config_file }, +#endif { "bounce_message_file", opt_stringptr, &bounce_message_file }, { "bounce_message_text", opt_stringptr, &bounce_message_text }, { "bounce_return_body", opt_bool, &bounce_return_body }, @@ -174,6 +186,8 @@ static optionlist optionlist_config[] = { { "check_spool_space", opt_Kint, &check_spool_space }, { "daemon_smtp_port", opt_stringptr|opt_hidden, &daemon_smtp_port }, { "daemon_smtp_ports", opt_stringptr, &daemon_smtp_port }, + { "daemon_startup_retries", opt_int, &daemon_startup_retries }, + { "daemon_startup_sleep", opt_time, &daemon_startup_sleep }, { "delay_warning", opt_timelist, &delay_warning }, { "delay_warning_condition", opt_stringptr, &delay_warning_condition }, { "deliver_drop_privilege", opt_bool, &deliver_drop_privilege }, @@ -181,6 +195,8 @@ static optionlist optionlist_config[] = { { "delivery_date_remove", opt_bool, &delivery_date_remove }, { "dns_again_means_nonexist", opt_stringptr, &dns_again_means_nonexist }, { "dns_check_names_pattern", opt_stringptr, &check_dns_names_pattern }, + { "dns_csa_search_limit", opt_int, &dns_csa_search_limit }, + { "dns_csa_use_reverse", opt_bool, &dns_csa_use_reverse }, { "dns_ipv4_lookup", opt_stringptr, &dns_ipv4_lookup }, { "dns_retrans", opt_time, &dns_retrans }, { "dns_retry", opt_int, &dns_retry }, @@ -318,8 +334,23 @@ static optionlist optionlist_config[] = { { "smtp_receive_timeout", opt_time, &smtp_receive_timeout }, { "smtp_reserve_hosts", opt_stringptr, &smtp_reserve_hosts }, { "smtp_return_error_details",opt_bool, &smtp_return_error_details }, +#ifdef WITH_CONTENT_SCAN + { "spamd_address", opt_stringptr, &spamd_address }, +#endif { "split_spool_directory", opt_bool, &split_spool_directory }, { "spool_directory", opt_stringptr, &spool_directory }, +#ifdef LOOKUP_SQLITE + { "sqlite_lock_timeout", opt_int, &sqlite_lock_timeout }, +#endif +#ifdef EXPERIMENTAL_SRS + { "srs_config", opt_stringptr, &srs_config }, + { "srs_hashlength", opt_int, &srs_hashlength }, + { "srs_hashmin", opt_int, &srs_hashmin }, + { "srs_maxage", opt_int, &srs_maxage }, + { "srs_secrets", opt_stringptr, &srs_secrets }, + { "srs_usehash", opt_bool, &srs_usehash }, + { "srs_usetimestamp", opt_bool, &srs_usetimestamp }, +#endif { "strip_excess_angle_brackets", opt_bool, &strip_excess_angle_brackets }, { "strip_trailing_dot", opt_bool, &strip_trailing_dot }, { "syslog_duplication", opt_bool, &syslog_duplication }, @@ -417,6 +448,122 @@ return US""; +/************************************************* +* Deal with an assignment to a macro * +*************************************************/ + +/* This function is called when a line that starts with an upper case letter is +encountered. The argument "line" should contain a complete logical line, and +start with the first letter of the macro name. The macro name and the +replacement text are extracted and stored. Redefinition of existing, +non-command line, macros is permitted using '==' instead of '='. + +Arguments: + s points to the start of the logical line + +Returns: nothing +*/ + +static void +read_macro_assignment(uschar *s) +{ +uschar name[64]; +int namelen = 0; +BOOL redef = FALSE; +macro_item *m; +macro_item *mlast = NULL; + +while (isalnum(*s) || *s == '_') + { + if (namelen >= sizeof(name) - 1) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, + "macro name too long (maximum is %d characters)", sizeof(name) - 1); + name[namelen++] = *s++; + } +name[namelen] = 0; + +while (isspace(*s)) s++; +if (*s++ != '=') + log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "malformed macro definition"); + +if (*s == '=') + { + redef = TRUE; + s++; + } +while (isspace(*s)) s++; + +/* If an existing macro of the same name was defined on the command line, we +just skip this definition. It's an error to attempt to redefine a macro without +redef set to TRUE, or to redefine a macro when it hasn't been defined earlier. +It is also an error to define a macro whose name begins with the name of a +previously defined macro. Note: it is documented that the other way round +works. */ + +for (m = macros; m != NULL; m = m->next) + { + int len = Ustrlen(m->name); + + if (Ustrcmp(m->name, name) == 0) + { + if (!m->command_line && !redef) + log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "macro \"%s\" is already " + "defined (use \"==\" if you want to redefine it", name); + break; + } + + if (len < namelen && Ustrstr(name, m->name) != NULL) + log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "\"%s\" cannot be defined as " + "a macro because previously defined macro \"%s\" is a substring", + name, m->name); + + /* We cannot have this test, because it is documented that a substring + macro is permitted (there is even an example). + * + * if (len > namelen && Ustrstr(m->name, name) != NULL) + * log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "\"%s\" cannot be defined as " + * "a macro because it is a substring of previously defined macro \"%s\"", + * name, m->name); + */ + + mlast = m; + } + +/* Check for an overriding command-line definition. */ + +if (m != NULL && m->command_line) return; + +/* Redefinition must refer to an existing macro. */ + +if (redef) + { + if (m == NULL) + log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "can't redefine an undefined macro " + "\"%s\"", name); + } + +/* We have a new definition. The macro_item structure includes a final vector +called "name" which is one byte long. Thus, adding "namelen" gives us enough +room to store the "name" string. */ + +else + { + m = store_get(sizeof(macro_item) + namelen); + if (macros == NULL) macros = m; else mlast->next = m; + Ustrncpy(m->name, name, namelen); + m->name[namelen] = 0; + m->next = NULL; + m->command_line = FALSE; + } + +/* Set the value of the new or redefined macro */ + +m->replacement = string_copy(s); +} + + + + /************************************************* * Read configuration line * @@ -459,7 +606,7 @@ for (;;) { if (config_file_stack != NULL) /* EOF inside .include */ { - fclose(config_file); + (void)fclose(config_file); config_file = config_file_stack->file; config_filename = config_file_stack->filename; config_lineno = config_file_stack->lineno; @@ -2595,8 +2742,11 @@ if (!config_changed) && statbuf.st_uid != config_uid /* owner not the special one */ #endif ) || /* or */ - (statbuf.st_gid != exim_gid && /* group not exim & */ - (statbuf.st_mode & 020) != 0) || /* group writeable */ + (statbuf.st_gid != exim_gid /* group not exim & */ + #ifdef CONFIGURE_GROUP + && statbuf.st_gid != config_gid /* group not the special one */ + #endif + && (statbuf.st_mode & 020) != 0) || /* group writeable */ /* or */ ((statbuf.st_mode & 2) != 0)) /* world writeable */ @@ -2610,65 +2760,7 @@ a macro definition. */ while ((s = get_config_line()) != NULL) { - if (isupper(s[0])) - { - macro_item *m; - macro_item *mlast = NULL; - uschar name[64]; - int namelen = 0; - - while (isalnum(*s) || *s == '_') - { - if (namelen >= sizeof(name) - 1) - log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, - "macro name too long (maximum is %d characters)", sizeof(name) - 1); - name[namelen++] = *s++; - } - name[namelen] = 0; - while (isspace(*s)) s++; - if (*s++ != '=') log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, - "malformed macro definition"); - while (isspace(*s)) s++; - - /* If an existing macro of the same name was defined on the command line, - we just skip this definition. Otherwise it's an error to attempt to - redefine a macro. It is also an error to define a macro whose name begins - with the name of a previously-defined macro. */ - - for (m = macros; m != NULL; m = m->next) - { - int len = Ustrlen(m->name); - - if (Ustrcmp(m->name, name) == 0) - { - if (m->command_line) break; - log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "macro \"%s\" is already " - "defined", name); - } - - if (len < namelen && Ustrstr(name, m->name) != NULL) - log_write(0, LOG_CONFIG|LOG_PANIC_DIE, "\"%s\" cannot be defined as " - "a macro because previously defined macro \"%s\" is a substring", - name, m->name); - - mlast = m; - } - if (m != NULL) continue; /* Found an overriding command-line definition */ - - m = store_get(sizeof(macro_item) + namelen); - m->next = NULL; - m->command_line = FALSE; - if (mlast == NULL) macros = m; else mlast->next = m; - - /* This use of strcpy() is OK because we have obtained a block of store - whose size is based on the length of "name". The definition of the - macro_item structure includes a final vector called "name" which is one - byte long. Thus, adding "namelen" gives us enough room to store the "name" - string. */ - - Ustrcpy(m->name, name); - m->replacement = string_copy(s); - } + if (isupper(s[0])) read_macro_assignment(s); else if (Ustrncmp(s, "domainlist", 10) == 0) read_named_list(&domainlist_anchor, &domainlist_count, @@ -3050,16 +3142,33 @@ driver_instance **p = anchor; driver_instance *d = NULL; uschar *buffer; -/* Now process the configuration lines */ - while ((buffer = get_config_line()) != NULL) { uschar name[64]; + uschar *s; + + /* Read the first name on the line and test for the start of a new driver. A + macro definition indicates the end of the previous driver. If this isn't the + start of a new driver, the line will be re-read. */ - /* Read the first name on the line and test for the start of a new driver. - If this isn't the start of a new driver, the line will be re-read. */ + s = readconf_readname(name, sizeof(name), buffer); - uschar *s = readconf_readname(name, sizeof(name), buffer); + /* Handle macro definition, first finishing off the initialization of the + previous driver, if any. */ + + if (isupper(*name) && *s == '=') + { + if (d != NULL) + { + if (d->driver_name == NULL) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG, + "no driver defined for %s \"%s\"", class, d->name); + (d->info->init)(d); + d = NULL; + } + read_macro_assignment(buffer); + continue; + } /* If the line starts with a name terminated by a colon, we are at the start of the definition of a new driver. The rest of the line must be @@ -3107,7 +3216,8 @@ while ((buffer = get_config_line()) != NULL) continue; } - /* Give an error if we have not set up a current driver yet. */ + /* Not the start of a new driver. Give an error if we have not set up a + current driver yet. */ if (d == NULL) log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "%s name missing", class); @@ -3561,7 +3671,8 @@ if (skip) return; } -/* Read each ACL and add it into the tree */ +/* Read each ACL and add it into the tree. Macro (re)definitions are allowed +between ACLs. */ acl_line = get_config_line(); @@ -3572,8 +3683,15 @@ while(acl_line != NULL) uschar *error; p = readconf_readname(name, sizeof(name), acl_line); - if (*p != ':') - log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "missing ACL name"); + if (isupper(*name) && *p == '=') + { + read_macro_assignment(acl_line); + acl_line = get_config_line(); + continue; + } + + if (*p != ':' || name[0] == 0) + log_write(0, LOG_PANIC_DIE|LOG_CONFIG_IN, "missing or malformed ACL name"); node = store_get(sizeof(tree_node) + Ustrlen(name)); Ustrcpy(node->name, name); @@ -3696,7 +3814,7 @@ while(next_section[0] != 0) } } -fclose(config_file); +(void)fclose(config_file); } /* End of readconf.c */