source: trunk/src/sh_nmail.c@ 273

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

Debug code removed.

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