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