Source File nt/notification.c

    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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, ... )
    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, ...)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)
    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,
    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,
    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)
    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)
    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 | }