Source File nt/notification.c

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