debian experimental exim-daemon-heavy config
[exim.git] / src / src / functions.h
... / ...
CommitLineData
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
5/* Copyright (c) University of Cambridge 1995 - 2018 */
6/* Copyright (c) The Exim Maintainers 2020 */
7/* See the file NOTICE for conditions of use and distribution. */
8
9
10/* Prototypes for functions that appear in various modules. Gathered together
11to avoid having a lot of tiddly little headers with only a couple of lines in
12them. However, some functions that are used (or not used) by utility programs
13are in in fact in separate headers. */
14#ifndef _FUNCTIONS_H_
15#define _FUNCTIONS_H_
16
17#include <ctype.h>
18#include <sys/time.h>
19
20
21#ifdef EXIM_PERL
22extern gstring *call_perl_cat(gstring *, uschar **, uschar *,
23 uschar **) WARN_UNUSED_RESULT;
24extern void cleanup_perl(void);
25extern uschar *init_perl(uschar *);
26#endif
27
28
29#ifndef DISABLE_TLS
30extern const char *
31 std_dh_prime_default(void);
32extern const char *
33 std_dh_prime_named(const uschar *);
34
35extern uschar * tls_cert_crl_uri(void *, uschar * mod);
36extern uschar * tls_cert_ext_by_oid(void *, uschar *, int);
37extern uschar * tls_cert_issuer(void *, uschar * mod);
38extern uschar * tls_cert_not_before(void *, uschar * mod);
39extern uschar * tls_cert_not_after(void *, uschar * mod);
40extern uschar * tls_cert_ocsp_uri(void *, uschar * mod);
41extern uschar * tls_cert_serial_number(void *, uschar * mod);
42extern uschar * tls_cert_signature(void *, uschar * mod);
43extern uschar * tls_cert_signature_algorithm(void *, uschar * mod);
44extern uschar * tls_cert_subject(void *, uschar * mod);
45extern uschar * tls_cert_subject_altname(void *, uschar * mod);
46extern uschar * tls_cert_version(void *, uschar * mod);
47
48extern uschar * tls_cert_der_b64(void * cert);
49extern uschar * tls_cert_fprt_md5(void *);
50extern uschar * tls_cert_fprt_sha1(void *);
51extern uschar * tls_cert_fprt_sha256(void *);
52
53extern void tls_clean_env(void);
54extern BOOL tls_client_start(client_conn_ctx *, smtp_connect_args *,
55 void *, tls_support *, uschar **);
56
57extern void tls_close(void *, int);
58extern BOOL tls_could_read(void);
59extern void tls_daemon_init(void);
60extern BOOL tls_dropprivs_validate_require_cipher(BOOL);
61extern BOOL tls_export_cert(uschar *, size_t, void *);
62extern int tls_feof(void);
63extern int tls_ferror(void);
64extern void tls_free_cert(void **);
65extern int tls_getc(unsigned);
66extern uschar *tls_getbuf(unsigned *);
67extern void tls_get_cache(void);
68extern BOOL tls_import_cert(const uschar *, void **);
69extern int tls_read(void *, uschar *, size_t);
70extern int tls_server_start(const uschar *, uschar **);
71extern BOOL tls_smtp_buffered(void);
72extern int tls_ungetc(int);
73extern int tls_write(void *, const uschar *, size_t, BOOL);
74extern uschar *tls_validate_require_cipher(void);
75extern void tls_version_report(FILE *);
76# ifdef USE_OPENSSL
77extern BOOL tls_openssl_options_parse(uschar *, long *);
78# endif
79extern uschar * tls_field_from_dn(uschar *, const uschar *);
80extern BOOL tls_is_name_for_cert(const uschar *, void *);
81
82# ifdef SUPPORT_DANE
83extern int tlsa_lookup(const host_item *, dns_answer *, BOOL);
84# endif
85
86#endif /*DISABLE_TLS*/
87
88
89/* Everything else... */
90
91extern acl_block *acl_read(uschar *(*)(void), uschar **);
92extern int acl_check(int, uschar *, uschar *, uschar **, uschar **);
93extern int acl_eval(int, uschar *, uschar **, uschar **);
94
95extern tree_node *acl_var_create(uschar *);
96extern void acl_var_write(uschar *, uschar *, void *);
97
98#ifdef EXPERIMENTAL_ARC
99extern void *arc_ams_setup_sign_bodyhash(void);
100extern const uschar *arc_header_feed(gstring *, BOOL);
101extern gstring *arc_sign(const uschar *, gstring *, uschar **);
102extern void arc_sign_init(void);
103extern const uschar *acl_verify_arc(void);
104extern uschar * fn_arc_domains(void);
105#endif
106
107extern void assert_no_variables(void *, int, const char *, int);
108extern int auth_call_pam(const uschar *, uschar **);
109extern int auth_call_pwcheck(uschar *, uschar **);
110extern int auth_call_radius(const uschar *, uschar **);
111extern int auth_call_saslauthd(const uschar *, const uschar *,
112 const uschar *, const uschar *, uschar **);
113extern int auth_check_serv_cond(auth_instance *);
114extern int auth_check_some_cond(auth_instance *, uschar *, uschar *, int);
115extern int auth_client_item(void *, auth_instance *, const uschar **,
116 unsigned, int, uschar *, int);
117
118
119extern int auth_get_data(uschar **, const uschar *, int);
120extern int auth_get_no64_data(uschar **, uschar *);
121extern int auth_prompt(const uschar *);
122extern int auth_read_input(const uschar *);
123extern gstring * auth_show_supported(gstring *);
124extern uschar *auth_xtextencode(uschar *, int);
125extern int auth_xtextdecode(uschar *, uschar **);
126
127#ifdef EXPERIMENTAL_ARC
128extern gstring *authres_arc(gstring *);
129#endif
130#ifndef DISABLE_DKIM
131extern gstring *authres_dkim(gstring *);
132#endif
133#ifdef SUPPORT_DMARC
134extern gstring *authres_dmarc(gstring *);
135#endif
136extern gstring *authres_smtpauth(gstring *);
137#ifdef SUPPORT_SPF
138extern gstring *authres_spf(gstring *);
139#endif
140
141extern uschar *b64encode(const uschar *, int);
142extern uschar *b64encode_taint(const uschar *, int, BOOL);
143extern int b64decode(const uschar *, uschar **);
144extern int bdat_getc(unsigned);
145extern uschar *bdat_getbuf(unsigned *);
146extern int bdat_ungetc(int);
147extern void bdat_flush_data(void);
148
149extern void bits_clear(unsigned int *, size_t, int *);
150extern void bits_set(unsigned int *, size_t, int *);
151
152extern void cancel_cutthrough_connection(BOOL, const uschar *);
153extern gstring *cat_file(FILE *, gstring *, uschar *);
154extern gstring *cat_file_tls(void *, gstring *, uschar *);
155extern int check_host(void *, const uschar *, const uschar **, uschar **);
156extern uschar **child_exec_exim(int, BOOL, int *, BOOL, int, ...);
157extern pid_t child_open_exim_function(int *, const uschar *);
158extern pid_t child_open_exim2_function(int *, uschar *, uschar *,
159 const uschar *);
160extern pid_t child_open_function(uschar **, uschar **, int,
161 int *, int *, BOOL, const uschar *);
162extern pid_t child_open_uid(const uschar **, const uschar **, int,
163 uid_t *, gid_t *, int *, int *, uschar *, BOOL, const uschar *);
164extern BOOL cleanup_environment(void);
165extern void cutthrough_data_puts(uschar *, int);
166extern void cutthrough_data_put_nl(void);
167extern uschar *cutthrough_finaldot(void);
168extern BOOL cutthrough_flush_send(void);
169extern BOOL cutthrough_headers_send(void);
170extern BOOL cutthrough_predata(void);
171extern void release_cutthrough_connection(const uschar *);
172
173extern void daemon_go(void);
174
175#ifdef EXPERIMENTAL_DCC
176extern int dcc_process(uschar **);
177#endif
178
179extern void debug_logging_activate(uschar *, uschar *);
180extern void debug_logging_stop(void);
181extern void debug_print_argv(const uschar **);
182extern void debug_print_ids(uschar *);
183extern void debug_printf_indent(const char *, ...) PRINTF_FUNCTION(1,2);
184extern void debug_print_string(uschar *);
185extern void debug_print_tree(tree_node *);
186extern void debug_vprintf(int, const char *, va_list);
187extern void debug_print_socket(int);
188
189extern void decode_bits(unsigned int *, size_t, int *,
190 uschar *, bit_table *, int, uschar *, int);
191extern void delete_pid_file(void);
192extern address_item *deliver_make_addr(uschar *, BOOL);
193extern void delivery_log(int, address_item *, int, uschar *);
194extern int deliver_message(uschar *, BOOL, BOOL);
195extern void deliver_msglog(const char *, ...) PRINTF_FUNCTION(1,2);
196extern void deliver_set_expansions(address_item *);
197extern int deliver_split_address(address_item *);
198extern void deliver_succeeded(address_item *);
199
200extern uschar *deliver_get_sender_address (uschar *id);
201extern void delivery_re_exec(int);
202
203extern void die_tainted(const uschar *, const uschar *, int);
204extern BOOL directory_make(const uschar *, const uschar *, int, BOOL);
205#ifndef DISABLE_DKIM
206extern uschar *dkim_exim_query_dns_txt(const uschar *);
207extern void dkim_exim_sign_init(void);
208
209extern BOOL dkim_transport_write_message(transport_ctx *,
210 struct ob_dkim *, const uschar ** errstr);
211#endif
212extern dns_address *dns_address_from_rr(dns_answer *, dns_record *);
213extern int dns_basic_lookup(dns_answer *, const uschar *, int);
214extern uschar *dns_build_reverse(const uschar *);
215extern time_t dns_expire_from_soa(dns_answer *, int);
216extern void dns_init(BOOL, BOOL, BOOL);
217extern BOOL dns_is_aa(const dns_answer *);
218extern BOOL dns_is_secure(const dns_answer *);
219extern int dns_lookup(dns_answer *, const uschar *, int, const uschar **);
220extern void dns_pattern_init(void);
221extern int dns_special_lookup(dns_answer *, const uschar *, int, const uschar **);
222extern dns_record *dns_next_rr(const dns_answer *, dns_scan *, int);
223extern uschar *dns_text_type(int);
224extern void dscp_list_to_stream(FILE *);
225extern BOOL dscp_lookup(const uschar *, int, int *, int *, int *);
226
227extern void enq_end(uschar *);
228extern BOOL enq_start(uschar *, unsigned);
229#ifndef DISABLE_EVENT
230extern uschar *event_raise(uschar *, const uschar *, uschar *);
231extern void msg_event_raise(const uschar *, const address_item *);
232#endif
233
234extern int exim_chown_failure(int, const uschar*, uid_t, gid_t);
235extern const uschar * exim_errstr(int);
236extern void exim_exit(int) NORETURN;
237extern void exim_nullstd(void);
238extern void exim_setugid(uid_t, gid_t, BOOL, uschar *);
239extern void exim_underbar_exit(int) NORETURN;
240extern void exim_wait_tick(struct timeval *, int);
241extern int exp_bool(address_item *addr,
242 uschar *mtype, uschar *mname, unsigned dgb_opt, uschar *oname, BOOL bvalue,
243 uschar *svalue, BOOL *rvalue);
244extern BOOL expand_check_condition(uschar *, uschar *, uschar *);
245extern uschar *expand_file_big_buffer(const uschar *);
246extern uschar *expand_string(uschar *); /* public, cannot make const */
247extern const uschar *expand_cstring(const uschar *); /* ... so use this one */
248extern uschar *expand_getkeyed(const uschar *, const uschar *);
249
250extern uschar *expand_hide_passwords(uschar * );
251extern uschar *expand_string_copy(const uschar *);
252extern int_eximarith_t expand_string_integer(uschar *, BOOL);
253extern void modify_variable(uschar *, void *);
254
255extern BOOL fd_ready(int, time_t);
256
257extern int filter_interpret(uschar *, int, address_item **, uschar **);
258extern BOOL filter_personal(string_item *, BOOL);
259extern BOOL filter_runtest(int, uschar *, BOOL, BOOL);
260extern BOOL filter_system_interpret(address_item **, uschar **);
261
262extern uschar * fn_hdrs_added(void);
263
264extern void header_add(int, const char *, ...);
265extern header_line *header_add_at_position_internal(BOOL, uschar *, BOOL, int, const char *, ...);
266extern int header_checkname(header_line *, BOOL);
267extern BOOL header_match(uschar *, BOOL, BOOL, string_item *, int, ...);
268extern int host_address_extract_port(uschar *);
269extern uschar *host_and_ident(BOOL);
270extern int host_aton(const uschar *, int *);
271extern void host_build_hostlist(host_item **, const uschar *, BOOL);
272extern ip_address_item *host_build_ifacelist(const uschar *, uschar *);
273extern void host_build_log_info(void);
274extern void host_build_sender_fullhost(void);
275extern int host_find_byname(host_item *, const uschar *, int,
276 const uschar **, BOOL);
277extern int host_find_bydns(host_item *, const uschar *, int, uschar *, uschar *,
278 uschar *, const dnssec_domains *, const uschar **, BOOL *);
279extern ip_address_item *host_find_interfaces(void);
280extern BOOL host_is_in_net(const uschar *, const uschar *, int);
281extern BOOL host_is_tls_on_connect_port(int);
282extern int host_item_get_port(host_item *);
283extern void host_mask(int, int *, int);
284extern int host_name_lookup(void);
285extern int host_nmtoa(int, int *, int, uschar *, int);
286extern uschar *host_ntoa(int, const void *, uschar *, int *);
287extern int host_scan_for_local_hosts(host_item *, host_item **, BOOL *);
288
289extern uschar *imap_utf7_encode(uschar *, const uschar *,
290 uschar, uschar *, uschar **);
291
292extern void invert_address(uschar *, uschar *);
293extern int ip_addr(void *, int, const uschar *, int);
294extern int ip_bind(int, int, uschar *, int);
295extern int ip_connect(int, int, const uschar *, int, int, const blob *);
296extern int ip_connectedsocket(int, const uschar *, int, int,
297 int, host_item *, uschar **, const blob *);
298extern int ip_get_address_family(int);
299extern void ip_keepalive(int, const uschar *, BOOL);
300extern int ip_recv(client_conn_ctx *, uschar *, int, time_t);
301extern int ip_socket(int, int);
302
303extern int ip_tcpsocket(const uschar *, uschar **, int, host_item *);
304extern int ip_unixsocket(const uschar *, uschar **);
305extern int ip_streamsocket(const uschar *, uschar **, int, host_item *);
306
307extern int ipv6_nmtoa(int *, uschar *);
308
309extern uschar *local_part_quote(uschar *);
310extern int log_create(uschar *);
311extern int log_create_as_exim(uschar *);
312extern void log_close_all(void);
313
314extern macro_item * macro_create(const uschar *, const uschar *, BOOL);
315extern BOOL macro_read_assignment(uschar *);
316extern uschar *macros_expand(int, int *, BOOL *);
317extern void mainlog_close(void);
318#ifdef WITH_CONTENT_SCAN
319extern int malware(const uschar *, int);
320extern int malware_in_file(uschar *);
321extern void malware_init(void);
322extern gstring * malware_show_supported(gstring *);
323#endif
324extern int match_address_list(const uschar *, BOOL, BOOL, const uschar **,
325 unsigned int *, int, int, const uschar **);
326extern int match_address_list_basic(const uschar *, const uschar **, int);
327extern int match_check_list(const uschar **, int, tree_node **, unsigned int **,
328 int(*)(void *, const uschar *, const uschar **, uschar **), void *, int,
329 const uschar *, const uschar **);
330extern int match_isinlist(const uschar *, const uschar **, int, tree_node **,
331 unsigned int *, int, BOOL, const uschar **);
332extern int match_check_string(const uschar *, const uschar *, int, BOOL, BOOL, BOOL,
333 const uschar **);
334extern void md5_end(md5 *, const uschar *, int, uschar *);
335extern void md5_mid(md5 *, const uschar *);
336extern void md5_start(md5 *);
337extern void millisleep(int);
338#ifdef WITH_CONTENT_SCAN
339struct mime_boundary_context;
340extern int mime_acl_check(uschar *acl, FILE *f,
341 struct mime_boundary_context *, uschar **, uschar **);
342extern int mime_decode(const uschar **);
343extern ssize_t mime_decode_base64(FILE *, FILE *, uschar *);
344extern int mime_regex(const uschar **);
345extern void mime_set_anomaly(int);
346#endif
347extern uschar *moan_check_errorcopy(uschar *);
348extern BOOL moan_skipped_syntax_errors(uschar *, error_block *, uschar *,
349 BOOL, uschar *);
350extern void moan_smtp_batch(uschar *, const char *, ...) PRINTF_FUNCTION(2,3);
351extern BOOL moan_send_message(uschar *, int, error_block *eblock,
352 header_line *, FILE *, uschar *);
353extern void moan_tell_someone(uschar *, address_item *,
354 const uschar *, const char *, ...) PRINTF_FUNCTION(4,5);
355extern BOOL moan_to_sender(int, error_block *, header_line *, FILE *, BOOL);
356extern void moan_write_from(FILE *);
357extern void moan_write_references(FILE *, uschar *);
358extern FILE *modefopen(const uschar *, const char *, mode_t);
359
360extern int open_cutthrough_connection( address_item * addr );
361
362extern uschar *parse_extract_address(uschar *, uschar **, int *, int *, int *,
363 BOOL);
364extern int parse_forward_list(uschar *, int, address_item **, uschar **,
365 const uschar *, uschar *, error_block **);
366extern uschar *parse_find_address_end(uschar *, BOOL);
367extern uschar *parse_find_at(uschar *);
368extern const uschar *parse_fix_phrase(const uschar *, int, uschar *, int);
369extern uschar *parse_message_id(uschar *, uschar **, uschar **);
370extern const uschar *parse_quote_2047(const uschar *, int, uschar *, uschar *, int, BOOL);
371extern uschar *parse_date_time(uschar *str, time_t *t);
372extern int vaguely_random_number(int);
373#ifndef DISABLE_TLS
374extern int vaguely_random_number_fallback(int);
375#endif
376
377extern BOOL queue_action(uschar *, int, uschar **, int, int);
378extern void queue_check_only(void);
379extern unsigned queue_count(void);
380extern unsigned queue_count_cached(void);
381extern void queue_list(int, uschar **, int);
382#ifdef EXPERIMENTAL_QUEUE_RAMP
383extern void queue_notify_daemon(const uschar * hostname);
384#endif
385extern void queue_run(uschar *, uschar *, BOOL);
386
387extern int random_number(int);
388extern const uschar *rc_to_string(int);
389extern int rda_interpret(redirect_block *, int, uschar *, uschar *,
390 uschar *, uschar *, uschar *, ugid_block *, address_item **,
391 uschar **, error_block **, int *, uschar *);
392extern int rda_is_filter(const uschar *);
393extern BOOL readconf_depends(driver_instance *, uschar *);
394extern void readconf_driver_init(uschar *, driver_instance **,
395 driver_info *, int, void *, int, optionlist *, int);
396extern uschar *readconf_find_option(void *);
397extern void readconf_main(BOOL);
398extern void readconf_options_from_list(optionlist *, unsigned, const uschar *, uschar *);
399extern BOOL readconf_print(uschar *, uschar *, BOOL);
400extern uschar *readconf_printtime(int);
401extern uschar *readconf_readname(uschar *, int, uschar *);
402extern int readconf_readtime(const uschar *, int, BOOL);
403extern void readconf_rest(void);
404extern uschar *readconf_retry_error(const uschar *, const uschar *, int *, int *);
405extern void readconf_save_config(const uschar *);
406extern void read_message_body(BOOL);
407extern void receive_bomb_out(uschar *, uschar *) NORETURN;
408extern BOOL receive_check_fs(int);
409extern BOOL receive_check_set_sender(uschar *);
410extern BOOL receive_msg(BOOL);
411extern int_eximarith_t receive_statvfs(BOOL, int *);
412extern void receive_swallow_smtp(void);
413#ifdef WITH_CONTENT_SCAN
414extern int regex(const uschar **);
415#endif
416extern BOOL regex_match_and_setup(const pcre *, const uschar *, int, int);
417extern const pcre *regex_must_compile(const uschar *, BOOL, BOOL);
418extern void retry_add_item(address_item *, uschar *, int);
419extern BOOL retry_check_address(const uschar *, host_item *, uschar *, BOOL,
420 uschar **, uschar **);
421extern retry_config *retry_find_config(const uschar *, const uschar *, int, int);
422extern BOOL retry_ultimate_address_timeout(uschar *, const uschar *,
423 dbdata_retry *, time_t);
424extern void retry_update(address_item **, address_item **, address_item **);
425extern uschar *rewrite_address(uschar *, BOOL, BOOL, rewrite_rule *, int);
426extern uschar *rewrite_address_qualify(uschar *, BOOL);
427extern header_line *rewrite_header(header_line *,
428 const uschar *, const uschar *,
429 rewrite_rule *, int, BOOL);
430extern uschar *rewrite_one(uschar *, int, BOOL *, BOOL, uschar *,
431 rewrite_rule *);
432extern void rewrite_test(uschar *);
433extern uschar *rfc2047_decode2(uschar *, BOOL, uschar *, int, int *, int *,
434 uschar **);
435extern int route_address(address_item *, address_item **, address_item **,
436 address_item **, address_item **, int);
437extern int route_check_prefix(const uschar *, const uschar *, unsigned *);
438extern int route_check_suffix(const uschar *, const uschar *, unsigned *);
439extern BOOL route_findgroup(uschar *, gid_t *);
440extern BOOL route_finduser(const uschar *, struct passwd **, uid_t *);
441extern BOOL route_find_expanded_group(uschar *, uschar *, uschar *, gid_t *,
442 uschar **);
443extern BOOL route_find_expanded_user(uschar *, uschar *, uschar *,
444 struct passwd **, uid_t *, uschar **);
445extern void route_init(void);
446extern gstring * route_show_supported(gstring *);
447extern void route_tidyup(void);
448
449extern uschar *search_find(void *, const uschar *, uschar *, int,
450 const uschar *, int, int, int *, const uschar *);
451extern int search_findtype(const uschar *, int);
452extern int search_findtype_partial(const uschar *, int *, const uschar **, int *,
453 int *, const uschar **);
454extern void *search_open(const uschar *, int, int, uid_t *, gid_t *);
455extern void search_tidyup(void);
456extern void set_process_info(const char *, ...) PRINTF_FUNCTION(1,2);
457extern void sha1_end(hctx *, const uschar *, int, uschar *);
458extern void sha1_mid(hctx *, const uschar *);
459extern void sha1_start(hctx *);
460extern int sieve_interpret(uschar *, int, uschar *, uschar *, uschar *,
461 uschar *, address_item **, uschar **);
462extern void sigalrm_handler(int);
463extern BOOL smtp_buffered(void);
464extern void smtp_closedown(uschar *);
465extern void smtp_command_timeout_exit(void) NORETURN;
466extern void smtp_command_sigterm_exit(void) NORETURN;
467extern void smtp_data_timeout_exit(void) NORETURN;
468extern void smtp_data_sigint_exit(void) NORETURN;
469extern void smtp_deliver_init(void);
470extern uschar *smtp_cmd_hist(void);
471extern int smtp_connect(smtp_connect_args *, const blob *);
472extern int smtp_sock_connect(host_item *, int, int, uschar *,
473 transport_instance * tb, int, const blob *);
474extern int smtp_feof(void);
475extern int smtp_ferror(void);
476extern uschar *smtp_get_connection_info(void);
477extern BOOL smtp_get_interface(uschar *, int, address_item *,
478 uschar **, uschar *);
479extern BOOL smtp_get_port(uschar *, address_item *, int *, uschar *);
480extern int smtp_getc(unsigned);
481extern uschar *smtp_getbuf(unsigned *);
482extern void smtp_get_cache(void);
483extern int smtp_handle_acl_fail(int, int, uschar *, uschar *);
484extern void smtp_log_no_mail(void);
485extern void smtp_message_code(uschar **, int *, uschar **, uschar **, BOOL);
486extern void smtp_proxy_tls(void *, uschar *, size_t, int *, int) NORETURN;
487extern BOOL smtp_read_response(void *, uschar *, int, int, int);
488extern void *smtp_reset(void *);
489extern void smtp_respond(uschar *, int, BOOL, uschar *);
490extern void smtp_notquit_exit(uschar *, uschar *, uschar *, ...);
491extern void smtp_port_for_connect(host_item *, int);
492extern void smtp_send_prohibition_message(int, uschar *);
493extern int smtp_setup_msg(void);
494extern BOOL smtp_start_session(void);
495extern int smtp_ungetc(int);
496extern BOOL smtp_verify_helo(void);
497extern int smtp_write_command(void *, int, const char *, ...) PRINTF_FUNCTION(3,4);
498#ifdef WITH_CONTENT_SCAN
499extern int spam(const uschar **);
500extern FILE *spool_mbox(unsigned long *, const uschar *, uschar **);
501#endif
502extern void spool_clear_header_globals(void);
503extern BOOL spool_move_message(uschar *, uschar *, uschar *, uschar *);
504extern int spool_open_datafile(uschar *);
505extern int spool_open_temp(uschar *);
506extern int spool_read_header(uschar *, BOOL, BOOL);
507extern int spool_write_header(uschar *, int, uschar **);
508extern int stdin_getc(unsigned);
509extern int stdin_feof(void);
510extern int stdin_ferror(void);
511extern int stdin_ungetc(int);
512
513extern void store_exit(void);
514extern gstring *string_append(gstring *, int, ...) WARN_UNUSED_RESULT;
515extern gstring *string_append_listele(gstring *, uschar, const uschar *) WARN_UNUSED_RESULT;
516extern gstring *string_append_listele_n(gstring *, uschar, const uschar *, unsigned) WARN_UNUSED_RESULT;
517extern gstring *string_append2_listele_n(gstring *, const uschar *, const uschar *, unsigned) WARN_UNUSED_RESULT;
518extern uschar *string_base62(unsigned long int);
519extern gstring *string_cat (gstring *, const uschar * ) WARN_UNUSED_RESULT;
520extern gstring *string_catn(gstring *, const uschar *, int) WARN_UNUSED_RESULT;
521extern int string_compare_by_pointer(const void *, const void *);
522extern uschar *string_copy_dnsdomain(uschar *);
523extern uschar *string_copy_malloc(const uschar *);
524extern uschar *string_dequote(const uschar **);
525extern uschar *string_format_size(int, uschar *);
526extern int string_interpret_escape(const uschar **);
527extern int string_is_ip_address(const uschar *, int *);
528#ifdef SUPPORT_I18N
529extern BOOL string_is_utf8(const uschar *);
530#endif
531extern const uschar *string_printing2(const uschar *, BOOL);
532extern uschar *string_split_message(uschar *);
533extern uschar *string_unprinting(uschar *);
534#ifdef SUPPORT_I18N
535extern uschar *string_address_utf8_to_alabel(const uschar *, uschar **);
536extern uschar *string_domain_alabel_to_utf8(const uschar *, uschar **);
537extern uschar *string_domain_utf8_to_alabel(const uschar *, uschar **);
538extern uschar *string_localpart_alabel_to_utf8(const uschar *, uschar **);
539extern uschar *string_localpart_utf8_to_alabel(const uschar *, uschar **);
540#endif
541
542#define string_format(buf, siz, fmt, ...) \
543 string_format_trc(buf, siz, US __FUNCTION__, __LINE__, fmt, __VA_ARGS__)
544extern BOOL string_format_trc(uschar *, int, const uschar *, unsigned,
545 const char *, ...) ALMOST_PRINTF(5,6);
546
547#define string_vformat(g, flgs, fmt, ap) \
548 string_vformat_trc(g, US __FUNCTION__, __LINE__, \
549 STRING_SPRINTF_BUFFER_SIZE, flgs, fmt, ap)
550extern gstring *string_vformat_trc(gstring *, const uschar *, unsigned,
551 unsigned, unsigned, const char *, va_list);
552
553#define string_open_failed(eno, fmt, ...) \
554 string_open_failed_trc(eno, US __FUNCTION__, __LINE__, fmt, __VA_ARGS__)
555extern uschar *string_open_failed_trc(int, const uschar *, unsigned,
556 const char *, ...) PRINTF_FUNCTION(4,5);
557
558#define string_nextinlist(lp, sp, b, l) \
559 string_nextinlist_trc((lp), (sp), (b), (l), US __FUNCTION__, __LINE__)
560extern uschar *string_nextinlist_trc(const uschar **listptr, int *separator, uschar *buffer, int buflen,
561 const uschar * func, int line);
562
563extern int strcmpic(const uschar *, const uschar *);
564extern int strncmpic(const uschar *, const uschar *, int);
565extern uschar *strstric(uschar *, uschar *, BOOL);
566
567extern int test_harness_fudged_queue_time(int);
568extern void tcp_init(void);
569#ifdef EXIM_TFO_PROBE
570extern void tfo_probe(void);
571#endif
572extern void tls_modify_variables(tls_support *);
573extern uschar *tod_stamp(int);
574
575extern BOOL transport_check_waiting(const uschar *, const uschar *, int, uschar *,
576 BOOL *, oicf, void*);
577extern void transport_init(void);
578extern void transport_do_pass_socket(const uschar *, const uschar *,
579 const uschar *, uschar *, int);
580extern BOOL transport_pass_socket(const uschar *, const uschar *, const uschar *, uschar *,
581 int);
582extern uschar *transport_rcpt_address(address_item *, BOOL);
583extern BOOL transport_set_up_command(const uschar ***, uschar *,
584 BOOL, int, address_item *, uschar *, uschar **);
585extern void transport_update_waiting(host_item *, uschar *);
586extern BOOL transport_write_block(transport_ctx *, uschar *, int, BOOL);
587extern void transport_write_reset(int);
588extern BOOL transport_write_string(int, const char *, ...);
589extern BOOL transport_headers_send(transport_ctx *,
590 BOOL (*)(transport_ctx *, uschar *, int));
591extern gstring * transport_show_supported(gstring *);
592extern BOOL transport_write_message(transport_ctx *, int);
593extern void tree_add_duplicate(uschar *, address_item *);
594extern void tree_add_nonrecipient(uschar *);
595extern void tree_add_unusable(host_item *);
596extern void tree_dup(tree_node **, tree_node *);
597extern int tree_insertnode(tree_node **, tree_node *);
598extern tree_node *tree_search(tree_node *, const uschar *);
599extern void tree_write(tree_node *, FILE *);
600extern void tree_walk(tree_node *, void (*)(uschar*, uschar*, void*), void *);
601
602#ifdef WITH_CONTENT_SCAN
603extern void unspool_mbox(void);
604#endif
605#ifdef SUPPORT_I18N
606extern void utf8_version_report(FILE *);
607#endif
608
609extern int verify_address(address_item *, FILE *, int, int, int, int,
610 uschar *, uschar *, BOOL *);
611extern int verify_check_dnsbl(int, const uschar **, uschar **);
612extern int verify_check_header_address(uschar **, uschar **, int, int, int,
613 uschar *, uschar *, int, int *);
614extern int verify_check_headers(uschar **);
615extern int verify_check_header_names_ascii(uschar **);
616extern int verify_check_host(uschar **);
617extern int verify_check_notblind(BOOL);
618extern int verify_check_given_host(const uschar **, const host_item *);
619extern int verify_check_this_host(const uschar **, unsigned int *,
620 const uschar*, const uschar *, const uschar **);
621extern address_item *verify_checked_sender(uschar *);
622extern void verify_get_ident(int);
623extern BOOL verify_sender(int *, uschar **);
624extern BOOL verify_sender_preliminary(int *, uschar **);
625extern void version_init(void);
626
627extern BOOL write_chunk(transport_ctx *, uschar *, int);
628extern ssize_t write_to_fd_buf(int, const uschar *, size_t);
629
630
631/******************************************************************************/
632/* Predicate: if an address is in a tainted pool.
633By extension, a variable pointing to this address is tainted.
634*/
635
636static inline BOOL
637is_tainted(const void * p)
638{
639#if defined(COMPILE_UTILITY) || defined(MACRO_PREDEF) || defined(EM_VERSION_C)
640return FALSE;
641
642#else
643extern BOOL is_tainted_fn(const void *);
644return is_tainted_fn(p);
645#endif
646}
647
648/******************************************************************************/
649/* String functions */
650static inline uschar * __Ustrcat(uschar * dst, const uschar * src, const char * func, int line)
651{
652#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
653if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcat", CUS func, line);
654#endif
655return US strcat(CS dst, CCS src);
656}
657static inline uschar * __Ustrcpy(uschar * dst, const uschar * src, const char * func, int line)
658{
659#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
660if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrcpy", CUS func, line);
661#endif
662return US strcpy(CS dst, CCS src);
663}
664static inline uschar * __Ustrncat(uschar * dst, const uschar * src, size_t n, const char * func, int line)
665{
666#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
667if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncat", CUS func, line);
668#endif
669return US strncat(CS dst, CCS src, n);
670}
671static inline uschar * __Ustrncpy(uschar * dst, const uschar * src, size_t n, const char * func, int line)
672{
673#if !defined(COMPILE_UTILITY) && !defined(MACRO_PREDEF)
674if (!is_tainted(dst) && is_tainted(src)) die_tainted(US"Ustrncpy", CUS func, line);
675#endif
676return US strncpy(CS dst, CCS src, n);
677}
678/*XXX will likely need unchecked copy also */
679
680
681/* Advance the string pointer given over any whitespace.
682Return the next char as there's enought places using it to be useful. */
683
684#define Uskip_whitespace(sp) skip_whitespace(CUSS sp)
685
686static inline uschar skip_whitespace(const uschar ** sp)
687{ while (isspace(**sp)) (*sp)++; return **sp; }
688
689
690/******************************************************************************/
691
692#if !defined(MACRO_PREDEF) && !defined(COMPILE_UTILITY)
693/* exim_chown - in some NFSv4 setups *seemes* to be an issue with
694chown(<exim-uid>, <exim-gid>).
695
696Probably because the idmapping is broken, misconfigured or set up in
697an unusal way. (see Bug 2931). As I'm not sure, if this was a single
698case of misconfiguration, or if there are more such broken systems
699out, I try to impose as least impact as possible and for now just write
700a panic log entry pointing to the bug report. You're encouraged to
701contact the developers, if you experience this issue.
702
703fd the file descriptor (or -1 if not valid)
704name the file name for error messages or for file operations,
705 if fd is < 0
706owner the owner
707group the group
708
709returns 0 on success, -1 on failure */
710
711static inline int
712exim_fchown(int fd, uid_t owner, gid_t group, const uschar *name)
713{
714return fchown(fd, owner, group)
715 ? exim_chown_failure(fd, name, owner, group) : 0;
716}
717
718static inline int
719exim_chown(const uschar *name, uid_t owner, gid_t group)
720{
721return chown(CCS name, owner, group)
722 ? exim_chown_failure(-1, name, owner, group) : 0;
723}
724#endif /* !MACRO_PREDEF && !COMPILE_UTILITY */
725
726/******************************************************************************/
727/* String functions */
728
729#if !defined(MACRO_PREDEF)
730/*************************************************
731* Copy and save string *
732*************************************************/
733
734/* This function assumes that memcpy() is faster than strcpy().
735The result is explicitly nul-terminated.
736*/
737
738static inline uschar *
739string_copyn_taint_trc(const uschar * s, unsigned len,
740 BOOL tainted, const char * func, int line)
741{
742uschar * ss = store_get_3(len + 1, tainted, func, line);
743memcpy(ss, s, len);
744ss[len] = '\0';
745return ss;
746}
747
748static inline uschar *
749string_copy_taint_trc(const uschar * s, BOOL tainted, const char * func, int line)
750{ return string_copyn_taint_trc(s, Ustrlen(s), tainted, func, line); }
751
752static inline uschar *
753string_copyn_trc(const uschar * s, unsigned len, const char * func, int line)
754{ return string_copyn_taint_trc(s, len, is_tainted(s), func, line); }
755static inline uschar *
756string_copy_trc(const uschar * s, const char * func, int line)
757{ return string_copy_taint_trc(s, is_tainted(s), func, line); }
758
759
760/* String-copy functions explicitly setting the taint status */
761
762#define string_copyn_taint(s, len, tainted) \
763 string_copyn_taint_trc((s), (len), (tainted), __FUNCTION__, __LINE__)
764#define string_copy_taint(s, tainted) \
765 string_copy_taint_trc((s), (tainted), __FUNCTION__, __LINE__)
766
767/* Simple string-copy functions maintaining the taint */
768
769#define string_copyn(s, len) \
770 string_copyn_taint_trc((s), (len), is_tainted(s), __FUNCTION__, __LINE__)
771#define string_copy(s) \
772 string_copy_taint_trc((s), is_tainted(s), __FUNCTION__, __LINE__)
773
774
775/*************************************************
776* Copy, lowercase and save string *
777*************************************************/
778
779/*
780Argument: string to copy
781Returns: copy of string in new store, with letters lowercased
782*/
783
784static inline uschar *
785string_copylc(const uschar *s)
786{
787uschar *ss = store_get(Ustrlen(s) + 1, is_tainted(s));
788uschar *p = ss;
789while (*s != 0) *p++ = tolower(*s++);
790*p = 0;
791return ss;
792}
793
794
795
796/*************************************************
797* Copy, lowercase, and save string, given length *
798*************************************************/
799
800/* It is assumed the data contains no zeros. A zero is added
801onto the end.
802
803Arguments:
804 s string to copy
805 n number of characters
806
807Returns: copy of string in new store, with letters lowercased
808*/
809
810static inline uschar *
811string_copynlc(uschar *s, int n)
812{
813uschar *ss = store_get(n + 1, is_tainted(s));
814uschar *p = ss;
815while (n-- > 0) *p++ = tolower(*s++);
816*p = 0;
817return ss;
818}
819
820
821# ifndef COMPILE_UTILITY
822/*************************************************
823* Copy and save string in longterm store *
824*************************************************/
825
826/* This function assumes that memcpy() is faster than strcpy().
827
828Argument: string to copy
829Returns: copy of string in new store
830*/
831
832static inline uschar *
833string_copy_perm(const uschar *s, BOOL force_taint)
834{
835int old_pool = store_pool;
836int len = Ustrlen(s) + 1;
837uschar *ss;
838
839store_pool = POOL_PERM;
840ss = store_get(len, force_taint || is_tainted(s));
841memcpy(ss, s, len);
842store_pool = old_pool;
843return ss;
844}
845# endif
846
847
848
849/* sprintf into a buffer, taint-unchecked */
850
851static inline void
852string_format_nt(uschar * buf, int siz, const char * fmt, ...)
853{
854gstring gs = { .size = siz, .ptr = 0, .s = buf };
855va_list ap;
856va_start(ap, fmt);
857(void) string_vformat(&gs, SVFMT_TAINT_NOCHK, fmt, ap);
858va_end(ap);
859}
860
861
862
863/******************************************************************************/
864/* Growable-string functions */
865
866/* Create a growable-string with some preassigned space */
867
868#define string_get_tainted(size, tainted) \
869 string_get_tainted_trc((size), (tainted), __FUNCTION__, __LINE__)
870
871static inline gstring *
872string_get_tainted_trc(unsigned size, BOOL tainted, const char * func, unsigned line)
873{
874gstring * g = store_get_3(sizeof(gstring) + size, tainted, func, line);
875g->size = size;
876g->ptr = 0;
877g->s = US(g + 1);
878return g;
879}
880
881#define string_get(size) \
882 string_get_trc((size), __FUNCTION__, __LINE__)
883
884static inline gstring *
885string_get_trc(unsigned size, const char * func, unsigned line)
886{
887return string_get_tainted_trc(size, FALSE, func, line);
888}
889
890/* NUL-terminate the C string in the growable-string, and return it. */
891
892static inline uschar *
893string_from_gstring(gstring * g)
894{
895if (!g) return NULL;
896g->s[g->ptr] = '\0';
897return g->s;
898}
899
900static inline unsigned
901gstring_length(const gstring * g)
902{
903return g ? (unsigned)g->ptr : 0;
904}
905
906
907#define gstring_release_unused(g) \
908 gstring_release_unused_trc(g, __FUNCTION__, __LINE__)
909
910static inline void
911gstring_release_unused_trc(gstring * g, const char * file, unsigned line)
912{
913if (g) store_release_above_3(g->s + (g->size = g->ptr + 1), file, line);
914}
915
916
917/* sprintf-append to a growable-string */
918
919#define string_fmt_append(g, fmt, ...) \
920 string_fmt_append_f_trc(g, US __FUNCTION__, __LINE__, \
921 SVFMT_EXTEND|SVFMT_REBUFFER, fmt, __VA_ARGS__)
922
923#define string_fmt_append_f(g, flgs, fmt, ...) \
924 string_fmt_append_f_trc(g, US __FUNCTION__, __LINE__, \
925 flgs, fmt, __VA_ARGS__)
926
927static inline gstring *
928string_fmt_append_f_trc(gstring * g, const uschar * func, unsigned line,
929 unsigned flags, const char *format, ...)
930{
931va_list ap;
932va_start(ap, format);
933g = string_vformat_trc(g, func, line, STRING_SPRINTF_BUFFER_SIZE,
934 flags, format, ap);
935va_end(ap);
936return g;
937}
938
939
940/* Copy the content of a string to tainted memory */
941
942static inline void
943gstring_rebuffer(gstring * g)
944{
945uschar * s = store_get(g->size, TRUE);
946memcpy(s, g->s, g->ptr);
947g->s = s;
948}
949
950
951/******************************************************************************/
952
953#define store_get_dns_answer() store_get_dns_answer_trc(CUS __FUNCTION__, __LINE__)
954
955static inline dns_answer *
956store_get_dns_answer_trc(const uschar * func, unsigned line)
957{
958return store_get_3(sizeof(dns_answer), TRUE, CCS func, line); /* use tainted mem */
959}
960
961/******************************************************************************/
962/* Routines with knowledge of spool layout */
963
964# ifndef COMPILE_UTILITY
965static inline void
966spool_pname_buf(uschar * buf, int len)
967{
968snprintf(CS buf, len, "%s/%s/input", spool_directory, queue_name);
969}
970
971static inline uschar *
972spool_dname(const uschar * purpose, uschar * subdir)
973{
974return string_sprintf("%s/%s/%s/%s",
975 spool_directory, queue_name, purpose, subdir);
976}
977# endif
978
979static inline uschar *
980spool_q_sname(const uschar * purpose, const uschar * q, uschar * subdir)
981{
982return string_sprintf("%s%s%s%s%s",
983 q, *q ? "/" : "",
984 purpose,
985 *subdir ? "/" : "", subdir);
986}
987
988static inline uschar *
989spool_sname(const uschar * purpose, uschar * subdir)
990{
991return spool_q_sname(purpose, queue_name, subdir);
992}
993
994static inline uschar *
995spool_q_fname(const uschar * purpose, const uschar * q,
996 const uschar * subdir, const uschar * fname, const uschar * suffix)
997{
998return string_sprintf("%s/%s/%s/%s/%s%s",
999 spool_directory, q, purpose, subdir, fname, suffix);
1000}
1001
1002static inline uschar *
1003spool_fname(const uschar * purpose, const uschar * subdir, const uschar * fname,
1004 const uschar * suffix)
1005{
1006#ifdef COMPILE_UTILITY /* version avoiding string-extension */
1007int len = Ustrlen(spool_directory) + 1 + Ustrlen(queue_name) + 1 + Ustrlen(purpose) + 1
1008 + Ustrlen(subdir) + 1 + Ustrlen(fname) + Ustrlen(suffix) + 1;
1009uschar * buf = store_get(len, FALSE);
1010string_format(buf, len, "%s/%s/%s/%s/%s%s",
1011 spool_directory, queue_name, purpose, subdir, fname, suffix);
1012return buf;
1013#else
1014return spool_q_fname(purpose, queue_name, subdir, fname, suffix);
1015#endif
1016}
1017
1018static inline void
1019set_subdir_str(uschar * subdir_str, const uschar * name,
1020 int search_sequence)
1021{
1022subdir_str[0] = split_spool_directory == (search_sequence == 0)
1023 ? name[5] : '\0';
1024subdir_str[1] = '\0';
1025}
1026
1027/******************************************************************************/
1028/* Time calculations */
1029
1030static inline void
1031timesince(struct timeval * diff, const struct timeval * then)
1032{
1033gettimeofday(diff, NULL);
1034diff->tv_sec -= then->tv_sec;
1035if ((diff->tv_usec -= then->tv_usec) < 0)
1036 {
1037 diff->tv_sec--;
1038 diff->tv_usec += 1000*1000;
1039 }
1040}
1041
1042static inline uschar *
1043string_timediff(const struct timeval * diff)
1044{
1045static uschar buf[sizeof("0.000s")];
1046
1047if (diff->tv_sec >= 5 || !LOGGING(millisec))
1048 return readconf_printtime((int)diff->tv_sec);
1049
1050snprintf(CS buf, sizeof(buf), "%u.%03us", (uint)diff->tv_sec, (uint)diff->tv_usec/1000);
1051return buf;
1052}
1053
1054
1055static inline uschar *
1056string_timesince(const struct timeval * then)
1057{
1058struct timeval diff;
1059timesince(&diff, then);
1060return string_timediff(&diff);
1061}
1062
1063static inline void
1064report_time_since(const struct timeval * t0, const uschar * where)
1065{
1066# ifdef MEASURE_TIMING
1067struct timeval diff;
1068timesince(&diff, t0);
1069fprintf(stderr, "%d %s:\t%ld.%06ld\n",
1070 (uint)getpid(), where, (long)diff.tv_sec, (long)diff.tv_usec);
1071# endif
1072}
1073
1074
1075static inline void
1076testharness_pause_ms(int millisec)
1077{
1078#ifndef MEASURE_TIMING
1079if (f.running_in_test_harness && f.testsuite_delays) millisleep(millisec);
1080#endif
1081}
1082
1083/******************************************************************************/
1084/* Taint-checked file opens */
1085
1086static inline int
1087exim_open2(const char *pathname, int flags)
1088{
1089if (!is_tainted(pathname)) return open(pathname, flags);
1090log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
1091errno = EACCES;
1092return -1;
1093}
1094static inline int
1095exim_open(const char *pathname, int flags, mode_t mode)
1096{
1097if (!is_tainted(pathname)) return open(pathname, flags, mode);
1098log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
1099errno = EACCES;
1100return -1;
1101}
1102static inline int
1103exim_openat(int dirfd, const char *pathname, int flags)
1104{
1105if (!is_tainted(pathname)) return openat(dirfd, pathname, flags);
1106log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
1107errno = EACCES;
1108return -1;
1109}
1110static inline int
1111exim_openat4(int dirfd, const char *pathname, int flags, mode_t mode)
1112{
1113if (!is_tainted(pathname)) return openat(dirfd, pathname, flags, mode);
1114log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
1115errno = EACCES;
1116return -1;
1117}
1118
1119static inline FILE *
1120exim_fopen(const char *pathname, const char *mode)
1121{
1122if (!is_tainted(pathname)) return fopen(pathname, mode);
1123log_write(0, LOG_MAIN|LOG_PANIC, "Tainted filename '%s'", pathname);
1124errno = EACCES;
1125return NULL;
1126}
1127
1128static inline DIR *
1129exim_opendir(const uschar * name)
1130{
1131if (!is_tainted(name)) return opendir(CCS name);
1132log_write(0, LOG_MAIN|LOG_PANIC, "Tainted dirname '%s'", name);
1133errno = EACCES;
1134return NULL;
1135}
1136
1137/******************************************************************************/
1138# if !defined(COMPILE_UTILITY)
1139/* Process manipulation */
1140
1141static inline pid_t
1142exim_fork(const unsigned char * purpose)
1143{
1144pid_t pid;
1145DEBUG(D_any) debug_printf("%s forking for %s\n", process_purpose, purpose);
1146if ((pid = fork()) == 0)
1147 {
1148 process_purpose = purpose;
1149 DEBUG(D_any) debug_printf("postfork: %s\n", purpose);
1150 }
1151else
1152 {
1153 testharness_pause_ms(100); /* let child work */
1154 DEBUG(D_any) debug_printf("%s forked for %s: %d\n", process_purpose, purpose, (int)pid);
1155 }
1156return pid;
1157}
1158
1159
1160static inline pid_t
1161child_open_exim(int * fdptr, const uschar * purpose)
1162{ return child_open_exim_function(fdptr, purpose); }
1163
1164static inline pid_t
1165child_open_exim2(int * fdptr, uschar * sender,
1166 uschar * sender_auth, const uschar * purpose)
1167{ return child_open_exim2_function(fdptr, sender, sender_auth, purpose); }
1168
1169static inline pid_t
1170child_open(uschar **argv, uschar **envp, int newumask, int *infdptr,
1171 int *outfdptr, BOOL make_leader, const uschar * purpose)
1172{ return child_open_function(argv, envp, newumask, infdptr,
1173 outfdptr, make_leader, purpose);
1174}
1175
1176# endif /* !COMPILE_UTILITY */
1177
1178/******************************************************************************/
1179#endif /* !MACRO_PREDEF */
1180
1181#endif /* _FUNCTIONS_H_ */
1182
1183/* vi: aw
1184*/
1185/* End of functions.h */