Set protocol to "smtps" after EHLO->STARTTLS->HELO (was "smtp").
[users/jgh/exim.git] / src / src / filter.c
1 /* $Cambridge: exim/src/src/filter.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2004 */
8 /* See the file NOTICE for conditions of use and distribution. */
9
10
11 /* Code for mail filtering functions. */
12
13 #include "exim.h"
14
15
16 /* Command arguments and left/right points in conditions can contain different
17 types of data, depending on the particular command or condition. Originally,
18 (void *) was used as "any old type", with casts, but this gives trouble and
19 warnings in some environments. So now it is done "properly", with a union. We
20 need to declare the structures first because some of them are recursive. */
21
22 struct filter_cmd;
23 struct condition_block;
24
25 union argtypes {
26   struct string_item     *a;
27   BOOL                    b;
28   struct condition_block *c;
29   struct filter_cmd      *f;
30   int                     i;
31   uschar                 *u;
32 };
33
34 /* Local structures used in this module */
35
36 typedef struct filter_cmd {
37   struct filter_cmd *next;
38   int command;
39   BOOL seen;
40   BOOL noerror;
41   union argtypes args[1];
42 } filter_cmd;
43
44 typedef struct condition_block {
45   struct condition_block *parent;
46   int type;
47   BOOL testfor;
48   union argtypes left;
49   union argtypes right;
50 } condition_block;
51
52 /* Miscellaneous other declarations */
53
54 static uschar **error_pointer;
55 static uschar *log_filename;
56 static int  filter_options;
57 static int  line_number;
58 static int  expect_endif;
59 static int  had_else_endif;
60 static int  log_fd;
61 static int  log_mode;
62 static int  output_indent;
63 static BOOL filter_delivered;
64 static BOOL finish_obeyed;
65 static BOOL seen_force;
66 static BOOL seen_value;
67 static BOOL noerror_force;
68
69 enum { had_neither, had_else, had_elif, had_endif };
70
71 static BOOL read_command_list(uschar **, filter_cmd ***, BOOL);
72
73
74 /* The string arguments for the mail command. The header line ones (that are
75 permitted to include \n followed by white space) first, and then the body text
76 one (it can have \n anywhere). Then the file names and once_repeat, which may
77 not contain \n. */
78
79 static char *mailargs[] = {  /* "to" must be first, and */
80   "to",                      /* "cc" and "bcc" must follow */
81   "cc",
82   "bcc",
83   "from",
84   "reply_to",
85   "subject",
86   "extra_headers",           /* miscellaneous added header lines */
87   "text",
88   "file",
89   "log",
90   "once",
91   "once_repeat"
92 };
93
94 /* The count of string arguments */
95
96 #define MAILARGS_STRING_COUNT (sizeof(mailargs)/sizeof(uschar *))
97
98 /* The count of string arguments that are actually passed over as strings
99 (once_repeat is converted to an int). */
100
101 #define mailargs_string_passed (MAILARGS_STRING_COUNT - 1)
102
103 /* This defines the offsets for the arguments; first the string ones, and
104 then the non-string ones. The order must be as above. */
105
106 enum { mailarg_index_to,
107        mailarg_index_cc,
108        mailarg_index_bcc,
109        mailarg_index_from,
110        mailarg_index_reply_to,
111        mailarg_index_subject,
112        mailarg_index_headers,      /* misc headers must be last */
113        mailarg_index_text,         /* text is first after headers */
114        mailarg_index_file,         /* between text and expand are filenames */
115        mailarg_index_log,
116        mailarg_index_once,
117        mailarg_index_once_repeat,  /* a time string */
118        mailarg_index_expand,       /* first non-string argument */
119        mailarg_index_return,
120        mailargs_total              /* total number of arguments */
121        };
122
123 /* Offsets in the data structure for the string arguments (note that
124 once_repeat isn't a string argument at this point.) */
125
126 static int reply_offsets[] = {  /* must be in same order as above */
127   offsetof(reply_item, to),
128   offsetof(reply_item, cc),
129   offsetof(reply_item, bcc),
130   offsetof(reply_item, from),
131   offsetof(reply_item, reply_to),
132   offsetof(reply_item, subject),
133   offsetof(reply_item, headers),
134   offsetof(reply_item, text),
135   offsetof(reply_item, file),
136   offsetof(reply_item, logfile),
137   offsetof(reply_item, oncelog),
138 };
139
140 /* Condition identities and names, with negated versions for some
141 of them. */
142
143 enum { cond_and, cond_or, cond_personal, cond_begins, cond_BEGINS,
144        cond_ends, cond_ENDS, cond_is, cond_IS, cond_matches,
145        cond_MATCHES, cond_contains, cond_CONTAINS, cond_delivered,
146        cond_above, cond_below, cond_errormsg, cond_firsttime,
147        cond_manualthaw, cond_foranyaddress };
148
149 static char *cond_names[] = {
150   "and", "or", "personal",
151   "begins", "BEGINS", "ends", "ENDS",
152   "is", "IS", "matches", "MATCHES", "contains",
153   "CONTAINS", "delivered", "above", "below", "error_message",
154   "first_delivery", "manually_thawed", "foranyaddress" };
155
156 static char *cond_not_names[] = {
157   "", "", "not personal",
158   "does not begin", "does not BEGIN",
159   "does not end", "does not END",
160   "is not", "IS not", "does not match",
161   "does not MATCH", "does not contain", "does not CONTAIN",
162   "not delivered", "not above", "not below", "not error_message",
163   "not first_delivery", "not manually_thawed", "not foranyaddress" };
164
165 /* Tables of binary condition words and their corresponding types. Not easy
166 to amalgamate with the above because of the different variants. */
167
168 static char *cond_words[] = {
169    "BEGIN",
170    "BEGINS",
171    "CONTAIN",
172    "CONTAINS",
173    "END",
174    "ENDS",
175    "IS",
176    "MATCH",
177    "MATCHES",
178    "above",
179    "begin",
180    "begins",
181    "below",
182    "contain",
183    "contains",
184    "end",
185    "ends",
186    "is",
187    "match",
188    "matches"};
189
190 static int cond_word_count = (sizeof(cond_words)/sizeof(uschar *));
191
192 static int cond_types[] = { cond_BEGINS, cond_BEGINS, cond_CONTAINS,
193   cond_CONTAINS, cond_ENDS, cond_ENDS, cond_IS, cond_MATCHES, cond_MATCHES,
194   cond_above, cond_begins, cond_begins, cond_below, cond_contains,
195   cond_contains, cond_ends, cond_ends, cond_is, cond_matches, cond_matches };
196
197 /* Command identities: must be kept in step with the list of command words
198 and the list of expanded argument counts which follow. */
199
200 enum { add_command, defer_command, deliver_command, elif_command, else_command,
201        endif_command, finish_command, fail_command, freeze_command,
202        headers_command, if_command, logfile_command, logwrite_command,
203        mail_command, noerror_command, pipe_command, save_command, seen_command,
204        testprint_command, unseen_command, vacation_command };
205
206 static char *command_list[] = {
207   "add",     "defer",   "deliver", "elif", "else",      "endif",    "finish",
208   "fail",    "freeze",  "headers", "if",   "logfile",   "logwrite", "mail",
209   "noerror", "pipe",    "save",    "seen", "testprint", "unseen",   "vacation"
210 };
211
212 static int command_list_count = sizeof(command_list)/sizeof(uschar *);
213
214 /* This table contains the number of expanded arguments in the bottom 4 bits.
215 If the top bit is set, it means that the default for the command is "seen". */
216
217 static uschar command_exparg_count[] = {
218       2, /* add */
219       1, /* defer */
220   128+2, /* deliver */
221       0, /* elif */
222       0, /* else */
223       0, /* endif */
224       0, /* finish */
225       1, /* fail */
226       1, /* freeze */
227       1, /* headers */
228       0, /* if */
229       1, /* logfile */
230       1, /* logwrite */
231       MAILARGS_STRING_COUNT, /* mail */
232       0, /* noerror */
233   128+0, /* pipe */
234   128+1, /* save */
235       0, /* seen */
236       1, /* testprint */
237       0, /* unseen */
238       MAILARGS_STRING_COUNT /* vacation */
239 };
240
241
242
243 /*************************************************
244 *          Find next significant uschar            *
245 *************************************************/
246
247 /* Function to skip over white space and, optionally, comments.
248
249 Arguments:
250   ptr              pointer to next character
251   comment_allowed  if TRUE, comments (# to \n) are skipped
252
253 Returns:           pointer to next non-whitespace character
254 */
255
256 static uschar *
257 nextsigchar(uschar *ptr, BOOL comment_allowed)
258 {
259 for (;;)
260   {
261   while (isspace(*ptr))
262     {
263     if (*ptr == '\n') line_number++;
264     ptr++;
265     }
266   if (comment_allowed && *ptr == '#')
267     {
268     while (*(++ptr) != '\n' && *ptr != 0);
269     continue;
270     }
271   else break;
272   }
273 return ptr;
274 }
275
276
277
278 /*************************************************
279 *                Read one word                   *
280 *************************************************/
281
282 /* The terminator is white space unless bracket is TRUE, in which
283 case ( and ) terminate.
284
285 Arguments
286   ptr       pointer to next character
287   buffer    where to put the word
288   size      size of buffer
289   bracket   if TRUE, terminate on ( and ) as well as space
290
291 Returns:    pointer to the next significant character after the word
292 */
293
294 static uschar *
295 nextword(uschar *ptr, uschar *buffer, int size, BOOL bracket)
296 {
297 uschar *bp = buffer;
298 while (*ptr != 0 && !isspace(*ptr) &&
299        (!bracket || (*ptr != '(' && *ptr != ')')))
300   {
301   if (bp - buffer < size - 1) *bp++ = *ptr++; else
302     {
303     *error_pointer = string_sprintf("word is too long in line %d of "
304       "filter file (max = %d chars)", line_number, size);
305     break;
306     }
307   }
308 *bp = 0;
309 return nextsigchar(ptr, TRUE);
310 }
311
312
313
314 /*************************************************
315 *                Read one item                   *
316 *************************************************/
317
318 /* Might be a word, or might be a quoted string; in the latter case
319 do the escape stuff.
320
321 Arguments:
322   ptr        pointer to next character
323   buffer     where to put the item
324   size       size of buffer
325   bracket    if TRUE, terminate non-quoted on ( and ) as well as space
326
327 Returns:     the next significant character after the item
328 */
329
330 static uschar *
331 nextitem(uschar *ptr, uschar *buffer, int size, BOOL bracket)
332 {
333 uschar *bp = buffer;
334 if (*ptr != '\"') return nextword(ptr, buffer, size, bracket);
335
336 while (*(++ptr) != 0 && *ptr != '\"' && *ptr != '\n')
337   {
338   if (bp - buffer >= size - 1)
339     {
340     *error_pointer = string_sprintf("string is too long in line %d of "
341       "filter file (max = %d chars)", line_number, size);
342     break;
343     }
344
345   if (*ptr != '\\') *bp++ = *ptr; else
346     {
347     if (isspace(ptr[1]))    /* \<whitespace>NL<whitespace> ignored */
348       {
349       uschar *p = ptr + 1;
350       while (*p != '\n' && isspace(*p)) p++;
351       if (*p == '\n')
352         {
353         line_number++;
354         ptr = p;
355         while (ptr[1] != '\n' && isspace(ptr[1])) ptr++;
356         continue;
357         }
358       }
359
360     *bp++ = string_interpret_escape(&ptr);
361     }
362   }
363
364 if (*ptr == '\"') ptr++;
365   else if (*error_pointer == NULL)
366     *error_pointer = string_sprintf("quote missing at end of string "
367       "in line %d", line_number);
368
369 *bp = 0;
370 return nextsigchar(ptr, TRUE);
371 }
372
373
374
375
376 /*************************************************
377 *          Convert a string + K|M to a number    *
378 *************************************************/
379
380 /*
381 Arguments:
382   s        points to text string
383   OK       set TRUE if a valid number was read
384
385 Returns:   the number, or 0 on error (with *OK FALSE)
386 */
387
388 static int
389 get_number(uschar *s, BOOL *ok)
390 {
391 int value, count;
392 *ok = FALSE;
393 if (sscanf(CS s, "%i%n", &value, &count) != 1) return 0;
394 if (tolower(s[count]) == 'k') { value *= 1024; count++; }
395 if (tolower(s[count]) == 'm') { value *= 1024*1024; count++; }
396 while (isspace((s[count]))) count++;
397 if (s[count] != 0) return 0;
398 *ok = TRUE;
399 return value;
400 }
401
402
403
404 /*************************************************
405 *            Read one condition                  *
406 *************************************************/
407
408 /* A complete condition must be terminated by "then"; bracketed internal
409 conditions must be terminated by a closing bracket. They are read by calling
410 this function recursively.
411
412 Arguments:
413   ptr             points to start of condition
414   condition_block where to hang the created condition block
415   toplevel        TRUE when called at the top level
416
417 Returns:          points to next character after "then"
418 */
419
420 static uschar *
421 read_condition(uschar *ptr, condition_block **cond, BOOL toplevel)
422 {
423 uschar buffer[1024];
424 BOOL testfor = TRUE;
425 condition_block *current_parent = NULL;
426 condition_block **current = cond;
427
428 *current = NULL;
429
430 /* Loop to read next condition */
431
432 for (;;)
433   {
434   condition_block *c;
435
436   /* reaching the end of the input is an error. */
437
438   if (*ptr == 0)
439     {
440     *error_pointer = string_sprintf("\"then\" missing at end of filter file");
441     break;
442     }
443
444   /* Opening bracket at the start of a condition introduces a nested
445   condition, which must be terminated by a closing bracket. */
446
447   if (*ptr == '(')
448     {
449     ptr = read_condition(nextsigchar(ptr+1, TRUE), &c, FALSE);
450     if (*error_pointer != NULL) break;
451     if (*ptr != ')')
452       {
453       *error_pointer = string_sprintf("expected \")\" in line %d of "
454         "filter file", line_number);
455       break;
456       }
457     if (!testfor)
458       {
459       c->testfor = !c->testfor;
460       testfor = TRUE;
461       }
462     ptr = nextsigchar(ptr+1, TRUE);
463     }
464
465
466   /* Closing bracket at the start of a condition is an error. Give an
467   explicit message, as otherwise "unknown condition" would be confusing. */
468
469   else if (*ptr == ')')
470     {
471     *error_pointer = string_sprintf("unexpected \")\" in line %d of "
472       "filter file", line_number);
473     break;
474     }
475
476   /* Otherwise we expect a word or a string. */
477
478   else
479     {
480     ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
481     if (*error_pointer != NULL) break;
482
483     /* "Then" at the start of a condition is an error */
484
485     if (Ustrcmp(buffer, "then") == 0)
486       {
487       *error_pointer = string_sprintf("unexpected \"then\" near line %d of "
488         "filter file", line_number);
489       break;
490       }
491
492     /* "Not" at the start of a condition negates the testing condition. */
493
494     if (Ustrcmp(buffer, "not") == 0)
495       {
496       testfor = !testfor;
497       continue;
498       }
499
500     /* Build a condition block from the specific word. */
501
502     c = store_get(sizeof(condition_block));
503     c->left.u = c->right.u = NULL;
504     c->testfor = testfor;
505     testfor = TRUE;
506
507     /* Check for conditions that start with a keyword */
508
509     if (Ustrcmp(buffer, "delivered") == 0) c->type = cond_delivered;
510     else if (Ustrcmp(buffer, "error_message") == 0) c->type = cond_errormsg;
511     else if (Ustrcmp(buffer, "first_delivery") == 0) c->type = cond_firsttime;
512     else if (Ustrcmp(buffer, "manually_thawed") == 0) c->type = cond_manualthaw;
513
514     /* Personal can be followed by any number of aliases */
515
516     else if (Ustrcmp(buffer, "personal") == 0)
517       {
518       c->type = cond_personal;
519       for (;;)
520         {
521         string_item *aa;
522         uschar *saveptr = ptr;
523         ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
524         if (*error_pointer != NULL) break;
525         if (Ustrcmp(buffer, "alias") != 0)
526           {
527           ptr = saveptr;
528           break;
529           }
530         ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
531         if (*error_pointer != NULL) break;
532         aa = store_get(sizeof(string_item));
533         aa->text = string_copy(buffer);
534         aa->next = c->left.a;
535         c->left.a = aa;
536         }
537       }
538
539     /* Foranyaddress must be followed by a string and a condition enclosed
540     in parentheses, which is handled as a subcondition. */
541
542     else if (Ustrcmp(buffer, "foranyaddress") == 0)
543       {
544       ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
545       if (*error_pointer != NULL) break;
546       if (*ptr != '(')
547         {
548         *error_pointer = string_sprintf("\"(\" expected after \"foranyaddress\" "
549           "near line %d of filter file", line_number);
550         break;
551         }
552
553       c->type = cond_foranyaddress;
554       c->left.u = string_copy(buffer);
555
556       ptr = read_condition(nextsigchar(ptr+1, TRUE), &(c->right.c), FALSE);
557       if (*error_pointer != NULL) break;
558       if (*ptr != ')')
559         {
560         *error_pointer = string_sprintf("expected \")\" in line %d of "
561           "filter file", line_number);
562         break;
563         }
564       if (!testfor)
565         {
566         c->testfor = !c->testfor;
567         testfor = TRUE;
568         }
569       ptr = nextsigchar(ptr+1, TRUE);
570       }
571
572     /* If it's not a word we recognize, then it must be the lefthand
573     operand of one of the comparison words. */
574
575     else
576       {
577       int i;
578       uschar *isptr = NULL;
579
580       c->left.u = string_copy(buffer);
581       ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
582       if (*error_pointer != NULL) break;
583
584       /* Handle "does|is [not]", preserving the pointer after "is" in
585       case it isn't that, but the form "is <string>". */
586
587       if (strcmpic(buffer, US"does") == 0 || strcmpic(buffer, US"is") == 0)
588         {
589         if (buffer[0] == 'i') { c->type = cond_is; isptr = ptr; }
590         if (buffer[0] == 'I') { c->type = cond_IS; isptr = ptr; }
591
592         ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
593         if (*error_pointer != NULL) break;
594         if (strcmpic(buffer, US"not") == 0)
595           {
596           c->testfor = !c->testfor;
597           if (isptr != NULL) isptr = ptr;
598           ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
599           if (*error_pointer != NULL) break;
600           }
601         }
602
603       for (i = 0; i < cond_word_count; i++)
604         {
605         if (Ustrcmp(buffer, cond_words[i]) == 0)
606           {
607           c->type = cond_types[i];
608           break;
609           }
610         }
611
612       /* If an unknown word follows "is" or "is not"
613       it's actually the argument. Reset to read it. */
614
615       if (i >= cond_word_count)
616         {
617         if (isptr != NULL)
618           {
619           ptr = isptr;
620           }
621         else
622           {
623           *error_pointer = string_sprintf("unrecognized condition word \"%s\" "
624             "near line %d of filter file", buffer, line_number);
625           break;
626           }
627         }
628
629       /* Get the RH argument. */
630
631       ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
632       if (*error_pointer != NULL) break;
633       c->right.u = string_copy(buffer);
634       }
635     }
636
637   /* We have read some new condition and set it up in the condition block
638   c; point the current pointer at it, and then deal with what follows. */
639
640   *current = c;
641
642   /* Closing bracket terminates if this is a lower-level condition. Otherwise
643   it is unexpected. */
644
645   if (*ptr == ')')
646     {
647     if (toplevel)
648       *error_pointer = string_sprintf("unexpected \")\" in line %d of "
649         "filter file", line_number);
650     break;
651     }
652
653   /* Opening bracket following a condition is an error; give an explicit
654   message to make it clearer what is wrong. */
655
656   else if (*ptr == '(')
657     {
658     *error_pointer = string_sprintf("unexpected \"(\" in line %d of "
659       "filter file", line_number);
660     break;
661     }
662
663   /* Otherwise the next thing must be one of the words "and", "or" or "then" */
664
665   else
666     {
667     uschar *saveptr = ptr;
668     ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
669     if (*error_pointer != NULL) break;
670
671     /* "Then" terminates a toplevel condition; otherwise a closing bracket
672     has been omitted. Put a string terminator at the start of "then" so
673     that reflecting the condition can be done when testing. */
674
675     if (Ustrcmp(buffer, "then") == 0)
676       {
677       if (toplevel) *saveptr = 0;
678         else *error_pointer = string_sprintf("missing \")\" at end of "
679           "condition near line %d of filter file", line_number);
680       break;
681       }
682
683     /* "And" causes a new condition block to replace the one we have
684     just read, which becomes the left sub-condition. The current pointer
685     is reset to the pointer for the right sub-condition. We have to keep
686     track of the tree of sequential "ands", so as to traverse back up it
687     if an "or" is met. */
688
689     else if (Ustrcmp(buffer, "and") == 0)
690       {
691       condition_block *andc = store_get(sizeof(condition_block));
692       andc->parent = current_parent;
693       andc->type = cond_and;
694       andc->testfor = TRUE;
695       andc->left.c = c;
696       andc->right.u = NULL;    /* insurance */
697       *current = andc;
698       current = &(andc->right.c);
699       current_parent = andc;
700       }
701
702     /* "Or" is similar, but has to be done a bit more carefully to
703     ensure that "and" is more binding. If there's a parent set, we
704     are following a sequence of "and"s and must track back to their
705     start. */
706
707     else if (Ustrcmp(buffer, "or") == 0)
708       {
709       condition_block *orc = store_get(sizeof(condition_block));
710       condition_block *or_parent = NULL;
711
712       if (current_parent != NULL)
713         {
714         while (current_parent->parent != NULL &&
715                current_parent->parent->type == cond_and)
716           current_parent = current_parent->parent;
717
718         /* If the parent has a parent, it must be an "or" parent. */
719
720         if (current_parent->parent != NULL)
721           or_parent = current_parent->parent;
722         }
723
724       orc->parent = or_parent;
725       if (or_parent == NULL) *cond = orc; else
726         or_parent->right.c = orc;
727       orc->type = cond_or;
728       orc->testfor = TRUE;
729       orc->left.c = (current_parent == NULL)? c : current_parent;
730       orc->right.c = NULL;   /* insurance */
731       current = &(orc->right.c);
732       current_parent = orc;
733       }
734
735     /* Otherwise there is a disaster */
736
737     else
738       {
739       *error_pointer = string_sprintf("\"and\" or \"or\" or \"%s\" "
740         "expected near line %d of filter file, but found \"%s\"",
741           toplevel? "then" : ")", line_number, buffer);
742       break;
743       }
744     }
745   }
746
747 return nextsigchar(ptr, TRUE);
748 }
749
750
751
752 /*************************************************
753 *             Ouput the current indent           *
754 *************************************************/
755
756 static void
757 indent(void)
758 {
759 int i;
760 for (i = 0; i < output_indent; i++) debug_printf(" ");
761 }
762
763
764
765 /*************************************************
766 *          Condition printer: for debugging      *
767 *************************************************/
768
769 /*
770 Arguments:
771   c           the block at the top of the tree
772   toplevel    TRUE at toplevel - stops overall brackets
773
774 Returns:      nothing
775 */
776
777 static void
778 print_condition(condition_block *c, BOOL toplevel)
779 {
780 char *name = (c->testfor)? cond_names[c->type] : cond_not_names[c->type];
781 switch(c->type)
782   {
783   case cond_personal:
784   case cond_delivered:
785   case cond_errormsg:
786   case cond_firsttime:
787   case cond_manualthaw:
788   debug_printf("%s", name);
789   break;
790
791   case cond_is:
792   case cond_IS:
793   case cond_matches:
794   case cond_MATCHES:
795   case cond_contains:
796   case cond_CONTAINS:
797   case cond_begins:
798   case cond_BEGINS:
799   case cond_ends:
800   case cond_ENDS:
801   case cond_above:
802   case cond_below:
803   debug_printf("%s %s %s", c->left.u, (char *)name, c->right.u);
804   break;
805
806   case cond_and:
807   if (!c->testfor) debug_printf("not (");
808   print_condition(c->left.c, FALSE);
809   debug_printf(" %s ", cond_names[c->type]);
810   print_condition(c->right.c, FALSE);
811   if (!c->testfor) debug_printf(")");
812   break;
813
814   case cond_or:
815   if (!c->testfor) debug_printf("not (");
816   else if (!toplevel) debug_printf("(");
817   print_condition(c->left.c, FALSE);
818   debug_printf(" %s ", cond_names[c->type]);
819   print_condition(c->right.c, FALSE);
820   if (!toplevel || !c->testfor) debug_printf(")");
821   break;
822
823   case cond_foranyaddress:
824   debug_printf("%s %s (", name, c->left.u);
825   print_condition(c->right.c, FALSE);
826   debug_printf(")");
827   break;
828   }
829 }
830
831
832
833
834 /*************************************************
835 *            Read one filtering command          *
836 *************************************************/
837
838 /*
839 Arguments:
840    pptr        points to pointer to first character of command; the pointer
841                  is updated to point after the last character read
842    lastcmdptr  points to pointer to pointer to last command; used for hanging
843                  on the newly read command
844
845 Returns:       TRUE if command successfully read, else FALSE
846 */
847
848 static BOOL
849 read_command(uschar **pptr, filter_cmd ***lastcmdptr)
850 {
851 int command, i, cmd_bit;
852 filter_cmd *new, **newlastcmdptr;
853 BOOL yield = TRUE;
854 BOOL was_seen_or_unseen = FALSE;
855 BOOL was_noerror = FALSE;
856 uschar buffer[1024];
857 uschar *ptr = *pptr;
858 uschar *saveptr;
859 uschar *fmsg = NULL;
860
861 /* Read the next word and find which command it is. Command words are normally
862 terminated by white space, but there are two exceptions, which are the "if" and
863 "elif" commands. We must allow for them to be terminated by an opening bracket,
864 as brackets are allowed in conditions and users will expect not to require
865 white space here. */
866
867 if (Ustrncmp(ptr, "if(", 3) == 0)
868   {
869   Ustrcpy(buffer, "if");
870   ptr += 2;
871   }
872 else if (Ustrncmp(ptr, "elif(", 5) == 0)
873   {
874   Ustrcpy(buffer, "elif");
875   ptr += 4;
876   }
877 else
878   {
879   ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
880   if (*error_pointer != NULL) return FALSE;
881   }
882
883 for (command = 0; command < command_list_count; command++)
884   if (Ustrcmp(buffer, command_list[command]) == 0) break;
885
886 /* Handle the individual commands */
887
888 switch (command)
889   {
890   /* Add takes two arguments, separated by the word "to". Headers has two
891   arguments, but the first must be "add", "remove", or "charset", and it gets
892   stored in the second argument slot. Neither may be preceded by seen, unseen
893   or noerror. */
894
895   case add_command:
896   case headers_command:
897   if (seen_force || noerror_force)
898     {
899     *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
900       "found before an \"%s\" command near line %d",
901         command_list[command], line_number);
902     yield = FALSE;
903     }
904   /* Fall through */
905
906   /* Logwrite, logfile, pipe, and testprint all take a single argument, save
907   and logfile can have an option second argument for the mode, and deliver can
908   have "errors_to <address>" in a system filter, or in a user filter if the
909   address is the current one. */
910
911   case deliver_command:
912   case logfile_command:
913   case logwrite_command:
914   case pipe_command:
915   case save_command:
916   case testprint_command:
917
918   ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
919   if (*buffer == 0)
920     *error_pointer = string_sprintf("\"%s\" requires an argument "
921       "near line %d of filter file", command_list[command], line_number);
922
923   if (*error_pointer != NULL) yield = FALSE; else
924     {
925     union argtypes argument, second_argument;
926
927     argument.u = second_argument.u = NULL;
928
929     if (command == add_command)
930       {
931       argument.u = string_copy(buffer);
932       ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
933       if (*buffer == 0 || Ustrcmp(buffer, "to") != 0)
934         *error_pointer = string_sprintf("\"to\" expected in \"add\" command "
935           "near line %d of filter file", line_number);
936       else
937         {
938         ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
939         if (*buffer == 0)
940           *error_pointer = string_sprintf("value missing after \"to\" "
941             "near line %d of filter file", line_number);
942         else second_argument.u = string_copy(buffer);
943         }
944       }
945
946     else if (command == headers_command)
947       {
948       if (Ustrcmp(buffer, "add") == 0)
949         second_argument.b = TRUE;
950       else
951         if (Ustrcmp(buffer, "remove") == 0) second_argument.b = FALSE;
952       else
953         if (Ustrcmp(buffer, "charset") == 0)
954           second_argument.b = TRUE_UNSET;
955       else
956         {
957         *error_pointer = string_sprintf("\"add\", \"remove\", or \"charset\" "
958           "expected after \"headers\" near line %d of filter file",
959             line_number);
960         yield = FALSE;
961         }
962
963       if (!system_filtering && second_argument.b != TRUE_UNSET)
964         {
965         *error_pointer = string_sprintf("header addition and removal is "
966           "available only in system filters: near line %d of filter file",
967           line_number);
968         yield = FALSE;
969         break;
970         }
971
972       if (yield)
973         {
974         ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
975         if (*buffer == 0)
976           *error_pointer = string_sprintf("value missing after \"add\", "
977             "\"remove\", or \"charset\" near line %d of filter file",
978               line_number);
979         else argument.u = string_copy(buffer);
980         }
981       }
982
983     /* The argument for the logwrite command must end in a newline, and the save
984     and logfile commands can have an optional mode argument. The deliver
985     command can have an optional "errors_to <address>" for a system filter,
986     or for a user filter if the address is the user's address. Accept the
987     syntax here - the check is later. */
988
989     else
990       {
991       if (command == logwrite_command)
992         {
993         int len = Ustrlen(buffer);
994         if (len == 0 || buffer[len-1] != '\n') Ustrcat(buffer, "\n");
995         }
996
997       argument.u = string_copy(buffer);
998
999       if (command == save_command || command == logfile_command)
1000         {
1001         if (isdigit(*ptr))
1002           {
1003           ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1004           second_argument.i = (int)Ustrtol(buffer, NULL, 8);
1005           }
1006         else second_argument.i = -1;
1007         }
1008
1009       else if (command == deliver_command)
1010         {
1011         uschar *save_ptr = ptr;
1012         ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1013         if (Ustrcmp(buffer, "errors_to") == 0)
1014           {
1015           ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1016           second_argument.u = string_copy(buffer);
1017           }
1018         else ptr = save_ptr;
1019         }
1020       }
1021
1022     /* Set up the command block. Seen defaults TRUE for delivery commands,
1023     FALSE for logging commands, and it doesn't matter for testprint, as
1024     that doesn't change the "delivered" status. */
1025
1026     if (*error_pointer != NULL) yield = FALSE; else
1027       {
1028       new = store_get(sizeof(filter_cmd) + sizeof(union argtypes));
1029       new->next = NULL;
1030       **lastcmdptr = new;
1031       *lastcmdptr = &(new->next);
1032       new->command = command;
1033       new->seen = seen_force? seen_value : command_exparg_count[command] >= 128;
1034       new->noerror = noerror_force;
1035       new->args[0] = argument;
1036       new->args[1] = second_argument;
1037       }
1038     }
1039   break;
1040
1041
1042   /* Elif, else and endif just set a flag if expected. */
1043
1044   case elif_command:
1045   case else_command:
1046   case endif_command:
1047   if (expect_endif > 0)
1048     had_else_endif = (command == elif_command)? had_elif :
1049                      (command == else_command)? had_else : had_endif;
1050   else
1051     {
1052     *error_pointer = string_sprintf("unexpected \"%s\" command near "
1053       "line %d of filter file", buffer, line_number);
1054     yield = FALSE;
1055     }
1056   break;
1057
1058
1059   /* Defer, freeze, and fail are available only if permitted. */
1060
1061   case defer_command:
1062   cmd_bit = RDO_DEFER;
1063   goto DEFER_FREEZE_FAIL;
1064
1065   case fail_command:
1066   cmd_bit = RDO_FAIL;
1067   goto DEFER_FREEZE_FAIL;
1068
1069   case freeze_command:
1070   cmd_bit = RDO_FREEZE;
1071
1072   DEFER_FREEZE_FAIL:
1073   if ((filter_options & cmd_bit) == 0)
1074     {
1075     *error_pointer = string_sprintf("filtering command \"%s\" is disabled: "
1076       "near line %d of filter file", buffer, line_number);
1077     yield = FALSE;
1078     break;
1079     }
1080
1081   /* A text message can be provided after the "text" keyword, or
1082   as a string in quotes. */
1083
1084   saveptr = ptr;
1085   ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1086   if (*saveptr != '\"' && (*buffer == 0 || Ustrcmp(buffer, "text") != 0))
1087     {
1088     ptr = saveptr;
1089     fmsg = US"";
1090     }
1091   else
1092     {
1093     if (*saveptr != '\"')
1094       ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1095     fmsg = string_copy(buffer);
1096     }
1097
1098   /* Drop through and treat as "finish", but never set "seen". */
1099
1100   seen_value = FALSE;
1101
1102   /* Finish has no arguments; fmsg defaults to NULL */
1103
1104   case finish_command:
1105   new = store_get(sizeof(filter_cmd));
1106   new->next = NULL;
1107   **lastcmdptr = new;
1108   *lastcmdptr = &(new->next);
1109   new->command = command;
1110   new->seen = seen_force? seen_value : FALSE;
1111   new->args[0].u = fmsg;
1112   break;
1113
1114
1115   /* Seen, unseen, and noerror are not allowed before if, which takes a
1116   condition argument and then and else sub-commands. */
1117
1118   case if_command:
1119   if (seen_force || noerror_force)
1120     {
1121     *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1122       "found before an \"if\" command near line %d",
1123         line_number);
1124     yield = FALSE;
1125     }
1126
1127   /* Set up the command block for if */
1128
1129   new = store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1130   new->next = NULL;
1131   **lastcmdptr = new;
1132   *lastcmdptr = &(new->next);
1133   new->command = command;
1134   new->seen = FALSE;
1135   new->args[0].u = NULL;
1136   new->args[1].u = new->args[2].u = NULL;
1137   new->args[3].u = ptr;
1138
1139   /* Read the condition */
1140
1141   ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1142   if (*error_pointer != NULL) { yield = FALSE; break; }
1143
1144   /* Read the commands to be obeyed if the condition is true */
1145
1146   newlastcmdptr = &(new->args[1].f);
1147   if (!read_command_list(&ptr, &newlastcmdptr, TRUE)) yield = FALSE;
1148
1149   /* If commands were successfully read, handle the various possible
1150   terminators. There may be a number of successive "elif" sections. */
1151
1152   else
1153     {
1154     while (had_else_endif == had_elif)
1155       {
1156       filter_cmd *newnew =
1157         store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1158       new->args[2].f = newnew;
1159       new = newnew;
1160       new->next = NULL;
1161       new->command = command;
1162       new->seen = FALSE;
1163       new->args[0].u = NULL;
1164       new->args[1].u = new->args[2].u = NULL;
1165       new->args[3].u = ptr;
1166
1167       ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1168       if (*error_pointer != NULL) { yield = FALSE; break; }
1169       newlastcmdptr = &(new->args[1].f);
1170       if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1171         yield = FALSE;
1172       }
1173
1174     if (yield == FALSE) break;
1175
1176     /* Handle termination by "else", possibly following one or more
1177     "elsif" sections. */
1178
1179     if (had_else_endif == had_else)
1180       {
1181       newlastcmdptr = &(new->args[2].f);
1182       if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1183         yield = FALSE;
1184       else if (had_else_endif != had_endif)
1185         {
1186         *error_pointer = string_sprintf("\"endif\" missing near line %d of "
1187           "filter file", line_number);
1188         yield = FALSE;
1189         }
1190       }
1191
1192     /* Otherwise the terminator was "endif" - this is checked by
1193     read_command_list(). The pointer is already set to NULL. */
1194     }
1195
1196   /* Reset the terminator flag. */
1197
1198   had_else_endif = had_neither;
1199   break;
1200
1201
1202   /* The mail & vacation commands have a whole slew of keyworded arguments.
1203   The final argument values are the file expand and return message booleans,
1204   whose offsets are defined in mailarg_index_{expand,return}. Although they
1205   are logically booleans, because they are stored in a uschar * value, we use
1206   NULL and not FALSE, to keep 64-bit compilers happy. */
1207
1208   case mail_command:
1209   case vacation_command:
1210   new = store_get(sizeof(filter_cmd) + mailargs_total * sizeof(union argtypes));
1211   new->next = NULL;
1212   new->command = command;
1213   new->seen = seen_force? seen_value : FALSE;
1214   new->noerror = noerror_force;
1215   for (i = 0; i < mailargs_total; i++) new->args[i].u = NULL;
1216
1217   /* Read keyword/value pairs until we hit one that isn't. The data
1218   must contain only printing chars plus tab, though the "text" value
1219   can also contain newlines. The "file" keyword can be preceded by the
1220   word "expand", and "return message" has no data. */
1221
1222   for (;;)
1223     {
1224     uschar *saveptr = ptr;
1225     ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1226     if (*error_pointer != NULL)
1227       {
1228       yield = FALSE;
1229       break;
1230       }
1231
1232     /* Ensure "return" is followed by "message"; that's a complete option */
1233
1234     if (Ustrcmp(buffer, "return") == 0)
1235       {
1236       new->args[mailarg_index_return].u = US"";  /* not NULL => TRUE */
1237       ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1238       if (Ustrcmp(buffer, "message") != 0)
1239         {
1240         *error_pointer = string_sprintf("\"return\" not followed by \"message\" "
1241           " near line %d of filter file", line_number);
1242         yield = FALSE;
1243         break;
1244         }
1245       continue;
1246       }
1247
1248     /* Ensure "expand" is followed by "file", then fall through to process the
1249     file keyword. */
1250
1251     if (Ustrcmp(buffer, "expand") == 0)
1252       {
1253       new->args[mailarg_index_expand].u = US"";  /* not NULL => TRUE */
1254       ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1255       if (Ustrcmp(buffer, "file") != 0)
1256         {
1257         *error_pointer = string_sprintf("\"expand\" not followed by \"file\" "
1258           " near line %d of filter file", line_number);
1259         yield = FALSE;
1260         break;
1261         }
1262       }
1263
1264     /* Scan for the keyword */
1265
1266     for (i = 0; i < MAILARGS_STRING_COUNT; i++)
1267       if (Ustrcmp(buffer, mailargs[i]) == 0) break;
1268
1269     /* Not found keyword; assume end of this command */
1270
1271     if (i >= MAILARGS_STRING_COUNT)
1272       {
1273       ptr = saveptr;
1274       break;
1275       }
1276
1277     /* Found keyword, read the data item */
1278
1279     ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1280     if (*error_pointer != NULL)
1281       {
1282       yield = FALSE;
1283       break;
1284       }
1285     else new->args[i].u = string_copy(buffer);
1286     }
1287
1288   /* If this is the vacation command, apply some default settings to
1289   some of the arguments. */
1290
1291   if (command == vacation_command)
1292     {
1293     if (new->args[mailarg_index_file].u == NULL)
1294       {
1295       new->args[mailarg_index_file].u = string_copy(US".vacation.msg");
1296       new->args[mailarg_index_expand].u = US"";   /* not NULL => TRUE */
1297       }
1298     if (new->args[mailarg_index_log].u == NULL)
1299       new->args[mailarg_index_log].u = string_copy(US".vacation.log");
1300     if (new->args[mailarg_index_once].u == NULL)
1301       new->args[mailarg_index_once].u = string_copy(US".vacation");
1302     if (new->args[mailarg_index_once_repeat].u == NULL)
1303       new->args[mailarg_index_once_repeat].u = string_copy(US"7d");
1304     if (new->args[mailarg_index_subject].u == NULL)
1305       new->args[mailarg_index_subject].u = string_copy(US"On vacation");
1306     }
1307
1308   /* Join the address on to the chain of generated addresses */
1309
1310   **lastcmdptr = new;
1311   *lastcmdptr = &(new->next);
1312   break;
1313
1314
1315   /* Seen and unseen just set flags */
1316
1317   case seen_command:
1318   case unseen_command:
1319   if (seen_force)
1320     {
1321     *error_pointer = string_sprintf("\"seen\" or \"unseen\" repeated "
1322       "near line %d", line_number);
1323     yield = FALSE;
1324     }
1325   seen_value = (command == seen_command);
1326   seen_force = TRUE;
1327   was_seen_or_unseen = TRUE;
1328   break;
1329
1330
1331   /* So does noerror */
1332
1333   case noerror_command:
1334   noerror_force = TRUE;
1335   was_noerror = TRUE;
1336   break;
1337
1338
1339   /* Oops */
1340
1341   default:
1342   *error_pointer = string_sprintf("unknown filtering command \"%s\" "
1343     "near line %d of filter file", buffer, line_number);
1344   yield = FALSE;
1345   break;
1346   }
1347
1348 if (!was_seen_or_unseen && !was_noerror)
1349   {
1350   seen_force = FALSE;
1351   noerror_force = FALSE;
1352   }
1353
1354 *pptr = ptr;
1355 return yield;
1356 }
1357
1358
1359
1360 /*************************************************
1361 *              Read a list of commands           *
1362 *************************************************/
1363
1364 /* If condional is TRUE, the list must be terminated
1365 by the words "else" or "endif".
1366
1367 Arguments:
1368   pptr        points to pointer to next character; the pointer is updated
1369   lastcmdptr  points to pointer to pointer to previously-read command; used
1370                 for hanging on the new command
1371   conditional TRUE if this command is the subject of a condition
1372
1373 Returns:      TRUE on success
1374 */
1375
1376 static BOOL
1377 read_command_list(uschar **pptr, filter_cmd ***lastcmdptr, BOOL conditional)
1378 {
1379 if (conditional) expect_endif++;
1380 had_else_endif = had_neither;
1381 while (**pptr != 0 && had_else_endif == had_neither)
1382   {
1383   if (!read_command(pptr, lastcmdptr)) return FALSE;
1384   *pptr = nextsigchar(*pptr, TRUE);
1385   }
1386 if (conditional)
1387   {
1388   expect_endif--;
1389   if (had_else_endif == had_neither)
1390     {
1391     *error_pointer = US"\"endif\" missing at end of filter file";
1392     return FALSE;
1393     }
1394   }
1395 return TRUE;
1396 }
1397
1398
1399
1400
1401 /*************************************************
1402 *             Test a condition                   *
1403 *************************************************/
1404
1405 /*
1406 Arguments:
1407   c              points to the condition block; c->testfor indicated whether
1408                    it's a positive or negative condition
1409   toplevel       TRUE if called from "if" directly; FALSE otherwise
1410
1411 Returns:         TRUE if the condition is met
1412 */
1413
1414 static BOOL
1415 test_condition(condition_block *c, BOOL toplevel)
1416 {
1417 BOOL yield;
1418 const pcre *re;
1419 uschar *exp[2], *p, *pp;
1420 const uschar *regcomp_error = NULL;
1421 int regcomp_error_offset;
1422 int val[2];
1423 int i;
1424
1425 if (c == NULL) return TRUE;  /* does this ever occur? */
1426
1427 switch (c->type)
1428   {
1429   case cond_and:
1430   yield = test_condition(c->left.c, FALSE) &&
1431           *error_pointer == NULL &&
1432           test_condition(c->right.c, FALSE);
1433   break;
1434
1435   case cond_or:
1436   yield = test_condition(c->left.c, FALSE) ||
1437           (*error_pointer == NULL &&
1438           test_condition(c->right.c, FALSE));
1439   break;
1440
1441   /* The personal test is meaningless in a system filter. The tests are now in
1442   a separate function (so Sieve can use them). However, an Exim filter does not
1443   scan Cc: (hence the FALSE argument). */
1444
1445   case cond_personal:
1446   yield = system_filtering? FALSE : filter_personal(c->left.a, FALSE);
1447   break;
1448
1449   case cond_delivered:
1450   yield = filter_delivered;
1451   break;
1452
1453   /* Only TRUE if a message is actually being processed; FALSE for address
1454   testing and verification. */
1455
1456   case cond_errormsg:
1457   yield = message_id[0] != 0 &&
1458     (sender_address == NULL || sender_address[0] == 0);
1459   break;
1460
1461   /* Only FALSE if a message is actually being processed; TRUE for address
1462   and filter testing and verification. */
1463
1464   case cond_firsttime:
1465   yield = filter_test != NULL || message_id[0] == 0 || deliver_firsttime;
1466   break;
1467
1468   /* Only TRUE if a message is actually being processed; FALSE for address
1469   testing and verification. */
1470
1471   case cond_manualthaw:
1472   yield = message_id[0] != 0 && deliver_manual_thaw;
1473   break;
1474
1475   /* The foranyaddress condition loops through a list of addresses */
1476
1477   case cond_foranyaddress:
1478   p = c->left.u;
1479   pp = expand_string(p);
1480   if (pp == NULL)
1481     {
1482     *error_pointer = string_sprintf("failed to expand \"%s\" in "
1483       "filter file: %s", p, expand_string_message);
1484     return FALSE;
1485     }
1486
1487   yield = FALSE;
1488   parse_allow_group = TRUE;     /* Allow group syntax */
1489
1490   while (*pp != 0)
1491     {
1492     uschar *error;
1493     int start, end, domain;
1494     int saveend;
1495
1496     p = parse_find_address_end(pp, FALSE);
1497     saveend = *p;
1498
1499     *p = 0;
1500     filter_thisaddress =
1501       parse_extract_address(pp, &error, &start, &end, &domain, FALSE);
1502     *p = saveend;
1503
1504     if (filter_thisaddress != NULL)
1505       {
1506       if ((filter_test != NULL && debug_selector != 0) ||
1507           (debug_selector & D_filter) != 0)
1508         {
1509         indent();
1510         debug_printf("Extracted address %s\n", filter_thisaddress);
1511         }
1512       yield = test_condition(c->right.c, FALSE);
1513       }
1514
1515     if (yield) break;
1516     if (saveend == 0) break;
1517     pp = p + 1;
1518     }
1519
1520   parse_allow_group = FALSE;      /* Reset group syntax flags */
1521   parse_found_group = FALSE;
1522   break;
1523
1524   /* All other conditions have left and right values that need expanding;
1525   on error, it doesn't matter what value is returned. */
1526
1527   default:
1528   p = c->left.u;
1529   for (i = 0; i < 2; i++)
1530     {
1531     exp[i] = expand_string(p);
1532     if (exp[i] == NULL)
1533       {
1534       *error_pointer = string_sprintf("failed to expand \"%s\" in "
1535         "filter file: %s", p, expand_string_message);
1536       return FALSE;
1537       }
1538     p = c->right.u;
1539     }
1540
1541   /* Inner switch for the different cases */
1542
1543   switch(c->type)
1544     {
1545     case cond_is:
1546     yield = strcmpic(exp[0], exp[1]) == 0;
1547     break;
1548
1549     case cond_IS:
1550     yield = Ustrcmp(exp[0], exp[1]) == 0;
1551     break;
1552
1553     case cond_contains:
1554     yield = strstric(exp[0], exp[1], FALSE) != NULL;
1555     break;
1556
1557     case cond_CONTAINS:
1558     yield = Ustrstr(exp[0], exp[1]) != NULL;
1559     break;
1560
1561     case cond_begins:
1562     yield = strncmpic(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1563     break;
1564
1565     case cond_BEGINS:
1566     yield = Ustrncmp(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1567     break;
1568
1569     case cond_ends:
1570     case cond_ENDS:
1571       {
1572       int len = Ustrlen(exp[1]);
1573       uschar *s = exp[0] + Ustrlen(exp[0]) - len;
1574       yield = (s < exp[0])? FALSE :
1575         ((c->type == cond_ends)? strcmpic(s, exp[1]) : Ustrcmp(s, exp[1])) == 0;
1576       }
1577     break;
1578
1579     case cond_matches:
1580     case cond_MATCHES:
1581     if ((filter_test != NULL && debug_selector != 0) ||
1582         (debug_selector & D_filter) != 0)
1583       {
1584       debug_printf("Match expanded arguments:\n");
1585       debug_printf("  Subject = %s\n", exp[0]);
1586       debug_printf("  Pattern = %s\n", exp[1]);
1587       }
1588
1589     re = pcre_compile(CS exp[1],
1590       PCRE_COPT | ((c->type == cond_matches)? PCRE_CASELESS : 0),
1591       (const char **)&regcomp_error, &regcomp_error_offset, NULL);
1592
1593     if (re == NULL)
1594       {
1595       *error_pointer = string_sprintf("error while compiling "
1596         "regular expression \"%s\": %s at offset %d",
1597         exp[1], regcomp_error, regcomp_error_offset);
1598       return FALSE;
1599       }
1600
1601     yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1);
1602     break;
1603
1604     /* For above and below, convert the strings to numbers */
1605
1606     case cond_above:
1607     case cond_below:
1608     for (i = 0; i < 2; i++)
1609       {
1610       val[i] = get_number(exp[i], &yield);
1611       if (!yield)
1612         {
1613         *error_pointer = string_sprintf("malformed numerical string \"%s\"",
1614           exp[i]);
1615         return FALSE;
1616         }
1617       }
1618     yield = (c->type == cond_above)? (val[0] > val[1]) : (val[0] < val[1]);
1619     break;
1620     }
1621   break;
1622   }
1623
1624 if ((filter_test != NULL && debug_selector != 0) ||
1625     (debug_selector & D_filter) != 0)
1626   {
1627   indent();
1628   debug_printf("%sondition is %s: ",
1629     toplevel? "C" : "Sub-c",
1630     (yield == c->testfor)? "true" : "false");
1631   print_condition(c, TRUE);
1632   debug_printf("\n");
1633   }
1634
1635 return yield == c->testfor;
1636 }
1637
1638
1639
1640 /*************************************************
1641 *          Interpret chain of commands           *
1642 *************************************************/
1643
1644 /* In testing state, just say what would be done rather than doing it. The
1645 testprint command just expands and outputs its argument in testing state, and
1646 does nothing otherwise.
1647
1648 Arguments:
1649   commands    points to chain of commands to interpret
1650   generated   where to hang newly-generated addresses
1651
1652 Returns:      FF_DELIVERED     success, a significant action was taken
1653               FF_NOTDELIVERED  success, no significant action
1654               FF_DEFER         defer requested
1655               FF_FAIL          fail requested
1656               FF_FREEZE        freeze requested
1657               FF_ERROR         there was a problem
1658 */
1659
1660 static int
1661 interpret_commands(filter_cmd *commands, address_item **generated)
1662 {
1663 uschar *s;
1664 int mode;
1665 address_item *addr;
1666 BOOL condition_value;
1667
1668 while (commands != NULL)
1669   {
1670   int ff_ret;
1671   uschar *fmsg, *ff_name;
1672   uschar *expargs[MAILARGS_STRING_COUNT];
1673
1674   int i, n[2];
1675
1676   /* Expand the relevant number of arguments for the command that are
1677   not NULL. */
1678
1679   for (i = 0; i < (command_exparg_count[commands->command] & 15); i++)
1680     {
1681     uschar *ss = commands->args[i].u;
1682     if (ss == NULL)
1683       {
1684       expargs[i] = NULL;
1685       }
1686     else
1687       {
1688       expargs[i] = expand_string(ss);
1689       if (expargs[i] == NULL)
1690         {
1691         *error_pointer = string_sprintf("failed to expand \"%s\" in "
1692           "%s command: %s", ss, command_list[commands->command],
1693           expand_string_message);
1694         return FF_ERROR;
1695         }
1696       }
1697     }
1698
1699   /* Now switch for each command, setting the "delivered" flag if any of them
1700   have "seen" set. */
1701
1702   if (commands->seen) filter_delivered = TRUE;
1703
1704   switch(commands->command)
1705     {
1706     case add_command:
1707     for (i = 0; i < 2; i++)
1708       {
1709       uschar *ss = expargs[i];
1710       uschar *end;
1711
1712       if (i == 1 && (*ss++ != 'n' || ss[1] != 0))
1713         {
1714         *error_pointer = string_sprintf("unknown variable \"%s\" in \"add\" "
1715           "command", expargs[i]);
1716         return FF_ERROR;
1717         }
1718
1719       /* Allow for "--" at the start of the value (from -$n0) for example */
1720       if (i == 0) while (ss[0] == '-' && ss[1] == '-') ss += 2;
1721
1722       n[i] = (int)Ustrtol(ss, &end, 0);
1723       if (*end != 0)
1724         {
1725         *error_pointer = string_sprintf("malformed number \"%s\" in \"add\" "
1726           "command", ss);
1727         return FF_ERROR;
1728         }
1729       }
1730
1731     filter_n[n[1]] += n[0];
1732     if (filter_test != NULL) printf("Add %d to n%d\n", n[0], n[1]);
1733     break;
1734
1735     /* A deliver command's argument must be a valid address. Its optional
1736     second argument (system filter only) must also be a valid address. */
1737
1738     case deliver_command:
1739     for (i = 0; i < 2; i++)
1740       {
1741       s = expargs[i];
1742       if (s != NULL)
1743         {
1744         int start, end, domain;
1745         uschar *error;
1746         uschar *ss = parse_extract_address(s, &error, &start, &end, &domain,
1747           FALSE);
1748         if (ss != NULL)
1749           expargs[i] = ((filter_options & RDO_REWRITE) != 0)?
1750             rewrite_address(ss, TRUE, FALSE, global_rewrite_rules,
1751               rewrite_existflags) :
1752             rewrite_address_qualify(ss, TRUE);
1753         else
1754           {
1755           *error_pointer = string_sprintf("malformed address \"%s\" in "
1756             "filter file: %s", s, error);
1757           return FF_ERROR;
1758           }
1759         }
1760       }
1761
1762     /* Stick the errors address into a simple variable, as it will
1763     be referenced a few times. Check that the caller is permitted to
1764     specify it. */
1765
1766     s = expargs[1];
1767
1768     if (s != NULL && !system_filtering)
1769       {
1770       uschar *ownaddress = expand_string(US"$local_part@$domain");
1771       if (strcmpic(ownaddress, s) != 0)
1772         {
1773         *error_pointer = US"errors_to must point to the caller's address";
1774         return FF_ERROR;
1775         }
1776       }
1777
1778     /* Test case: report what would happen */
1779
1780     if (filter_test != NULL)
1781       {
1782       indent();
1783       printf("%seliver message to: %s%s%s%s\n",
1784         (commands->seen)? "D" : "Unseen d",
1785         expargs[0],
1786         commands->noerror? " (noerror)" : "",
1787         (s != NULL)? " errors_to " : "",
1788         (s != NULL)? s : US"");
1789       }
1790
1791     /* Real case. */
1792
1793     else
1794       {
1795       DEBUG(D_filter) debug_printf("Filter: %sdeliver message to: %s%s%s%s\n",
1796         (commands->seen)? "" : "unseen ",
1797         expargs[0],
1798         commands->noerror? " (noerror)" : "",
1799         (s != NULL)? " errors_to " : "",
1800         (s != NULL)? s : US"");
1801
1802       /* Create the new address and add it to the chain, setting the
1803       af_ignore_error flag if necessary, and the errors address, which can be
1804       set in a system filter and to the local address in user filters. */
1805
1806       addr = deliver_make_addr(expargs[0], TRUE);  /* TRUE => copy s */
1807       addr->p.errors_address = (s == NULL)?
1808         s : string_copy(s);                        /* Default is NULL */
1809       if (commands->noerror) setflag(addr, af_ignore_error);
1810       addr->next = *generated;
1811       *generated = addr;
1812       }
1813     break;
1814
1815     case save_command:
1816     s = expargs[0];
1817     mode = commands->args[1].i;
1818
1819     /* Test case: report what would happen */
1820
1821     if (filter_test != NULL)
1822       {
1823       indent();
1824       if (mode < 0)
1825         printf("%save message to: %s%s\n", (commands->seen)?
1826           "S" : "Unseen s", s, commands->noerror? " (noerror)" : "");
1827       else
1828         printf("%save message to: %s %04o%s\n", (commands->seen)?
1829           "S" : "Unseen s", s, mode, commands->noerror? " (noerror)" : "");
1830       }
1831
1832     /* Real case: Ensure save argument starts with / if there is a home
1833     directory to prepend. */
1834
1835     else
1836       {
1837       DEBUG(D_filter) debug_printf("Filter: %ssave message to: %s%s\n",
1838         (commands->seen)? "" : "unseen ", s,
1839         commands->noerror? " (noerror)" : "");
1840       if (s[0] != '/' && deliver_home != NULL && deliver_home[0] != 0)
1841         s = string_sprintf("%s/%s", deliver_home, s);
1842
1843       /* Create the new address and add it to the chain, setting the
1844       af_pfr and af_file flags, the af_ignore_error flag if necessary, and the
1845       mode value. */
1846
1847       addr = deliver_make_addr(s, TRUE);  /* TRUE => copy s */
1848       setflag(addr, af_pfr|af_file);
1849       if (commands->noerror) setflag(addr, af_ignore_error);
1850       addr->mode = mode;
1851       addr->next = *generated;
1852       *generated = addr;
1853       }
1854     break;
1855
1856     case pipe_command:
1857     s = string_copy(commands->args[0].u);
1858     if (filter_test != NULL)
1859       {
1860       indent();
1861       printf("%sipe message to: %s%s\n", (commands->seen)?
1862         "P" : "Unseen p", s, commands->noerror? " (noerror)" : "");
1863       }
1864     else /* Ensure pipe command starts with | */
1865       {
1866       DEBUG(D_filter) debug_printf("Filter: %spipe message to: %s%s\n",
1867         (commands->seen)? "" : "unseen ", s,
1868         commands->noerror? " (noerror)" : "");
1869       if (s[0] != '|') s = string_sprintf("|%s", s);
1870
1871       /* Create the new address and add it to the chain, setting the
1872       af_ignore_error flag if necessary. Set the af_expand_pipe flag so that
1873       each command argument is expanded in the transport after the command
1874       has been split up into separate arguments. */
1875
1876       addr = deliver_make_addr(s, TRUE);  /* TRUE => copy s */
1877       setflag(addr, af_pfr|af_expand_pipe);
1878       if (commands->noerror) setflag(addr, af_ignore_error);
1879       addr->next = *generated;
1880       *generated = addr;
1881
1882       /* If there are any numeric variables in existence (e.g. after a regex
1883       condition), or if $thisaddress is set, take a copy for use in the
1884       expansion. Note that we can't pass NULL for filter_thisaddress, because
1885       NULL terminates the list. */
1886
1887       if (expand_nmax >= 0 || filter_thisaddress != NULL)
1888         {
1889         int i;
1890         int ecount = (expand_nmax >= 0)? expand_nmax : -1;
1891         uschar **ss = store_get(sizeof(uschar *) * (ecount + 3));
1892         addr->pipe_expandn = ss;
1893         if (filter_thisaddress == NULL) filter_thisaddress = US"";
1894         *ss++ = string_copy(filter_thisaddress);
1895         for (i = 0; i <= expand_nmax; i++)
1896           *ss++ = string_copyn(expand_nstring[i], expand_nlength[i]);
1897         *ss = NULL;
1898         }
1899       }
1900     break;
1901
1902     /* Set up the file name and mode, and close any previously open
1903     file. */
1904
1905     case logfile_command:
1906     log_mode = commands->args[1].i;
1907     if (log_mode == -1) log_mode = 0600;
1908     if (log_fd >= 0)
1909       {
1910       close(log_fd);
1911       log_fd = -1;
1912       }
1913     log_filename = expargs[0];
1914     if (filter_test != NULL)
1915       {
1916       indent();
1917       printf("%sogfile %s\n", (commands->seen)? "Seen l" : "L", log_filename);
1918       }
1919     break;
1920
1921     case logwrite_command:
1922     s = expargs[0];
1923
1924     if (filter_test != NULL)
1925       {
1926       indent();
1927       printf("%sogwrite \"%s\"\n", (commands->seen)? "Seen l" : "L",
1928         string_printing(s));
1929       }
1930
1931     /* Attempt to write to a log file only if configured as permissible.
1932     Logging may be forcibly skipped for verifying or testing. */
1933
1934     else if ((filter_options & RDO_LOG) != 0)   /* Locked out */
1935       {
1936       DEBUG(D_filter)
1937         debug_printf("filter log command aborted: euid=%ld\n",
1938         (long int)geteuid());
1939       *error_pointer = US"logwrite command forbidden";
1940       return FF_ERROR;
1941       }
1942     else if ((filter_options & RDO_REALLOG) != 0)
1943       {
1944       int len;
1945       DEBUG(D_filter) debug_printf("writing filter log as euid %ld\n",
1946         (long int)geteuid());
1947       if (log_fd < 0)
1948         {
1949         if (log_filename == NULL)
1950           {
1951           *error_pointer = US"attempt to obey \"logwrite\" command "
1952             "without a previous \"logfile\"";
1953           return FF_ERROR;
1954           }
1955         log_fd = Uopen(log_filename, O_CREAT|O_APPEND|O_WRONLY, log_mode);
1956         if (log_fd < 0)
1957           {
1958           *error_pointer = string_open_failed(errno, "filter log file \"%s\"",
1959             log_filename);
1960           return FF_ERROR;
1961           }
1962         }
1963       len = Ustrlen(s);
1964       if (write(log_fd, s, len) != len)
1965         {
1966         *error_pointer = string_sprintf("write error on file \"%s\": %s",
1967           log_filename, strerror(errno));
1968         return FF_ERROR;
1969         }
1970       }
1971     else
1972       {
1973       DEBUG(D_filter) debug_printf("skipping logwrite (verifying or testing)\n");
1974       }
1975     break;
1976
1977     /* Header addition and removal is available only in the system filter. The
1978     command is rejected at parse time otherwise. However "headers charset" is
1979     always permitted. */
1980
1981     case headers_command:
1982       {
1983       int subtype = commands->args[1].i;
1984       s = expargs[0];
1985
1986       if (filter_test != NULL)
1987         printf("Headers %s \"%s\"\n", (subtype == TRUE)? "add" :
1988           (subtype == FALSE)? "remove" : "charset", string_printing(s));
1989
1990       if (subtype == TRUE)
1991         {
1992         while (isspace(*s)) s++;
1993         if (s[0] != 0)
1994           {
1995           header_add(htype_other, "%s%s", s, (s[Ustrlen(s)-1] == '\n')?
1996             "" : "\n");
1997           header_last->type = header_checkname(header_last, FALSE);
1998           if (header_last->type >= 'a') header_last->type = htype_other;
1999           }
2000         }
2001
2002       else if (subtype == FALSE)
2003         {
2004         int sep = 0;
2005         uschar *ss;
2006         uschar *list = s;
2007         uschar buffer[128];
2008         while ((ss = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
2009                != NULL)
2010           header_remove(0, ss);
2011         }
2012
2013       /* This setting lasts only while the filter is running; on exit, the
2014       variable is reset to the previous value. */
2015
2016       else headers_charset = s;
2017       }
2018     break;
2019
2020     /* Defer, freeze, and fail are available only when explicitly permitted.
2021     These commands are rejected at parse time otherwise. The message can get
2022     very long by the inclusion of message headers; truncate if it is, and also
2023     ensure printing characters so as not to mess up log files. */
2024
2025     case defer_command:
2026     ff_name = US"defer";
2027     ff_ret = FF_DEFER;
2028     goto DEFERFREEZEFAIL;
2029
2030     case fail_command:
2031     ff_name = US"fail";
2032     ff_ret = FF_FAIL;
2033     goto DEFERFREEZEFAIL;
2034
2035     case freeze_command:
2036     ff_name = US"freeze";
2037     ff_ret = FF_FREEZE;
2038
2039     DEFERFREEZEFAIL:
2040     fmsg = expargs[0];
2041     if (Ustrlen(fmsg) > 1024) Ustrcpy(fmsg + 1000, " ... (truncated)");
2042     fmsg = string_printing(fmsg);
2043     *error_pointer = fmsg;
2044
2045     if (filter_test != NULL)
2046       {
2047       indent();
2048       printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg);
2049       }
2050     else DEBUG(D_filter) debug_printf("Filter: %s \"%s\"\n", ff_name, fmsg);
2051     return ff_ret;
2052
2053     case finish_command:
2054     if (filter_test != NULL)
2055       {
2056       indent();
2057       printf("%sinish\n", (commands->seen)? "Seen f" : "F");
2058       }
2059     else
2060       {
2061       DEBUG(D_filter) debug_printf("Filter: %sfinish\n",
2062         (commands->seen)? " Seen " : "");
2063       }
2064     finish_obeyed = TRUE;
2065     return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2066
2067     case if_command:
2068       {
2069       uschar *save_address = filter_thisaddress;
2070       int ok = FF_DELIVERED;
2071       condition_value = test_condition(commands->args[0].c, TRUE);
2072       if (*error_pointer != NULL) ok = FF_ERROR; else
2073         {
2074         output_indent += 2;
2075         ok = interpret_commands(commands->args[condition_value? 1:2].f,
2076           generated);
2077         output_indent -= 2;
2078         }
2079       filter_thisaddress = save_address;
2080       if (finish_obeyed || (ok != FF_DELIVERED && ok != FF_NOTDELIVERED))
2081         return ok;
2082       }
2083     break;
2084
2085
2086     /* To try to catch runaway loops, do not generate mail if the
2087     return path is unset or if a non-trusted user supplied -f <>
2088     as the return path. */
2089
2090     case mail_command:
2091     case vacation_command:
2092     if (return_path == NULL || return_path[0] == 0)
2093       {
2094       if (filter_test != NULL)
2095         printf("%s command ignored because return_path is empty\n",
2096           command_list[commands->command]);
2097       else DEBUG(D_filter) debug_printf("%s command ignored because return_path "
2098         "is empty\n", command_list[commands->command]);
2099       break;
2100       }
2101
2102     /* Check the contents of the strings. The type of string can be deduced
2103     from the value of i.
2104
2105     . If i is equal to mailarg_index_text it's a text string for the body,
2106       where anything goes.
2107
2108     . If i is > mailarg_index_text, we are dealing with a file name, which
2109       cannot contain non-printing characters.
2110
2111     . If i is less than mailarg_index_headers we are dealing with something
2112       that will go in a single message header line, where newlines must be
2113       followed by white space.
2114
2115     . If i is equal to mailarg_index_headers, we have a string that contains
2116       one or more headers. Newlines that are not followed by white space must
2117       be followed by a header name.
2118     */
2119
2120     for (i = 0; i < MAILARGS_STRING_COUNT; i++)
2121       {
2122       uschar *p;
2123       uschar *s = expargs[i];
2124
2125       if (s == NULL) continue;
2126
2127       if (i != mailarg_index_text) for (p = s; *p != 0; p++)
2128         {
2129         int c = *p;
2130         if (i > mailarg_index_text)
2131           {
2132           if (!mac_isprint(c))
2133             {
2134             *error_pointer = string_sprintf("non-printing character in \"%s\" "
2135               "in %s command", string_printing(s),
2136               command_list[commands->command]);
2137             return FF_ERROR;
2138             }
2139           }
2140
2141         /* i < mailarg_index_text */
2142
2143         else if (c == '\n' && !isspace(p[1]))
2144           {
2145           if (i < mailarg_index_headers)
2146             {
2147             *error_pointer = string_sprintf("\\n not followed by space in "
2148               "\"%.1024s\" in %s command", string_printing(s),
2149               command_list[commands->command]);
2150             return FF_ERROR;
2151             }
2152
2153           /* Check for the start of a new header line within the string */
2154
2155           else
2156             {
2157             uschar *pp;
2158             for (pp = p + 1;; pp++)
2159               {
2160               c = *pp;
2161               if (c == ':' && pp != p + 1) break;
2162               if (c == 0 || c == ':' || isspace(*pp))
2163                 {
2164                 *error_pointer = string_sprintf("\\n not followed by space or "
2165                   "valid header name in \"%.1024s\" in %s command",
2166                   string_printing(s), command_list[commands->command]);
2167                 return FF_ERROR;
2168                 }
2169               pp++;
2170               }
2171             p = pp;
2172             }
2173           }
2174         }       /* Loop to scan the string */
2175
2176       /* The string is OK */
2177
2178       commands->args[i].u = s;
2179       }
2180
2181     /* Proceed with mail or vacation command */
2182
2183     if (filter_test != NULL)
2184       {
2185       uschar *to = commands->args[mailarg_index_to].u;
2186       indent();
2187       printf("%sail to: %s%s%s\n", (commands->seen)? "Seen m" : "M",
2188         (to == NULL)? US"<default>" : to,
2189         (commands->command == vacation_command)? " (vacation)" : "",
2190         (commands->noerror)? " (noerror)" : "");
2191       for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2192         {
2193         uschar *arg = commands->args[i].u;
2194         if (arg != NULL)
2195           {
2196           int len = Ustrlen(mailargs[i]);
2197           int indent = (debug_selector != 0)? output_indent : 0;
2198           while (len++ < 7 + indent) printf(" ");
2199           printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2200             (commands->args[mailarg_index_expand].u != NULL &&
2201               Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2202           }
2203         }
2204       if (commands->args[mailarg_index_return].u != NULL)
2205         printf("Return original message\n");
2206       }
2207     else
2208       {
2209       uschar *tt;
2210       uschar *to = commands->args[mailarg_index_to].u;
2211       if (to == NULL) to = expand_string(US"$reply_address");
2212       while (isspace(*to)) to++;
2213
2214       for (tt = to; *tt != 0; tt++)     /* Get rid of newlines so that */
2215         if (*tt == '\n') *tt = ' ';     /* the eventual log line is OK */
2216
2217       DEBUG(D_filter)
2218         {
2219         debug_printf("Filter: %smail to: %s%s%s\n",
2220           (commands->seen)? "seen " : "",
2221           to,
2222           (commands->command == vacation_command)? " (vacation)" : "",
2223           (commands->noerror)? " (noerror)" : "");
2224         for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2225           {
2226           uschar *arg = commands->args[i].u;
2227           if (arg != NULL)
2228             {
2229             int len = Ustrlen(mailargs[i]);
2230             while (len++ < 15) debug_printf(" ");
2231             debug_printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2232               (commands->args[mailarg_index_expand].u != NULL &&
2233                 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2234             }
2235           }
2236         }
2237
2238       /* Create the "address" for the autoreply */
2239
2240       addr = deliver_make_addr(string_sprintf(">%.256s", to), FALSE);
2241       setflag(addr, af_pfr);
2242       if (commands->noerror) setflag(addr, af_ignore_error);
2243       addr->next = *generated;
2244       *generated = addr;
2245       addr->reply = store_get(sizeof(reply_item));
2246       addr->reply->from = NULL;
2247       addr->reply->to = string_copy(to);
2248       addr->reply->file_expand =
2249         commands->args[mailarg_index_expand].u != NULL;
2250       addr->reply->expand_forbid = expand_forbid;
2251       addr->reply->return_message =
2252         commands->args[mailarg_index_return].u != NULL;
2253       addr->reply->once_repeat = 0;
2254
2255       if (commands->args[mailarg_index_once_repeat].u != NULL)
2256         {
2257         addr->reply->once_repeat =
2258           readconf_readtime(commands->args[mailarg_index_once_repeat].u, 0,
2259             FALSE);
2260         if (addr->reply->once_repeat < 0)
2261           {
2262           *error_pointer = string_sprintf("Bad time value for \"once_repeat\" "
2263             "in mail or vacation command: %s",
2264             commands->args[mailarg_index_once_repeat]);
2265           return FF_ERROR;
2266           }
2267         }
2268
2269       /* Set up all the remaining string arguments (those other than "to") */
2270
2271       for (i = 1; i < mailargs_string_passed; i++)
2272         {
2273         uschar *ss = commands->args[i].u;
2274         *((uschar **)(((uschar *)(addr->reply)) + reply_offsets[i])) =
2275           (ss == NULL)? NULL : string_copy(ss);
2276         }
2277       }
2278     break;
2279
2280     case testprint_command:
2281     if (filter_test != NULL || (debug_selector & D_filter) != 0)
2282       {
2283       uschar *s = string_printing(expargs[0]);
2284       if (filter_test == NULL)
2285         debug_printf("Filter: testprint: %s\n", s);
2286       else
2287         printf("Testprint: %s\n", s);
2288       }
2289     }
2290
2291   commands = commands->next;
2292   }
2293
2294 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2295 }
2296
2297
2298
2299 /*************************************************
2300 *        Test for a personal message             *
2301 *************************************************/
2302
2303 /* This function is global so that it can also be called from the code that
2304 implements Sieve filters.
2305
2306 Arguments:
2307   aliases    a chain of aliases
2308   scan_cc    TRUE if Cc: and Bcc: are to be scanned (Exim filters do not)
2309
2310 Returns:     TRUE if the message is deemed to be personal
2311 */
2312
2313 BOOL
2314 filter_personal(string_item *aliases, BOOL scan_cc)
2315 {
2316 uschar *self, *self_from, *self_to;
2317 uschar *psself = NULL, *psself_from = NULL, *psself_to = NULL;
2318 void *reset_point = store_get(0);
2319 BOOL yield;
2320 header_line *h;
2321 int to_count = 2;
2322 int from_count = 9;
2323
2324 /* If any header line in the message starts with "List-", it is not
2325 a personal message. */
2326
2327 for (h = header_list; h != NULL; h = h->next)
2328   {
2329   if (h->type != htype_old && h->slen > 5 &&
2330       strncmpic(h->text, US"List-", 5) == 0)
2331     return FALSE;
2332   }
2333
2334 /* Set up "my" address */
2335
2336 self = string_sprintf("%s@%s", deliver_localpart, deliver_domain);
2337 self_from = rewrite_one(self, rewrite_from, NULL, FALSE, US"",
2338   global_rewrite_rules);
2339 self_to   = rewrite_one(self, rewrite_to, NULL, FALSE, US"",
2340   global_rewrite_rules);
2341
2342
2343 if (self_from == NULL) self_from = self;
2344 if (self_to == NULL) self_to = self;
2345
2346 /* If there's a prefix or suffix set, we must include the prefixed/
2347 suffixed version of the local part in the tests. */
2348
2349 if (deliver_localpart_prefix != NULL || deliver_localpart_suffix != NULL)
2350   {
2351   psself = string_sprintf("%s%s%s@%s",
2352     (deliver_localpart_prefix == NULL)? US"" : deliver_localpart_prefix,
2353     deliver_localpart,
2354     (deliver_localpart_suffix == NULL)? US"" : deliver_localpart_suffix,
2355     deliver_domain);
2356   psself_from = rewrite_one(psself, rewrite_from, NULL, FALSE, US"",
2357     global_rewrite_rules);
2358   psself_to   = rewrite_one(psself, rewrite_to, NULL, FALSE, US"",
2359     global_rewrite_rules);
2360   if (psself_from == NULL) psself_from = psself;
2361   if (psself_to == NULL) psself_to = psself;
2362   to_count += 2;
2363   from_count += 2;
2364   }
2365
2366 /* Do all the necessary tests; the counts are adjusted for {pre,suf}fix */
2367
2368 yield =
2369   (
2370   header_match(US"to:", TRUE, TRUE, aliases, to_count, self, self_to, psself,
2371                psself_to) ||
2372     (scan_cc &&
2373        (
2374        header_match(US"cc:", TRUE, TRUE, aliases, to_count, self, self_to,
2375                              psself, psself_to)
2376        ||
2377        header_match(US"bcc:", TRUE, TRUE, aliases, to_count, self, self_to,
2378                               psself, psself_to)
2379        )
2380     )
2381   ) &&
2382
2383   header_match(US"from:", TRUE, FALSE, aliases, from_count, "^server@",
2384     "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
2385     "^owner-[^@]+@", self, self_from, psself, psself_from) &&
2386
2387   header_match(US"auto-submitted:", FALSE, FALSE, NULL, 1, "auto-") &&
2388   header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
2389
2390   (sender_address == NULL || sender_address[0] != 0);
2391
2392 store_reset(reset_point);
2393 return yield;
2394 }
2395
2396
2397
2398 /*************************************************
2399 *            Interpret a mail filter file        *
2400 *************************************************/
2401
2402 /*
2403 Arguments:
2404   filter      points to the entire file, read into store as a single string
2405   options     controls whether various special things are allowed, and requests
2406               special actions
2407   generated   where to hang newly-generated addresses
2408   error       where to pass back an error text
2409
2410 Returns:      FF_DELIVERED     success, a significant action was taken
2411               FF_NOTDELIVERED  success, no significant action
2412               FF_DEFER         defer requested
2413               FF_FAIL          fail requested
2414               FF_FREEZE        freeze requested
2415               FF_ERROR         there was a problem
2416 */
2417
2418 int
2419 filter_interpret(uschar *filter, int options, address_item **generated,
2420   uschar **error)
2421 {
2422 int i;
2423 int yield = FF_ERROR;
2424 uschar *ptr = filter;
2425 uschar *save_headers_charset = headers_charset;
2426 filter_cmd *commands = NULL;
2427 filter_cmd **lastcmdptr = &commands;
2428
2429 DEBUG(D_route) debug_printf("Filter: start of processing\n");
2430
2431 /* Initialize "not in an if command", set the global flag that is always TRUE
2432 while filtering, and zero the variables. */
2433
2434 expect_endif = 0;
2435 output_indent = 0;
2436 filter_running = TRUE;
2437 for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
2438
2439 /* To save having to pass certain values about all the time, make them static.
2440 Also initialize the line number, for error messages, and the log file
2441 variables. */
2442
2443 filter_options = options;
2444 filter_delivered = FALSE;
2445 finish_obeyed = FALSE;
2446 error_pointer = error;
2447 *error_pointer = NULL;
2448 line_number = 1;
2449 log_fd = -1;
2450 log_mode = 0600;
2451 log_filename = NULL;
2452
2453 /* Scan filter file for syntax and build up an interpretation thereof, and
2454 interpret the compiled commands, and if testing, say whether we ended up
2455 delivered or not, unless something went wrong. */
2456
2457 seen_force = FALSE;
2458 ptr = nextsigchar(ptr, TRUE);
2459
2460 if (read_command_list(&ptr, &lastcmdptr, FALSE))
2461   yield = interpret_commands(commands, generated);
2462
2463 if (filter_test != NULL || (debug_selector & D_filter) != 0)
2464   {
2465   uschar *s = US"";
2466   switch(yield)
2467     {
2468     case FF_DEFER:
2469     s = US"Filtering ended by \"defer\".";
2470     break;
2471
2472     case FF_FREEZE:
2473     s = US"Filtering ended by \"freeze\".";
2474     break;
2475
2476     case FF_FAIL:
2477     s = US"Filtering ended by \"fail\".";
2478     break;
2479
2480     case FF_DELIVERED:
2481     s = US"Filtering set up at least one significant delivery "
2482            "or other action.\n"
2483            "No other deliveries will occur.";
2484     break;
2485
2486     case FF_NOTDELIVERED:
2487     s = US"Filtering did not set up a significant delivery.\n"
2488            "Normal delivery will occur.";
2489     break;
2490
2491     case FF_ERROR:
2492     s = string_sprintf("Filter error: %s", *error);
2493     break;
2494     }
2495
2496   if (filter_test != NULL) printf("%s\n", CS s);
2497     else debug_printf("%s\n", s);
2498   }
2499
2500 /* Close the log file if it was opened, and kill off any numerical variables
2501 before returning. Reset the header decoding charset. */
2502
2503 if (log_fd >= 0) close(log_fd);
2504 expand_nmax = -1;
2505 filter_running = FALSE;
2506 headers_charset = save_headers_charset;
2507
2508 DEBUG(D_route) debug_printf("Filter: end of processing\n");
2509 return yield;
2510 }
2511
2512
2513 /* End of filter.c */