source: trunk/src/sh_nmail.c@ 306

Last change on this file since 306 was 304, checked in by katerina, 14 years ago

Fix for ticket #228 (null poiter dereference in handler for SetMailAlias).

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