modules/nt/notification.c

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

FUNCTIONS

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
  26. NT_check_irtnfy
  27. NT_gather_ntfy_addresses
  28. NT_gather_frwd_addresses
  29. get_overlapping_routes_list
  30. NT_write_all_ntfs
  31. NT_write_all_frwds
  32. NT_send_forw_creation
  33. NT_forw_create_req

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

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