source: trunk/src/sh_nmail.c@ 280

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

Fix for bugs in log monitoring (tickets #196, #199), and allow shell command monitoring (ticket #197).

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