1 /* This file is part of Mailfromd.
2    Copyright (C) 2005-2021 Sergey Poznyakoff
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include <sys/types.h>
18 #include <regex.h>
19 #include <mailutils/cctype.h>
20 #include <mailutils/mailutils.h>
21 #include <mfapi.h>
22 #include <dns.h>
23 #include <mailutils/alloc.h>
24 #include <sysexits.h>
25 #include "libmf.h"
26 #include "mfdb.h"
27 #include "bitmask.h"
28 #include "filenames.h"
29 
30 /* A simplified version of the bitmask above, used for SMTP state mask */
31 #define STATMASK(n) ((unsigned)1<<(n))
32 
33 #define SP(s) ((s) ? (s) : "(null)")
34 
35 #ifndef INADDR_NONE
36 # define INADDR_NONE ((unsigned long) -1)
37 #endif
38 
39 /* Exception codes. */
40 typedef enum mf_exception_code {
41 #include <mflib/status.ex>
42 	mf_exception_count
43 } mf_exception;
44 
45 /* SMTP states */
46 enum smtp_state {
47 	smtp_state_none,
48 	smtp_state_begin,
49 	smtp_state_first=smtp_state_begin,
50 	smtp_state_connect,
51 	smtp_state_helo,
52 	smtp_state_envfrom,
53 	smtp_state_envrcpt,
54 	smtp_state_data,
55 	smtp_state_header,
56 	smtp_state_eoh,
57 	smtp_state_body,
58 	smtp_state_eom,
59 
60 	smtp_state_end,
61 
62 	smtp_state_count
63 };
64 
65 #define MFAM_STDIO 0
66 #define MFAM_UNIX  1
67 #define MFAM_INET  2
68 #define MFAM_INET6 3
69 
70 
71 mf_status dns_to_mf_status(dns_status s);
72 
73 mf_status resolve_ipstr(const char *ipstr, char **hbuf);
74 mf_status resolve_ipstr_domain(const char *ipstr, const char *domain,
75 			       char **phbuf);
76 mf_status resolve_hostname(const char *host, char **pipbuf);
77 
78 
79 /* Debugging macros */
80 extern mu_debug_handle_t mfd_debug_handle;
81 #include "mfd-dbgmod.h"
82 
83 
84 /* Syslog flavor */
85 #ifdef USE_SYSLOG_ASYNC
86 # include <syslog_async.h>
87 #endif
88 
89 
90 /* FIXME */
91 void enable_prog_trace(const char *modlist);
92 void disable_prog_trace(const char *modlist);
93 
94 
95 /* Global variables declarations */
96 #define MAILFROMD_DAEMON        0
97 #define MAILFROMD_TEST          1
98 #define MAILFROMD_SHOW_DEFAULTS 2
99 #define MAILFROMD_RUN           3
100 
101 extern char *script_file;
102 extern char *ext_pp;
103 extern char *ext_pp_options;
104 extern int ext_pp_options_given;
105 extern int location_column_option;
106 extern int mode;
107 extern int mtasim_option;
108 extern unsigned optimization_level;
109 extern enum smtp_state test_state;
110 extern int regex_flags;
111 extern size_t variable_count;
112 extern int script_dump_macros;
113 extern int script_dump_xref;
114 extern int stack_trace_option;
115 extern const char *program_version;
116 extern char *callout_server_url;
117 
118 extern size_t stack_size;
119 extern size_t stack_max_size;
120 extern size_t stack_expand_incr;
121 enum stack_expand_policy {
122 	stack_expand_twice,
123 	stack_expand_add
124 };
125 extern enum stack_expand_policy stack_expand_policy;
126 
127 extern size_t max_match_mx;
128 
129 
130 /* Filter script parser */
131 
132 typedef enum {
133 	dtype_unspecified,
134 	dtype_string,
135 	dtype_number,
136 	dtype_pointer
137 } data_type_t;
138 
139 /* Parse tree node */
140 typedef struct node NODE;
141 
142 typedef struct mu_locus_range mf_yyltype_t;
143 
144 struct if_node {            /* if statement */
145 	NODE *cond;         /* Condition */
146 	NODE *if_true;      /* True branch */
147 	NODE *if_false;     /* False branch */
148 };
149 
150 struct poll_data {                 /* Poll test */
151 	NODE *email;
152 	NODE *client_addr;
153 	NODE *ehlo;
154 	NODE *mailfrom;
155 };
156 
157 /* Opcodes for available binary operations */
158 enum bin_opcode {
159 	bin_and,
160 	bin_or,
161 	bin_eq,
162 	bin_ne,
163 	bin_lt,
164 	bin_le,
165 	bin_gt,
166 	bin_ge,
167 	bin_match,
168 	bin_fnmatch,
169 	bin_add,
170 	bin_sub,
171 	bin_mul,
172 	bin_div,
173 	bin_mod,
174 	bin_logand,
175 	bin_logor,
176 	bin_logxor,
177 	bin_shl,
178 	bin_shr
179 };
180 
181 #define QUALIFIER_MX      0x1
182 
183 struct bin_node {                  /* A binary operation */
184 	enum bin_opcode opcode;    /* Operation code */
185 	int qualifier;             /* Used to indicate MX MATCHES/FNMATCHES */
186 	NODE *arg[2];              /* arg[0] - left side argument,
187 				      arg[1] - right side argument */
188 };
189 
190 /* Unary operations */
191 enum un_opcode {
192 	unary_not,
193 	unary_minus,
194 	unary_lognot
195 };
196 
197 struct un_node {                   /* A unary operation node */
198 	enum un_opcode opcode;     /* Operation code */
199 	data_type_t result_type;   /* Result type */
200 	NODE *arg;                 /* Argument */
201 };
202 
203 /* Return action node: accept/reject/tempfail/continue */
204 struct return_node {
205 	sfsistat stat;             /* Return status */
206 	NODE *code;                /* Code */
207 	NODE *xcode;               /* Extended code */
208 	NODE *message;             /* Textual message */
209 };
210 
211 enum msgmod_opcode {               /* Message modification operation */
212 	header_add,                /* Add a header */
213 	header_replace,            /* Replace a header value */
214 	header_delete,             /* Delete a header */
215 	header_insert,             /* Insert a header */
216 	rcpt_add,                  /* Add a recipient */
217 	rcpt_delete,               /* Delete a recipient */
218 	quarantine,                /* Quarantine a message */
219 	body_repl,                 /* Replace message body */
220 	body_repl_fd,              /* Replace message body from file */
221 	set_from                   /* Change envelope sender */
222 };
223 
224 struct msgmod_closure {
225 	enum msgmod_opcode opcode;   /* Operation code */
226 	char *name;                  /* Object name */
227 	char *value;                 /* Object value */
228 	unsigned idx;                /* Object index */
229 };
230 
231 struct header_node {
232 	enum msgmod_opcode opcode;   /* Operation code */
233 	struct literal *name;        /* Header name */
234 	NODE *value;                 /* Header value */
235 };
236 
237 struct builtin_node {              /* Call to a built-in function */
238 	const struct builtin *builtin; /* Buit-in function */
239 	NODE *args;                    /* Actual arguments */
240 };
241 
242 struct concat_node {              /* Concatenation of arg[0] and arg[1] */
243 	NODE *arg[2];
244 };
245 
246 struct asgn_node {                /* Assignment */
247 	struct variable *var;     /* Variable */
248 	size_t nframes;           /* Number of frames to skip */
249 	NODE *node;               /* Expression to be evaluated and assigned
250 				     to it */
251 };
252 
253 enum lexical_context {
254 	context_none,
255 	context_handler,
256 	context_catch,
257 	context_function
258 };
259 
260 struct catch_node {
261 	struct exmask *exmask;    /* Exception mask */
262 	enum lexical_context context; /* Context in which it occurs */
263 	NODE *node;               /* Subtree */
264 };
265 
266 struct try_node {
267 	NODE *node;               /* Subtree */
268 	NODE *catch;              /* Catch node */
269 };
270 
271 struct function_call {
272 	struct function *func;    /* Function description */
273 	NODE *args;               /* List of actual arguments */
274 };
275 
276 struct value {
277 	data_type_t type;
278 	union {
279 		long number;
280 		struct literal *literal;
281 	} v;
282 };
283 
284 struct valist {
285 	struct valist *next;
286 	struct value value;
287 };
288 
289 struct case_stmt {
290 	struct case_stmt *next;
291 	struct mu_locus_range locus;
292 	struct valist *valist;
293 	NODE *node;
294 };
295 
296 struct switch_stmt {
297 	NODE *node;                 /* Condition */
298 	struct case_stmt *cases;    /* Switch branches */
299 	/* Auxiliary data for code generation */
300 	size_t tabsize;             /* Size of the XLAT table */
301 	size_t off;                 /* Offset of the table in DS */
302 	struct switch_stmt *next;   /* Link to the next switch statement */
303 };
304 
305 struct cast_node {
306 	data_type_t data_type;
307 	NODE *node;
308 };
309 
310 struct positional_arg {
311 	data_type_t data_type;
312 	int number;
313 };
314 
315 struct progdecl {
316 	enum smtp_state tag;
317 	size_t auto_count;
318 	NODE *tree;
319 };
320 
321 struct funcdecl {
322 	struct function *func;
323 	size_t auto_count;
324 	NODE *tree;
325 };
326 
327 struct throw_node {
328 	int code;
329 	NODE *expr;
330 };
331 
332 struct var_ref {
333 	struct variable *variable;  /* Variable being referenced */
334 	size_t nframes;             /* Number of frames to skip */
335 };
336 
337 struct regcomp_data {
338 	NODE *expr;
339 	int flags;
340 	size_t regind;
341 };
342 
343 struct loop_node {
344 	struct literal *ident;
345 	NODE *stmt;
346 	NODE *for_stmt;
347 	NODE *beg_while;
348 	NODE *end_while;
349 	NODE *body;
350 };
351 
352 struct argx_node {
353 	int nargs;
354 	NODE *node;
355 };
356 
357 struct sedcomp_node {
358 	size_t index;
359 	NODE *expr; /* Substitution expression */
360 	int flags;
361 };
362 
363 struct sed_node {
364 	NODE *comp;
365 	NODE *arg;
366 };
367 
368 #include "node-type.h"
369 
370 /* Parse tree node */
371 struct node {
372 	NODE *next;                   /* Link to the next node */
373 	enum node_type type;          /* Node type */
374 	struct mu_locus_range locus;           /* Corresponding input location */
375 	union {
376 		struct literal *literal;
377 		long number;
378 		struct if_node cond;
379 		struct bin_node bin;
380 		struct un_node un;
381 		struct return_node ret;
382 		struct header_node hdr;
383 		struct builtin_node builtin;
384 		NODE *node;
385 		struct concat_node concat;
386 		struct var_ref var_ref;
387 		struct asgn_node asgn;
388 		void *val;
389 		struct catch_node catch;
390 		struct try_node try;
391 		struct throw_node throw;
392 		struct function_call call;
393 		struct switch_stmt switch_stmt;
394 		struct cast_node cast;
395 		struct positional_arg arg;
396 		struct progdecl progdecl;
397 		struct funcdecl funcdecl;
398 		struct regcomp_data regcomp_data;
399 		struct sym_regex *regex;
400 		struct loop_node loop;
401 		struct argx_node argx;
402 		struct sedcomp_node sedcomp;
403 		struct sed_node sed;
404 	} v;
405 };
406 
407 struct stmtlist {
408 	NODE *head;
409 	NODE *tail;
410 };
411 
412 struct exmask {
413 	struct exmask *next;
414 	struct bitmask bm;
415 	int all;                /* If 1, set all bits in the exmask */
416 	size_t off;             /* Offset of the table in DS */
417 };
418 
419 
420 /* Expressions, built-in functions and variables */
421 
422 typedef struct eval_environ *eval_environ_t;  /* Evaluation environment */
423 typedef unsigned long prog_counter_t;         /* Program counter */
424 
425 /* Data types */
426 
427 #define SYMENT_STRUCT(name)			\
428 	char *name;\
429 	unsigned refcnt
430 
431 #define SYM_VOLATILE    0x01  /* Variable can change outside of the compiled
432 				 code */
433 #define SYM_REFERENCED  0x02  /* Variable is referenced */
434 #define SYM_INITIALIZED 0x04  /* Variable is initialized by set */
435 #define SYM_PRECIOUS    0x08  /* Variable is precious, i.e. is not affected
436 				 by rset */
437 #define SYM_EXTERN      0x10  /* Symbol is external (for future use) */
438 #define SYM_STATIC      0x20  /* Symbol is static */
439 #define SYM_PUBLIC      0x40  /* Symbol is public */
440 
441 #define SYM_PASSTOGGLE  0x80  /* Symbol processing pass toggle, used
442 				 in _ds_variable_count_fun and friends. */
443 
444 struct mf_symbol {
445 	SYMENT_STRUCT(name);       /* Variable name */
446 	struct mf_symbol *alias;
447 	struct module *module;     /* Backlink to the module where it is
448 				      defined */
449 	struct mu_locus_range locus;        /* Location of the definition */
450 	unsigned flags;            /* SYM_ flags */
451 };
452 
453 #define MFD_BUILTIN_CAPTURE    0x01  /* Builtin needs message capturing */
454 #define MFD_BUILTIN_VARIADIC   0x02  /* Builtin is variadic */
455 #define MFD_BUILTIN_NO_PROMOTE 0x04  /* For variadic functions:
456 					do not promote varargs to string */
457 #define MFD_BUILTIN_REGEX_FLAGS 0x08 /* The built-in takes the value of the
458 					regex_flags as the first (implicit)
459 					argument. */
460 
461 struct builtin {
462 	SYMENT_STRUCT(name);
463 	void (*handler) (eval_environ_t); /* C handler */
464 	size_t parmcount;                 /* Number of parameters */
465 	data_type_t *parmtype;            /* Parameter types */
466 	size_t optcount;                  /* Number of optional parameters
467 					     (size_t) -1 for varargs */
468 	data_type_t rettype;              /* Return type */
469 	unsigned statemask;               /* States where the function can
470 					     be used */
471 	int flags;                        /* Flags */
472 };
473 
474 struct function {      /* User-defined function */
475 	struct mf_symbol sym;
476 	NODE *node;              /* Function definition (syntax tree) */
477 	prog_counter_t entry;    /* Entry point to the function code */
478 	struct exmask *exmask;   /* Exception mask */
479 	unsigned statemask;      /* States where the function can
480 				    be used */
481 	size_t parmcount;        /* Number of parameters */
482 	size_t optcount;         /* Number of optional parameters */
483 	int varargs;             /* 1 if function takes variable number of
484 				    arguments */
485 	data_type_t *parmtype;   /* Parameter types */
486 	data_type_t rettype;     /* Return type */
487 };
488 
489 typedef enum {
490 	storage_extern,
491 	storage_auto,
492 	storage_param
493 } storage_class_t;
494 
495 struct variable {
496 	struct mf_symbol sym;
497 	data_type_t type;          /* Variable type */
498 	storage_class_t storage_class; /* Storage class */
499 	size_t off;                /* Offset in the data segment */
500 	size_t ord;                /* Ordinal number in the parmlist
501 				      (for parameters only) */
502 	size_t *addrptr;           /* Address pointer (for built-in vars) */
503 	struct variable *shadowed; /* Points to the variable shadowed by
504 				      this one */
505 	int initialized;           /* Is the variable initialized (for
506 				      automatic variables) */
507 	mu_list_t xref;            /* List of struct mu_locus_range */
508 	struct variable *next;     /* Next variable in this class */
509 };
510 
511 struct literal {
512 	SYMENT_STRUCT(text);
513 	unsigned flags;            /* SYM_* flags */
514 	size_t off;                /* Offset in DS */
515 	struct sym_regex *regex;   /* Any correspondig regexes */
516 };
517 
518 struct constant {
519 	struct mf_symbol sym;
520 	struct value value;        /* Constant value */
521 };
522 
523 #define REG_EXTENDED_NAME "extended"
524 #define REG_ICASE_NAME "icase"
525 #define REG_NEWLINE_NAME "newline"
526 
527 #define REGEX_STRING_BUFSIZE \
528  (sizeof(REG_EXTENDED_NAME) + \
529   sizeof(REG_ICASE_NAME) + \
530   sizeof(REG_NEWLINE_NAME) + 1)
531 
532 char *regex_flags_to_string(int flags, char *buf, size_t size);
533 
534 int add_legacy_milter_port(const char *str);
535 
536 void mflog_setup(void);
537 void mflog_reopen(const char *tag);
538 
539 void builtin_setup(void);
540 void pragma_setup(void);
541 
542 void print_code(void);
543 void print_xref(void);
544 void print_used_macros(void);
545 
546 /* symbols.c */
547 extern struct symtab *stab_module;
548 extern struct symtab *stab_builtin;
549 extern struct symtab *stab_pragma;
550 extern struct symtab *stab_literal;
551 
552 void init_symbols(void);
553 void free_symbols(void);
554 
555 struct mf_symbol *symbol_resolve_alias(struct mf_symbol *sp);
556 void va_builtin_install (char *name, void (*handler) (eval_environ_t),
557 			 data_type_t rettype, size_t argcount, ...);
558 void va_builtin_install_ex (char *name, void (*handler) (eval_environ_t),
559 			    unsigned statemsk,
560 			    data_type_t rettype, size_t argcount,
561 			    size_t optcount, int flags, ...);
562 
563 const struct builtin *builtin_lookup(const char *name);
564 struct variable *variable_install(const char *name);
565 struct variable *variable_lookup(const char *name);
566 struct variable *variable_replace(const char *name, struct variable *newvar);
567 void variable_remove(struct variable *var);
568 struct variable *builtin_variable_install(const char *name,
569 					  data_type_t type,
570 					  unsigned flags,
571 					  size_t *addrptr);
572 void defer_initialize_variable(const char *arg, const char *val,
573 			       struct mu_locus_range const *locus);
574 
575 int variable_or_constant_lookup(const char *name, void **dptr);
576 
577 struct function *function_install(const char *name,
578 				  size_t parmcnt, size_t optcnt, int varargs,
579 				  data_type_t *parmtypes,
580 				  data_type_t rettype,
581 				  const struct mu_locus_range *locus);
582 struct function *function_lookup(const char *name);
583 struct literal *literal_lookup(const char *text);
584 struct constant *define_constant(const char *name, struct value *value,
585 				 unsigned flags,
586 				 struct mu_locus_range const *loc);
587 const struct constant *constant_lookup(const char *name);
588 const struct value *constant_lookup_value(const char *name);
589 
590 struct sym_regex {
591 	struct literal *lit;        /* Corresponding literal */
592 	int regflags;               /* Compilation flags */
593 	unsigned flags;             /* VAR_* flags */
594 	size_t index;               /* Index in the regtab */
595 	struct sym_regex *next; /* Next sym_regex with the same name, but
596 				   different regflags */
597 };
598 
599 struct sym_regex *install_regex(struct literal *lit, unsigned regflags);
600 
601 void install_alias(const char *name, struct function *fun,
602 		   const struct mu_locus_range *locus);
603 
604 
605 struct rt_regex {
606 	int compiled;
607 	regex_t re;
608 	size_t expr;
609 	int regflags;
610 };
611 
612 void register_regex(struct sym_regex *rp);
613 void finalize_regex(void);
614 
615 size_t next_transform_index(void);
616 void install_transform(size_t index, transform_t tp);
617 transform_t get_transform(size_t index);
618 
619 
620 struct pragma {
621 	SYMENT_STRUCT(name);
622 	int minargs;
623 	int maxargs;
624 	void (*handler) (int, char **, const char *);
625 };
626 
627 void install_pragma(const char *name, int minargs, int maxargs,
628 		    void (*handler) (int, char **, const char *));
629 const struct pragma *lookup_pragma(const char *name);
630 
631 
632 enum import_type {
633 	import_literal,
634 	import_regex,
635 	import_transform
636 };
637 
638 struct import_rule {
639 	struct import_rule *next;  /* Next rule */
640 	enum import_type type;     /* Type of this rule */
641 	struct literal *literal;   /* Literal */
642 	int neg;                   /* Negate regex */
643 	regex_t re;                /* Regular expression */
644 	transform_t xform;         /* Transform expression */
645 };
646 
647 struct import_rule_list {
648 	struct import_rule *head, *tail;
649 };
650 
651 struct import_rule *import_rule_create(struct literal *lit);
652 
653 
654 enum module_namespace {
655 	namespace_function,
656 	namespace_variable,
657 	namespace_constant
658 };
659 #define MODULE_NAMESPACE_COUNT 3
660 
661 struct module {
662 	SYMENT_STRUCT(name);
663 	const char *file;
664 	const char *dclname;
665 	unsigned flags;
666 	struct symtab *symtab[MODULE_NAMESPACE_COUNT];
667 	struct import_rule *import_rules;
668 	struct module_list *submodule_head, *submodule_tail;
669 	mu_list_t /* of struct input_file_ident */ incl_sources;
670 };
671 
672 struct module_list {
673 	struct module *module;
674 	struct module_list *next;
675 };
676 
677 extern struct module *top_module;
678 
679 #define MODULE_SYMTAB(m,ns) ((m)->symtab[ns])
680 #define TOP_MODULE_SYMTAB(ns) MODULE_SYMTAB(top_module,ns)
681 int set_top_module(const char *name, const char *file,
682 		   struct import_rule *import_rules,
683 		   struct mu_locus_range const *locus);
684 void pop_top_module(void);
685 void collect_modules(struct module ***pmodv, size_t *pmodc);
686 int module_symtab_enumerate(enum module_namespace ns, symtab_enumerator_t fun,
687 			    void *data);
688 
689 
690 /* Preprocessor functions */
691 struct input_file_ident {
692 	ino_t i_node;
693 	dev_t device;
694 };
695 
696 void include_path_setup(void);
697 
698 FILE *pp_extrn_start(const char *name, pid_t *ppid);
699 void pp_extrn_shutdown(FILE *file, pid_t pid);
700 int preprocess_input(void);
701 
702 void require_module(const char *modname, struct import_rule *import_rules);
703 
704 int parse_include(const char *text, int once);
705 int parse_require(const char *text, mf_yyltype_t *loc);
706 int parse_line(char *text, struct mu_locus_point *pt);
707 int parse_line_cpp(char *text, struct mu_locus_point *pt);
708 void alloc_ext_pp(void);
709 int source_lookup(struct input_file_ident *idptr);
710 
711 #define LEX_NONE   0
712 #define LEX_ONCE   1
713 #define LEX_MODULE 2
714 
715 int lex_new_source(const char *name, int once);
716 void lex_bye(void);
717 void lex_drain_input(void);
718 void tie_in_onblock(int enable);
719 
720 /* Parser functions */
721 int yyparse();
722 int yylex();
723 int yyerror(char const *s);
724 void free_parser_data(void);
725 void add_include_dir(const char *dir);
726 int parse_program(char *name, int ydebug);
727 void parse_pragma(const char *text);
728 struct mu_locus_range const *get_locus(void);
729 const char *msgmod_opcode_str(enum msgmod_opcode opcode);
730 const char *sfsistat_str(sfsistat s);
731 const char *mf_exception_str(unsigned ex);
732 
733 mf_exception  mf_status_to_exception(mf_status s);
734 
735 const char *storage_class_str(storage_class_t sc);
736 enum smtp_state string_to_state(const char *name);
737 const char *state_to_string(enum smtp_state state);
738 void parse_error(const char *fmt, ...) MU_PRINTFLIKE(1,2);
739 void parse_error_locus(struct mu_locus_range const *loc, const char *fmt, ...)
740 	               MU_PRINTFLIKE(2,3);
741 void parse_warning(const char *fmt, ...) MU_PRINTFLIKE(1,2);
742 void parse_warning_locus(struct mu_locus_range const *loc, const char *fmt, ...)
743 	                 MU_PRINTFLIKE(2,3);
744 
745 void print_syntax_tree(void);
746 void print_macros(void);
747 const char *function_name(void);
748 void lex_setup(void);
749 struct literal *string_alloc(const char *str, size_t len);
750 void string_begin(void);
751 void string_add(const char *str, size_t len);
752 void string_add_char(unsigned char c);
753 struct literal *string_finish(void);
754 void free_string_space(void);
755 void init_string_space(void);
756 data_type_t builtin_const_value(const char *s, size_t len,
757 				const char **sval, long *nval);
758 const char *symbit_to_qualifier(unsigned f);
759 void advance_line(void);
760 
761 char *mf_strdup(const char *str);
762 
763 void regex_push(void);
764 void regex_pop(void);
765 
766 void register_macro(enum smtp_state tag, const char *macro);
767 char *get_stage_macro_string(enum gacopyz_stage i);
768 struct exmask *exmask_create(void);
769 
770 void variable_check_initialized(struct variable *var,
771 				struct mu_locus_range const *loc);
772 
773 
774 /* Data types and declarations for handling compiled configuration code */
775 
776 /* Entry points for each SMTP state */
777 extern prog_counter_t entry_point[smtp_state_count];
778 
779 /* Functions for accessing %rcpt_count */
780 unsigned long get_rcpt_count(eval_environ_t env);
781 void clear_rcpt_count(eval_environ_t env);
782 void incr_rcpt_count(eval_environ_t env);
783 
784 void set_last_poll_helo(eval_environ_t env, const char *text);
785 void set_last_poll_greeting(eval_environ_t env, const char *text);
786 void set_last_poll_host(eval_environ_t env, const char *host_addr);
787 void set_last_poll_sent(eval_environ_t env, const char *send);
788 void set_last_poll_recv(eval_environ_t env, const char *recv);
789 
790 void set_milter_client_address(eval_environ_t env, milter_sockaddr_t *addr,
791 			       socklen_t len);
792 void set_milter_server_address(eval_environ_t env, milter_sockaddr_t *addr,
793 			       socklen_t len);
794 void set_milter_server_id(eval_environ_t env, const char *id);
795 
796 void set_cache_used(eval_environ_t env, int value);
797 
798 /* Evaluation environment functions */
799 eval_environ_t
800 create_environment(SMFICTX *ctx,
801 		   const char *(*getsym)(void *data, const char *str),
802 		   int (*setreply)(void *data, char *code, char *xcode,
803 				   char *message),
804 		   void (*msgmod)(void *data, struct msgmod_closure *op),
805 		   void *data);
806 void destroy_environment(eval_environ_t env);
807 void env_init(eval_environ_t env);
808 void env_init_dataseg(eval_environ_t env);
809 void env_save_catches(eval_environ_t env);
810 
811 # ifndef ATTRIBUTE_NORETURN
812 #  define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
813 # endif
814 
815 void env_throw(eval_environ_t env, mf_exception exception,
816 	       const char *fmt, ...)
817 	       MU_PRINTFLIKE(3,4) ATTRIBUTE_NORETURN;
818 void env_throw_bi(eval_environ_t env, mf_exception exception,
819 		  const char *biname,
820 		  const char *fmt, ...) MU_PRINTFLIKE(4,5) ATTRIBUTE_NORETURN;
821 void env_throw_0(eval_environ_t env, mf_exception exception,
822 		 size_t text_off) ATTRIBUTE_NORETURN;
823 
824 void env_push_string(eval_environ_t env, char *arg);
825 void env_push_number(eval_environ_t env, long arg);
826 void env_push_pointer(eval_environ_t env, void *arg);
827 void env_make_frame(eval_environ_t env);
828 void env_make_frame0(eval_environ_t env);
829 void env_leave_frame(eval_environ_t env, int nargs);
830 int env_set_variable(eval_environ_t env, char *ident, char *value);
831 int eval_environment(eval_environ_t env, prog_counter_t pc);
832 sfsistat environment_get_status(eval_environ_t env);
833 const char *environment_get_null_symbol(eval_environ_t env,
834 					struct mu_locus_range *locus);
835 SMFICTX *env_get_context(eval_environ_t env);
836 size_t env_get_line_count(eval_environ_t env);
837 int env_get_stream(eval_environ_t env, mu_stream_t *pstr);
838 int env_get_header(eval_environ_t env, mu_header_t *hdr);
839 void env_reposition(eval_environ_t env);
840 int env_capture_start(eval_environ_t env);
841 int env_capture_write(eval_environ_t env, const char *buf, size_t size);
842 int env_capture_write_args(eval_environ_t env, ...);
843 void env_final_gc(eval_environ_t env);
844 
845 void env_msgmod_append(eval_environ_t env, enum msgmod_opcode opcode,
846 		       const char *name, const char *value, unsigned idx);
847 void env_msgmod_clear(eval_environ_t env);
848 size_t env_msgmod_count(eval_environ_t env);
849 int env_msgmod_apply(eval_environ_t env, mu_list_action_t fun, void *data);
850 
851 void capture_on(void);
852 const char *env_get_macro(eval_environ_t env, const char *symbol);
853 
854 void mfl_smtp_io_callback(void *data, const char *key, const char *value);
855 
856 
857 /* Runtime functions */
858 const char *mailfromd_msgid(SMFICTX *ctx);
859 void log_status(sfsistat status, SMFICTX *ctx);
860 void trace(const char *fmt, ...) MU_PRINTFLIKE(1,2);
861 int convert_rate(const char *arg, double *rate);
862 void priv_setup(void);
863 void mailfromd_daemon(void);
864 void save_cmdline(int argc, char **argv);
865 void pp_define(const char *symbol);
866 void test_message_data_init(eval_environ_t env);
867 
868 void mailfromd_test(int argc, char **argv);
869 void mailfromd_run(prog_counter_t entry, int argc, char **argv);
870 
871 void milter_enable_state(enum smtp_state state);
872 int milter_session_server(const char *id,
873 			  int fd,
874 			  struct sockaddr const *sa, socklen_t len,
875 			  void *server_data, void *srvman_data);
876 int mfd_callout_session_server(const char *id, int fd,
877 			       struct sockaddr const *sa, socklen_t len,
878 			       void *server_data, void *srvman_data);
879 void milter_setlogmask(int mask);
880 void milter_settimeout(time_t t);
881 
882 int xeval(eval_environ_t env, enum smtp_state tag);
883 
884 int relayed_domain_p(char *name);
885 size_t mem_search(const char *str, int c, size_t size);
886 
887 
888 
889 typedef struct mf_stack *mf_stack_t;
890 mf_stack_t mf_stack_create(size_t elsize, size_t count);
891 void mf_stack_destroy(mf_stack_t *pstk);
892 void mf_stack_push(mf_stack_t stk, void *item);
893 int mf_stack_pop(mf_stack_t stk, void *ptr);
894 int mf_stack_peek(mf_stack_t stk, size_t n, void *ptr);
895 
896 size_t mf_stack_count(mf_stack_t stk);
897 
898 typedef int (*mf_stack_enumerator) (void *item, void *data);
899 
900 int mf_stack_enumerate_desc(mf_stack_t stk, mf_stack_enumerator fun,
901 			    void *data);
902 int mf_stack_enumerate_asc(mf_stack_t stk, mf_stack_enumerator fun,
903 			   void *data);
904 
905 
906 int mf_stream_to_message(mu_stream_t stream, mu_message_t *msg);
907 void mf_add_runtime_params(struct mu_cfg_param *p);
908 
909 
910 /* deprecation.c */
911 void deprecation_warning(const char *fmt, ...) MU_PRINTFLIKE(1,2);
912 void deprecation_warning_locus(const struct mu_locus_range *locus, const char *fmt, ...)
913 	MU_PRINTFLIKE(2,3);
914 
915 void final_deprecation_warning(void);
916 int enable_deprecation_warnings(void);
917 
918 
919 enum fixup_op
920 {
921 	fixup_noop,
922 	fixup_delete_line,
923 	fixup_insert_line,
924 	fixup_append_line,
925 	fixup_replace_line,
926 	fixup_delete_chars,
927 	fixup_insert_chars,
928 	fixup_replace_chars,
929 	fixup_rename_file,
930 	fixup_end
931 };
932 
933 void add_fixup_command(enum fixup_op opcode, mf_yyltype_t *locus, char *arg);
934 void add_fixup_command_fmt(enum fixup_op opcode, mf_yyltype_t *locus,
935 			   const char *fmt, ...)
936 	MU_PRINTFLIKE(3,4);
937 void add_fixup_command_locus(enum fixup_op opcode, const struct mu_locus_range *locus,
938 			     char *arg);
939 void fixup_create_script(void);
940 
941 /* savsrv.c */
942 int callout_session_server(const char *id, int fd,
943 			   struct sockaddr const *sa, socklen_t len,
944 			   void *server_data, void *srvman_data);
945 void trimcrlf(char *buf);
946 
947 /* savclt.c */
948 void schedule_callout(const char *email, const char *ehlo,
949 		      const char *mailfrom,
950 		      const char *client_addr);
951 extern struct sockaddr *callout_server_sa;
952 extern socklen_t callout_server_sa_len;
953 
954 /* exclist.c */
955 void define_exception(struct literal *lit, struct mu_locus_range const *locus);
956 void enumerate_exceptions(int (*efn)(const struct constant *cp,
957 				     const struct literal *lit,
958 				     void *data),
959 			  void *data);
960 void fixup_exceptions(void);
961 void free_exceptions(void);
962 
963 
964