source: trunk/src/sh_nmail.c@ 245

Last change on this file since 245 was 240, checked in by katerina, 15 years ago

Fix bugs in mailer code (ticket #160, #161).

File size: 20.5 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2008 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#if defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
23#define _XOPEN_SOURCE 500
24#endif
25
26#include <string.h>
27#include <time.h>
28
29#if defined(SH_WITH_MAIL)
30
31#undef FIL__
32#define FIL__ _("sh_nmail.c")
33
34#include "samhain.h"
35#include "sh_pthread.h"
36#include "sh_mem.h"
37#include "sh_mail.h"
38#include "sh_tiger.h"
39#include "sh_string.h"
40#include "sh_utils.h"
41#include "sh_fifo.h"
42#include "sh_filter.h"
43#include "sh_mail_int.h"
44
45SH_MUTEX_INIT(mutex_listall, PTHREAD_MUTEX_INITIALIZER);
46SH_MUTEX_INIT(mutex_flush_l, PTHREAD_MUTEX_INITIALIZER);
47
48/* Pointer to last address */
49
50static struct alias * last = NULL;
51
52/* List of mail recipients */
53
54static struct alias * recipient_list = NULL;
55
56static struct alias * compiled_recipient_list = NULL;
57static sh_filter_type compiled_mail_filter = SH_FILT_INIT;
58
59/* List of mail aliases */
60
61static struct alias * alias_list = NULL;
62
63/* List of all recipients */
64
65struct alias * all_recipients = NULL;
66
67int check_double (const char * str, struct alias * list)
68{
69 if (str && list)
70 {
71 struct alias * item = list;
72
73 while (item)
74 {
75 if (0 == strcmp(sh_string_str(item->recipient), str))
76 return -1;
77 item = item->next;
78 }
79 }
80 return 0;
81}
82
83struct alias * add_recipient_intern(const char * str,
84 struct alias * list)
85{
86 if (str)
87 {
88 struct alias * new = SH_ALLOC(sizeof(struct alias));
89 new->next = list;
90 new->mx_list = NULL;
91 new->mail_filter = NULL;
92 new->recipient_list = NULL;
93 new->severity = (-1);
94 new->send_mail = 0;
95 new->recipient = sh_string_new_from_lchar(str, strlen(str));
96 list = new;
97
98 SH_MUTEX_LOCK_UNSAFE(mutex_listall);
99 new->all_next = all_recipients;
100 all_recipients = new;
101 SH_MUTEX_UNLOCK_UNSAFE(mutex_listall);
102 }
103 return list;
104}
105
106int sh_nmail_close_recipient(const char * str)
107{
108 (void) str;
109
110 if (last)
111 {
112 last = NULL;
113 return 0;
114 }
115 return -1;
116}
117
118/* Add a single recipient
119 */
120int sh_nmail_add_recipient(const char * str)
121{
122 if (0 == check_double(str, recipient_list))
123 {
124 recipient_list = add_recipient_intern(str, recipient_list);
125 last = recipient_list;
126 return 0;
127 }
128 return -1;
129}
130
131/* Add a compiled-in address. These share the compiled_mail_filter
132 */
133int sh_nmail_add_compiled_recipient(const char * str)
134{
135 if (0 == check_double(str, compiled_recipient_list))
136 {
137 compiled_recipient_list =
138 add_recipient_intern(str, compiled_recipient_list);
139 if (compiled_recipient_list)
140 compiled_recipient_list->mail_filter = &compiled_mail_filter;
141 last = compiled_recipient_list;
142 return 0;
143 }
144 return -1;
145}
146
147/* Add an alias; format is name ":" comma-delimited_list_of_recipients
148 */
149int sh_nmail_add_alias(const char * str)
150{
151#define SH_ALIASES_RECP_NUM 256
152 size_t lengths[SH_ALIASES_RECP_NUM];
153 unsigned int nfields = SH_ALIASES_RECP_NUM;
154 char * new = sh_util_strdup(str);
155 char * p = strchr(new, ':');
156 char * q;
157
158 if (p && strlen(p) > 1)
159 {
160 unsigned int i;
161 char ** array;
162
163 *p = '\0'; q = p; ++p;
164 if (strlen(new) > 0)
165 {
166 --q; while ((q != new) && *q == ' ') { *q = '\0'; --q; }
167 }
168 else
169 {
170 goto err;
171 }
172
173 if (0 == check_double(new, alias_list))
174 {
175
176 array = split_array_list(p, &nfields, lengths);
177
178 if (array && nfields > 0)
179 {
180 struct alias * newalias = SH_ALLOC(sizeof(struct alias));
181 newalias->recipient_list = NULL;
182 newalias->mail_filter = NULL;
183 newalias->mx_list = NULL;
184 newalias->severity = (-1);
185 /* This is the alias */
186 newalias->recipient = sh_string_new_from_lchar(new, strlen(new));
187
188 for (i = 0; i < nfields; ++i)
189 {
190 if (lengths[i] > 0 &&
191 0 == check_double(array[i], newalias->recipient_list))
192 {
193 newalias->recipient_list =
194 add_recipient_intern(array[i],newalias->recipient_list);
195 }
196 }
197
198 SH_FREE(array);
199
200 if (newalias->recipient_list == NULL)
201 {
202 SH_FREE(newalias);
203 goto err;
204 }
205
206 newalias->next = alias_list;
207 alias_list = newalias;
208 last = alias_list;
209
210 SH_FREE(new);
211 return 0;
212 }
213 }
214 }
215 err:
216 SH_FREE(new);
217 return -1;
218}
219
220
221/* <<<<<<<<<<<<<<< Recipient List >>>>>>>>>>>>>>>>>>>>>> */
222
223static struct alias * find_list (const char * alias, int * single)
224{
225 struct alias * list = NULL;
226
227 *single = 0;
228
229 if (!alias)
230 {
231 list = all_recipients;
232 }
233 else
234 {
235 struct alias * test = alias_list;
236
237 while (test)
238 {
239 if (0 == strcmp(alias, sh_string_str(test->recipient)))
240 {
241 list = test->recipient_list;
242 break;
243 }
244 test = test->next;
245 }
246
247 if (!list)
248 {
249 test = recipient_list;
250 while (test)
251 {
252 if (0 == strcmp(alias, sh_string_str(test->recipient)))
253 {
254 list = test;
255 *single = 1;
256 break;
257 }
258 test = test->next;
259 }
260 }
261
262 if (!list)
263 {
264 test = compiled_recipient_list;
265 while (test)
266 {
267 if (0 == strcmp(alias, sh_string_str(test->recipient)))
268 {
269 list = test;
270 *single = 1;
271 break;
272 }
273 test = test->next;
274 }
275 }
276 }
277 return list;
278}
279
280/* Returns zero (no) or one (yes). Used to tag messages that are
281 * valid for a given recipient (or mailing list alias).
282 */
283int sh_nmail_valid_message_for_alias (int level,
284 const char * message,
285 const char * alias,
286 const void * rcv_info)
287{
288 struct alias * rcv = (struct alias *) rcv_info;
289
290 if (!alias || 0 == strcmp(alias, sh_string_str(rcv->recipient)))
291 {
292 if ((level & rcv->severity) == 0)
293 {
294 return 0;
295 }
296
297 if (rcv->mail_filter)
298 {
299 if (0 != sh_filter_filter(message, rcv->mail_filter))
300 {
301 return 0;
302 }
303 }
304 }
305
306 return 1;
307}
308
309/* Returns number of recipients */
310
311static
312int sh_nmail_compute_recipients (int level, const char * message,
313 const char * alias, int flagit)
314{
315 struct alias * list = NULL;
316 int single = 0;
317 int retval = 0;
318
319 if (flagit)
320 {
321 list = all_recipients;
322 while (list)
323 {
324 list->send_mail = 0;
325 list = list->all_next;
326 }
327 list = NULL;
328 }
329
330 if (message)
331 {
332 int flag = 0;
333
334 list = find_list (alias, &single);
335 if (list == all_recipients)
336 flag = 1;
337
338 while (list)
339 {
340 /* Check severity
341 */
342 if ((list->severity & level) == 0)
343 {
344 if (single) break;
345 if (flag)
346 list = list->all_next;
347 else
348 list = list->next;
349 continue;
350 }
351
352 /* Check filter
353 */
354 if (list->mail_filter &&
355 0 != sh_filter_filter(message, list->mail_filter))
356 {
357 if (single) break;
358 if (flag)
359 list = list->all_next;
360 else
361 list = list->next;
362 continue;
363 }
364
365 /* Mark the entry
366 */
367 if (flagit)
368 list->send_mail = 1;
369 if (flag)
370 list = list->all_next;
371 else
372 list = list->next;
373 ++retval;
374 }
375 }
376 return retval;
377}
378
379/* Is not called from same(recursively) or different thread
380 */
381static
382int sh_nmail_flag_recipients (int level, const char * message,
383 const char * alias)
384{
385 int retval = 0;
386
387 if (message)
388 {
389 SH_MUTEX_LOCK_UNSAFE(mutex_listall);
390 retval = sh_nmail_compute_recipients (level, message, alias, 1);
391 SH_MUTEX_UNLOCK_UNSAFE(mutex_listall);
392 }
393 return retval;
394}
395
396/* Can be called from same thread with mutex_listall held via sh_nmail_flush()
397 */
398static
399int sh_nmail_test_recipients (int level, const char * message,
400 const char * alias)
401{
402 int retval = 0;
403
404 if (message)
405 {
406 if (0 == SH_MUTEX_TRYLOCK_UNSAFE(mutex_flush_l))
407 {
408 SH_MUTEX_LOCK_UNSAFE(mutex_listall);
409 retval = sh_nmail_compute_recipients (level, message, alias, 0);
410 SH_MUTEX_UNLOCK_UNSAFE(mutex_listall);
411 SH_MUTEX_UNLOCK_UNSAFE(mutex_flush_l);
412 }
413 }
414 return retval;
415}
416
417/* <<<<<<<<<<<<<<<<<<< Mail the message >>>>>>>>>>>>>>>>>>>>>> */
418
419SH_MUTEX_RECURSIVE(mutex_nmail_msg);
420SH_MUTEX_STATIC(nmail_lock, PTHREAD_MUTEX_INITIALIZER);
421
422/*
423 * First test list of recipients, then call sh_mail_pushstack().
424 */
425int sh_nmail_pushstack (int level, const char * message,
426 const char * alias)
427{
428 int retval = 0;
429
430 if (0 != sh_nmail_test_recipients (level, message, alias))
431 {
432 retval = sh_mail_pushstack(level, message, alias);
433 }
434 return retval;
435}
436
437static int nmail_count = 0;
438
439/*
440 * First mark list of recipients, then call sh_mail_msg().
441 */
442int sh_nmail_msg (int level, const char * message,
443 const char * alias)
444{
445 volatile int retval = 0;
446
447 /* Need to:
448 * -- wait if different thread, and
449 * -- fail if same thread. */
450 SH_MUTEX_RECURSIVE_INIT(mutex_nmail_msg);
451 SH_MUTEX_RECURSIVE_LOCK(mutex_nmail_msg);
452
453 /* Only same thread beyond this point. We fail
454 * if count > 0 already. */
455 if (0 == SH_MUTEX_TRYLOCK_UNSAFE(nmail_lock))
456 {
457 ++nmail_count;
458 if (nmail_count != 1)
459 {
460 --nmail_count;
461 SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
462 goto cleanup;
463 }
464 SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
465
466 if (0 != sh_nmail_flag_recipients (level, message, alias))
467 {
468 /* Need to keep info for sh_nmail_pushstack()
469 */
470 SH_MUTEX_LOCK(mutex_listall);
471 retval = sh_mail_msg(message);
472 SH_MUTEX_UNLOCK(mutex_listall);
473
474 if (retval != 0)
475 {
476 sh_mail_pushstack(level, message, alias);
477 }
478 }
479 SH_MUTEX_LOCK_UNSAFE(nmail_lock);
480 --nmail_count;
481 SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
482 }
483 cleanup:
484 ; /* label at end of compound statement */
485 SH_MUTEX_RECURSIVE_UNLOCK(mutex_nmail_msg);
486 return retval;
487}
488
489static int sh_nmail_flush_int (void);
490
491int sh_nmail_flush ()
492{
493 int retval = 0;
494
495 if (0 == SH_MUTEX_TRYLOCK_UNSAFE(nmail_lock))
496 {
497 ++nmail_count;
498 if (nmail_count != 1)
499 {
500 --nmail_count;
501 SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
502 return retval;
503 }
504 SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
505
506 retval = sh_nmail_flush_int ();
507
508 SH_MUTEX_LOCK_UNSAFE(nmail_lock);
509 --nmail_count;
510 SH_MUTEX_UNLOCK_UNSAFE(nmail_lock);
511 }
512 return retval;
513}
514
515/* warning: variable ‘list’ might be clobbered by ‘longjmp’ or ‘vfork’*/
516static struct alias ** list_dummy;
517
518/*
519 * Loop over all recipients in stack.
520 * For each distinct one, mark all messages for sending.
521 * Then call sh_mail_msg().
522 */
523
524static int sh_nmail_flush_int ()
525{
526 int retval = 0;
527 sh_string * msg = NULL;
528 sh_string * smsg = NULL;
529 struct alias * list;
530 struct alias * dlist;
531
532 /* warning: variable ‘list’ might be clobbered by ‘longjmp’ or ‘vfork’*/
533 list_dummy = &list;
534
535 SH_MUTEX_LOCK(mutex_listall);
536
537 /* Reset recipient list
538 */
539 list = all_recipients;
540 while (list)
541 {
542 list->send_mail = 0;
543 list = list->all_next;
544 }
545
546 /* Check (i) compiled recipients, (b) aliases, (c) single recipients.
547 * For each, tag all messages, then call sh_mail_msg with
548 * appropriate address list.
549 */
550
551 reset_list(fifo_mail);
552
553 /* Compiled recipients
554 */
555 list = compiled_recipient_list;
556
557 if (list)
558 {
559 msg = tag_list(fifo_mail, sh_string_str(list->recipient),
560 sh_nmail_valid_message_for_alias, list);
561 }
562
563 if (msg)
564 {
565 while (list)
566 {
567 list->send_mail = 1;
568 list = list->next;
569 }
570
571 list = compiled_recipient_list;
572
573 SH_MUTEX_LOCK(mutex_flush_l);
574 (void) sh_mail_msg(sh_string_str(msg));
575 SH_MUTEX_UNLOCK(mutex_flush_l);
576
577 sh_string_destroy(&msg);
578
579 list = compiled_recipient_list;
580 while (list)
581 {
582 list->send_mail = 0;
583 list = list->next;
584 }
585 }
586
587 /* Aliases
588 */
589
590 list = alias_list;
591
592 while (list) {
593
594 /* Work through the recipient list. As smsg stores last msg,
595 * we send a batch whenever msg != smsg, and continue from
596 * that point in the recipient list.
597 */
598 struct alias * lnew;
599
600 while (list)
601 {
602 msg = tag_list(fifo_mail, sh_string_str(list->recipient),
603 sh_nmail_valid_message_for_alias, list);
604
605 if (msg)
606 {
607 if (!smsg) /* init */
608 {
609 smsg = sh_string_copy(msg);
610 }
611 else
612 {
613 if (0 != strcmp(sh_string_str(smsg), sh_string_str(msg)))
614 {
615 /*
616 * Don't set list = list->next here, since we want
617 * to continue with this recipient in the next batch.
618 */
619 sh_string_destroy(&msg);
620 break;
621 }
622 }
623 lnew = list->recipient_list;
624 while (lnew)
625 {
626 lnew->send_mail = 1;
627 lnew= lnew->next;
628 }
629 sh_string_destroy(&msg);
630 }
631 list = list->next;
632 }
633
634 /* Continue here if smsg != msg */
635
636 if (smsg)
637 {
638 SH_MUTEX_LOCK(mutex_flush_l);
639 (void) sh_mail_msg(sh_string_str(smsg));
640 SH_MUTEX_UNLOCK(mutex_flush_l);
641 sh_string_destroy(&smsg);
642 }
643
644 /* Reset old list of recipients (up to current point in list)
645 * and then continue with list from current point on.
646 */
647 dlist = alias_list;
648 while (dlist)
649 {
650 lnew = dlist->recipient_list;
651 while (lnew)
652 {
653 lnew->send_mail = 0;
654 lnew = lnew->next;
655 }
656 dlist = dlist->next;
657 }
658 }
659
660
661 /* Single recipients
662 */
663 list = recipient_list;
664
665 while (list) {
666
667 /* Work through the recipient list. As smsg stores last msg,
668 * we send a batch whenever msg != smsg, and continue from
669 * that point in the recipient list.
670 */
671
672 while (list)
673 {
674 msg = tag_list(fifo_mail, sh_string_str(list->recipient),
675 sh_nmail_valid_message_for_alias, list);
676
677 if (msg)
678 {
679 if (!smsg) /* init */
680 {
681 smsg = sh_string_copy(msg);
682 }
683 else
684 {
685 if (0 != strcmp(sh_string_str(smsg), sh_string_str(msg)))
686 {
687 /*
688 * Don't set list = list->next here, since we want
689 * to continue with this recipient in the next batch.
690 */
691 sh_string_destroy(&msg);
692 break;
693 }
694 }
695 list->send_mail = 1;
696 sh_string_destroy(&msg);
697 }
698 list = list->next;
699 }
700
701 /* Continue here if smsg != msg */
702
703 if (smsg)
704 {
705 SH_MUTEX_LOCK(mutex_flush_l);
706 (void) sh_mail_msg(sh_string_str(smsg));
707 SH_MUTEX_UNLOCK(mutex_flush_l);
708 sh_string_destroy(&smsg);
709 }
710
711 /* Reset old list of recipients (up to current point in list)
712 * and then continue with list from current point on.
713 */
714 dlist = recipient_list;
715 while (dlist)
716 {
717 dlist->send_mail = 0;
718 dlist = dlist->next;
719 }
720 }
721
722 /* Remove all mails for which no recipient failed
723 */
724
725 sh.mailNum.alarm_last -= commit_list(fifo_mail);
726 SH_MUTEX_UNLOCK(mutex_listall);
727
728 return retval;
729}
730
731
732
733/* <<<<<<<<<<<<<<<<<<< Severity >>>>>>>>>>>>>>>>>>>>>> */
734
735/*
736 * -- set severity threshold for recipient or alias
737 */
738int sh_nmail_set_severity (const char * str)
739{
740 if (last == recipient_list || last == alias_list)
741 {
742 if (0 == sh_error_set_level(str, &(last->severity)))
743 {
744 /* All recipients in alias share the severity
745 */
746 if (last == alias_list)
747 {
748 struct alias * ptr = last->recipient_list;
749
750 while (ptr)
751 {
752 ptr->severity = last->severity;
753 ptr = ptr->next;
754 }
755 }
756 return 0;
757 }
758 }
759 return (-1);
760}
761
762/* <<<<<<<<<<<<<<<<<<< Filters >>>>>>>>>>>>>>>>>>>>>> */
763
764
765int sh_nmail_add_generic (const char * str, int flag)
766{
767 if (last)
768 {
769 if (NULL == last->mail_filter)
770 last->mail_filter = sh_filter_alloc();
771
772 /* All recipients in alias share the mail filter
773 */
774 if (last == alias_list)
775 {
776 struct alias * ptr = last->recipient_list;
777
778 while (ptr)
779 {
780 ptr->mail_filter = last->mail_filter;
781 ptr = ptr->next;
782 }
783 }
784
785 return (sh_filter_add (str, last->mail_filter, flag));
786 }
787 return (-1);
788}
789
790/*
791 * -- add keywords to the OR filter
792 */
793int sh_nmail_add_or (const char * str)
794{
795 return sh_nmail_add_generic(str, SH_FILT_OR);
796}
797
798/*
799 * -- add keywords to the AND filter
800 */
801int sh_nmail_add_and (const char * str)
802{
803 return sh_nmail_add_generic(str, SH_FILT_AND);
804}
805
806/*
807 * -- add keywords to the NOT filter
808 */
809int sh_nmail_add_not (const char * str)
810{
811 return sh_nmail_add_generic(str, SH_FILT_NOT);
812}
813
814
815/* <<<<<<<<<<<<<<<<<<< Mailkey per Alias >>>>>>>>>>>>>>>>>>>>>>>>> */
816
817#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
818#include <sys/mman.h>
819#endif
820
821#include "zAVLTree.h"
822
823zAVLTree * mailkeys = NULL;
824
825struct alias_mailkey {
826 char * alias;
827 unsigned int mailcount;
828 time_t id_audit;
829 char mailkey_old[KEY_LEN+1];
830 char mailkey_new[KEY_LEN+1];
831};
832
833static zAVLKey sh_nmail_getkey(void const *item)
834{
835 const struct alias_mailkey * t = (const struct alias_mailkey *) item;
836 return (zAVLKey) t->alias;
837}
838
839/* Return mailkey for alias. If there's no key yet, create it and
840 * store it in the AVL tree.
841 * This is called from sh_mail_msg,
842 * which is called from sh_nmail_msg,
843 * which is protected by a mutex.
844 */
845int sh_nmail_get_mailkey (const char * alias, char * buf, size_t bufsiz,
846 time_t * id_audit)
847{
848 char hashbuf[KEYBUF_SIZE];
849
850 start:
851
852 if (mailkeys)
853 {
854 struct alias_mailkey * t;
855
856 if (!alias)
857 t = (struct alias_mailkey *) zAVLSearch (mailkeys, _("(null)"));
858 else
859 t = (struct alias_mailkey *) zAVLSearch (mailkeys, alias);
860
861 if (t)
862 {
863 /* iterate the key
864 */
865 (void) sl_strlcpy(t->mailkey_new,
866 sh_tiger_hash (t->mailkey_old, TIGER_DATA, KEY_LEN,
867 hashbuf, sizeof(hashbuf)),
868 KEY_LEN+1);
869 (void) sl_strlcpy(buf, t->mailkey_new, bufsiz);
870 ++(t->mailcount);
871 }
872 else
873 {
874 t = SH_ALLOC(sizeof(struct alias_mailkey));
875
876 MLOCK(t, sizeof(struct alias_mailkey));
877
878 if (!alias)
879 t->alias = sh_util_strdup(_("(null)"));
880 else
881 t->alias = sh_util_strdup(alias);
882
883 t->mailcount = 0;
884 t->id_audit = time(NULL);
885
886 BREAKEXIT(sh_util_keyinit);
887 (void) sh_util_keyinit (t->mailkey_old, KEY_LEN+1);
888
889 /* iterate the key
890 */
891 (void) sl_strlcpy(t->mailkey_new,
892 sh_tiger_hash (t->mailkey_old, TIGER_DATA, KEY_LEN,
893 hashbuf, sizeof(hashbuf)),
894 KEY_LEN+1);
895 (void) sl_strlcpy(buf, t->mailkey_new, bufsiz);
896 (void) zAVLInsert(mailkeys, t);
897 }
898
899 /* X(n) -> X(n-1)
900 */
901 (void) sl_strlcpy (t->mailkey_old, t->mailkey_new, KEY_LEN+1);
902
903 *id_audit = t->id_audit;
904
905 return (t->mailcount);
906 }
907
908 mailkeys = zAVLAllocTree (sh_nmail_getkey);
909 goto start;
910}
911
912/* <<<<<<<<<<<<<<<<<<< Free for Reconfigure >>>>>>>>>>>>>>>>>>>>>> */
913
914
915static void free_recipient_list(struct alias * list)
916{
917 struct alias * new;
918
919 while (list)
920 {
921 new = list;
922 list = new->next;
923 if (new->mx_list)
924 free_mx(new->mx_list);
925 if (new->mail_filter)
926 {
927 sh_filter_free(new->mail_filter);
928 SH_FREE(new->mail_filter);
929 }
930 sh_string_destroy(&(new->recipient));
931 SH_FREE(new);
932 }
933}
934
935/* Free everything to prepare for reconfigure
936 */
937void sh_nmail_free()
938{
939 SH_MUTEX_LOCK_UNSAFE(mutex_listall);
940 all_recipients = NULL;
941 SH_MUTEX_UNLOCK_UNSAFE(mutex_listall);
942
943 free_recipient_list(recipient_list);
944 recipient_list = NULL;
945
946 sh_filter_free(&compiled_mail_filter);
947
948 while (alias_list)
949 {
950 struct alias * item = alias_list;
951
952 alias_list = item->next;
953
954 sh_string_destroy(&(item->recipient));
955 free_recipient_list(item->recipient_list);
956 if (item->mail_filter)
957 {
958 sh_filter_free(item->mail_filter);
959 SH_FREE(item->mail_filter);
960 }
961 SH_FREE(item);
962 }
963 alias_list = NULL;
964
965 last = compiled_recipient_list;
966 return;
967}
968
969/* defined(SH_WITH_MAIL) */
970#endif
Note: See TracBrowser for help on using the repository browser.