documented for use from local_scan().
Argument: fdptr pointer to int for the stdin fd
+ purpose of the child process, for debug
Returns: pid of the created process or -1 if anything has gone wrong
*/
pid_t
-child_open_exim(int *fdptr)
+child_open_exim_function(int * fdptr, const uschar * purpose)
{
-return child_open_exim2(fdptr, US"<>", bounce_sender_authentication);
+return child_open_exim2_function(fdptr, US"<>", bounce_sender_authentication,
+ purpose);
}
fdptr pointer to int for the stdin fd
sender for a sender address (data for -f)
sender_authentication authenticated sender address or NULL
+ purpose of the child process, for debug
Returns: pid of the created process or -1 if anything has gone wrong
*/
pid_t
-child_open_exim2(int *fdptr, uschar *sender, uschar *sender_authentication)
+child_open_exim2_function(int * fdptr, uschar * sender,
+ uschar * sender_authentication, const uschar * purpose)
{
int pfd[2];
int save_errno;
if (pipe(pfd) != 0) return (pid_t)(-1);
oldsignal = signal(SIGCHLD, SIG_DFL);
-pid = fork();
+pid = exim_fork(purpose);
/* Child process: make the reading end of the pipe into the standard input and
close the writing end. If debugging, pass debug_fd as stderr. Then re-exec
otherwise. Save the old state for resetting on the wait. */
oldsignal = signal(SIGCHLD, SIG_DFL);
-pid = fork();
+pid = exim_fork(US"queryprogram"); /* queryprogram tpt is sole caller */
/* Handle the child process. First, set the required environment. We must do
this before messing with the pipes, in order to be able to write debugging
expansion above did a lookup. */
search_tidyup();
-pid = fork();
+pid = exim_fork(US"daemon accept");
/* Handle the child process */
mac_smtp_fflush();
- if ((dpid = fork()) == 0)
+ if ((dpid = exim_fork(US"daemon-accept delivery")) == 0)
{
(void)fclose(smtp_in);
(void)fclose(smtp_out);
if (f.running_in_test_harness || write_pid)
{
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"daemon del pidfile")) == 0)
{
if (override_pid_file_path)
(void)child_exec_exim(CEE_EXEC_PANIC, FALSE, NULL, FALSE, 3,
if (getppid() != 1)
{
- pid_t pid = fork();
+ pid_t pid = exim_fork(US"daemon");
if (pid < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE,
"fork() failed when starting daemon: %s", strerror(errno));
if (pid > 0) exit(EXIT_SUCCESS); /* in parent process, just exit */
if (queue_interval > 0 &&
(local_queue_run_max <= 0 || queue_run_count < local_queue_run_max))
{
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"queue runner")) == 0)
{
DEBUG(D_any) debug_printf("Starting queue-runner: pid %d\n",
(int)getpid());
search_tidyup();
-if ((pid = fork()) == 0)
+if ((pid = exim_fork(US"delivery (local)")) == 0)
{
BOOL replicate = TRUE;
"message for %s transport): %s", addr->transport->warn_message,
addr->transport->name, expand_string_message);
- else if ((pid = child_open_exim(&fd)) > 0)
+ else if ((pid = child_open_exim(&fd, US"warning message")) > 0)
{
FILE *f = fdopen(fd, "wb");
if (errors_reply_to && !contains_header(US"Reply-To", warn_message))
search_tidyup();
DEBUG(D_deliver) debug_printf("forking transport process\n");
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"transport")) == 0)
{
int fd = pfd[pipe_write];
host_item *h;
int fd;
/* create exim process to send message */
- pid = child_open_exim(&fd);
+ pid = child_open_exim(&fd, US"DSN");
DEBUG(D_deliver) debug_printf("DSN: child_open_exim returns: %d\n", pid);
/* Make a subprocess to send a message */
- if ((pid = child_open_exim(&fd)) < 0)
+ if ((pid = child_open_exim(&fd, US"bounce message")) < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "Process %d (parent %d) failed to "
"create child process to send failure message: %s", getpid(),
getppid(), strerror(errno));
{
header_line *h;
int fd;
- pid_t pid = child_open_exim(&fd);
+ pid_t pid = child_open_exim(&fd, US"delay-warning message");
if (pid > 0)
{
goto fail;
where = US"fork";
- if ((pid = fork()) < 0)
+ if ((pid = exim_fork(US"tls-proxy interproc")) < 0)
goto fail;
else if (pid == 0) /* child: fork again to totally disconnect */
pid_t pid;
if (i == argc - 1)
(void)deliver_message(argv[i], forced_delivery, deliver_give_up);
- else if ((pid = fork()) == 0)
+ 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");
pid_t pid;
search_tidyup();
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"local-accept delivery")) == 0)
{
int rc;
close_unwanted(); /* Close unwanted file descriptors and TLS */
extern void cancel_cutthrough_connection(BOOL, const uschar *);
extern int check_host(void *, const uschar *, const uschar **, uschar **);
extern uschar **child_exec_exim(int, BOOL, int *, BOOL, int, ...);
+extern pid_t child_open_exim_function(int *, const uschar *);
+extern pid_t child_open_exim2_function(int *, uschar *, uschar *,
+ const uschar *);
extern pid_t child_open_uid(const uschar **, const uschar **, int,
uid_t *, gid_t *, int *, int *, uschar *, BOOL);
extern BOOL cleanup_environment(void);
return NULL;
}
+/******************************************************************************/
+/* Process manipulation */
+
+static inline pid_t
+exim_fork(const unsigned char * purpose)
+{
+pid_t pid = fork();
+if (pid == 0) process_purpose = purpose;
+return pid;
+}
+
+#define child_open_exim(p, r) child_open_exim_function((p), (r))
+#define child_open_exim2(p, s, a, r) child_open_exim2_function((p), (s), (a), (r))
+
+/******************************************************************************/
#endif /* !MACRO_PREDEF */
#endif /* _FUNCTIONS_H_ */
uschar *process_info;
int process_info_len = 0;
uschar *process_log_path = NULL;
+const uschar *process_purpose = US"fresh exec";
#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
uschar *hosts_proxy = NULL;
extern uschar *process_info; /* For SIGUSR1 output */
extern int process_info_len;
extern uschar *process_log_path; /* Alternate path */
+extern const uschar *process_purpose; /* for debug output */
extern BOOL prod_requires_admin; /* TRUE if prodding requires admin */
#if defined(SUPPORT_PROXY) || defined(SUPPORT_SOCKS)
#include "store.h"
+/* Some people (Marc Merlin et al) are maintaining a patch that allows for
+dynamic local_scan() libraries. This code is not yet in Exim proper, but it
+helps the maintainers if we keep their ABI version numbers here. This may
+mutate into more general support later. The major number is increased when the
+ABI is changed in a non backward compatible way. The minor number is increased
+each time a new feature is added (in a way that doesn't break backward
+compatibility). */
+
+#define LOCAL_SCAN_ABI_VERSION_MAJOR 4
+#define LOCAL_SCAN_ABI_VERSION_MINOR 1
+#define LOCAL_SCAN_ABI_VERSION \
+ LOCAL_SCAN_ABI_VERSION_MAJOR.LOCAL_SCAN_ABI_VERSION_MINOR
+
+
+
/* The function and its return codes. */
extern int local_scan(int, uschar **);
#define SPOOL_DATA_START_OFFSET (MESSAGE_ID_LENGTH+3)
-/* Some people (Marc Merlin et al) are maintaining a patch that allows for
-dynamic local_scan() libraries. This code is not yet in Exim proper, but it
-helps the maintainers if we keep their ABI version numbers here. This may
-mutate into more general support later. The major number is increased when the
-ABI is changed in a non backward compatible way. The minor number is increased
-each time a new feature is added (in a way that doesn't break backward
-compatibility). */
-
-#define LOCAL_SCAN_ABI_VERSION_MAJOR 4
-#define LOCAL_SCAN_ABI_VERSION_MINOR 0
-#define LOCAL_SCAN_ABI_VERSION \
- LOCAL_SCAN_ABI_VERSION_MAJOR.LOCAL_SCAN_ABI_VERSION_MINOR
-
/* Structure definitions that are documented as visible in the function. */
typedef struct header_line {
extern int child_close(pid_t, int);
extern pid_t child_open(uschar **, uschar **, int, int *, int *, BOOL);
-extern pid_t child_open_exim(int *);
-extern pid_t child_open_exim2(int *, uschar *, uschar *);
extern void debug_printf(const char *, ...) PRINTF_FUNCTION(1,2);
extern uschar *expand_string(uschar *);
extern void header_add(int, const char *, ...);
# define string_copy(s) string_copy_function(s)
# define string_copyn(s, n) string_copyn_function((s), (n))
# define string_copy_taint(s, t) string_copy_taint_function((s), (t))
+# define child_open_exim(p) child_open_exim_function((p), US"from local_scan")
+# define child_open_exim2(p, s, a) child_open_exim2_function((p), (s), (a), US"from local_scan")
extern uschar * string_copy_function(const uschar *);
extern uschar * string_copyn_function(const uschar *, int n);
extern uschar * string_copy_taint_function(const uschar *, BOOL tainted);
+extern pid_t child_open_exim_function(int *, const uschar *);
+extern pid_t child_open_exim2_function(int *, uschar *, uschar *, const uschar *);
#endif
/* End of local_scan.h */
int
log_create_as_exim(uschar *name)
{
-pid_t pid = fork();
+pid_t pid = exim_fork(US"logfile create");
int status = 1;
int fd = -1;
&& (s2 = expand_string(string_sprintf("${address:%s}", s)))
&& *s2
)
- pid = child_open_exim2(&fd, s2, bounce_sender_authentication);
+ pid = child_open_exim2(&fd, s2, bounce_sender_authentication,
+ US"moan_send_message");
else
{
s = NULL;
- pid = child_open_exim(&fd);
+ pid = child_open_exim(&fd, US"moan_send_message");
}
#else
-pid = child_open_exim(&fd);
+pid = child_open_exim(&fd, US"moan_send_message");
#endif
if (pid < 0)
FILE *f;
va_list ap;
int fd;
-int pid = child_open_exim(&fd);
+int pid = child_open_exim(&fd, US"moan_tell_someone");
if (pid < 0)
{
/* If we can't create a process to send the message, just forget about
it. */
-pid = child_open_exim(&fd);
+pid = child_open_exim(&fd, US"moan_skipped_syntax_errors");
if (pid < 0)
{
else
for (i = 0; qpid[i]; ) i++;
DEBUG(D_queue_run) debug_printf("q2stage forking\n");
- if ((qpid[i] = fork()))
+ if ((qpid[i] = exim_fork(US"qrun phase one")))
continue; /* parent loops around */
DEBUG(D_queue_run) debug_printf("q2stage child\n");
}
#endif
single_item_retry:
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"qrun delivery")) == 0)
{
int rc;
testharness_pause_ms(100);
oldsignal = signal(SIGCHLD, SIG_DFL);
search_tidyup();
-if ((pid = fork()) == 0)
+if ((pid = exim_fork(US"router interpret")) == 0)
{
header_line *waslast = header_last; /* Save last header */
otherwise. Save the old state for resetting on the wait. */
oldsignal = signal(SIGCHLD, SIG_DFL);
- pid = fork();
+ pid = exim_fork(US"require-files");
/* If fork() fails, reinstate the original error and behave as if
this block of code were not present. This is the same behaviour as happens
{
int pid, fd;
- if ((pid = child_open_exim2(&fd,envelope_from,envelope_from))>=1)
+ if ((pid = child_open_exim2(&fd, envelope_from, envelope_from,
+ US"sieve-notify")) >= 1)
{
FILE *f;
uschar *buffer;
f = fdopen(fd, "wb");
fprintf(f,"From: %s\n", from.length == -1
- ? expand_string(US"$local_part_prefix$local_part$local_part_suffix@$domain") : from.character);
+ ? expand_string(US"$local_part_prefix$local_part$local_part_suffix@$domain")
+ : from.character);
for (string_item * p = recipient; p; p=p->next)
fprintf(f,"To: %s\n",p->text);
fprintf(f,"Auto-Submitted: auto-notified; %s\n",filter->enotify_mailto_owner);
message.length=Ustrlen(message.character);
}
/* Allocation is larger than necessary, but enough even for split MIME words */
- buffer_capacity=32+4*message.length;
+ buffer_capacity = 32 + 4*message.length;
buffer=store_get(buffer_capacity, TRUE);
- if (message.length!=-1) fprintf(f,"Subject: %s\n",parse_quote_2047(message.character, message.length, US"utf-8", buffer, buffer_capacity, TRUE));
+ if (message.length != -1)
+ fprintf(f, "Subject: %s\n", parse_quote_2047(message.character,
+ message.length, US"utf-8", buffer, buffer_capacity, TRUE));
fprintf(f,"\n");
if (body.length>0) fprintf(f,"%s\n",body.character);
fflush(f);
(void)child_close(pid, 0);
}
}
- if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0)
- {
+ if ((filter_test != FTEST_NONE && debug_selector != 0) || debug_selector & D_filter)
debug_printf("Notification to `%s': '%s'.\n",method.character,message.length!=-1 ? message.character : CUS "");
- }
#endif
}
else
- {
- if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0)
- {
+ if ((filter_test != FTEST_NONE && debug_selector != 0) || debug_selector & D_filter)
debug_printf("Repeated notification to `%s' ignored.\n",method.character);
- }
- }
}
else
- {
- if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0)
- {
+ if ((filter_test != FTEST_NONE && debug_selector != 0) || debug_selector & D_filter)
debug_printf("Ignoring notification, triggering message contains Auto-submitted: field.\n");
- }
- }
}
}
#endif
oldsignal = signal(SIGCHLD, SIG_IGN);
- if ((pid = fork()) == 0)
+ if ((pid = exim_fork(US"etrn command")) == 0)
{
smtp_input = FALSE; /* This process is not associated with the */
(void)fclose(smtp_in); /* SMTP call any more. */
/* If not serializing, do the exec right away. Otherwise, fork down
into another process. */
- if (!smtp_etrn_serialize || (pid = fork()) == 0)
+ if ( !smtp_etrn_serialize
+ || (pid = exim_fork(US"etrn serialised command")) == 0)
{
DEBUG(D_exec) debug_print_argv(argv);
exim_nullstd(); /* Ensure std{in,out,err} exist */
oldsignal = signal(SIGCHLD, SIG_DFL);
fflush(NULL);
-if ((pid = fork()) < 0)
+if ((pid = exim_fork(US"cipher validate")) < 0)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork failed for TLS check");
if (pid == 0)
smtp dots, or check string processing. */
if (pipe(pfd) != 0) goto TIDY_UP; /* errno set */
-if ((write_pid = fork()) == 0)
+if ((write_pid = exim_fork(US"transport filter")) == 0)
{
BOOL rc;
(void)close(fd_read);
DEBUG(D_transport) debug_printf("transport_pass_socket entered\n");
-if ((pid = fork()) == 0)
+if ((pid = exim_fork(US"continued-transport interproc")) == 0)
{
/* Disconnect entirely from the parent process. If we are running in the
test harness, wait for a bit to allow the previous process time to finish,
write the log, etc., so that the output is always in the same order for
automatic comparison. */
- if ((pid = fork()) != 0)
+ if ((pid = exim_fork(US"continued-transport")) != 0)
{
DEBUG(D_transport) debug_printf("transport_pass_socket succeeded (final-pid %d)\n", pid);
_exit(EXIT_SUCCESS);
/* Make a subprocess to send the message */
-pid = child_open_exim(&fd);
-
-/* Creation of child failed; defer this delivery. */
-
-if (pid < 0)
+if ((pid = child_open_exim(&fd, US"autoreply")) < 0)
{
+ /* Creation of child failed; defer this delivery. */
+
addr->transport_return = DEFER;
addr->basic_errno = errno;
addr->message = string_sprintf("Failed to create child process to send "
/* Now fork a process to handle the output that comes down the pipe. */
-if ((outpid = fork()) < 0)
+if ((outpid = exim_fork(US"pipe-transport output")) < 0)
{
addr->basic_errno = errno;
addr->transport_return = DEFER;
int rc, i;
close(pfd[1]);
-if ((rc = fork()))
+if ((rc = exim_fork(US"tls proxy")))
{
DEBUG(D_transport) debug_printf("proxy-proc final-pid %d\n", rc);
_exit(rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
#ifndef DISABLE_TLS
if (tls_out.active.sock >= 0)
{
- int pid = fork();
+ int pid = exim_fork(US"tls proxy interproc");
if (pid == 0) /* child; fork again to disconnect totally */
{
testharness_pause_ms(100); /* let parent debug out */