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