* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2017 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
va_end(ap);
}
+/***********************************************
+* Handler for SIGTERM *
+***********************************************/
+static void
+term_handler(int sig)
+{
+ exit(1);
+}
/*************************************************
{
if (smtp_input)
{
- #ifdef SUPPORT_TLS
- tls_close(TRUE, FALSE); /* Shut down the TLS library */
- #endif
+#ifdef SUPPORT_TLS
+ tls_close(NULL, TLS_NO_SHUTDOWN); /* Shut down the TLS library */
+#endif
(void)close(fileno(smtp_in));
(void)close(fileno(smtp_out));
smtp_in = NULL;
* Show supported features *
*************************************************/
-/* This function is called for -bV/--version and for -d to output the optional
-features of the current Exim binary.
-
-Arguments: a FILE for printing
-Returns: nothing
-*/
-
static void
-show_whats_supported(FILE *f)
+show_db_version(FILE * f)
{
- auth_info *authi;
-
#ifdef DB_VERSION_STRING
-fprintf(f, "Berkeley DB: %s\n", DB_VERSION_STRING);
+DEBUG(D_any)
+ {
+ fprintf(f, "Library version: BDB: Compile: %s\n", DB_VERSION_STRING);
+ fprintf(f, " Runtime: %s\n",
+ db_version(NULL, NULL, NULL));
+ }
+else
+ fprintf(f, "Berkeley DB: %s\n", DB_VERSION_STRING);
+
#elif defined(BTREEVERSION) && defined(HASHVERSION)
#ifdef USE_DB
fprintf(f, "Probably Berkeley DB version 1.8x (native mode)\n");
#else
fprintf(f, "Probably Berkeley DB version 1.8x (compatibility mode)\n");
#endif
+
#elif defined(_DBM_RDONLY) || defined(dbm_dirfno)
fprintf(f, "Probably ndbm\n");
#elif defined(USE_TDB)
fprintf(f, "Probably GDBM (compatibility mode)\n");
#endif
#endif
+}
+
+
+/* This function is called for -bV/--version and for -d to output the optional
+features of the current Exim binary.
+
+Arguments: a FILE for printing
+Returns: nothing
+*/
+
+static void
+show_whats_supported(FILE * f)
+{
+auth_info * authi;
+
+DEBUG(D_any) {} else show_db_version(f);
fprintf(f, "Support for:");
#ifdef SUPPORT_CRYPTEQ
fprintf(f, " TCPwrappers");
#endif
#ifdef SUPPORT_TLS
- #ifdef USE_GNUTLS
+# ifdef USE_GNUTLS
fprintf(f, " GnuTLS");
- #else
+# else
fprintf(f, " OpenSSL");
- #endif
+# endif
#endif
#ifdef SUPPORT_TRANSLATE_IP_ADDRESS
fprintf(f, " translate_ip_address");
#ifdef WITH_CONTENT_SCAN
fprintf(f, " Content_Scanning");
#endif
+#ifdef SUPPORT_DANE
+ fprintf(f, " DANE");
+#endif
#ifndef DISABLE_DKIM
fprintf(f, " DKIM");
#endif
#ifdef SUPPORT_SOCKS
fprintf(f, " SOCKS");
#endif
+#ifdef SUPPORT_SPF
+ fprintf(f, " SPF");
+#endif
#ifdef TCP_FASTOPEN
deliver_init();
if (tcp_fastopen_ok) fprintf(f, " TCP_Fast_Open");
#ifdef EXPERIMENTAL_QUEUEFILE
fprintf(f, " Experimental_QUEUEFILE");
#endif
-#ifdef EXPERIMENTAL_SPF
- fprintf(f, " Experimental_SPF");
-#endif
#ifdef EXPERIMENTAL_SRS
fprintf(f, " Experimental_SRS");
#endif
+#ifdef EXPERIMENTAL_ARC
+ fprintf(f, " Experimental_ARC");
+#endif
#ifdef EXPERIMENTAL_BRIGHTMAIL
fprintf(f, " Experimental_Brightmail");
#endif
-#ifdef EXPERIMENTAL_DANE
- fprintf(f, " Experimental_DANE");
-#endif
#ifdef EXPERIMENTAL_DCC
fprintf(f, " Experimental_DCC");
#endif
#ifdef EXPERIMENTAL_DSN_INFO
fprintf(f, " Experimental_DSN_info");
#endif
+#ifdef EXPERIMENTAL_REQUIRETLS
+ fprintf(f, " Experimental_REQUIRETLS");
+#endif
fprintf(f, "\n");
fprintf(f, "Lookups (built-in):");
#endif
fprintf(f, "\n");
-fprintf(f, "Authenticators:");
-#ifdef AUTH_CRAM_MD5
- fprintf(f, " cram_md5");
-#endif
-#ifdef AUTH_CYRUS_SASL
- fprintf(f, " cyrus_sasl");
-#endif
-#ifdef AUTH_DOVECOT
- fprintf(f, " dovecot");
-#endif
-#ifdef AUTH_GSASL
- fprintf(f, " gsasl");
-#endif
-#ifdef AUTH_HEIMDAL_GSSAPI
- fprintf(f, " heimdal_gssapi");
-#endif
-#ifdef AUTH_PLAINTEXT
- fprintf(f, " plaintext");
-#endif
-#ifdef AUTH_SPA
- fprintf(f, " spa");
-#endif
-#ifdef AUTH_TLS
- fprintf(f, " tls");
-#endif
-fprintf(f, "\n");
-
-fprintf(f, "Routers:");
-#ifdef ROUTER_ACCEPT
- fprintf(f, " accept");
-#endif
-#ifdef ROUTER_DNSLOOKUP
- fprintf(f, " dnslookup");
-#endif
-#ifdef ROUTER_IPLITERAL
- fprintf(f, " ipliteral");
-#endif
-#ifdef ROUTER_IPLOOKUP
- fprintf(f, " iplookup");
-#endif
-#ifdef ROUTER_MANUALROUTE
- fprintf(f, " manualroute");
-#endif
-#ifdef ROUTER_QUERYPROGRAM
- fprintf(f, " queryprogram");
-#endif
-#ifdef ROUTER_REDIRECT
- fprintf(f, " redirect");
-#endif
-fprintf(f, "\n");
+auth_show_supported(f);
+route_show_supported(f);
+transport_show_supported(f);
-fprintf(f, "Transports:");
-#ifdef TRANSPORT_APPENDFILE
- fprintf(f, " appendfile");
- #ifdef SUPPORT_MAILDIR
- fprintf(f, "/maildir");
- #endif
- #ifdef SUPPORT_MAILSTORE
- fprintf(f, "/mailstore");
- #endif
- #ifdef SUPPORT_MBX
- fprintf(f, "/mbx");
- #endif
-#endif
-#ifdef TRANSPORT_AUTOREPLY
- fprintf(f, " autoreply");
-#endif
-#ifdef TRANSPORT_LMTP
- fprintf(f, " lmtp");
-#endif
-#ifdef TRANSPORT_PIPE
- fprintf(f, " pipe");
-#endif
-#ifdef EXPERIMENTAL_QUEUEFILE
- fprintf(f, " queuefile");
-#endif
-#ifdef TRANSPORT_SMTP
- fprintf(f, " smtp");
+#ifdef WITH_CONTENT_SCAN
+malware_show_supported(f);
#endif
-fprintf(f, "\n");
if (fixed_never_users[0] > 0)
{
gnu_get_libc_version());
#endif
+show_db_version(f);
+
#ifdef SUPPORT_TLS
tls_version_report(f);
#endif
"If the string is not recognised, you'll get this help (on stderr).\n"
"\n"
" exim -bI:help this information\n"
-" exim -bI:dscp dscp value keywords known\n"
-" exim -bI:sieve list of supported sieve extensions, one per line.\n"
+" exim -bI:dscp list of known dscp value keywords\n"
+" exim -bI:sieve list of supported sieve extensions\n"
);
return;
case CMDINFO_SIEVE:
/* The list of commandline macros should be very short.
Accept the N*M complexity. */
-for (m = macros; m; m = m->next) if (m->command_line)
+for (m = macros_user; m; m = m->next) if (m->command_line)
{
found = FALSE;
for (w = whites; *w; ++w)
running_in_test_harness =
*running_status == '<' && Ustrcmp(running_status, "<<<testing>>>") == 0;
+if (running_in_test_harness)
+ debug_store = TRUE;
/* The C standard says that the equivalent of setlocale(LC_ALL, "C") is obeyed
at the start of a program; however, it seems that some environments do not
set_process_info("initializing");
os_restarting_signal(SIGUSR1, usr1_handler);
+/* If running in a dockerized environment, the TERM signal is only
+delegated to the PID 1 if we request it by setting an signal handler */
+if (getpid() == 1) signal(SIGTERM, term_handler);
+
/* SIGHUP is used to get the daemon to reconfigure. It gets set as appropriate
in the daemon code. For the rest of Exim's uses, we ignore it. */
while (isspace(*s)) s++;
}
- for (m = macros; m; m = m->next)
+ for (m = macros_user; m; m = m->next)
if (Ustrcmp(m->name, name) == 0)
{
fprintf(stderr, "exim: duplicated -D in command line\n");
exit(EXIT_FAILURE);
}
- m = macro_create(string_copy(name), string_copy(s), TRUE);
+ m = macro_create(name, s, TRUE);
if (clmacro_count >= MAX_CLMACROS)
{
default: badarg = TRUE; break;
}
- break;
+ break;
+ }
+
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS)
+ /* -MS set REQUIRETLS on (new) message */
+
+ else if (*argrest == 'S')
+ {
+ tls_requiretls |= REQUIRETLS_MSG;
+ break;
}
+#endif
/* -M[x]: various operations on the following list of message ids:
-M deliver the messages, ignoring next retry times and thawing
readconf_main(checking || list_options);
-if (builtin_macros_create_trigger) DEBUG(D_any)
- debug_printf("Builtin macros created (expensive) due to config line '%.*s'\n",
- Ustrlen(builtin_macros_create_trigger)-1, builtin_macros_create_trigger);
/* Now in directory "/" */
Don't attempt it if logging is disabled, or if listing variables or if
verifying/testing addresses or expansions. */
-if (((debug_selector & D_any) != 0 || LOGGING(arguments))
- && really_exim && !list_options && !checking)
+if ( (debug_selector & D_any || LOGGING(arguments))
+ && really_exim && !list_options && !checking)
{
int i;
uschar *p = big_buffer;
Ustrcpy(p, "cwd= (failed)");
- Ustrncpy(p + 4, initial_cwd, big_buffer_size-5);
+ if (!initial_cwd)
+ p += 13;
+ else
+ {
+ Ustrncpy(p + 4, initial_cwd, big_buffer_size-5);
+ p += 4 + Ustrlen(initial_cwd);
+ /* in case p is near the end and we don't provide enough space for
+ * string_format to be willing to write. */
+ *p = '\0';
+ }
- while (*p) p++;
(void)string_format(p, big_buffer_size - (p - big_buffer), " %d args:", argc);
while (*p) p++;
for (i = 0; i < argc; i++)
if (list_options)
{
+ BOOL fail = FALSE;
set_process_info("listing variables");
- if (recipients_arg >= argc) readconf_print(US"all", NULL, flag_n);
- else for (i = recipients_arg; i < argc; i++)
+ if (recipients_arg >= argc)
+ fail = !readconf_print(US"all", NULL, flag_n);
+ else for (i = recipients_arg; i < argc; i++)
+ {
+ if (i < argc - 1 &&
+ (Ustrcmp(argv[i], "router") == 0 ||
+ Ustrcmp(argv[i], "transport") == 0 ||
+ Ustrcmp(argv[i], "authenticator") == 0 ||
+ Ustrcmp(argv[i], "macro") == 0 ||
+ Ustrcmp(argv[i], "environment") == 0))
{
- if (i < argc - 1 &&
- (Ustrcmp(argv[i], "router") == 0 ||
- Ustrcmp(argv[i], "transport") == 0 ||
- Ustrcmp(argv[i], "authenticator") == 0 ||
- Ustrcmp(argv[i], "macro") == 0 ||
- Ustrcmp(argv[i], "environment") == 0))
- {
- readconf_print(argv[i+1], argv[i], flag_n);
- i++;
- }
- else readconf_print(argv[i], NULL, flag_n);
+ fail |= !readconf_print(argv[i+1], argv[i], flag_n);
+ i++;
}
- exim_exit(EXIT_SUCCESS, US"main");
+ else
+ fail = !readconf_print(argv[i], NULL, flag_n);
+ }
+ exim_exit(fail ? EXIT_FAILURE : EXIT_SUCCESS, US"main");
}
if (list_config)
{
set_process_info("listing config");
- readconf_print(US"config", NULL, flag_n);
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(readconf_print(US"config", NULL, flag_n)
+ ? EXIT_SUCCESS : EXIT_FAILURE, US"main");
}
/* Only admin users may see config-file macros this way */
- if (!admin_user) macros = mlast = NULL;
+ if (!admin_user) macros_user = macros = mlast = NULL;
/* Allow $recipients for this testing */
{
if (version_printed)
{
+ if (Ustrchr(config_main_filelist, ':'))
+ printf("Configuration file search path is %s\n", config_main_filelist);
printf("Configuration file is %s\n", config_main_filename);
return EXIT_SUCCESS;
}
case when it is forced by -oMa. However, we must flag that it isn't a socket,
so that the test for IP options is skipped for -bs input. */
-if (sender_host_address != NULL && sender_fullhost == NULL)
+if (sender_host_address && !sender_fullhost)
{
host_build_sender_fullhost();
set_process_info("handling incoming connection from %s via -oMa",