debug tidying
[exim.git] / src / src / child.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
3386088d 5/* Copyright (c) University of Cambridge 1995 - 2015 */
059ec3d9
PH
6/* See the file NOTICE for conditions of use and distribution. */
7
8
9#include "exim.h"
10
11static void (*oldsignal)(int);
12
13
14/*************************************************
15* Ensure an fd has a given value *
16*************************************************/
17
18/* This function is called when we want to ensure that a certain fd has a
19specific value (one of 0, 1, 2). If it hasn't got it already, close the value
20we want, duplicate the fd, then close the old one.
21
22Arguments:
23 oldfd original fd
24 newfd the fd we want
25
26Returns: nothing
27*/
28
29static void
30force_fd(int oldfd, int newfd)
31{
32if (oldfd == newfd) return;
f1e894f3
PH
33(void)close(newfd);
34(void)dup2(oldfd, newfd);
35(void)close(oldfd);
059ec3d9
PH
36}
37
38
e7726cbf 39#ifndef STAND_ALONE
059ec3d9
PH
40/*************************************************
41* Build argv list and optionally re-exec Exim *
42*************************************************/
43
44/* This function is called when Exim wants to re-exec (overlay) itself in the
45current process. This is different to child_open_exim(), which runs another
46Exim process in parallel (but it then calls this function). The function's
47basic job is to build the argv list according to the values of current options
48settings. There is a basic list that all calls require, and an additional list
49that some do not require. Further additions can be given as additional
50arguments. An option specifies whether the exec() is actually to happen, and if
51so, what is to be done if it fails.
52
53Arguments:
54 exec_type CEE_RETURN_ARGV => don't exec; return the argv list
55 CEE_EXEC_EXIT => just exit() on exec failure
56 CEE_EXEC_PANIC => panic-die on exec failure
57 kill_v if TRUE, don't pass on the D_v flag
58 pcount if not NULL, points to extra size of argv required, and if
59 CEE_RETURN_ARGV is specified, it is updated to give the
60 number of slots used
61 minimal TRUE if only minimal argv is required
62 acount number of additional arguments
63 ... further values to add to argv
64
65Returns: if CEE_RETURN_ARGV is given, returns a pointer to argv;
66 otherwise, does not return
67*/
68
69uschar **
70child_exec_exim(int exec_type, BOOL kill_v, int *pcount, BOOL minimal,
71 int acount, ...)
72{
73int first_special = -1;
74int n = 0;
e37f8a84 75int extra = pcount ? *pcount : 0;
8ac90765
JH
76uschar **argv;
77
eb24befc 78argv = store_get((extra + acount + MAX_CLMACROS + 21) * sizeof(char *), FALSE);
059ec3d9
PH
79
80/* In all case, the list starts out with the path, any macros, and a changed
81config file. */
82
83argv[n++] = exim_path;
84if (clmacro_count > 0)
85 {
86 memcpy(argv + n, clmacros, clmacro_count * sizeof(uschar *));
87 n += clmacro_count;
88 }
8768d548 89if (f.config_changed)
059ec3d9
PH
90 {
91 argv[n++] = US"-C";
92 argv[n++] = config_main_filename;
93 }
94
95/* These values are added only for non-minimal cases. If debug_selector is
96precisely D_v, we have to assume this was started by a non-admin user, and
97we suppress the flag when requested. (This happens when passing on an SMTP
98connection, and after ETRN.) If there's more debugging going on, an admin user
99was involved, so we do pass it on. */
100
101if (!minimal)
102 {
103 if (debug_selector == D_v)
104 {
105 if (!kill_v) argv[n++] = US"-v";
106 }
107 else
108 {
109 if (debug_selector != 0)
110 argv[n++] = string_sprintf("-d=0x%x", debug_selector);
111 }
32393657
JH
112 DEBUG(D_any)
113 {
114 argv[n++] = US"-MCd";
115 argv[n++] = US process_purpose;
116 }
ff966302 117 if (!f.testsuite_delays) argv[n++] = US"-odd";
8768d548
JH
118 if (f.dont_deliver) argv[n++] = US"-N";
119 if (f.queue_smtp) argv[n++] = US"-odqs";
120 if (f.synchronous_delivery) argv[n++] = US"-odi";
059ec3d9
PH
121 if (connection_max_messages >= 0)
122 argv[n++] = string_sprintf("-oB%d", connection_max_messages);
e37f8a84
JH
123 if (*queue_name)
124 {
125 argv[n++] = US"-MCG";
126 argv[n++] = queue_name;
127 }
059ec3d9
PH
128 }
129
130/* Now add in any others that are in the call. Remember which they were,
131for more helpful diagnosis on failure. */
132
133if (acount > 0)
134 {
135 va_list ap;
136 va_start(ap, acount);
137 first_special = n;
138 while (acount-- > 0)
139 argv[n++] = va_arg(ap, uschar *);
140 va_end(ap);
141 }
142
143/* Terminate the list, and return it, if that is what is wanted. */
144
145argv[n] = NULL;
146if (exec_type == CEE_RETURN_ARGV)
147 {
4b01271f 148 if (pcount) *pcount = n;
059ec3d9
PH
149 return argv;
150 }
151
152/* Otherwise, do the exec() here, and handle the consequences of an unexpected
153failure. We know that there will always be at least one extra option in the
154call when exec() is done here, so it can be used to add to the panic data. */
155
55414b25 156DEBUG(D_exec) debug_print_argv(CUSS argv);
059ec3d9
PH
157exim_nullstd(); /* Make sure std{in,out,err} exist */
158execv(CS argv[0], (char *const *)argv);
159
160log_write(0,
161 LOG_MAIN | ((exec_type == CEE_EXEC_EXIT)? LOG_PANIC : LOG_PANIC_DIE),
162 "re-exec of exim (%s) with %s failed: %s", exim_path, argv[first_special],
163 strerror(errno));
164
165/* Get here if exec_type == CEE_EXEC_EXIT.
166Note: this must be _exit(), not exit(). */
167
168_exit(EX_EXECFAILED);
169
170return NULL; /* To keep compilers happy */
171}
172
173
174
175
176/*************************************************
177* Create a child Exim process *
178*************************************************/
179
180/* This function is called when Exim wants to run a parallel instance of itself
181in order to inject a message via the standard input. The function creates a
182child process and runs Exim in it. It sets up a pipe to the standard input of
183the new process, and returns that to the caller via fdptr. The function returns
184the pid of the new process, or -1 if things go wrong. If debug_fd is
185non-negative, it is passed as stderr.
186
5977a0b3
PH
187This interface is now a just wrapper for the more complicated function
188child_open_exim2(), which has additional arguments. The wrapper must continue
189to exist, even if all calls from within Exim are changed, because it is
190documented for use from local_scan().
191
059ec3d9 192Argument: fdptr pointer to int for the stdin fd
8e9fdd63 193 purpose of the child process, for debug
059ec3d9
PH
194Returns: pid of the created process or -1 if anything has gone wrong
195*/
196
197pid_t
8e9fdd63 198child_open_exim_function(int * fdptr, const uschar * purpose)
059ec3d9 199{
8e9fdd63
JH
200return child_open_exim2_function(fdptr, US"<>", bounce_sender_authentication,
201 purpose);
5977a0b3
PH
202}
203
204
205/* This is a more complicated function for creating a child Exim process, with
206more arguments.
207
208Arguments:
209 fdptr pointer to int for the stdin fd
210 sender for a sender address (data for -f)
211 sender_authentication authenticated sender address or NULL
8e9fdd63 212 purpose of the child process, for debug
5977a0b3
PH
213
214Returns: pid of the created process or -1 if anything has gone wrong
215*/
216
217pid_t
8e9fdd63
JH
218child_open_exim2_function(int * fdptr, uschar * sender,
219 uschar * sender_authentication, const uschar * purpose)
5977a0b3 220{
059ec3d9
PH
221int pfd[2];
222int save_errno;
223pid_t pid;
224
225/* Create the pipe and fork the process. Ensure that SIGCHLD is set to
226SIG_DFL before forking, so that the child process can be waited for. We
227sometimes get here with it set otherwise. Save the old state for resetting
228on the wait. */
229
230if (pipe(pfd) != 0) return (pid_t)(-1);
231oldsignal = signal(SIGCHLD, SIG_DFL);
8e9fdd63 232pid = exim_fork(purpose);
059ec3d9
PH
233
234/* Child process: make the reading end of the pipe into the standard input and
235close the writing end. If debugging, pass debug_fd as stderr. Then re-exec
4c04137d 236Exim with appropriate options. In the test harness, use -odi unless queue_only
75e0e026
PH
237is set, so that the bounce is fully delivered before returning. Failure is
238signalled with EX_EXECFAILED (specified by CEE_EXEC_EXIT), but this shouldn't
239occur. */
059ec3d9
PH
240
241if (pid == 0)
242 {
243 force_fd(pfd[pipe_read], 0);
f1e894f3 244 (void)close(pfd[pipe_write]);
059ec3d9 245 if (debug_fd > 0) force_fd(debug_fd, 2);
8768d548 246 if (f.running_in_test_harness && !queue_only)
75e0e026 247 {
96c81511 248 if (sender_authentication)
75e0e026
PH
249 child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 9,
250 US "-odi", US"-t", US"-oem", US"-oi", US"-f", sender, US"-oMas",
251 sender_authentication, message_id_option);
252 else
253 child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 7,
254 US "-odi", US"-t", US"-oem", US"-oi", US"-f", sender,
255 message_id_option);
256 /* Control does not return here. */
257 }
258 else /* Not test harness */
259 {
96c81511 260 if (sender_authentication)
75e0e026
PH
261 child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 8,
262 US"-t", US"-oem", US"-oi", US"-f", sender, US"-oMas",
263 sender_authentication, message_id_option);
264 else
265 child_exec_exim(CEE_EXEC_EXIT, FALSE, NULL, FALSE, 6,
266 US"-t", US"-oem", US"-oi", US"-f", sender, message_id_option);
267 /* Control does not return here. */
268 }
059ec3d9
PH
269 }
270
271/* Parent process. Save fork() errno and close the reading end of the stdin
272pipe. */
273
274save_errno = errno;
f1e894f3 275(void)close(pfd[pipe_read]);
059ec3d9
PH
276
277/* Fork succeeded */
278
279if (pid > 0)
280 {
281 *fdptr = pfd[pipe_write]; /* return writing end of stdin pipe */
282 return pid; /* and pid of new process */
283 }
284
285/* Fork failed */
286
f1e894f3 287(void)close(pfd[pipe_write]);
059ec3d9
PH
288errno = save_errno;
289return (pid_t)(-1);
290}
75e0e026 291#endif /* STAND_ALONE */
059ec3d9
PH
292
293
294
295/*************************************************
296* Create a non-Exim child process *
297*************************************************/
298
299/* This function creates a child process and runs the given command in it. It
300sets up pipes to the standard input and output of the new process, and returns
301them to the caller. The standard error is cloned to the output. If there are
302any file descriptors "in the way" in the new process, they are closed. A new
303umask is supplied for the process, and an optional new uid and gid are also
304available. These are used by the queryprogram router to set an unprivileged id.
b668c215
PH
305SIGUSR1 is always disabled in the new process, as it is not going to be running
306Exim (the function child_open_exim() is provided for that). This function
307returns the pid of the new process, or -1 if things go wrong.
059ec3d9
PH
308
309Arguments:
310 argv the argv for exec in the new process
311 envp the envp for exec in the new process
312 newumask umask to set in the new process
313 newuid point to uid for the new process or NULL for no change
314 newgid point to gid for the new process or NULL for no change
315 infdptr pointer to int into which the fd of the stdin of the new process
316 is placed
317 outfdptr pointer to int into which the fd of the stdout/stderr of the new
318 process is placed
319 wd if not NULL, a path to be handed to chdir() in the new process
320 make_leader if TRUE, make the new process a process group leader
eb24befc 321 purpose for debug: reason for running the task
8e669ac1 322
059ec3d9
PH
323Returns: the pid of the created process or -1 if anything has gone wrong
324*/
325
326pid_t
55414b25
JH
327child_open_uid(const uschar **argv, const uschar **envp, int newumask,
328 uid_t *newuid, gid_t *newgid, int *infdptr, int *outfdptr, uschar *wd,
eb24befc 329 BOOL make_leader, const uschar * purpose)
059ec3d9
PH
330{
331int save_errno;
332int inpfd[2], outpfd[2];
333pid_t pid;
334
335/* Create the pipes. */
336
337if (pipe(inpfd) != 0) return (pid_t)(-1);
338if (pipe(outpfd) != 0)
339 {
f1e894f3
PH
340 (void)close(inpfd[pipe_read]);
341 (void)close(inpfd[pipe_write]);
059ec3d9
PH
342 return (pid_t)(-1);
343 }
344
345/* Fork the process. Ensure that SIGCHLD is set to SIG_DFL before forking, so
346that the child process can be waited for. We sometimes get here with it set
347otherwise. Save the old state for resetting on the wait. */
348
349oldsignal = signal(SIGCHLD, SIG_DFL);
eb24befc 350pid = exim_fork(purpose);
059ec3d9 351
59e82a2a
PH
352/* Handle the child process. First, set the required environment. We must do
353this before messing with the pipes, in order to be able to write debugging
354output when things go wrong. */
059ec3d9
PH
355
356if (pid == 0)
357 {
59e82a2a 358 signal(SIGUSR1, SIG_IGN);
605021fc 359 signal(SIGPIPE, SIG_DFL);
59e82a2a 360
96c81511 361 if (newgid && setgid(*newgid) < 0)
59e82a2a
PH
362 {
363 DEBUG(D_any) debug_printf("failed to set gid=%ld in subprocess: %s\n",
364 (long int)(*newgid), strerror(errno));
365 goto CHILD_FAILED;
366 }
367
96c81511 368 if (newuid && setuid(*newuid) < 0)
59e82a2a
PH
369 {
370 DEBUG(D_any) debug_printf("failed to set uid=%ld in subprocess: %s\n",
371 (long int)(*newuid), strerror(errno));
372 goto CHILD_FAILED;
373 }
374
375 (void)umask(newumask);
376
96c81511 377 if (wd && Uchdir(wd) < 0)
59e82a2a
PH
378 {
379 DEBUG(D_any) debug_printf("failed to chdir to %s: %s\n", wd,
380 strerror(errno));
381 goto CHILD_FAILED;
382 }
383
384 /* Becomes a process group leader if requested, and then organize the pipes.
385 Any unexpected failure is signalled with EX_EXECFAILED; these are all "should
386 never occur" failures, except for exec failing because the command doesn't
387 exist. */
388
389 if (make_leader && setpgid(0,0) < 0)
390 {
391 DEBUG(D_any) debug_printf("failed to set group leader in subprocess: %s\n",
392 strerror(errno));
393 goto CHILD_FAILED;
394 }
059ec3d9 395
f1e894f3 396 (void)close(inpfd[pipe_write]);
059ec3d9
PH
397 force_fd(inpfd[pipe_read], 0);
398
f1e894f3 399 (void)close(outpfd[pipe_read]);
059ec3d9
PH
400 force_fd(outpfd[pipe_write], 1);
401
f1e894f3
PH
402 (void)close(2);
403 (void)dup2(1, 2);
059ec3d9 404
059ec3d9
PH
405 /* Now do the exec */
406
96c81511
JH
407 if (envp) execve(CS argv[0], (char *const *)argv, (char *const *)envp);
408 else execv(CS argv[0], (char *const *)argv);
059ec3d9
PH
409
410 /* Failed to execv. Signal this failure using EX_EXECFAILED. We are
411 losing the actual errno we got back, because there is no way to return
59e82a2a 412 this information. */
059ec3d9
PH
413
414 CHILD_FAILED:
415 _exit(EX_EXECFAILED); /* Note: must be _exit(), NOT exit() */
416 }
417
418/* Parent process. Save any fork failure code, and close the reading end of the
419stdin pipe, and the writing end of the stdout pipe. */
420
421save_errno = errno;
f1e894f3
PH
422(void)close(inpfd[pipe_read]);
423(void)close(outpfd[pipe_write]);
059ec3d9
PH
424
425/* Fork succeeded; return the input/output pipes and the pid */
426
427if (pid > 0)
428 {
429 *infdptr = inpfd[pipe_write];
430 *outfdptr = outpfd[pipe_read];
431 return pid;
432 }
433
434/* Fork failed; reset fork errno before returning */
435
f1e894f3
PH
436(void)close(inpfd[pipe_write]);
437(void)close(outpfd[pipe_read]);
059ec3d9
PH
438errno = save_errno;
439return (pid_t)(-1);
440}
441
442
443
444
445/*************************************************
446* Create child process without uid change *
447*************************************************/
448
449/* This function is a wrapper for child_open_uid() that doesn't have the uid,
b668c215
PH
450gid and working directory changing arguments. The function is provided so as to
451have a clean interface for use from local_scan(), but also saves writing NULL
452arguments several calls that would otherwise use child_open_uid().
059ec3d9
PH
453
454Arguments:
455 argv the argv for exec in the new process
456 envp the envp for exec in the new process
457 newumask umask to set in the new process
458 infdptr pointer to int into which the fd of the stdin of the new process
459 is placed
460 outfdptr pointer to int into which the fd of the stdout/stderr of the new
461 process is placed
462 make_leader if TRUE, make the new process a process group leader
eb24befc 463 purpose for debug: reason for running the task
059ec3d9
PH
464
465Returns: the pid of the created process or -1 if anything has gone wrong
466*/
467
468pid_t
eb24befc
JH
469child_open_function(uschar **argv, uschar **envp, int newumask, int *infdptr,
470 int *outfdptr, BOOL make_leader, const uschar * purpose)
059ec3d9 471{
55414b25 472return child_open_uid(CUSS argv, CUSS envp, newumask, NULL, NULL,
eb24befc 473 infdptr, outfdptr, NULL, make_leader, purpose);
059ec3d9
PH
474}
475
476
477
478
479/*************************************************
480* Close down child process *
481*************************************************/
482
483/* Wait for the given process to finish, with optional timeout.
484
485Arguments
486 pid: the pid to wait for
487 timeout: maximum time to wait; 0 means for as long as it takes
488
489Returns: >= 0 process terminated by exiting; value is process
490 ending status; if an execve() failed, the value
491 is typically 127 (defined as EX_EXECFAILED)
492 < 0 & > -256 process was terminated by a signal; value is the
493 negation of the signal number
494 -256 timed out
495 -257 other error in wait(); errno still set
496*/
497
498int
499child_close(pid_t pid, int timeout)
500{
501int yield;
502
503if (timeout > 0)
504 {
505 sigalrm_seen = FALSE;
c2a1bba0 506 ALARM(timeout);
059ec3d9
PH
507 }
508
509for(;;)
510 {
511 int status;
512 pid_t rc = waitpid(pid, &status, 0);
513 if (rc == pid)
514 {
515 int lowbyte = status & 255;
d7625a4d 516 yield = lowbyte == 0 ? (status >> 8) & 255 : -lowbyte;
059ec3d9
PH
517 break;
518 }
519 if (rc < 0)
520 {
d7625a4d
JH
521 /* This "shouldn't happen" test does happen on MacOS: for some reason
522 I do not understand we seems to get an alarm signal despite not having
523 an active alarm set. There seems to be only one, so just go round again. */
524
525 if (errno == EINTR && sigalrm_seen && timeout <= 0) continue;
526
527 yield = (errno == EINTR && sigalrm_seen) ? -256 : -257;
059ec3d9
PH
528 break;
529 }
530 }
531
c2a1bba0 532if (timeout > 0) ALARM_CLR(0);
059ec3d9
PH
533
534signal(SIGCHLD, oldsignal); /* restore */
535return yield;
536}
537
538/* End of child.c */