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