*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
*/
void
-exim_exit(int rc, const uschar * process)
+exim_exit(int rc)
{
search_tidyup();
store_exit();
DEBUG(D_any)
- debug_printf(">>>>>>>>>>>>>>>> Exim pid=%d %s%s%sterminating with rc=%d "
- ">>>>>>>>>>>>>>>>\n", (int)getpid(),
- process ? "(" : "", process, process ? ") " : "", rc);
+ debug_printf(">>>>>>>>>>>>>>>> Exim pid=%d (%s) terminating with rc=%d "
+ ">>>>>>>>>>>>>>>>\n",
+ (int)getpid(), process_purpose, rc);
exit(rc);
}
void
-exim_underbar_exit(int rc, const uschar * process)
+exim_underbar_exit(int rc)
{
store_exit();
DEBUG(D_any)
- debug_printf(">>>>>>>>>>>>>>>> Exim pid=%d %s%s%sterminating with rc=%d "
- ">>>>>>>>>>>>>>>>\n", (int)getpid(),
- process ? "(" : "", process, process ? ") " : "", rc);
+ debug_printf(">>>>>>>>>>>>>>>> Exim pid=%d (%s) terminating with rc=%d "
+ ">>>>>>>>>>>>>>>>\n",
+ (int)getpid(), process_purpose, rc);
_exit(rc);
}
uschar *parse_error = NULL;
uschar *address = parse_extract_address(s, &parse_error, &start, &end, &domain,
FALSE);
-if (address == NULL)
+if (!address)
{
fprintf(stdout, "syntax error: %s\n", parse_error);
*exit_value = 2;
static void
show_whats_supported(FILE * fp)
{
+rmark reset_point = store_mark();
+gstring * g;
DEBUG(D_any) {} else show_db_version(fp);
-fprintf(fp, "Support for:");
+g = string_cat(NULL, US"Support for:");
#ifdef SUPPORT_CRYPTEQ
- fprintf(fp, " crypteq");
+ g = string_cat(g, US" crypteq");
#endif
#if HAVE_ICONV
- fprintf(fp, " iconv()");
+ g = string_cat(g, US" iconv()");
#endif
#if HAVE_IPV6
- fprintf(fp, " IPv6");
+ g = string_cat(g, US" IPv6");
#endif
#ifdef HAVE_SETCLASSRESOURCES
- fprintf(fp, " use_setclassresources");
+ g = string_cat(g, US" use_setclassresources");
#endif
#ifdef SUPPORT_PAM
- fprintf(fp, " PAM");
+ g = string_cat(g, US" PAM");
#endif
#ifdef EXIM_PERL
- fprintf(fp, " Perl");
+ g = string_cat(g, US" Perl");
#endif
#ifdef EXPAND_DLFUNC
- fprintf(fp, " Expand_dlfunc");
+ g = string_cat(g, US" Expand_dlfunc");
#endif
#ifdef USE_TCP_WRAPPERS
- fprintf(fp, " TCPwrappers");
+ g = string_cat(g, US" TCPwrappers");
#endif
#ifdef USE_GNUTLS
- fprintf(fp, " GnuTLS");
+ g = string_cat(g, US" GnuTLS");
#endif
#ifdef USE_OPENSSL
- fprintf(fp, " OpenSSL");
+ g = string_cat(g, US" OpenSSL");
#endif
#ifdef SUPPORT_TRANSLATE_IP_ADDRESS
- fprintf(fp, " translate_ip_address");
+ g = string_cat(g, US" translate_ip_address");
#endif
#ifdef SUPPORT_MOVE_FROZEN_MESSAGES
- fprintf(fp, " move_frozen_messages");
+ g = string_cat(g, US" move_frozen_messages");
#endif
#ifdef WITH_CONTENT_SCAN
- fprintf(fp, " Content_Scanning");
+ g = string_cat(g, US" Content_Scanning");
#endif
#ifdef SUPPORT_DANE
- fprintf(fp, " DANE");
+ g = string_cat(g, US" DANE");
#endif
#ifndef DISABLE_DKIM
- fprintf(fp, " DKIM");
+ g = string_cat(g, US" DKIM");
#endif
#ifndef DISABLE_DNSSEC
- fprintf(fp, " DNSSEC");
+ g = string_cat(g, US" DNSSEC");
#endif
#ifndef DISABLE_EVENT
- fprintf(fp, " Event");
+ g = string_cat(g, US" Event");
#endif
#ifdef SUPPORT_I18N
- fprintf(fp, " I18N");
+ g = string_cat(g, US" I18N");
#endif
#ifndef DISABLE_OCSP
- fprintf(fp, " OCSP");
+ g = string_cat(g, US" OCSP");
#endif
#ifndef DISABLE_PIPE_CONNECT
- fprintf(fp, " PIPE_CONNECT");
+ g = string_cat(g, US" PIPE_CONNECT");
#endif
#ifndef DISABLE_PRDR
- fprintf(fp, " PRDR");
+ g = string_cat(g, US" PRDR");
#endif
#ifdef SUPPORT_PROXY
- fprintf(fp, " PROXY");
+ g = string_cat(g, US" PROXY");
#endif
#ifdef SUPPORT_SOCKS
- fprintf(fp, " SOCKS");
+ g = string_cat(g, US" SOCKS");
#endif
#ifdef SUPPORT_SPF
- fprintf(fp, " SPF");
+ g = string_cat(g, US" SPF");
#endif
#ifdef SUPPORT_DMARC
- fprintf(fp, " DMARC");
+ g = string_cat(g, US" DMARC");
#endif
#ifdef TCP_FASTOPEN
tcp_init();
- if (f.tcp_fastopen_ok) fprintf(fp, " TCP_Fast_Open");
+ if (f.tcp_fastopen_ok) g = string_cat(g, US" TCP_Fast_Open");
#endif
#ifdef EXPERIMENTAL_ARC
- fprintf(fp, " Experimental_ARC");
+ g = string_cat(g, US" Experimental_ARC");
#endif
#ifdef EXPERIMENTAL_BRIGHTMAIL
- fprintf(fp, " Experimental_Brightmail");
+ g = string_cat(g, US" Experimental_Brightmail");
#endif
#ifdef EXPERIMENTAL_DCC
- fprintf(fp, " Experimental_DCC");
+ g = string_cat(g, US" Experimental_DCC");
#endif
#ifdef EXPERIMENTAL_DSN_INFO
- fprintf(fp, " Experimental_DSN_info");
+ g = string_cat(g, US" Experimental_DSN_info");
#endif
#ifdef EXPERIMENTAL_LMDB
- fprintf(fp, " Experimental_LMDB");
+ g = string_cat(g, US" Experimental_LMDB");
#endif
#ifdef EXPERIMENTAL_QUEUE_RAMP
- fprintf(fp, " Experimental_Queue_Ramp");
+ g = string_cat(g, US" Experimental_Queue_Ramp");
#endif
#ifdef EXPERIMENTAL_QUEUEFILE
- fprintf(fp, " Experimental_QUEUEFILE");
+ g = string_cat(g, US" Experimental_QUEUEFILE");
#endif
#if defined(EXPERIMENTAL_SRS) || defined(EXPERIMENTAL_SRS_NATIVE)
- fprintf(fp, " Experimental_SRS");
+ g = string_cat(g, US" Experimental_SRS");
#endif
#ifdef EXPERIMENTAL_TLS_RESUME
- fprintf(fp, " Experimental_TLS_resume");
+ g = string_cat(g, US" Experimental_TLS_resume");
#endif
-fprintf(fp, "\n");
+g = string_cat(g, US"\n");
-fprintf(fp, "Lookups (built-in):");
+g = string_cat(g, US"Lookups (built-in):");
#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
- fprintf(fp, " lsearch wildlsearch nwildlsearch iplsearch");
+ g = string_cat(g, US" lsearch wildlsearch nwildlsearch iplsearch");
#endif
#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
- fprintf(fp, " cdb");
+ g = string_cat(g, US" cdb");
#endif
#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
- fprintf(fp, " dbm dbmjz dbmnz");
+ g = string_cat(g, US" dbm dbmjz dbmnz");
#endif
#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
- fprintf(fp, " dnsdb");
+ g = string_cat(g, US" dnsdb");
#endif
#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
- fprintf(fp, " dsearch");
+ g = string_cat(g, US" dsearch");
#endif
#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
- fprintf(fp, " ibase");
+ g = string_cat(g, US" ibase");
#endif
#if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
- fprintf(fp, " json");
+ g = string_cat(g, US" json");
#endif
#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
- fprintf(fp, " ldap ldapdn ldapm");
+ g = string_cat(g, US" ldap ldapdn ldapm");
#endif
#ifdef EXPERIMENTAL_LMDB
- fprintf(fp, " lmdb");
+ g = string_cat(g, US" lmdb");
#endif
#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
- fprintf(fp, " mysql");
+ g = string_cat(g, US" mysql");
#endif
#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
- fprintf(fp, " nis nis0");
+ g = string_cat(g, US" nis nis0");
#endif
#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
- fprintf(fp, " nisplus");
+ g = string_cat(g, US" nisplus");
#endif
#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
- fprintf(fp, " oracle");
+ g = string_cat(g, US" oracle");
#endif
#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
- fprintf(fp, " passwd");
+ g = string_cat(g, US" passwd");
#endif
#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
- fprintf(fp, " pgsql");
+ g = string_cat(g, US" pgsql");
#endif
#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
- fprintf(fp, " redis");
+ g = string_cat(g, US" redis");
#endif
#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
- fprintf(fp, " sqlite");
+ g = string_cat(g, US" sqlite");
#endif
#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
- fprintf(fp, " testdb");
+ g = string_cat(g, US" testdb");
#endif
#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
- fprintf(fp, " whoson");
+ g = string_cat(g, US" whoson");
#endif
-fprintf(fp, "\n");
+g = string_cat(g, US"\n");
-auth_show_supported(fp);
-route_show_supported(fp);
-transport_show_supported(fp);
+g = auth_show_supported(g);
+g = route_show_supported(g);
+g = transport_show_supported(g);
#ifdef WITH_CONTENT_SCAN
-malware_show_supported(fp);
+g = malware_show_supported(g);
#endif
if (fixed_never_users[0] > 0)
{
int i;
- fprintf(fp, "Fixed never_users: ");
+ g = string_cat(g, US"Fixed never_users: ");
for (i = 1; i <= (int)fixed_never_users[0] - 1; i++)
- fprintf(fp, "%d:", (unsigned int)fixed_never_users[i]);
- fprintf(fp, "%d\n", (unsigned int)fixed_never_users[i]);
+ string_fmt_append(g, "%u:", (unsigned)fixed_never_users[i]);
+ g = string_fmt_append(g, "%u\n", (unsigned)fixed_never_users[i]);
}
-fprintf(fp, "Configure owner: %d:%d\n", config_uid, config_gid);
+g = string_fmt_append(g, "Configure owner: %d:%d\n", config_uid, config_gid);
+fputs(CS string_from_gstring(g), fp);
fprintf(fp, "Size of off_t: " SIZE_T_FMT "\n", sizeof(off_t));
#endif
} while (0);
+store_reset(reset_point);
}
uschar *real_sender_address;
uschar *originator_home = US"/";
size_t sz;
-rmark reset_point;
struct passwd *pw;
struct stat statbuf;
unprivileged = (real_uid != root_uid && original_euid != root_uid);
+/* For most of the args-parsing we need to use permanent pool memory */
+ {
+ int old_pool = store_pool;
+ store_pool = POOL_PERM;
+
/* Scan the program's arguments. Some can be dealt with right away; others are
simply recorded for checking and handling afterwards. Do a high-level switch
on the second character (the one after '-'), to save some effort. */
-for (i = 1; i < argc; i++)
+ for (i = 1; i < argc; i++)
{
BOOL badarg = FALSE;
- uschar *arg = argv[i];
- uschar *argrest;
+ uschar * arg = argv[i];
+ uschar * argrest;
int switchchar;
/* An argument not starting with '-' is the start of a recipients list;
/* sendmail uses -Ac and -Am to control which .cf file is used;
we ignore them. */
case 'A':
- if (*argrest == '\0') { badarg = TRUE; break; }
+ if (!*argrest) { badarg = TRUE; break; }
else
{
BOOL ignore = FALSE;
/* -bF: Run system filter test */
case 'F':
filter_test |= checking = FTEST_SYSTEM;
- if (*argrest) { badarg = TRUE; break; }
- if (++i < argc) filter_test_sfile = argv[i]; else
- exim_fail("exim: file name expected after %s\n", argv[i-1]);
+ if (*argrest) badarg = TRUE;
+ else if (++i < argc) filter_test_sfile = argv[i];
+ else exim_fail("exim: file name expected after %s\n", argv[i-1]);
break;
/* -bf: Run user filter test
if (!*argrest || Ustrcmp(argrest, "c") == 0)
{
if (++i >= argc) { badarg = TRUE; break; }
- sender_host_address = argv[i];
+ sender_host_address = string_copy_taint(argv[i], TRUE);
host_checking = checking = f.log_testing_mode = TRUE;
f.host_checking_callout = *argrest == 'c';
message_logs = FALSE;
a change! Enforce a prefix check if required. */
case 'C':
- if (*argrest == 0)
- {
- if(++i < argc) argrest = argv[i]; else
- { badarg = TRUE; break; }
- }
+ if (!*argrest)
+ if (++i < argc) argrest = argv[i]; else { badarg = TRUE; break; }
if (Ustrcmp(config_main_filelist, argrest) != 0)
{
#ifdef ALT_CONFIG_PREFIX
const uschar *list = argrest;
uschar *filename;
while((filename = string_nextinlist(&list, &sep, big_buffer,
- big_buffer_size)) != NULL)
- {
- if ((Ustrlen(filename) < len ||
- Ustrncmp(filename, ALT_CONFIG_PREFIX, len) != 0 ||
- Ustrstr(filename, "/../") != NULL) &&
- (Ustrcmp(filename, "/dev/null") != 0 || real_uid != root_uid))
+ big_buffer_size)))
+ if ( ( Ustrlen(filename) < len
+ || Ustrncmp(filename, ALT_CONFIG_PREFIX, len) != 0
+ || Ustrstr(filename, "/../") != NULL
+ )
+ && (Ustrcmp(filename, "/dev/null") != 0 || real_uid != root_uid)
+ )
exim_fail("-C Permission denied\n");
- }
#endif
if (real_uid != root_uid)
{
else
{
/* Well, the trust list at least is up to scratch... */
- rmark reset_point = store_mark();
+ rmark reset_point;
uschar *trusted_configs[32];
int nr_configs = 0;
int i = 0;
+ int old_pool = store_pool;
+ store_pool = POOL_MAIN;
+ reset_point = store_mark();
while (Ufgets(big_buffer, big_buffer_size, trust_list))
{
uschar *start = big_buffer, *nl;
if (nl)
*nl = 0;
trusted_configs[nr_configs++] = string_copy(start);
- if (nr_configs == 32)
+ if (nr_configs == nelem(trusted_configs))
break;
}
fclose(trust_list);
const uschar *list = argrest;
uschar *filename;
while (f.trusted_config && (filename = string_nextinlist(&list,
- &sep, big_buffer, big_buffer_size)) != NULL)
+ &sep, big_buffer, big_buffer_size)))
{
for (i=0; i < nr_configs; i++)
if (Ustrcmp(filename, trusted_configs[i]) == 0)
else /* No valid prefixes found in trust_list file. */
f.trusted_config = FALSE;
store_reset(reset_point);
+ store_pool = old_pool;
}
}
else /* Could not open trust_list file. */
f.debug_daemon = TRUE;
argrest++;
}
- if (*argrest != 0)
+ if (*argrest)
decode_bits(&selector, 1, debug_notall, argrest,
debug_options, debug_options_count, US"debug", 0);
debug_selector = selector;
the -F or be in the next argument. */
case 'F':
- if (*argrest == 0)
- {
- if(++i < argc) argrest = argv[i]; else
- { badarg = TRUE; break; }
- }
- originator_name = argrest;
+ if (!*argrest)
+ if (++i < argc) argrest = argv[i]; else { badarg = TRUE; break; }
+ originator_name = string_copy_taint(argrest, TRUE);
f.sender_name_forced = TRUE;
break;
{
int dummy_start, dummy_end;
uschar *errmess;
- if (*argrest == 0)
- {
- if (i+1 < argc) argrest = argv[++i]; else
- { badarg = TRUE; break; }
- }
- if (*argrest == 0)
+ if (!*argrest)
+ if (i+1 < argc) argrest = argv[++i]; else { badarg = TRUE; break; }
+ if (!*argrest)
*(sender_address = store_get(1, FALSE)) = '\0'; /* Ensure writeable memory */
else
{
- uschar *temp = argrest + Ustrlen(argrest) - 1;
+ uschar * temp = argrest + Ustrlen(argrest) - 1;
while (temp >= argrest && isspace(*temp)) temp--;
if (temp >= argrest && *temp == '.') f_end_dot = TRUE;
allow_domain_literals = TRUE;
#ifdef SUPPORT_I18N
allow_utf8_domains = TRUE;
#endif
- sender_address = parse_extract_address(argrest, &errmess,
- &dummy_start, &dummy_end, &sender_address_domain, TRUE);
+ if (!(sender_address = parse_extract_address(argrest, &errmess,
+ &dummy_start, &dummy_end, &sender_address_domain, TRUE)))
+ exim_fail("exim: bad -f address \"%s\": %s\n", argrest, errmess);
+
sender_address = string_copy_taint(sender_address, TRUE);
#ifdef SUPPORT_I18N
message_smtputf8 = string_is_utf8(sender_address);
#endif
allow_domain_literals = FALSE;
strip_trailing_dot = FALSE;
- if (!sender_address)
- exim_fail("exim: bad -f address \"%s\": %s\n", argrest, errmess);
}
f.sender_address_forced = TRUE;
}
To put it in will require a change to the spool header file format. */
case 'h':
- if (*argrest == 0)
- {
- if(++i < argc) argrest = argv[i]; else
- { badarg = TRUE; break; }
- }
+ if (!*argrest)
+ if (++i < argc) argrest = argv[i]; else { badarg = TRUE; break; }
if (!isdigit(*argrest)) badarg = TRUE;
break;
not to be documented for sendmail but mailx (at least) uses it) */
case 'i':
- if (*argrest == 0) f.dot_ends = FALSE; else badarg = TRUE;
+ if (!*argrest) f.dot_ends = FALSE; else badarg = TRUE;
break;
syslog_processname in the config file, but needs to be an admin option. */
case 'L':
- if (*argrest == '\0')
- {
- if(++i < argc) argrest = argv[i]; else
- { badarg = TRUE; break; }
- }
+ if (!*argrest)
+ if (++i < argc) argrest = argv[i]; else { badarg = TRUE; break; }
if ((sz = Ustrlen(argrest)) > 32)
exim_fail("exim: the -L syslog name is too long: \"%s\"\n", argrest);
if (sz < 1)
exim_fail("exim: the -L syslog name is too short\n");
- cmdline_syslog_name = argrest;
+ cmdline_syslog_name = string_copy_taint(argrest, TRUE);
break;
case 'M':
if (msg_action_arg >= 0)
exim_fail("exim: incompatible arguments\n");
- continue_transport = argv[++i];
- continue_hostname = argv[++i];
- continue_host_address = argv[++i];
+ continue_transport = string_copy_taint(argv[++i], TRUE);
+ continue_hostname = string_copy_taint(argv[++i], TRUE);
+ continue_host_address = string_copy_taint(argv[++i], TRUE);
continue_sequence = Uatoi(argv[++i]);
msg_action = MSG_DELIVER;
msg_action_arg = ++i;
case 'D': smtp_peer_options |= OPTION_DSN; break;
+ /* -MCd: for debug, set a process-purpose string */
+
+ case 'd': if (++i < argc)
+ process_purpose = string_copy_taint(argv[i], TRUE);
+ else badarg = TRUE;
+ break;
+
/* -MCG: set the queue name, to a non-default value */
- case 'G': if (++i < argc) queue_name = string_copy(argv[i]);
+ case 'G': if (++i < argc) queue_name = string_copy_taint(argv[i], TRUE);
else badarg = TRUE;
break;
Require three arguments for the proxied local address and port,
and the TLS cipher. */
- case 't': if (++i < argc) sending_ip_address = argv[i];
+ case 't': if (++i < argc)
+ sending_ip_address = string_copy_taint(argv[i], TRUE);
else badarg = TRUE;
- if (++i < argc) sending_port = (int)(Uatol(argv[i]));
+ if (++i < argc)
+ sending_port = (int)(Uatol(argv[i]));
else badarg = TRUE;
- if (++i < argc) continue_proxy_cipher = argv[i];
+ if (++i < argc)
+ continue_proxy_cipher = string_copy_taint(argv[i], TRUE);
else badarg = TRUE;
/*FALLTHROUGH*/
-Mvl show log
*/
- else if (*argrest == 0)
+ else if (!*argrest)
{
msg_action = MSG_DELIVER;
forced_delivery = f.deliver_force_thaw = TRUE;
else if (Ustrcmp(argrest, "G") == 0)
{
msg_action = MSG_SETQUEUE;
- queue_name_dest = argv[++i];
+ queue_name_dest = string_copy_taint(argv[++i], TRUE);
}
else if (Ustrcmp(argrest, "mad") == 0)
{
for sendmail it askes for "me too". Exim always does this. */
case 'm':
- if (*argrest != 0) badarg = TRUE;
+ if (*argrest) badarg = TRUE;
break;
their thing. It implies debugging at the D_v level. */
case 'N':
- if (*argrest == 0)
+ if (!*argrest)
{
f.dont_deliver = TRUE;
debug_selector |= D_v;
-O option=value and -Ooption=value. */
case 'O':
- if (*argrest == 0)
+ if (!*argrest)
if (++i >= argc)
exim_fail("exim: string expected after -O\n");
break;
/* -oMa: Set sender host address */
- if (Ustrcmp(argrest, "a") == 0) sender_host_address = argv[++i];
+ if (Ustrcmp(argrest, "a") == 0)
+ sender_host_address = string_copy_taint(argv[++i], TRUE);
/* -oMaa: Set authenticator name */
else if (Ustrcmp(argrest, "aa") == 0)
- sender_host_authenticated = argv[++i];
+ sender_host_authenticated = string_copy_taint(argv[++i], TRUE);
/* -oMas: setting authenticated sender */
/* -oMi: Set incoming interface address */
- else if (Ustrcmp(argrest, "i") == 0) interface_address = argv[++i];
+ else if (Ustrcmp(argrest, "i") == 0)
+ interface_address = string_copy_taint(argv[++i], TRUE);
/* -oMm: Message reference */
if (received_protocol)
exim_fail("received_protocol is set already\n");
else
- received_protocol = argv[++i];
+ received_protocol = string_copy_taint(argv[++i], TRUE);
/* -oMs: Set sender host name */
else if (Ustrcmp(argrest, "t") == 0)
{
sender_ident_set = TRUE;
- sender_ident = argv[++i];
+ sender_ident = string_copy_taint(argv[++i], TRUE);
}
/* Else a bad argument */
case 'X':
if (*argrest) badarg = TRUE;
- else override_local_interfaces = argv[++i];
+ else override_local_interfaces = string_copy_taint(argv[++i], TRUE);
break;
/* Unknown -o argument */
/* -panythingelse is taken as the Sendmail-compatible argument -prval:sval,
which sets the host protocol and host name */
- if (*argrest == 0)
- if (i+1 < argc)
- argrest = argv[++i];
- else
- { badarg = TRUE; break; }
+ if (!*argrest)
+ if (i+1 < argc) argrest = argv[++i]; else { badarg = TRUE; break; }
- if (*argrest != 0)
+ if (*argrest)
{
- uschar *hn;
+ uschar * hn = Ustrchr(argrest, ':');
if (received_protocol)
exim_fail("received_protocol is set already\n");
- hn = Ustrchr(argrest, ':');
- if (hn == NULL)
- received_protocol = argrest;
+ if (!hn)
+ received_protocol = string_copy_taint(argrest, TRUE);
else
{
- int old_pool = store_pool;
- store_pool = POOL_PERM;
- received_protocol = string_copyn(argrest, hn - argrest);
- store_pool = old_pool;
- sender_host_name = hn + 1;
+ received_protocol = string_copyn_taint(argrest, hn - argrest, TRUE);
+ sender_host_name = string_copy_taint(hn + 1, TRUE);
}
}
break;
only, optionally named, optionally starting from a given message id. */
if (!(list_queue || count_queue))
- if (*argrest == 0
+ if ( !*argrest
&& (i + 1 >= argc || argv[i+1][0] == '-' || mac_ismsgid(argv[i+1])))
{
queue_interval = 0;
if (i+1 < argc && mac_ismsgid(argv[i+1]))
- start_queue_run_id = argv[++i];
+ start_queue_run_id = string_copy_taint(argv[++i], TRUE);
if (i+1 < argc && mac_ismsgid(argv[i+1]))
- stop_queue_run_id = argv[++i];
+ stop_queue_run_id = string_copy_taint(argv[++i], TRUE);
}
/* -q[f][f][l][G<name>/]<n>: Run the queue at regular intervals, optionally
in all cases provided there are no further characters in this
argument. */
- if (*argrest != 0)
+ if (*argrest)
for (int i = 0; i < nelem(rsopts); i++)
if (Ustrcmp(argrest, rsopts[i]) == 0)
{
pick out particular messages. */
if (*argrest)
- deliver_selectstring = argrest;
+ deliver_selectstring = string_copy_taint(argrest, TRUE);
else if (i+1 < argc)
- deliver_selectstring = argv[++i];
+ deliver_selectstring = string_copy_taint(argv[++i], TRUE);
else
exim_fail("exim: string expected after -R\n");
break;
pick out particular messages. */
if (*argrest)
- deliver_selectstring_sender = argrest;
+ deliver_selectstring_sender = string_copy_taint(argrest, TRUE);
else if (i+1 < argc)
- deliver_selectstring_sender = argv[++i];
+ deliver_selectstring_sender = string_copy_taint(argv[++i], TRUE);
else
exim_fail("exim: string expected after -S\n");
break;
case 'T':
if (f.running_in_test_harness && Ustrcmp(argrest, "qt") == 0)
- fudged_queue_times = argv[++i];
+ fudged_queue_times = string_copy_taint(argv[++i], TRUE);
else badarg = TRUE;
break;
/* -t: Set flag to extract recipients from body of message. */
case 't':
- if (*argrest == 0) extract_recipients = TRUE;
+ if (!*argrest) extract_recipients = TRUE;
/* -ti: Set flag to extract recipients from body of message, and also
specify that dot does not end the message. */
/* -v: verify things - this is a very low-level debugging */
case 'v':
- if (*argrest == 0)
+ if (!*argrest)
{
debug_selector |= D_v;
debug_file = stderr;
As Exim is 8-bit clean, it just ignores this flag. */
case 'x':
- if (*argrest != 0) badarg = TRUE;
+ if (*argrest) badarg = TRUE;
break;
/* -X: in sendmail: takes one parameter, logfile, and sends debugging
logs to that file. We swallow the parameter and otherwise ignore it. */
case 'X':
- if (*argrest == '\0')
+ if (!*argrest)
if (++i >= argc)
exim_fail("exim: string expected after -X\n");
break;
case 'z':
- if (*argrest == '\0')
+ if (!*argrest)
if (++i < argc)
- log_oneline = argv[i];
+ log_oneline = string_copy_taint(argv[i], TRUE);
else
exim_fail("exim: file name expected after %s\n", argv[i-1]);
break;
/* If -R or -S have been specified without -q, assume a single queue run. */
-if ( (deliver_selectstring || deliver_selectstring_sender)
- && queue_interval < 0)
- queue_interval = 0;
+ if ( (deliver_selectstring || deliver_selectstring_sender)
+ && queue_interval < 0)
+ queue_interval = 0;
END_ARG:
+ store_pool = old_pool;
+ }
+
/* If usage_wanted is set we call the usage function - which never returns */
if (usage_wanted) exim_usage(called_as);
p = big_buffer + 3;
}
printing = string_printing(argv[i]);
- if (printing[0] == 0) quote = US"\""; else
+ if (!*printing) quote = US"\"";
+ else
{
const uschar *pp = printing;
quote = US"";
- while (*pp != 0) if (isspace(*pp++)) { quote = US"\""; break; }
+ while (*pp) if (isspace(*pp++)) { quote = US"\""; break; }
}
p += sprintf(CS p, " %s%.*s%s", quote, (int)(big_buffer_size -
(p - big_buffer) - 4), printing, quote);
if (bi_option)
{
(void)fclose(config_file);
- if (bi_command != NULL)
+ if (bi_command)
{
int i = 0;
uschar *argv[3];
argv[i++] = bi_command;
- if (alias_arg != NULL) argv[i++] = alias_arg;
+ if (alias_arg) argv[i++] = alias_arg;
argv[i++] = NULL;
setgroups(group_count, group_list);
exim_setugid(real_uid, real_gid, FALSE, US"running bi_command");
DEBUG(D_exec) debug_printf("exec %.256s %.256s\n", argv[0],
- (argv[1] == NULL)? US"" : argv[1]);
+ argv[1] ? argv[1] : US"");
execv(CS argv[0], (char *const *)argv);
exim_fail("exim: exec failed: %s\n", strerror(errno));
if (test_retry_arg >= argc)
{
printf("-brt needs a domain or address argument\n");
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
}
s1 = argv[test_retry_arg++];
s2 = NULL;
printf("\n");
}
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(EXIT_SUCCESS);
}
/* Handle a request to list one or more configuration options */
else
fail = !readconf_print(argv[i], NULL, flag_n);
}
- exim_exit(fail ? EXIT_FAILURE : EXIT_SUCCESS, US"main");
+ exim_exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
}
if (list_config)
{
set_process_info("listing config");
exim_exit(readconf_print(US"config", NULL, flag_n)
- ? EXIT_SUCCESS : EXIT_FAILURE, US"main");
+ ? EXIT_SUCCESS : EXIT_FAILURE);
}
if (prod_requires_admin && !f.admin_user)
{
fprintf(stderr, "exim: Permission denied\n");
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
}
set_process_info("delivering specified messages");
if (deliver_give_up) forced_delivery = f.deliver_force_thaw = TRUE;
{
int status;
pid_t pid;
+ /*XXX This use of argv[i] for msg_id should really be tainted, but doing
+ that runs into a later copy into the untainted global message_id[] */
if (i == argc - 1)
(void)deliver_message(argv[i], forced_delivery, deliver_give_up);
else if ((pid = exim_fork(US"cmdline-delivery")) == 0)
{
(void)deliver_message(argv[i], forced_delivery, deliver_give_up);
- exim_underbar_exit(EXIT_SUCCESS, US"cmdline-delivery");
+ exim_underbar_exit(EXIT_SUCCESS);
}
else if (pid < 0)
{
fprintf(stderr, "failed to fork delivery process for %s: %s\n", argv[i],
strerror(errno));
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
}
else wait(&status);
}
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(EXIT_SUCCESS);
}
else
set_process_info("running the queue (single queue run)");
queue_run(start_queue_run_id, stop_queue_run_id, FALSE);
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(EXIT_SUCCESS);
}
if (test_rewrite_arg >= argc)
{
printf("-brw needs an address argument\n");
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
}
rewrite_test(argv[test_rewrite_arg]);
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(EXIT_SUCCESS);
}
/* A locally-supplied message is considered to be coming from a local user
}
route_tidyup();
- exim_exit(exit_value, US"main");
+ exim_exit(exit_value);
}
/* Handle expansion checking. Either expand items on the command line, or read
deliver_datafile = -1;
}
- exim_exit(EXIT_SUCCESS, US"main: expansion test");
+ exim_exit(EXIT_SUCCESS);
}
if (smtp_start_session())
{
+ rmark reset_point;
for (; (reset_point = store_mark()); store_reset(reset_point))
{
if (smtp_setup_msg() <= 0) break;
}
smtp_log_no_mail();
}
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(EXIT_SUCCESS);
}
if (!smtp_start_session())
{
mac_smtp_fflush();
- exim_exit(EXIT_SUCCESS, US"smtp_start toplevel");
+ exim_exit(EXIT_SUCCESS);
}
}
while (more)
{
- reset_point = store_mark();
+ rmark reset_point = store_mark();
message_id[0] = 0;
/* Handle the SMTP case; call smtp_setup_mst() to deal with the initial SMTP
cancel_cutthrough_connection(TRUE, US"receive dropped");
if (more) goto moreloop;
smtp_log_no_mail(); /* Log no mail if configured */
- exim_exit(EXIT_FAILURE, US"receive toplevel");
+ exim_exit(EXIT_FAILURE);
}
}
else
{
cancel_cutthrough_connection(TRUE, US"message setup dropped");
smtp_log_no_mail(); /* Log no mail if configured */
- exim_exit(rc ? EXIT_FAILURE : EXIT_SUCCESS, US"msg setup toplevel");
+ exim_exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
}
}
if (error_handling == ERRORS_STDERR)
{
fprintf(stderr, "exim: too many recipients\n");
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
}
else
return
errmess = US"unqualified recipient address not allowed";
}
- if (recipient == NULL)
- {
+ if (!recipient)
if (error_handling == ERRORS_STDERR)
{
fprintf(stderr, "exim: bad recipient address \"%s\": %s\n",
string_printing(list[i]), errmess);
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
}
else
{
moan_to_sender(ERRMESS_BADARGADDRESS, &eblock, NULL, stdin, TRUE)?
errors_sender_rc : EXIT_FAILURE;
}
- }
receive_add_recipient(string_copy_taint(recipient, TRUE), -1);
s = ss;
DEBUG(D_receive)
{
- if (sender_address != NULL) debug_printf("Sender: %s\n", sender_address);
- if (recipients_list != NULL)
+ if (sender_address) debug_printf("Sender: %s\n", sender_address);
+ if (recipients_list)
{
debug_printf("Recipients:\n");
for (int i = 0; i < recipients_count; i++)
for real; when reading the headers of a message for filter testing,
it is TRUE if the headers were terminated by '.' and FALSE otherwise. */
- if (message_id[0] == 0) exim_exit(EXIT_FAILURE, US"main");
+ if (message_id[0] == 0) exim_exit(EXIT_FAILURE);
} /* Non-SMTP message reception */
/* If this is a filter testing run, there are headers in store, but
if (chdir("/")) /* Get away from wherever the user is running this from */
{
DEBUG(D_receive) debug_printf("chdir(\"/\") failed\n");
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
}
/* Now we run either a system filter test, or a user filter test, or both.
if ((filter_test & FTEST_SYSTEM) != 0)
if (!filter_runtest(filter_sfd, filter_test_sfile, TRUE, more))
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
memcpy(filter_sn, filter_n, sizeof(filter_sn));
if ((filter_test & FTEST_USER) != 0)
if (!filter_runtest(filter_ufd, filter_test_ufile, FALSE, more))
- exim_exit(EXIT_FAILURE, US"main");
+ exim_exit(EXIT_FAILURE);
- exim_exit(EXIT_SUCCESS, US"main");
+ exim_exit(EXIT_SUCCESS);
}
/* Else act on the result of message reception. We should not get here unless
pid_t pid;
search_tidyup();
- if ((pid = exim_fork(US"local-accept delivery")) == 0)
+ if ((pid = exim_fork(US"local-accept-delivery")) == 0)
{
int rc;
close_unwanted(); /* Close unwanted file descriptors and TLS */
rc = deliver_message(message_id, FALSE, FALSE);
search_tidyup();
exim_underbar_exit(!mua_wrapper || rc == DELIVER_MUA_SUCCEEDED
- ? EXIT_SUCCESS : EXIT_FAILURE, US"cmdline-delivery");
+ ? EXIT_SUCCESS : EXIT_FAILURE);
}
if (pid < 0)
log_write(0, LOG_MAIN|LOG_PANIC,
"process %d crashed with signal %d while delivering %s",
(int)pid, status & 0x00ff, message_id);
- if (mua_wrapper && (status & 0xffff) != 0) exim_exit(EXIT_FAILURE, US"main");
+ if (mua_wrapper && (status & 0xffff) != 0) exim_exit(EXIT_FAILURE);
}
}
}
store_reset(reset_point);
}
-exim_exit(EXIT_SUCCESS, US"main"); /* Never returns */
+exim_exit(EXIT_SUCCESS); /* Never returns */
return 0; /* To stop compiler warning */
}