## 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] */