* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2015 */
+/* Copyright (c) University of Cambridge 1995 - 2016 */
/* See the file NOTICE for conditions of use and distribution. */
#ifdef WITH_CONTENT_SCAN
fprintf(f, " Content_Scanning");
#endif
-#ifdef WITH_OLD_DEMIME
- fprintf(f, " Old_Demime");
-#endif
#ifndef DISABLE_DKIM
fprintf(f, " DKIM");
#endif
#ifndef DISABLE_DNSSEC
fprintf(f, " DNSSEC");
#endif
+#ifndef DISABLE_EVENT
+ fprintf(f, " Event");
+#endif
+#ifdef SUPPORT_I18N
+ fprintf(f, " I18N");
+#endif
#ifndef DISABLE_OCSP
fprintf(f, " OCSP");
#endif
#ifdef EXPERIMENTAL_DSN_INFO
fprintf(f, " Experimental_DSN_info");
#endif
-#ifdef EXPERIMENTAL_INTERNATIONAL
- fprintf(f, " Experimental_International");
-#endif
-#ifdef EXPERIMENTAL_EVENT
- fprintf(f, " Experimental_Event");
-#endif
-#ifdef EXPERIMENTAL_REDIS
- fprintf(f, " Experimental_Redis");
-#endif
fprintf(f, "\n");
fprintf(f, "Lookups (built-in):");
#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
fprintf(f, " pgsql");
#endif
+#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
+ fprintf(f, " redis");
+#endif
#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
fprintf(f, " sqlite");
#endif
#ifdef SUPPORT_TLS
tls_version_report(f);
#endif
-#ifdef EXPERIMENTAL_INTERNATIONAL
+#ifdef SUPPORT_I18N
utf8_version_report(f);
#endif
if (!needs_quote) return lpart;
size = ptr = 0;
-yield = string_cat(NULL, &size, &ptr, US"\"", 1);
+yield = string_catn(NULL, &size, &ptr, US"\"", 1);
for (;;)
{
uschar *nq = US Ustrpbrk(lpart, "\\\"");
if (nq == NULL)
{
- yield = string_cat(yield, &size, &ptr, lpart, Ustrlen(lpart));
+ yield = string_cat(yield, &size, &ptr, lpart);
break;
}
- yield = string_cat(yield, &size, &ptr, lpart, nq - lpart);
- yield = string_cat(yield, &size, &ptr, US"\\", 1);
- yield = string_cat(yield, &size, &ptr, nq, 1);
+ yield = string_catn(yield, &size, &ptr, lpart, nq - lpart);
+ yield = string_catn(yield, &size, &ptr, US"\\", 1);
+ yield = string_catn(yield, &size, &ptr, nq, 1);
lpart = nq + 1;
}
-yield = string_cat(yield, &size, &ptr, US"\"", 1);
+yield = string_catn(yield, &size, &ptr, US"\"", 1);
yield[ptr] = 0;
return yield;
}
while (p < ss && isspace(*p)) p++; /* leading space after cont */
}
- yield = string_cat(yield, &size, &ptr, p, ss - p);
+ yield = string_catn(yield, &size, &ptr, p, ss - p);
#ifdef USE_READLINE
if (fn_readline != NULL) free(readline_line);
#endif
+ /* yield can only be NULL if ss==p */
if (ss == p || yield[ptr-1] != '\\')
{
- yield[ptr] = 0;
+ if (yield) yield[ptr] = 0;
break;
}
yield[--ptr] = 0;
for (i = 0; i < REGEX_VARS; i++) regex_vars[i] = NULL;
-
/* If the program is called as "mailq" treat it as equivalent to "exim -bp";
this seems to be a generally accepted convention, since one finds symbolic
links called "mailq" in standard OS configurations. */
else if (*argrest == 'F')
{
- filter_test |= FTEST_SYSTEM;
+ filter_test |= checking = FTEST_SYSTEM;
if (*(++argrest) != 0) { badarg = TRUE; break; }
if (++i < argc) filter_test_sfile = argv[i]; else
{
{
if (*(++argrest) == 0)
{
- filter_test |= FTEST_USER;
+ filter_test |= checking = FTEST_USER;
if (++i < argc) filter_test_ufile = argv[i]; else
{
fprintf(stderr, "exim: file name expected after %s\n", argv[i-1]);
else if (Ustrcmp(argrest, "malware") == 0)
{
if (++i >= argc) { badarg = TRUE; break; }
+ checking = TRUE;
malware_test_file = argv[i];
}
else if (Ustrcmp(argrest, "rt") == 0)
{
+ checking = TRUE;
test_retry_arg = i + 1;
goto END_ARG;
}
else if (Ustrcmp(argrest, "rw") == 0)
{
+ checking = TRUE;
test_rewrite_arg = i + 1;
goto END_ARG;
}
printf("%s\n", CS version_copyright);
version_printed = TRUE;
show_whats_supported(stdout);
+ log_testing_mode = TRUE;
}
/* -bw: inetd wait mode, accept a listening socket as stdin */
if (temp >= argrest && *temp == '.') f_end_dot = TRUE;
allow_domain_literals = TRUE;
strip_trailing_dot = TRUE;
-#ifdef EXPERIMENTAL_INTERNATIONAL
+#ifdef SUPPORT_I18N
allow_utf8_domains = TRUE;
#endif
sender_address = parse_extract_address(argrest, &errmess,
&dummy_start, &dummy_end, &sender_address_domain, TRUE);
-#ifdef EXPERIMENTAL_INTERNATIONAL
+#ifdef SUPPORT_I18N
message_smtputf8 = string_is_utf8(sender_address);
allow_utf8_domains = FALSE;
#endif
This needs to happen before we read the main configuration. */
init_lookup_list();
-#ifdef EXPERIMENTAL_INTERNATIONAL
+#ifdef SUPPORT_I18N
if (running_in_test_harness) smtputf8_advertise_hosts = NULL;
#endif
/* Read the main runtime configuration data; this gives up if there
is a failure. It leaves the configuration file open so that the subsequent
-configuration data for delivery can be read if needed. */
+configuration data for delivery can be read if needed.
+
+NOTE: immediatly after opening the configuration file we change the working
+directory to "/"! Later we change to $spool_directory. We do it there, because
+during readconf_main() some expansion takes place already. */
+
+/* Store the initial cwd before we change directories */
+if ((initial_cwd = os_getcwd(NULL, 0)) == NULL)
+ {
+ perror("exim: can't get the current working directory");
+ exit(EXIT_FAILURE);
+ }
+
+/* checking:
+ -be[m] expansion test -
+ -b[fF] filter test new
+ -bh[c] host test -
+ -bmalware malware_test_file new
+ -brt retry test new
+ -brw rewrite test new
+ -bt address test -
+ -bv[s] address verify -
+ list_options:
+ -bP <option> (except -bP config, which sets list_config)
+
+If any of these options is set, we suppress warnings about configuration
+issues (currently about tls_advertise_hosts and keep_environment not being
+defined) */
+
+readconf_main(checking || list_options);
+
+/* Now in directory "/" */
+
+if (cleanup_environment() == FALSE)
+ log_write(0, LOG_PANIC_DIE, "Can't cleanup environment");
-readconf_main();
/* If an action on specific messages is requested, or if a daemon or queue
runner is being started, we need to know if Exim was called by an admin user.
temporary files are created; Exim doesn't use these (apart from when delivering
to MBX mailboxes), but called libraries such as DBM libraries may require them.
If TMPDIR is found in the environment, reset it to the value defined in the
-TMPDIR macro, if this macro is defined. */
+EXIM_TMPDIR macro, if this macro is defined. For backward compatibility this
+macro may be called TMPDIR in old "Local/Makefile"s. It's converted to
+EXIM_TMPDIR by the build scripts.
+*/
-#ifdef TMPDIR
+#ifdef EXIM_TMPDIR
{
uschar **p;
- for (p = USS environ; *p != NULL; p++)
+ if (environ) for (p = USS environ; *p != NULL; p++)
{
if (Ustrncmp(*p, "TMPDIR=", 7) == 0 &&
- Ustrcmp(*p+7, TMPDIR) != 0)
+ Ustrcmp(*p+7, EXIM_TMPDIR) != 0)
{
- uschar *newp = malloc(Ustrlen(TMPDIR) + 8);
- sprintf(CS newp, "TMPDIR=%s", TMPDIR);
+ uschar *newp = malloc(Ustrlen(EXIM_TMPDIR) + 8);
+ sprintf(CS newp, "TMPDIR=%s", EXIM_TMPDIR);
*p = newp;
- DEBUG(D_any) debug_printf("reset TMPDIR=%s in environment\n", TMPDIR);
+ DEBUG(D_any) debug_printf("reset TMPDIR=%s in environment\n", EXIM_TMPDIR);
}
}
}
uschar **new;
uschar **newp;
int count = 0;
- while (*p++ != NULL) count++;
+ if (environ) while (*p++ != NULL) count++;
if (envtz == NULL) count++;
newp = new = malloc(sizeof(uschar *) * (count + 1));
- for (p = USS environ; *p != NULL; p++)
+ if (environ) for (p = USS environ; *p != NULL; p++)
{
if (Ustrncmp(*p, "TZ=", 3) == 0) continue;
*newp++ = *p;
{
int i;
uschar *p = big_buffer;
- char * dummy;
Ustrcpy(p, "cwd= (failed)");
- dummy = /* quieten compiler */ getcwd(CS p+4, big_buffer_size - 4);
+
+ Ustrncpy(p + 4, initial_cwd, big_buffer_size-5);
+
while (*p) p++;
(void)string_format(p, big_buffer_size - (p - big_buffer), " %d args:", argc);
while (*p) p++;
Note that authority for performing certain actions on messages is tested in the
queue_action() function. */
-if (!trusted_caller && !checking && filter_test == FTEST_NONE)
+if (!trusted_caller && !checking)
{
sender_host_name = sender_host_address = interface_address =
sender_ident = received_protocol = NULL;
(Ustrcmp(argv[i], "router") == 0 ||
Ustrcmp(argv[i], "transport") == 0 ||
Ustrcmp(argv[i], "authenticator") == 0 ||
- Ustrcmp(argv[i], "macro") == 0))
+ Ustrcmp(argv[i], "macro") == 0 ||
+ Ustrcmp(argv[i], "environment") == 0))
{
readconf_print(argv[i+1], argv[i], flag_n);
i++;
if (list_config)
{
set_process_info("listing config");
- readconf_print(US"config", NULL, FALSE);
+ readconf_print(US"config", NULL, flag_n);
exim_exit(EXIT_SUCCESS);
}
+/* Initialise subsystems as required */
+#ifndef DISABLE_DKIM
+dkim_exim_init();
+#endif
+deliver_init();
+
+
/* Handle a request to deliver one or more messages that are already on the
queue. Values of msg_action other than MSG_DELIVER and MSG_LOAD are dealt with
above. MSG_LOAD is handled with -be (which is the only time it applies) below.
if (sender_address == NULL /* No sender_address set */
|| /* OR */
(sender_address[0] != 0 && /* Non-empty sender address, AND */
- !checking && /* Not running tests, AND */
- filter_test == FTEST_NONE)) /* Not testing a filter */
+ !checking)) /* Not running tests, including filter tests */
{
sender_address = originator_login;
sender_address_forced = FALSE;
if (expansion_test)
{
+ dns_init(FALSE, FALSE, FALSE);
if (msg_action_arg > 0 && msg_action == MSG_LOAD)
{
uschar spoolname[256]; /* Not big_buffer; used in spool_read_header() */
}
message_id = argv[msg_action_arg];
(void)string_format(spoolname, sizeof(spoolname), "%s-H", message_id);
- if (!spool_open_datafile(message_id))
+ if ((deliver_datafile = spool_open_datafile(message_id)) < 0)
printf ("Failed to load message datafile %s\n", message_id);
if (spool_read_header(spoolname, TRUE, FALSE) != spool_read_OK)
printf ("Failed to load message %s\n", message_id);
"**** This is not for real!\n\n",
sender_host_address);
+ memset(sender_host_cache, 0, sizeof(sender_host_cache));
if (verify_check_host(&hosts_connection_nolog) == OK)
BIT_CLEAR(log_selector, log_selector_size, Li_smtp_connection);
log_write(L_smtp_connection, LOG_MAIN, "%s", smtp_get_connection_info());
deliver_drop_privilege = TRUE;
queue_smtp = FALSE;
queue_smtp_domains = NULL;
-#ifdef EXPERIMENTAL_INTERNATIONAL
+#ifdef SUPPORT_I18N
message_utf8_downconvert = -1; /* convert-if-needed */
#endif
}
{
smtp_in = stdin;
smtp_out = stdout;
+ memset(sender_host_cache, 0, sizeof(sender_host_cache));
if (verify_check_host(&hosts_connection_nolog) == OK)
BIT_CLEAR(log_selector, log_selector_size, Li_smtp_connection);
log_write(L_smtp_connection, LOG_MAIN, "%s", smtp_get_connection_info());
errors_sender_rc : EXIT_FAILURE;
}
-#ifdef EXPERIMENTAL_INTERNATIONAL
+#ifdef SUPPORT_I18N
{
BOOL b = allow_utf8_domains;
allow_utf8_domains = TRUE;
recipient =
parse_extract_address(s, &errmess, &start, &end, &domain, FALSE);
-#ifdef EXPERIMENTAL_INTERNATIONAL
+#ifdef SUPPORT_I18N
if (string_is_utf8(recipient))
message_smtputf8 = TRUE;
else