modules/nt/notification.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. NT_ntfy_filename_generate
  2. NT_forwd_filename_generate
  3. NT_cross_filename_generate
  4. NT_crossntfy_filename_generate
  5. NT_add_to_ntfy_hash
  6. NT_add_to_frwd_hash
  7. NT_add_to_cross_hash
  8. NT_add_to_ntfy_hash_list
  9. NT_add_to_frwd_hash_list
  10. NT_add_to_cross_hash_list
  11. NT_add_to_ntfy
  12. NT_add_to_cross
  13. NT_add_to_ntfy_list
  14. NT_send_ntfy
  15. NT_log_ntfy
  16. NT_delete_ntfy
  17. nt_gfunc_send
  18. NT_send_ntfy_list
  19. nt_gfunc_log
  20. NT_log_ntfy_list
  21. nt_gfunc_delete
  22. NT_delete_ntfy_list
  23. nt_free_list
  24. NT_unify_list
  25. NT_compare_lists

   1 /***************************************
   2   $Revision: 1.14 $
   3 
   4   NT (Notifications) module
   5 
   6   Status: REVIEWED, NOT TESTED
   7 
   8   Author(s):       Engin Gunduz
   9 
  10   ******************/ /******************
  11   Modification History:
  12         engin (06/07/2000) Created.
  13                 denis (25/09/2001) Modified for new API
  14   ******************/ /******************
  15   Copyright (c) 2000,2001,2002                    RIPE NCC
  16  
  17   All Rights Reserved
  18   
  19   Permission to use, copy, modify, and distribute this software and its
  20   documentation for any purpose and without fee is hereby granted,
  21   provided that the above copyright notice appear in all copies and that
  22   both that copyright notice and this permission notice appear in
  23   supporting documentation, and that the name of the author not be
  24   used in advertising or publicity pertaining to distribution of the
  25   software without specific, written prior permission.
  26   
  27   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  28   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  29   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  30   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  31   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  32   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  33  ***************************************/
  34 
  35 
  36 
  37 
  38 
  39 
  40 #include "notification.h"
  41 extern int supress_ack_notif;
  42 extern char * defmail;
  43 extern int reading_from_mail;
  44 extern int webupdate;
  45 extern char * forwlog;
  46 extern char *netupdclientIP;
  47 
  48 /*  Generates a unique file name and returns the full path of the filename 
  49     for storing notification message.  Creates the file at the same time. 
  50     May use PID or time or both to ensure uniqueness.  */
  51       
  52 char * NT_ntfy_filename_generate( const char * tmpdir, const char * e_mail)
     /* [<][>][^][v][top][bottom][index][help] */
  53 {
  54    FILE * ntfy_file;
  55    char * name;
  56    char * replaced_notihdr;
  57    char * replaced_notimailtxt;
  58    char * replaced_notinetworktxt;
  59        
  60    /* allocate space for name.  32 should be enough for PID */
  61    name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("notify") +36 ); 
  62  
  63    sprintf(name, "%s/%s-%s.%i", tmpdir, "notify", e_mail, (int)(getpid()) );
  64 
  65    /* create the file */
  66    if (( ntfy_file = fopen(name, "w")) == NULL)
  67    {
  68      fprintf(stderr, "Can't open notification file for creating, %s", name);
  69    }
  70 
  71    /* fprintf(ntfy_file, "To: %s\nFrom: %s\nSubject: Notification of RIPE Database changes\nReply-To: %s\n\n%s\n", 
  72                      e_mail, humailbox, humailbox, notitxt);*/
  73 
  74    fprintf(ntfy_file, "To: %s\n", e_mail);
  75    replaced_notihdr = UP_replace_globals(notihdr);
  76    fprintf(ntfy_file, "%s\n\n", replaced_notihdr);
  77    free(replaced_notihdr);
  78    fprintf(ntfy_file, "\n%s\n", notitxt);
  79    if (reading_from_mail)
  80    {
  81      replaced_notimailtxt = UP_replace_globals(notimailtxt);
  82      fprintf(ntfy_file, "%s\n\n", replaced_notimailtxt);
  83      free(replaced_notimailtxt);
  84    }
  85 
  86    if (networkupdate || webupdate )
  87    {
  88      replaced_notinetworktxt = UP_replace_globals(notinetworktxt);
  89      fprintf(ntfy_file, "%s\n\n", replaced_notinetworktxt);
  90      free(replaced_notinetworktxt);
  91    }
  92    
  93    /* close it */
  94    fclose(ntfy_file);
  95     
  96    return name;
  97 }
  98 
  99 
 100 
 101 
 102 /* Generates a unique file name and returns the full path of the filename 
 103    for storing forwarded message. Creates the file at the same time.  */ 
 104 char * NT_forwd_filename_generate( const char * tmpdir, const char * e_mail)
     /* [<][>][^][v][top][bottom][index][help] */
 105 {
 106    FILE * forwd_file;
 107    char * name;
 108    char * replaced_fwhdr;
 109    char * replaced_fwmailtxt;
 110    char * replaced_notinetworktxt;
 111           
 112    /* allocate space for name.  32 should be enough for PID */
 113    name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("forwd") +36 ); 
 114    
 115    sprintf(name, "%s/%s-%s.%i", tmpdir, "forwd", e_mail, (int)(getpid()) );
 116    /* create the file */
 117    if (( forwd_file = fopen(name, "w")) == NULL)
 118    {
 119      fprintf(stderr, "Can't open forward file, %s", name);
 120    }
 121 
 122    /* fprintf(forwd_file, "To: %s\nFrom: %s\nSubject:  Requested RIPE database object changes \nReply-To: %s\n\n%s\n", 
 123                       e_mail, humailbox, humailbox, fwtxt);*/
 124 
 125    fprintf(forwd_file, "To: %s\n", e_mail);
 126    replaced_fwhdr = UP_replace_globals(fwhdr);
 127    fprintf(forwd_file, "%s\n\n", replaced_fwhdr);
 128    free(replaced_fwhdr);
 129    fprintf(forwd_file, "\n%s\n", fwtxt);
 130 
 131    if (reading_from_mail)
 132    {
 133      replaced_fwmailtxt = UP_replace_globals(fwmailtxt);
 134      fprintf(forwd_file, "\n%s\n", replaced_fwmailtxt);
 135      free(replaced_fwmailtxt);
 136    }
 137    else if (networkupdate || webupdate)
 138    {
 139      replaced_notinetworktxt = UP_replace_globals(notinetworktxt);
 140      fprintf(forwd_file, "\n%s\n", replaced_notinetworktxt);
 141      free(replaced_notinetworktxt);
 142    }
 143 
 144    /* close it */
 145    fclose(forwd_file);
 146     
 147    return name;
 148 }
 149 
 150 
 151 
 152 
 153 /* Generates a unique file name and returns the full path of the filename 
 154    for storing cross notification message. Creates the file at the same time.  */ 
 155 char * NT_cross_filename_generate( const char * tmpdir, const char * e_mail, int mode)
     /* [<][>][^][v][top][bottom][index][help] */
 156 {
 157    FILE * cross_file;
 158    char * name;
 159       
 160    /* allocate space for name.  32 should be enough for PID */
 161    name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("cross") +36 ); 
 162    
 163    sprintf(name, "%s/%s-%s.%i", tmpdir, "cross", e_mail, (int)(getpid()) );
 164    /* create the file */
 165    if (( cross_file = fopen(name, "w")) == NULL)
 166    {
 167      fprintf(stderr, "Can't open cross notif file, %s", name);
 168    }
 169 
 170    if (mode == ADDITION)
 171    {
 172      fprintf(cross_file, "To: %s\nFrom: %s\n%s\nReply-To: %s\n\n", e_mail, humailbox, cno_subject_add, humailbox);
 173    }
 174    else
 175    {
 176      fprintf(cross_file, "To: %s\nFrom: %s\n%s\nReply-To: %s\n\n", e_mail, humailbox, cno_subject_del, humailbox);
 177    }
 178    
 179    /* close it */
 180    fclose(cross_file);
 181     
 182    return name;
 183 }
 184 
 185 
 186 
 187 
 188 
 189 /* Generates a unique file name and returns the full path of the filename for 
 190    storing notification message. Creates the file at the same time.  */
 191 char * NT_crossntfy_filename_generate( const char * tmpdir, const char * e_mail)
     /* [<][>][^][v][top][bottom][index][help] */
 192 {
 193    FILE * cross_file;
 194    char * name;
 195       
 196    /* allocate space for name.  32 should be enough for PID */
 197    name = (char*)malloc(strlen(tmpdir) + strlen(e_mail) + strlen("cross") +36 ); 
 198    
 199    sprintf(name, "%s/%s-%s.%i", tmpdir, "cross", e_mail, (int)(getpid()) );
 200 
 201    /* create the file */
 202    if (( cross_file = fopen(name, "w")) == NULL)
 203    {
 204      fprintf(stderr, "Can't open cross file, %s", name);
 205    }
 206 
 207    /* close it */
 208    fclose(cross_file);
 209     
 210    return name;
 211 }
 212 
 213 
 214 
 215 /* Adds the e-mail to the notify hash, generating appropriate temp files */
 216 void NT_add_to_ntfy_hash(GHashTable * ntfy_hash, char * e_mail)
     /* [<][>][^][v][top][bottom][index][help] */
 217 {
 218   if (g_hash_table_lookup(ntfy_hash ,e_mail) == NULL)
 219   { /* there is no such entry, so create it */
 220 
 221     g_hash_table_insert(ntfy_hash, strdup(e_mail), NT_ntfy_filename_generate(tmpdir, e_mail));
 222   }
 223 }
 224 
 225 
 226 
 227 /* Adds the e-mail to the forw hash, generating appropriate temp files */
 228 void NT_add_to_frwd_hash(GHashTable * frwd_hash, char * e_mail)
     /* [<][>][^][v][top][bottom][index][help] */
 229 {
 230   if (g_hash_table_lookup(frwd_hash ,e_mail) == NULL)
 231   { /* there is no such entry, so create it */
 232     g_hash_table_insert(frwd_hash, strdup(e_mail), NT_forwd_filename_generate(tmpdir, e_mail));
 233   }
 234     
 235 }
 236 
 237 
 238 
 239 /* Adds the e-mail to the cross hash, generating appropriate temp files */
 240 void NT_add_to_cross_hash(GHashTable * cross_hash, const char * e_mail, int mode)
     /* [<][>][^][v][top][bottom][index][help] */
 241 {
 242   /*  if e-mail is NULL, immediately return */
 243   if (e_mail == NULL)
 244   {
 245     return;
 246   }
 247 
 248   if (g_hash_table_lookup(cross_hash ,e_mail) == NULL)
 249   { /* there is no such entry, so create it */
 250     g_hash_table_insert(cross_hash, strdup(e_mail), NT_cross_filename_generate(tmpdir, e_mail, mode));
 251   }
 252 }
 253 
 254 
 255 
 256 /* Adds the e-mails in a linked list to the hash */
 257 void NT_add_to_ntfy_hash_list(GHashTable * ntfy_hash, GList * e_mail_list)
     /* [<][>][^][v][top][bottom][index][help] */
 258 {
 259    GList * temp = NULL;
 260 
 261    for (temp = e_mail_list; temp != NULL; temp = g_list_next(temp))
 262    {
 263      NT_add_to_ntfy_hash( ntfy_hash, (char *)(temp->data) );
 264    }
 265 }
 266 
 267 
 268 
 269 /* Adds the e-mails in a linked list to the hash */
 270 void NT_add_to_frwd_hash_list(GHashTable * frwd_hash, GList * e_mail_list)
     /* [<][>][^][v][top][bottom][index][help] */
 271 {
 272    GList * temp = NULL;
 273 
 274    for (temp = e_mail_list; temp != NULL; temp = g_list_next(temp))
 275    {
 276      NT_add_to_frwd_hash(frwd_hash, (char *)temp->data);
 277    }
 278 }
 279 
 280 
 281 
 282 /* Adds the e-mails in a linked list to the hash */
 283 void NT_add_to_cross_hash_list(GHashTable * cross_hash, GList * e_mail_list, int mode)
     /* [<][>][^][v][top][bottom][index][help] */
 284 {
 285    GList * temp = NULL;
 286 
 287    for (temp = e_mail_list; temp != NULL; temp = g_list_next(temp))
 288    {
 289      NT_add_to_cross_hash(cross_hash, (char *)temp->data, mode);
 290    }
 291 }
 292 
 293 
 294 
 295 /* Appends the argument strings to the file.  */
 296 void NT_add_to_ntfy( char * filename, char * fmt, ... )
     /* [<][>][^][v][top][bottom][index][help] */
 297 {
 298   va_list ap;  /* points to each unnamed arg in turn */
 299   FILE * ntfy_file;
 300  
 301   if (tracing)
 302   {
 303     printf("TRACING: NT_add_to_ntfy\n"); 
 304   }
 305   if (( ntfy_file = fopen(filename, "a")) == NULL)
 306   {
 307     fprintf(stderr, "Can't open notification file for writing, %s\n", filename);
 308     return;
 309   }
 310     
 311   va_start(ap, fmt);
 312   vfprintf(ntfy_file, fmt, ap);
 313 
 314   va_end(ap); /* clean up */
 315   fclose(ntfy_file);
 316 }
 317 
 318 
 319 
 320 /* Appends the argument strings to the file.  */
 321 void NT_add_to_cross(const char * e_mail, GHashTable * hash, char * fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 322 {
 323   va_list ap;  /* points to each unnamed arg in turn */
 324   FILE * cross_file = NULL;
 325   char * filename = NULL;
 326 
 327   if (tracing)
 328   {
 329     printf("TRACING: NT_add_to_cross\n"); 
 330   }
 331 
 332   /* if e-mail is NULL, immediately return */
 333   if(e_mail == NULL)
 334   {
 335     return;
 336   }
 337    
 338   if ( (filename = (char *)g_hash_table_lookup(hash, find_email_address(e_mail))) == NULL )
 339   {
 340     fprintf(stderr, "Can't find a cross notification file for e-mail %s\n", e_mail);
 341     return;
 342   }
 343 
 344   if ( ( cross_file = fopen(filename, "a")) == NULL )
 345   {
 346     fprintf(stderr, "Can't open cross notification file for writing, %s\n", filename);
 347   }
 348     
 349   va_start(ap, fmt);
 350   vfprintf(cross_file, fmt, ap);
 351 
 352   va_end(ap); /* clean up */
 353   fclose(cross_file);
 354 }
 355 
 356 
 357 
 358 
 359 /* Appends the argument string to the temp notif files in the list */
 360 void NT_add_to_ntfy_list(GList * list, GHashTable * hash, char * arg)
     /* [<][>][^][v][top][bottom][index][help] */
 361 {
 362   GList * temp = NULL;
 363 
 364   for(temp = list; temp != NULL; temp = g_list_next(temp))
 365   {
 366     NT_add_to_ntfy((char *)g_hash_table_lookup(hash, ((char *)temp->data)), "%s", arg);
 367   }
 368 }
 369 
 370 
 371 
 372 /* Sends the notification message which is stored in the temporary filefilename.  */
 373 void NT_send_ntfy( const char * filename, const char * to_address, const char * mailercommand)
     /* [<][>][^][v][top][bottom][index][help] */
 374 {
 375     char * mail_command_line = NULL;
 376     char * supress_file = NULL;
 377     FILE * notif_file, * supr_file_hdl;
 378     char buf[1024];
 379 
 380     /* if we are not supressing acks and notifs, send the notif */
 381     if (!supress_ack_notif)
 382         {
 383       if (to_address != NULL)
 384           {
 385         mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(filename) + 128);
 386         sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
 387         system(mail_command_line);
 388       }
 389     }
 390     /* if we are supressing acks and notifs, send notif to DEFMAIL  */
 391         else
 392         {
 393       supress_file = (char *)malloc(strlen(filename) + strlen(".supress") + 2); 
 394       sprintf(supress_file, "%s.supress", filename);
 395       if (( supr_file_hdl = fopen(supress_file, "w")) == NULL)
 396           {
 397         fprintf(stderr, "Can't open supress notif file, %s", supress_file);
 398       }
 399           else
 400           {
 401         fprintf(supr_file_hdl, "From: %s\nTo: %s\nSubject: Supressed notif mail\n\n",
 402             humailbox, defmail);
 403         if (( notif_file = fopen(filename, "r")) == NULL)
 404                 {
 405           fprintf(stderr, "Can't open notif file for reading, %s", filename);
 406         }
 407                 else
 408                 {
 409           while (fgets(buf, 1023, notif_file) != NULL)
 410                   {
 411             fprintf(supr_file_hdl, buf);
 412           }
 413           fclose(notif_file);
 414         }
 415       }
 416       fclose(supr_file_hdl);
 417       mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(defmail) 
 418             + strlen(supress_file) + 128);
 419       sprintf(mail_command_line, "%s %s < %s", mailercommand, defmail, supress_file);
 420       system(mail_command_line);
 421       unlink(supress_file);
 422       free(supress_file);
 423     }
 424 }
 425 
 426 
 427 
 428 /* Adds the notification message which is in the filename into "logfilename.date". */
 429 void NT_log_ntfy( const char * filename, const char * logfilename)
     /* [<][>][^][v][top][bottom][index][help] */
 430 {
 431   FILE * notif_file, * log_file;
 432   char * buf;
 433   time_t cur_time;
 434   char * time_str;
 435   char * logfile_date;
 436   char * date;
 437 
 438   if (tracing)
 439   {
 440     printf("TRACING: NT_log_ntfy is running: filename [%s]  logfilename [%s]\n", filename, logfilename);
 441   }
 442 
 443   buf = (char *)malloc(1024);
 444   if (( notif_file = fopen(filename, "r")) == NULL)
 445   {
 446     fprintf(stderr, "NT_log_ntfy: Can't open notification file for reading, [%s]\n", filename);
 447     return;
 448   }
 449 
 450   /* construct the "logfilename.date" string */
 451   logfile_date = (char *)malloc(strlen(logfilename) + 10);
 452   date = UP_get_current_date();
 453   snprintf(logfile_date, strlen(logfilename) + 10, "%s.%s", logfilename, date);
 454   free(date);
 455 
 456   if (( log_file = fopen(logfile_date, "a")) == NULL)
 457   {
 458     fprintf(stderr, "NT_log_ntfy: Can't open log file, %s\n", logfilename);
 459     return;
 460   }
 461 
 462   /* get time */
 463   cur_time = time(NULL);
 464   time_str = strdup(ctime(&cur_time));
 465   /* cut the '\n' at the end */
 466   time_str[strlen(time_str) - 1] = '\0';
 467 
 468   if ( networkupdate )
 469     fprintf(log_file, ">>> time: %s NETWORKUPDATE NOTIF (%s) <<<\n\n", 
 470                 time_str, netupdclientIP ? netupdclientIP : "NULL");
 471   else if ( webupdate )
 472     fprintf(log_file, ">>> time: %s WEB UPDATE NOTIF (%s) <<<\n\n", 
 473                 time_str, netupdclientIP ? netupdclientIP : "NULL");
 474   else
 475     fprintf(log_file, ">>> time: %s NOTIF <<<\n\n", time_str);
 476 
 477 
 478   while ( (buf=fgets(buf, 1024, notif_file)) != NULL )
 479   {
 480     fprintf(log_file, "%s", buf);
 481   }
 482   free(buf);
 483 
 484   fclose(notif_file);
 485   fclose(log_file);
 486 }
 487 
 488 
 489 /* Deletes the temporary notification file. */ 
 490 void NT_delete_ntfy( const char * filename)
     /* [<][>][^][v][top][bottom][index][help] */
 491 {
 492    unlink(filename);
 493 }
 494 
 495 
 496 /* The function required for NT_send_ntfy_list */
 497 void  nt_gfunc_send(gpointer key, gpointer value, gpointer user_data)
     /* [<][>][^][v][top][bottom][index][help] */
 498 {
 499   NT_send_ntfy((char *)value, (char *)key, (char *)user_data);
 500 }
 501 
 502 
 503        
 504 /* Sends the notification messages whose temp files are stored in filehash. */              
 505 void NT_send_ntfy_list( GHashTable * filehash, char * mailercommand)
     /* [<][>][^][v][top][bottom][index][help] */
 506 {
 507   g_hash_table_foreach( filehash, (GHFunc)nt_gfunc_send, mailercommand);
 508 }
 509 
 510 
 511 
 512 
 513 /* The function required for NT_log_ntfy_list */
 514 void  nt_gfunc_log(gpointer key, gpointer value, gpointer user_data)
     /* [<][>][^][v][top][bottom][index][help] */
 515 {
 516   NT_log_ntfy((char *)value, (char *)user_data);
 517 }
 518 
 519 
 520 
 521 
 522 /* Logs the notification whose temp files are in filehash to log_file. */
 523 void NT_log_ntfy_list( GHashTable * filehash, char * log_file)
     /* [<][>][^][v][top][bottom][index][help] */
 524 {
 525    g_hash_table_foreach( filehash, (GHFunc)nt_gfunc_log, log_file);
 526 }
 527 
 528 
 529 
 530 /* The function required for NT_delete_ntfy_list */
 531 void  nt_gfunc_delete(gpointer key, gpointer value, gpointer user_data)
     /* [<][>][^][v][top][bottom][index][help] */
 532 {
 533   NT_delete_ntfy((char *)value);
 534 }
 535 
 536 
 537 
 538 /* Deletes the temporary notification messages in the filehash. Empties and frees 
 539    the hash too.  */
 540 void NT_delete_ntfy_list( GHashTable * filehash)
     /* [<][>][^][v][top][bottom][index][help] */
 541 {
 542   g_hash_table_foreach(filehash, (GHFunc)nt_gfunc_delete, NULL);
 543   g_hash_table_destroy(filehash);
 544 }
 545 
 546 
 547 /* to be used with g_hash_table_foreach in NT_unify_list.
 548    Adds the 'value' to the list (a GList) */
 549 /* void nt_add_to_list(char * key, rpsl_attr_t * value, GList ** list)
 550 {
 551   *list = g_list_append(*list, strdup(value));
 552 }
 553 */
 554 
 555 
 556 /* to be used with g_hash_table_foreach in NT_unify_list.
 557    frees the 'key' and 'value' in the list (a GList) */
 558 void nt_free_list(char * key, char * value, void *nothing)
     /* [<][>][^][v][top][bottom][index][help] */
 559 {
 560   if ( key != NULL )
 561     free(key);
 562   if ( value != NULL )
 563     free(value);
 564 }
 565 
 566 
 567 
 568 /* "unifies" a list in a case insensitive manner */
 569 GList * NT_unify_list(GList * in_list)
     /* [<][>][^][v][top][bottom][index][help] */
 570 {
 571   GHashTable * unification_hash;
 572   GList ** out_list;
 573   GList * temp;
 574   GList *return_list = NULL;
 575   char * key, * value;
 576   int strcmp();
 577 
 578   /* allocate space for out_list */ 
 579   out_list = (GList **)malloc(sizeof(GList *));
 580   *out_list = NULL;
 581 
 582   /* initialize the hash to be used for unification process */
 583   unification_hash = g_hash_table_new(g_str_hash, g_str_equal);
 584 
 585   /* first put the list elements into a hash, to unify them */
 586   for (temp = in_list; temp != NULL; temp = g_list_next(temp))
 587   {
 588     /* convert the email address into lowercase, for comparison reasons only */
 589     key = rpsl_attr_get_clean_value((rpsl_attr_t *)(temp->data));
 590     value = strdup(key);
 591     g_strdown(key);
 592     
 593     if (g_hash_table_lookup(unification_hash, key) == NULL)
 594         { /* if it is not already in the hash table, add to the hash and append to new list */
 595       g_hash_table_insert(unification_hash, key, value);
 596       *out_list = g_list_insert_sorted( *out_list, strdup(value), strcmp );
 597 /*       *out_list = g_list_append( *out_list, strdup(value) ); */
 598     }
 599         else
 600         {  /* it is a duplicate email address, don't append to new list */
 601           free(key);
 602           free(value);
 603         }
 604   }
 605 
 606   /* now, delete the elements in the hash */
 607   g_hash_table_foreach(unification_hash, (GHFunc)nt_free_list, NULL);
 608 
 609   g_hash_table_destroy(unification_hash);
 610   
 611   return_list = *out_list;
 612   free(out_list);
 613   return return_list;
 614 }
 615 
 616 
 617 
 618 /* Gets GLists of irt atributes from old and new object. Compares these
 619    lists and returns a list of diferences */
 620 
 621 /* if option==1, return list contains only newly deleted irts
 622    if option==2, return list contains only newly added irts
 623    if option==3, return list contains both */
 624 
 625 GList *NT_compare_lists(GList *old_irts, GList *new_irts, int option)
     /* [<][>][^][v][top][bottom][index][help] */
 626 {
 627   typedef struct irt_details
 628   {
 629     gchar *irt_name;
 630         rpsl_attr_t *irts;
 631         gint   matched;
 632   } irt_details_t;
 633   
 634   GList *old_irt_details = NULL;
 635   GList *new_irt_details = NULL;
 636   GList *old_irts_item = NULL;
 637   GList *new_irts_item = NULL;
 638   GList *return_list = NULL;
 639   irt_details_t *irt_details;
 640   char *irt_name;
 641   
 642   if (tracing)
 643   { 
 644     printf("TRACING: NT_compare_lists is running: option: [%d]\n", option);
 645   }
 646 
 647   /* collect data from the old_irts */
 648   for ( old_irts_item = old_irts; old_irts_item != NULL; old_irts_item = g_list_next(old_irts_item) )
 649   {
 650     irt_details = (irt_details_t *)malloc(sizeof(irt_details_t));
 651         /* get irt name from attr */
 652         irt_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(old_irts_item->data) );
 653         /* enter details into irt_details structure */
 654         irt_details->irts = (rpsl_attr_t *)(old_irts_item->data);
 655         irt_details->irt_name = irt_name;
 656         irt_details->matched = 0;
 657         /* append irt_details structure to old_irt_details list */
 658         old_irt_details = g_list_append(old_irt_details, irt_details);
 659   }
 660   
 661   /* collect data from the new_irts and compare with the old in the same loop */
 662   for ( new_irts_item = new_irts; new_irts_item != NULL; new_irts_item = g_list_next(new_irts_item) )
 663   {
 664     irt_details = (irt_details_t *)malloc(sizeof(irt_details_t));
 665         /* get irt name from attr */
 666         irt_name = rpsl_attr_get_clean_value( (rpsl_attr_t *)(new_irts_item->data) );
 667         /* enter details into irt_details structure */
 668         irt_details->irts = (rpsl_attr_t *)(new_irts_item->data);
 669         irt_details->irt_name = irt_name;
 670         irt_details->matched = 0;
 671 
 672         /* compare the name with the names from the old list  */
 673         for ( old_irts_item = old_irt_details; old_irts_item != NULL; old_irts_item = g_list_next(old_irts_item) )
 674     {
 675           if ( ! strcmp(irt_name, ((irt_details_t *)(old_irts_item->data))->irt_name ) )
 676           {
 677             irt_details->matched = 1;
 678                 ((irt_details_t *)(old_irts_item->data))->matched = 1;
 679                 break;
 680           }
 681         }
 682 
 683         /* append irt_details structure to new_irt_details list */
 684         new_irt_details = g_list_append(new_irt_details, irt_details);
 685   }
 686   
 687   /* we now want a list of irts taken from the old and new irt_details lists
 688      where the matched flag is _NOT_ set. These will only exist in one list
 689          and have therefore just been added/deleted */
 690   /* if option==1, return list contains only newly deleted irts
 691      if option==2, return list contains only newly added irts
 692      if option==3, return list contains both */
 693   if ( option == 1 || option == 3 )
 694   {   
 695     for ( old_irts_item = old_irt_details; old_irts_item != NULL; old_irts_item = g_list_next(old_irts_item) )
 696     {
 697       if ( ! ((irt_details_t *)(old_irts_item->data))->matched )
 698           {
 699         if (tracing)
 700         { 
 701           printf("TRACING: NT_compare_lists: adding old irt to return list [%s]\n", ((irt_details_t *)(new_irts_item->data))->irt_name);
 702         }
 703 
 704             return_list = g_list_append(return_list, ((irt_details_t *)(old_irts_item->data))->irts );
 705           }
 706           free ( ((irt_details_t *)(old_irts_item->data))->irt_name );
 707     }
 708   }
 709   g_list_free(old_irt_details);
 710   if ( option == 2 || option == 3 )
 711   {   
 712     for ( new_irts_item = new_irt_details; new_irts_item != NULL; new_irts_item = g_list_next(new_irts_item) )
 713     {
 714       if ( ! ((irt_details_t *)(new_irts_item->data))->matched )
 715           {
 716         if (tracing)
 717         { 
 718           printf("TRACING: NT_compare_lists: adding new irt to return list [%s]\n", ((irt_details_t *)(new_irts_item->data))->irt_name);
 719         }
 720 
 721             return_list = g_list_append(return_list, ((irt_details_t *)(new_irts_item->data))->irts );
 722           }
 723           free ( ((irt_details_t *)(new_irts_item->data))->irt_name );
 724     }
 725   }
 726   g_list_free(new_irt_details);
 727   
 728   return return_list;
 729 }
 730 
 731 
 732 /* Gets old and new objects supplied, forms lists of any irt objects referenced 
 733    by these. Returns a GList of irt-nfy for any irt objects that heve been added
 734    or deleted.
 735 */
 736 GList *NT_check_irtnfy(rpsl_object_t *old_obj, rpsl_object_t *new_obj)
 737 {
 738   GList *old_irts = NULL; 
 739   GList *new_irts = NULL; 
 740   GList *changed_irts = NULL; 
 741 
 742   if (old_obj != NULL)
 743     old_irts = get_irts(old_obj);
 744   if (new_obj != NULL)
 745     new_irts = get_irts(new_obj);
 746 
 747   if ( old_irts != NULL && new_irts!= NULL )
 748   {
 749     /* compare lists for additions and deletions */
 750         changed_irts = NT_compare_lists(old_irts, new_irts, 3);
 751         return get_irtnfy_vector(changed_irts);
 752   }
 753   else if ( old_irts != NULL )
 754   {
 755     /* these irts have been deleted */
 756         return get_irtnfy_vector(old_irts);
 757   }
 758   else if ( new_irts != NULL )
 759   {
 760     /* these irts have been added */
 761         return get_irtnfy_vector(new_irts);
 762   }
 763   else
 764     return NULL;  /* no irt objects at all */
 765 }
 766 
 767 
 768 /* Gathers e-mail boxes to which we will send normal notification messages. It 
 769    takes old and new object strings, looks up maintainers and less specific inetnums/domains/routes 
 770    when necessary, finds the addresses (in mnt-nfy and notify attributes) and returns 
 771    a list of email addresses as strings. 
 772    Also now checks for irt-nfy in any irt objects that have been added or deleted */
 773 GList * NT_gather_ntfy_addresses( const char * old_object_str, const char * new_object_str)
 774 {
 775   GList *return_list = NULL, *temp = NULL;
 776   GList *mntners = NULL; 
 777   const GList *error_list = NULL; 
 778   rpsl_object_t *old_obj = NULL;
 779   rpsl_object_t *new_obj = NULL;
 780 
 781   if (tracing)
 782   { 
 783     printf("TRACING: NT_gather_ntfy_addresses is running: old_object_str : [%s]; new_object_str: [%s]\n", old_object_str ? old_object_str : "", new_object_str ? new_object_str : "");
 784   }
 785 
 786   if (old_object_str != NULL && new_object_str != NULL)
 787   { /* it was an update */
 788         old_obj = rpsl_object_init(old_object_str);
 789         error_list = rpsl_object_errors(old_obj);
 790         new_obj = rpsl_object_init(new_object_str);
 791         error_list = rpsl_object_errors(old_obj);
 792 
 793     /* start with the 'notify' in the object itself */
 794     temp = get_attr_list(old_obj, "notify");
 795     mntners = get_mntners(old_obj);
 796         /* now add the 'mnt-by' from any of the mntners in the old object only */
 797     temp = g_list_concat(temp, get_mntnfy_vector(mntners));
 798         /* now add the 'irt-by' from any of the irts in the old and new objects
 799            if they have just been added or deleted */
 800         temp = g_list_concat(temp, NT_check_irtnfy(old_obj, new_obj));
 801   }
 802   else if (old_object_str == NULL && new_object_str != NULL)
 803   { /* it was a creation */
 804         new_obj = rpsl_object_init(new_object_str);
 805         error_list = rpsl_object_errors(new_obj);
 806 
 807     if ( ! rpsl_object_has_error( new_obj, RPSL_ERRLVL_ERROR ) )
 808         {
 809       /* start with the 'notify' in the object itself */
 810       temp = get_attr_list(new_obj, "notify");
 811       mntners = get_mntners(new_obj);
 812           /* now add the 'mnt-by' from any of the mntners in the new object only */
 813       temp = g_list_concat(temp, get_mntnfy_vector(mntners));
 814           /* now add the 'irt-by' from any of the irts in the new object
 815                  as they have just been added */
 816           temp = g_list_concat(temp, NT_check_irtnfy(old_obj, new_obj));
 817         }
 818   }
 819   else if (old_object_str != NULL && new_object_str == NULL)
 820   { /* it was a deletion */
 821         old_obj = rpsl_object_init(old_object_str);
 822         error_list = rpsl_object_errors(old_obj);
 823 
 824     /* start with the 'notify' in the object itself */
 825     temp = get_attr_list(old_obj, "notify");
 826     mntners = get_mntners(old_obj);
 827         /* now add the 'mnt-by' from any of the mntners in the old object only */
 828     temp = g_list_concat(temp, get_mntnfy_vector(mntners));
 829         /* now add the 'irt-by' from any of the irts in the old object
 830            as they have just been deleted */
 831         temp = g_list_concat(temp, NT_check_irtnfy(old_obj, new_obj));
 832   }
 833 
 834   /* we have to 'unify' the list here!, return_list is now a list of malloc'd email address strings */
 835   return_list = NT_unify_list(temp);
 836   rpsl_attr_delete_list( temp );
 837   if ( old_obj )
 838     rpsl_object_delete(old_obj);
 839   if ( new_obj )
 840     rpsl_object_delete(new_obj);
 841 
 842   if (tracing)
 843   {
 844     printf( "TRACING: notif email addresses\n" );
 845     for ( temp=return_list; temp!=NULL; temp=g_list_next(temp) )
 846       printf( "TRACING: [%s]\n", (char *)(temp->data) );
 847   }
 848 
 849   return return_list;
 850 }
 851 
 852 
 853 
 854 /* Gathers e-mail boxes to which we will forward messages (or rather, objects). It 
 855    an object, looks up maintainers, finds the addresses (in upd-to attributes) and returns 
 856    a list of them. */
 857 GList * NT_gather_frwd_addresses(char * object_str)
 858 {
 859   GList *temp = NULL;
 860   GList *attr_item = NULL;
 861   GList *email_list = NULL;
 862   char *email;
 863   const GList *error_list = NULL; 
 864   rpsl_object_t *object;
 865   GList * mntners = NULL; 
 866 
 867   object = rpsl_object_init(object_str);
 868   error_list = rpsl_object_errors(object);
 869 
 870   mntners = get_mntners(object);
 871   /* get a list of upd-to attributes */
 872   temp = get_updto_vector(mntners);
 873   /* now extract the email text strings from the values of these attributes */
 874   for ( attr_item = temp; attr_item != NULL ; attr_item = g_list_next(attr_item) )
 875   {
 876     email = rpsl_attr_get_clean_value((rpsl_attr_t *)(attr_item->data));
 877     if (tracing)
 878     {
 879       printf("NT_gather_frwd_addresses: email [%s]\n", email );
 880     }
 881     email_list = g_list_append(email_list, email );
 882   }
 883   return email_list;
 884 }
 885 
 886 
 887 
 888 /* Accepts a parsed route object and returns a list of overlapping routes */
 889 overlap_routes get_overlapping_routes_list(rpsl_object_t * object)
 890 {
 891   char * route_prefix = NULL;
 892   GList * tmp_list;
 893   char * result;
 894   char * query_string;  
 895   overlap_routes result_routes;
 896     
 897   result_routes.less_spec = NULL;
 898   result_routes.exact_match = NULL;
 899   result_routes.more_spec = NULL;
 900       
 901   tmp_list = rpsl_object_get_attr(object, "route");  
 902 
 903   if (tmp_list != NULL && tmp_list->data != NULL)
 904   {
 905     route_prefix = rpsl_attr_get_clean_value((rpsl_attr_t *)(tmp_list->data));
 906   }
 907   else
 908   {
 909     return result_routes; /* then, this wasn't a route object */
 910   }
 911   
 912   /* get the less specific route objects */
 913   /* form the query string */
 914   query_string = (char *)malloc(strlen("-Troute -r -l ") + strlen(route_prefix) + 2);
 915   sprintf(query_string, "-Troute -r -l %s", route_prefix);
 916 
 917   /* get the results */ 
 918   result = send_and_get(query_host, query_port, query_string);
 919   free(query_string);
 920 
 921   /* and fill in the result field  */
 922   result_routes.less_spec = take_objects(result);
 923 
 924   /* get the exact match route objects */
 925   /* form the query string */
 926   query_string = (char *)malloc(strlen("-Troute -r -x ") + strlen(route_prefix) + 2);
 927   sprintf(query_string, "-Troute -r -x %s", route_prefix);
 928 
 929   /* get the results */ 
 930   result = send_and_get(query_host, query_port, query_string);
 931   free(query_string);
 932   
 933 
 934   /* filter out the route object itself */
 935   result = UP_filter_out_same_origins(result, object);
 936 
 937   /* and fill in the result field  */
 938   if (result != NULL)
 939   {
 940     result_routes.exact_match = take_objects(result);
 941   }
 942 
 943   /* get the more specific route objects */
 944   /* form the query string */
 945   query_string = (char *)malloc(strlen("-Troute -r -M ") + strlen(route_prefix) + 2);
 946   sprintf(query_string, "-Troute -r -M %s", route_prefix);
 947 
 948   /* get the results */ 
 949   result = send_and_get(query_host, query_port, query_string);
 950   free(query_string);
 951 
 952   /* and fill in the result field  */
 953   result_routes.more_spec = take_objects(result);
 954 
 955   /* Return the results */
 956   return result_routes;
 957 }
 958 
 959 
 960 
 961 /* Gets old and new versions of the object, and creates temporary notification
 962    files when necessary, and then writes appropriate strings into those
 963    temporary files. */
 964 void NT_write_all_ntfs(char * old_object, char * new_object, char * formatted_object,
 965                        const char * tempdir,
 966                        GHashTable * ntfy_hash,  GHashTable * forwd_hash, GHashTable * cross_hash, 
 967                        char * from_address)
 968 { 
 969    GList * e_mail_list = NULL;
 970    GList * temp = NULL;
 971    const GList *error_list = NULL; 
 972    char * e_mail_address = NULL;
 973    overlap_routes overlapping_routes;
 974    rpsl_object_t *object;
 975    char *arg2;
 976 
 977    if ( reading_from_mail )
 978    {
 979      /* from_address may contain also the name, like "Johnny Bravo <johnny@inter.net>",
 980         so extract the e-mail address from it */
 981      e_mail_address = find_email_address(from_address); 
 982 
 983      if (tracing)
 984      {
 985        printf("TRACING: NT_write_all_ntfs: from_address=[%s], e_mail_address=[%s]\n", from_address, e_mail_address);
 986      }
 987    }
 988    if (old_object != NULL && new_object != NULL)
 989    { 
 990      /* it was an update */
 991          object = rpsl_object_init(formatted_object ? formatted_object : new_object);
 992          error_list = rpsl_object_errors(object);
 993 
 994      if ( UP_remove_override_attr(object) )
 995        arg2 = rpsl_object_get_text(object, RPSL_STD_COLUMN);
 996          else
 997          {
 998            /* there was an override attr in this object and it has not been removed */
 999            arg2 = (char *)malloc(2);
1000            strcpy(arg2, "");    /* Don't include object in ack/notif msgs */
1001          }
1002 
1003      rpsl_object_delete(object);
1004    
1005      e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
1006      NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
1007      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nPREVIOUS OBJECT:\n\n");
1008      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, old_object);
1009      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n\nREPLACED BY:\n\n");
1010      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, arg2);
1011      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
1012    }
1013    else if (old_object == NULL && new_object != NULL)
1014    { 
1015      /* it was a creation */
1016          object = rpsl_object_init(formatted_object ? formatted_object : new_object);
1017          error_list = rpsl_object_errors(object);
1018 
1019      if ( UP_remove_override_attr(object) )
1020        arg2 = rpsl_object_get_text(object, RPSL_STD_COLUMN);
1021          else
1022          {
1023            /* there was an override attr in this object and it has not been removed */
1024            arg2 = (char *)malloc(2);
1025            strcpy(arg2, "");    /* Don't include object in ack/notif msgs */
1026          }
1027 
1028      rpsl_object_delete(object);
1029    
1030      e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
1031      NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
1032      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nOBJECT BELOW CREATED:\n\n");
1033      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, arg2);
1034      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
1035 
1036      /* We'll deal with cross notifications only when we create or delete route objects */
1037          object = rpsl_object_init(new_object);
1038          error_list = rpsl_object_errors(object);
1039 
1040      if (strcmp(rpsl_object_get_class(object), "route") == 0)
1041          {
1042        overlapping_routes = get_overlapping_routes_list(object);
1043        if (overlapping_routes.less_spec != NULL || overlapping_routes.exact_match != NULL ||
1044           overlapping_routes.more_spec != NULL )
1045            {
1046          NT_add_to_cross_hash(cross_hash, e_mail_address, ADDITION);
1047          NT_add_to_cross(e_mail_address, cross_hash, "%s\n\n%s\n\n%s\n\n", cno_explain_add, new_object, cno_overlap_add);
1048          if (overlapping_routes.less_spec != NULL)
1049                  {
1050            NT_add_to_cross(from_address, cross_hash, "LESS SPECIFIC MATCHES\n\n");
1051            for (temp = overlapping_routes.less_spec; temp != NULL; temp = g_list_next(temp))
1052                    {
1053              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1054            }
1055          }
1056          if (overlapping_routes.exact_match != NULL)
1057                  {
1058            NT_add_to_cross(from_address, cross_hash, "EXACT MATCHES\n\n");
1059            for (temp = overlapping_routes.exact_match; temp != NULL; temp = g_list_next(temp))
1060                    {
1061              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1062            }
1063          }
1064          if (overlapping_routes.more_spec != NULL)
1065                  {
1066            NT_add_to_cross(from_address, cross_hash, "MORE SPECIFIC MATCHES\n\n");
1067            for (temp = overlapping_routes.more_spec; temp != NULL; temp = g_list_next(temp))
1068                    {
1069              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1070            }
1071          }
1072        }
1073      }
1074          rpsl_object_delete(object);
1075    }
1076    else if (old_object != NULL && new_object == NULL)
1077    { /* it was a deletion */
1078      old_object = delete_delete_attrib(old_object);
1079          object = rpsl_object_init(old_object);
1080          error_list = rpsl_object_errors(object);
1081 
1082      if ( UP_remove_override_attr(object) )
1083        arg2 = rpsl_object_get_text(object, RPSL_STD_COLUMN);
1084          else
1085          {
1086            /* there was an override attr in this object and it has not been removed */
1087            arg2 = (char *)malloc(2);
1088            strcpy(arg2, "");    /* Don't include object in ack/notif msgs */
1089          }
1090 
1091      e_mail_list = NT_gather_ntfy_addresses(old_object, new_object);
1092      NT_add_to_ntfy_hash_list(ntfy_hash, e_mail_list); 
1093      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "---\nOBJECT BELOW DELETED:\n\n");
1094      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, arg2);
1095      NT_add_to_ntfy_list(e_mail_list, ntfy_hash, "\n");
1096 
1097      /* We'll deal with cross notifications only when we create or delete route objects */
1098      if (strcmp(rpsl_object_get_class(object), "route") == 0)
1099          {
1100        overlapping_routes = get_overlapping_routes_list(object);
1101        if (overlapping_routes.less_spec != NULL || overlapping_routes.exact_match != NULL ||
1102           overlapping_routes.more_spec != NULL )
1103            {
1104          NT_add_to_cross_hash(cross_hash, e_mail_address, DELETION);
1105          NT_add_to_cross(e_mail_address, cross_hash, "%s\n\n%s\n\n%s\n\n", cno_explain_del, old_object, cno_overlap_del);
1106          if (overlapping_routes.less_spec != NULL)
1107                  {
1108            NT_add_to_cross(from_address, cross_hash, "LESS SPECIFIC MATCHES\n\n");
1109            for (temp = overlapping_routes.less_spec; temp != NULL; temp = g_list_next(temp))
1110                    {
1111              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1112            }
1113          }
1114          if (overlapping_routes.exact_match != NULL)
1115                  {
1116            NT_add_to_cross(from_address, cross_hash, "EXACT MATCHES\n\n");
1117            for (temp = overlapping_routes.exact_match; temp != NULL; temp = g_list_next(temp))
1118                    {
1119              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1120            }
1121          }
1122          if (overlapping_routes.more_spec != NULL)
1123                  {
1124            NT_add_to_cross(from_address, cross_hash, "MORE SPECIFIC MATCHES\n\n");
1125            for (temp = overlapping_routes.more_spec; temp != NULL; temp = g_list_next(temp))
1126                    {
1127              NT_add_to_cross(from_address, cross_hash, "%s\n\n", (char *)temp->data);
1128            }
1129          }
1130        }
1131      }
1132          rpsl_object_delete(object);
1133    }
1134    free(arg2);
1135 }
1136 
1137 
1138 
1139 /* Gets old and new versions of the object, and creates temporary notification
1140    files when necessary, and then writes appropriate strings into those
1141    temporary files. */
1142 void NT_write_all_frwds(char * old_object_str, char * new_object_str, const char * tempdir,
1143                        GHashTable * ntfy_hash,  GHashTable * forwd_hash, GHashTable * cross_hash, 
1144                        const char * from_address)
1145 { 
1146    GList *e_mail_list = NULL;
1147    rpsl_object_t *object;
1148    char *arg2;
1149    const GList * error_list = NULL;
1150 
1151    if (tracing)
1152    {
1153      printf("TRACING: NT_write_all_frwds is running\n");
1154    }
1155    
1156    if ( new_object_str )
1157    {
1158          object = rpsl_object_init(new_object_str);
1159          error_list = rpsl_object_errors(object);
1160 
1161      if ( UP_remove_override_attr(object) )
1162        arg2 = rpsl_object_get_text(object, RPSL_STD_COLUMN);
1163          else
1164          {
1165            /* there was an override attr in this object and it has not been removed */
1166            arg2 = (char *)malloc(2);
1167            strcpy(arg2, "");    /* Don't include object in ack/notif msgs */
1168          }
1169    }
1170    
1171    if (old_object_str != NULL && new_object_str != NULL)
1172    { /* it was an update */
1173      e_mail_list = NT_gather_frwd_addresses(old_object_str);
1174      NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
1175      NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nUPDATE REQUESTED FOR:\n\n");
1176      NT_add_to_ntfy_list(e_mail_list, forwd_hash, arg2);
1177    }
1178    else if (old_object_str == NULL && new_object_str != NULL)
1179    { /* it was a creation */
1180      e_mail_list = NT_gather_frwd_addresses(new_object_str);
1181      NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
1182      NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nADDITION REQUESTED FOR:\n\n");
1183      NT_add_to_ntfy_list(e_mail_list, forwd_hash, arg2);
1184    }
1185    else if (old_object_str != NULL && new_object_str == NULL)
1186    { /* it was a deletion */
1187      e_mail_list = NT_gather_frwd_addresses(old_object_str);
1188      NT_add_to_frwd_hash_list(forwd_hash, e_mail_list);
1189      NT_add_to_ntfy_list(e_mail_list, forwd_hash, "----\nDELETION REQUESTED FOR:\n\n");
1190      NT_add_to_ntfy_list(e_mail_list, forwd_hash, old_object_str);
1191    }
1192 }
1193 
1194 
1195 
1196 /* Sends the creation forward message which is stored in the temporary file filename.  */
1197 void NT_send_forw_creation( const char * filename, const char * to_address, const char * mailercommand)
1198 {
1199     char * mail_command_line = NULL;
1200     char * supress_file = NULL;
1201     FILE * fc_file, * supr_file_hdl;
1202     char buf[1024];
1203 
1204     /* if we are not supressing acks and notifs, send the message */
1205     if (!supress_ack_notif)
1206         {
1207       if (to_address != NULL)
1208           {
1209         mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(filename) + 128);
1210         sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
1211         system(mail_command_line);
1212         free(mail_command_line);
1213       }
1214     }
1215         else
1216         {
1217       /* if we are supressing acks and notifs, send the message to DEFMAIL  */
1218       supress_file = (char *)malloc(strlen(filename) + strlen(".supress") + 2); 
1219       sprintf(supress_file, "%s.supress", filename);
1220       if (( supr_file_hdl = fopen(supress_file, "w")) == NULL)
1221           {
1222         fprintf(stderr, "Can't open supress forward creation file, %s", supress_file);
1223       }
1224           else
1225           {
1226         fprintf(supr_file_hdl, "From: %s\nTo: %s\nSubject: Supressed forward creation mail\n\n",
1227             humailbox, defmail);
1228         if (( fc_file = fopen(filename, "r")) == NULL)
1229                 {
1230           fprintf(stderr, "Can't open forward creation file for reading, %s", filename);
1231         }
1232                 else
1233                 {
1234           while (fgets(buf, 1023, fc_file) != NULL)
1235                   {
1236             fprintf(supr_file_hdl, buf);
1237           }
1238           fclose(fc_file);
1239         }
1240       }
1241       fclose(supr_file_hdl);
1242       mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(defmail) 
1243             + strlen(supress_file) + 128);
1244       sprintf(mail_command_line, "%s %s < %s", mailercommand, defmail, supress_file);
1245       system(mail_command_line);
1246       unlink(supress_file);
1247       free(supress_file);
1248     }
1249 }
1250 
1251 
1252 /* NT_forw_create_req forwards the maintainer, as-block and irt creation requests
1253    to <HUMAILBOX> */
1254 void NT_forw_create_req(const char * object_str)
1255 {
1256    FILE * forw_file;
1257    char * filename;
1258    char * replaced_mtfwheader;
1259    char * replaced_mtfwtxt;
1260 
1261    /* allocate space for name.  32 should be enough for PID */
1262    filename = (char*)malloc(strlen(tmpdir) + strlen("creat-forw") +34 ); 
1263    
1264    sprintf(filename, "%s/%s.%i", tmpdir, "creat-forw", (int)(getpid()) );
1265 
1266    /* create the file */
1267    if (( forw_file = fopen(filename, "w")) == NULL)
1268    {
1269      fprintf(stderr, "NT_forw_create_req: Can't open creation forward file for creating, %s", filename);
1270    }
1271 
1272    replaced_mtfwheader = UP_replace_globals(mtfwheader);
1273    replaced_mtfwtxt = UP_replace_globals(mtfwtxt);
1274    
1275    fprintf(forw_file, "%s\n\n", replaced_mtfwheader);
1276    
1277    if (reading_from_mail)
1278    {
1279      fprintf(forw_file, "%s\n\n", replaced_mtfwtxt);
1280    }
1281 
1282    /* print the object */
1283    fprintf(forw_file, "%s\n\n", object_str);
1284     
1285    /* close it */
1286    fclose(forw_file);
1287     
1288    /* send it */ 
1289    NT_send_forw_creation(filename, humailbox, mailcmd);
1290 
1291    /* log it */
1292    NT_log_ntfy(filename, forwlog);
1293    
1294    /* delete it */
1295    unlink(filename);
1296  
1297    /* free the mem */ 
1298    free(filename);
1299    free(replaced_mtfwheader);
1300    free(replaced_mtfwtxt);
1301 }

/* [<][>][^][v][top][bottom][index][help] */