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