void
set_process_info(const char *format, ...)
{
-int len;
+int len = sprintf(CS process_info, "%5d ", (int)getpid());
va_list ap;
-sprintf(CS process_info, "%5d ", (int)getpid());
-len = Ustrlen(process_info);
va_start(ap, format);
if (!string_vformat(process_info + len, PROCESS_INFO_SIZE - len - 2, format, ap))
Ustrcpy(process_info + len, "**** string overflowed buffer ****");
#ifdef SUPPORT_SOCKS
fprintf(f, " SOCKS");
#endif
+#ifdef TCP_FASTOPEN
+ fprintf(f, " TCP_Fast_Open");
+#endif
+#ifdef EXPERIMENTAL_LMDB
+ fprintf(f, " Experimental_LMDB");
+#endif
+#ifdef EXPERIMENTAL_QUEUEFILE
+ fprintf(f, " Experimental_QUEUEFILE");
+#endif
#ifdef EXPERIMENTAL_SPF
fprintf(f, " Experimental_SPF");
#endif
#if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
fprintf(f, " ldap ldapdn ldapm");
#endif
+#ifdef EXPERIMENTAL_LMDB
+ fprintf(f, " lmdb");
+#endif
#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
fprintf(f, " mysql");
#endif
#ifdef TRANSPORT_PIPE
fprintf(f, " pipe");
#endif
+#ifdef EXPERIMENTAL_QUEUEFILE
+ fprintf(f, " queuefile");
+#endif
#ifdef TRANSPORT_SMTP
fprintf(f, " smtp");
#endif
fprintf(f, "%d\n", (unsigned int)fixed_never_users[i]);
}
+fprintf(f, "Configure owner: %d:%d\n", config_uid, config_gid);
+
fprintf(f, "Size of off_t: " SIZE_T_FMT "\n", sizeof(off_t));
/* Everything else is details which are only worth reporting when debugging.
/* Typically, Exim will drop privileges if macros are supplied. In some
cases, we want to not do so.
-Arguments: none (macros is a global)
+Arguments: opt_D_used - true if the commandline had a "-D" option
Returns: true if trusted, false otherwise
*/
static BOOL
-macros_trusted(void)
+macros_trusted(BOOL opt_D_used)
{
#ifdef WHITELIST_D_MACROS
macro_item *m;
BOOL prev_char_item, found;
#endif
-if (macros == NULL)
+if (!opt_D_used)
return TRUE;
#ifndef WHITELIST_D_MACROS
return FALSE;
}
whites[i] = NULL;
-/* The list of macros should be very short. Accept the N*M complexity. */
-for (m = macros; m != NULL; m = m->next)
+/* 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)
{
found = FALSE;
for (w = whites; *w; ++w)
BOOL local_queue_only;
BOOL more = TRUE;
BOOL one_msg_action = FALSE;
+BOOL opt_D_used = FALSE;
BOOL queue_only_set = FALSE;
BOOL receiving_message = TRUE;
BOOL sender_ident_set = FALSE;
/* Ensure we have a buffer for constructing log entries. Use malloc directly,
because store_malloc writes a log entry on failure. */
-log_buffer = (uschar *)malloc(LOG_BUFFER_SIZE);
-if (log_buffer == NULL)
+if (!(log_buffer = US malloc(LOG_BUFFER_SIZE)))
{
fprintf(stderr, "exim: failed to get store for log buffer\n");
exit(EXIT_FAILURE);
#else
{
int ptr = 0;
- macro_item *mlast = NULL;
macro_item *m;
uschar name[24];
uschar *s = argrest;
+ opt_D_used = TRUE;
while (isspace(*s)) s++;
if (*s < 'A' || *s > 'Z')
while (isspace(*s)) s++;
}
- for (m = macros; m != NULL; m = m->next)
- {
+ for (m = macros; m; m = m->next)
if (Ustrcmp(m->name, name) == 0)
{
fprintf(stderr, "exim: duplicated -D in command line\n");
exit(EXIT_FAILURE);
}
- mlast = m;
- }
- m = store_get(sizeof(macro_item) + Ustrlen(name));
- m->next = NULL;
- m->command_line = TRUE;
- if (mlast == NULL) macros = m; else mlast->next = m;
- Ustrcpy(m->name, name);
- m->replacement = string_copy(s);
+ m = macro_create(name, s, TRUE, FALSE);
if (clmacro_count >= MAX_CLMACROS)
{
break;
}
+ else if (*argrest == 'C' && argrest[1] && !argrest[2])
+ {
+ switch(argrest[1])
+ {
/* -MCA: set the smtp_authenticated flag; this is useful only when it
precedes -MC (see above). The flag indicates that the host to which
Exim is connected has accepted an AUTH sequence. */
- else if (Ustrcmp(argrest, "CA") == 0)
- {
- smtp_authenticated = TRUE;
- break;
- }
+ case 'A': smtp_authenticated = TRUE; break;
/* -MCD: set the smtp_use_dsn flag; this indicates that the host
that exim is connected to supports the esmtp extension DSN */
- else if (Ustrcmp(argrest, "CD") == 0)
- {
- smtp_use_dsn = TRUE;
- break;
- }
+ case 'D': smtp_peer_options |= PEER_OFFERED_DSN; break;
/* -MCG: set the queue name, to a non-default value */
- else if (Ustrcmp(argrest, "CG") == 0)
- {
- if (++i < argc) queue_name = string_copy(argv[i]);
- else badarg = TRUE;
- break;
- }
+ case 'G': if (++i < argc) queue_name = string_copy(argv[i]);
+ else badarg = TRUE;
+ break;
+
+ /* -MCK: the peer offered CHUNKING. Must precede -MC */
+
+ case 'K': smtp_peer_options |= PEER_OFFERED_CHUNKING; break;
/* -MCP: set the smtp_use_pipelining flag; this is useful only when
it preceded -MC (see above) */
- else if (Ustrcmp(argrest, "CP") == 0)
- {
- smtp_use_pipelining = TRUE;
- break;
- }
+ case 'P': smtp_peer_options |= PEER_OFFERED_PIPE; break;
/* -MCQ: pass on the pid of the queue-running process that started
this chain of deliveries and the fd of its synchronizing pipe; this
is useful only when it precedes -MC (see above) */
- else if (Ustrcmp(argrest, "CQ") == 0)
- {
- if (++i < argc) passed_qr_pid = (pid_t)(Uatol(argv[i]));
- else badarg = TRUE;
- if (++i < argc) passed_qr_pipe = (int)(Uatol(argv[i]));
- else badarg = TRUE;
- break;
- }
+ case 'Q': if (++i < argc) passed_qr_pid = (pid_t)(Uatol(argv[i]));
+ else badarg = TRUE;
+ if (++i < argc) passed_qr_pipe = (int)(Uatol(argv[i]));
+ else badarg = TRUE;
+ break;
/* -MCS: set the smtp_use_size flag; this is useful only when it
precedes -MC (see above) */
- else if (Ustrcmp(argrest, "CS") == 0)
- {
- smtp_use_size = TRUE;
- break;
- }
+ case 'S': smtp_peer_options |= PEER_OFFERED_SIZE; break;
+#ifdef SUPPORT_TLS
/* -MCT: set the tls_offered flag; this is useful only when it
precedes -MC (see above). The flag indicates that the host to which
Exim is connected has offered TLS support. */
- #ifdef SUPPORT_TLS
- else if (Ustrcmp(argrest, "CT") == 0)
- {
- tls_offered = TRUE;
- break;
+ case 'T': smtp_peer_options |= PEER_OFFERED_TLS; break;
+#endif
+
+ default: badarg = TRUE; break;
+ }
+ break;
}
- #endif
/* -M[x]: various operations on the following list of message ids:
-M deliver the messages, ignoring next retry times and thawing
if (( /* EITHER */
(!trusted_config || /* Config changed, or */
- !macros_trusted()) && /* impermissible macros and */
+ !macros_trusted(opt_D_used)) && /* impermissible macros and */
real_uid != root_uid && /* Not root, and */
!running_in_test_harness /* Not fudged */
) || /* OR */
"syslog_processname is longer than 32 chars: aborting");
if (log_oneline)
- {
if (admin_user)
{
log_write(0, LOG_MAIN, "%s", log_oneline);
}
else
return EXIT_FAILURE;
- }
/* In some operating systems, the environment variable TMPDIR controls where
temporary files are created; Exim doesn't use these (apart from when delivering
#ifdef EXIM_TMPDIR
{
uschar **p;
- if (environ) for (p = USS environ; *p != NULL; p++)
- {
- if (Ustrncmp(*p, "TMPDIR=", 7) == 0 &&
- Ustrcmp(*p+7, EXIM_TMPDIR) != 0)
+ if (environ) for (p = USS environ; *p; p++)
+ if (Ustrncmp(*p, "TMPDIR=", 7) == 0 && Ustrcmp(*p+7, EXIM_TMPDIR) != 0)
{
- uschar *newp = malloc(Ustrlen(EXIM_TMPDIR) + 8);
+ uschar * newp = store_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", EXIM_TMPDIR);
}
- }
}
#endif
this. We have to make a new environment if TZ is wrong, but don't bother if
timestamps_utc is set, because then all times are in UTC anyway. */
-if (timezone_string != NULL && strcmpic(timezone_string, US"UTC") == 0)
- {
+if (timezone_string && strcmpic(timezone_string, US"UTC") == 0)
timestamps_utc = TRUE;
- }
else
{
uschar *envtz = US getenv("TZ");
- if ((envtz == NULL && timezone_string != NULL) ||
- (envtz != NULL &&
- (timezone_string == NULL ||
- Ustrcmp(timezone_string, envtz) != 0)))
+ if (envtz
+ ? !timezone_string || Ustrcmp(timezone_string, envtz) != 0
+ : timezone_string != NULL
+ )
{
uschar **p = USS environ;
uschar **new;
uschar **newp;
int count = 0;
- if (environ) while (*p++ != NULL) count++;
- if (envtz == NULL) count++;
- newp = new = malloc(sizeof(uschar *) * (count + 1));
- if (environ) for (p = USS environ; *p != NULL; p++)
+ if (environ) while (*p++) count++;
+ if (!envtz) count++;
+ newp = new = store_malloc(sizeof(uschar *) * (count + 1));
+ if (environ) for (p = USS environ; *p; p++)
+ if (Ustrncmp(*p, "TZ=", 3) != 0) *newp++ = *p;
+ if (timezone_string)
{
- if (Ustrncmp(*p, "TZ=", 3) == 0) continue;
- *newp++ = *p;
- }
- if (timezone_string != NULL)
- {
- *newp = malloc(Ustrlen(timezone_string) + 4);
+ *newp = store_malloc(Ustrlen(timezone_string) + 4);
sprintf(CS *newp++, "TZ=%s", timezone_string);
}
*newp = NULL;
root for -C or -D, the caller must either be root or be invoking a
trusted configuration file (when deliver_drop_privilege is false). */
-if (removed_privilege && (!trusted_config || macros != NULL) &&
- real_uid == exim_uid)
- {
+if ( removed_privilege
+ && (!trusted_config || opt_D_used)
+ && real_uid == exim_uid)
if (deliver_drop_privilege)
really_exim = TRUE; /* let logging work normally */
else
log_write(0, LOG_MAIN|LOG_PANIC,
"exim user lost privilege for using %s option",
trusted_config? "-D" : "-C");
- }
/* Start up Perl interpreter if Perl support is configured and there is a
perl_startup option, and the configuration or the command line specifies
ignored; rejecting here would just add complication, and it can just as
well be done later. Allow $recipients to be visible in the ACL. */
- if (acl_not_smtp_start != NULL)
+ if (acl_not_smtp_start)
{
uschar *user_msg, *log_msg;
enable_dollar_recipients = TRUE;
enable_dollar_recipients = FALSE;
}
+ /* Pause for a while waiting for input. If none received in that time,
+ close the logfile, if we had one open; then if we wait for a long-running
+ datasource (months, in one use-case) log rotation will not leave us holding
+ the file copy. */
+
+ if (!receive_timeout)
+ {
+ struct timeval t = { 30*60, 0 }; /* 30 minutess */
+ fd_set r;
+
+ FD_ZERO(&r); FD_SET(0, &r);
+ if (select(1, &r, NULL, NULL, &t) == 0) mainlog_close();
+ }
+
/* Read the data for the message. If filter_test is not FTEST_NONE, this
will just read the headers for the message, and not write anything onto the
spool. */