source: trunk/src/sh_nmail.c@ 272

Last change on this file since 272 was 272, checked in by katerina, 16 years ago

Fixes tickets #190, #191, #192, #193, and #194.

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