Source File ak/ack.c

    1    | /***************************************
    2    |   $Revision: 1.5 $
    3    |
    4    |   AK (Acknowledgement) module
    5    |
    6    |   Status: REVIEWED, NOT TESTED
    7    |
    8    |   Author(s):       Engin Gunduz
    9    |
    10   |   ******************/ /******************
    11   |   Modification History:
    12   |         engin (10/06/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   | #include "ack.h"
    38   | extern int supress_ack_notif;
    39   | extern char * humailbox;
    40   | extern char * failuretxt;
    41   | extern char * helpheader;
    42   | extern char * successtxt;
    43   | extern char * defmail;
    44   | extern char * acksig;
    45   | extern int * reading_from_mail;
    46   | extern int networkupdate;
    47   | extern up_subject_struct subject_result;
    48   | extern int count_successful;
    49   | extern int count_unsuccessful;
    50   |
    51   | /*
    52   |
    53   |   AK_add_to_ack: writes a message to the acknowledgement file.
    54   |     Also, prints it out to the stdout if it was a networkupdate
    55   |     (networkupdate is run through inetd, so stdout is our socket)
    56   |
    57   | */
    58   |
    59   | void AK_add_to_ack(const char * filename, char * fmt, ...){
    60   |
    61   |   va_list ap;  /* points to each unnamed arg in turn */
    62   |   char *p, *sval;
    63   |   int ival;
    64   |   double dval;
    65   |   FILE * ack_file;
    66   |
    67   |   if(( ack_file = fopen(filename, "a")) == NULL){
    68   |     fprintf(stderr, "Can't open ack file, %s", filename);
    69   |   }
    70   |
    71   |
    72   |   /* if this is a network update, print it out first to the
    73   |      stdout (which is socket) */
    74   |   if(networkupdate){
    75   |     va_start(ap, fmt);
    76   |     vprintf(fmt, ap);
    77   |     fflush(stdout);
    78   |     va_end(ap);
    79   |   }
    80   |
    81   |   /* and then to the file */
    82   |   va_start(ap, fmt);
    83   |
    84   |   for(p = fmt; *p; p++){
    85   |     if (*p != '%') {
    86   |       fprintf(ack_file, "%c", *p);
    87   |       continue;
    88   |     }
    89   |     switch(*++p) {
    90   |     case 'd':
    91   |       ival = va_arg(ap, int);
    92   |       fprintf(ack_file, "%d", ival);
    93   |       break;
    94   |     case 'f':
    95   |       dval = va_arg(ap, double);
    96   |       fprintf(ack_file, "%f", dval);
    97   |       break;
    98   |     case 'X':
    99   |       ival = va_arg(ap, int);
    100  |       fprintf(ack_file, "%X", ival);
    101  |       break;
    102  |     case 'x':
    103  |       ival = va_arg(ap, int);
    104  |       fprintf(ack_file, "%x", ival);
    105  |       break;
    106  |     case 's':
    107  |       sval = va_arg(ap, char *);
    108  |       fprintf(ack_file, "%s", sval);
    109  |       break;
    110  |     default:
    111  |       putchar(*p);
    112  |       break;
    113  |     }
    114  |   }
    115  |
    116  |   va_end(ap); /* clean up */
    117  |   fclose(ack_file);
    118  | }
    119  |
    120  |
    121  |
    122  | /* Adds a complete file to the ack file */
    123  |
    124  | void AK_add_file_to_ack(const char * ackfile, const char * filetoadd){
    125  |
    126  |   FILE * ack_file, * file_to_add;
    127  |   char   buf[1024];
    128  |
    129  |   if(( ack_file = fopen(ackfile, "a")) == NULL){
    130  |     fprintf(stderr, "AK_add_file_to_ack: Can't open ack file, %s\n", ackfile);
    131  |   }
    132  |
    133  |   if(( file_to_add = fopen(filetoadd, "r")) == NULL){
    134  |
    135  |     fprintf(stderr, "AK_add_file_to_ack: Can't open file, %s\n", filetoadd);
    136  |     fprintf(ack_file, "\nHelp file could not be found.\nPlease notify the database administrator.\n");
    137  |     fclose(ack_file);
    138  |     free(buf);
    139  |
    140  |   }else{
    141  |
    142  |     while(fgets(buf, 1023, file_to_add) != NULL){
    143  |       fprintf(ack_file, "%s", buf);
    144  |     }
    145  |
    146  |     fclose(ack_file);
    147  |     fclose(file_to_add);
    148  |   }
    149  | }
    150  |
    151  |
    152  | /*
    153  |
    154  |   AK_ack_file_name_generate: Generates a unique name for temporary acknowledgement
    155  |      files, and also creates it.
    156  |
    157  |       tmpdir: temporary directory (without a trailing '/')
    158  |       prefix: prefix for the temp file
    159  |
    160  |       returns: the generated name.
    161  | */
    162  |
    163  | char * AK_ack_file_name_generate( const char * tmpdir, const char * prefix)
    164  | {
    165  |    FILE * ack_file;
    166  |    char * name;
    167  |
    168  |    /* allocate space for name. 32 should be enough for PID */
    169  |    name = (char*)malloc(strlen(tmpdir) + strlen(prefix) + 35);
    170  |
    171  |    sprintf(name, "%s/%s.%i", tmpdir, prefix, (int)(getpid()) );
    172  |
    173  |    /* create the file */
    174  |    if (( ack_file = fopen(name, "w")) == NULL)
    175  |    {
    176  |      fprintf(stderr, "Can't open ack file, %s", name);
    177  |    }
    178  |
    179  |    /* close it */
    180  |    fclose(ack_file);
    181  |
    182  |    return name;
    183  | }
    184  |
    185  |
    186  | /*
    187  |
    188  | AK_send_ack: post-processes and sends the ack message contained in the temp file.
    189  |
    190  |
    191  | */
    192  |
    193  | void AK_send_ack( const char * filename, const char * to_address, const char * mailercommand)
    194  | {
    195  |     char * mail_command_line = NULL;
    196  |     char * supress_file = NULL, * temp_file = NULL;
    197  |     FILE * ack_file, * supr_file_hdl, * temp_file_hdl;
    198  |     char *txt_replaced;
    199  |     char buf[1024];
    200  |
    201  |     /* first check if we the user specified some non-keyword words in
    202  |        the subject line (in addition to some valid keywords)
    203  |        If so, we will add a warning to the ack file */
    204  |     if (subject_result.result == UP_SUBJ_UNRECOG)
    205  | 	{
    206  |       if (( ack_file = fopen(filename, "a")) == NULL)
    207  | 	  {
    208  |         fprintf(stderr, "Can't open ack file for appending, %s", filename);
    209  |       }
    210  | 	  else
    211  | 	  {
    212  |         fprintf(ack_file, "\nWarning: unknown keywords found in subject line:\n"
    213  |                    "%s\n"
    214  |                    "Thus, all keywords in subject line were ignored.\n",
    215  |                     subject_result.word_list ? subject_result.word_list : "" );
    216  |         fclose(ack_file);
    217  |       }
    218  |
    219  |     /* and now check if the user specified an invalid combination of keywords
    220  |        in the subject line, and if so, print an appropriate warning to ack */
    221  |     }
    222  | 	else if (subject_result.result == UP_SUBJ_INVALID_COMB)
    223  | 	{
    224  |       if (( ack_file = fopen(filename, "a")) == NULL)
    225  | 	  {
    226  |         fprintf(stderr, "Can't open ack file for appending, %s", filename);
    227  |       }
    228  | 	  else
    229  | 	  {
    230  |         fprintf(ack_file, "\nWarning: This combination of keywords in subject line is not allowed.\n"
    231  |                    "Thus, all keywords in subject line were ignored.\n");
    232  |         fclose(ack_file);
    233  |       }
    234  |     }
    235  |
    236  |     /* if the update didn't contain any objects and was not a request for help, put a warning */
    237  |     if (count_successful == 0 && count_unsuccessful == 0 && subject_result.result != UP_SUBJ_HELP_REQ)
    238  | 	{
    239  |       AK_add_to_ack(filename, "*** Warning: No objects were found in the message ***\n");
    240  |     }
    241  |
    242  |     /* add the ACKSIG to the ack */
    243  |     AK_add_to_ack(filename ,"\n%s", acksig);
    244  |
    245  |     /* Here, we will print out the header of the ACK message. It cannot be
    246  |        prepared before, since we wouldn't know if the header should use
    247  |        SUCCESSTXT or FAILURETXT */
    248  |     temp_file = (char *)malloc(strlen(filename) + strlen(".temp") + 2);
    249  |     sprintf(temp_file, "%s.temp", filename);
    250  |     if(( temp_file_hdl = fopen(temp_file, "w")) == NULL)
    251  | 	{
    252  |       fprintf(stderr, "Can't open temp ack file, %s\n", temp_file);
    253  |     }
    254  | 	else
    255  | 	{
    256  |       if ( subject_result.result == UP_SUBJ_HELP_REQ )
    257  |       {
    258  |         /* this is a request for help, so we will use the HELPHEADER */
    259  |         /* replace the global variables in helpheader */
    260  |         txt_replaced = UP_replace_globals(helpheader);
    261  |       }
    262  |       else if (count_unsuccessful > 0 || (count_successful + count_unsuccessful) == 0)
    263  | 	  {
    264  |         /* At least one of the objects failed or there wasn't any object in the
    265  |         update message. We will use FAILURETXT */
    266  |         /* replace the global variables in failuretxt */
    267  |         txt_replaced = UP_replace_globals(failuretxt);
    268  | 	  }
    269  | 	  else
    270  | 	  {
    271  |         /* All the objects in the update message were successful. So, we will
    272  |         use SUCCESSTXT */
    273  |         /* replace the global variables in successtxt */
    274  |         txt_replaced = UP_replace_globals(successtxt);
    275  | 	  }
    276  |
    277  |       /* print out the success/failure/help txt */
    278  |       fprintf(temp_file_hdl, "To: %s\n%s\n\n", to_address, txt_replaced);
    279  |       free(txt_replaced);
    280  |       /* and now copy over the rest of the ack message */
    281  |       if (( ack_file = fopen(filename, "r")) == NULL)
    282  | 	  {
    283  |         fprintf(stderr, "Can't open ack file for reading, %s", filename);
    284  |       }
    285  | 	  else
    286  | 	  {
    287  |         while (fgets(buf, 1024, ack_file) != NULL)
    288  | 		{
    289  |           fprintf(temp_file_hdl, "%s", buf);
    290  |         }
    291  |         fclose(ack_file);
    292  |       }
    293  |       fclose(temp_file_hdl);
    294  |       /* and copy rename the temp file  */
    295  |       rename(temp_file, filename);
    296  |       free(temp_file);
    297  |     }
    298  |
    299  |     /* if we are not supressing acks and notifs, send the ack */
    300  |     if (!supress_ack_notif)
    301  | 	{
    302  |       if (to_address != NULL)
    303  | 	  {
    304  |         mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(to_address)
    305  |             + strlen(filename) + 128);
    306  |         sprintf(mail_command_line, "%s %s < %s", mailercommand, to_address, filename);
    307  |         system(mail_command_line);
    308  |       }
    309  |     }
    310  | 	else
    311  | 	{
    312  |       /* if we are supressing acks and notifs, send ack to DEFMAIL  */
    313  |       supress_file = (char *)malloc(strlen(filename) + strlen(".supress") + 2);
    314  |       sprintf(supress_file, "%s.supress", filename);
    315  |       if (( supr_file_hdl = fopen(supress_file, "w")) == NULL)
    316  | 	  {
    317  |         fprintf(stderr, "Can't open supress ack file, %s", supress_file);
    318  |       }
    319  | 	  else
    320  | 	  {
    321  |         fprintf(supr_file_hdl, "From: %s\nTo: %s\nSubject: Supressed ack mail\n\n",
    322  |             humailbox, defmail);
    323  |         if (( ack_file = fopen(filename, "r")) == NULL)
    324  | 		{
    325  |           fprintf(stderr, "Can't open ack file for reading, %s", filename);
    326  |         }
    327  | 		else
    328  | 		{
    329  |           while (fgets(buf, 1024, ack_file) != NULL)
    330  | 		  {
    331  |             fprintf(supr_file_hdl, "%s", buf);
    332  |           }
    333  |           fclose(ack_file);
    334  |         }
    335  |     	fclose(supr_file_hdl);
    336  |     	mail_command_line = (char *)malloc(strlen(mailercommand) + strlen(defmail)
    337  |               + strlen(supress_file) + 128);
    338  |     	sprintf(mail_command_line, "%s %s < %s", mailercommand, defmail, supress_file);
    339  |     	system(mail_command_line);
    340  |     	unlink(supress_file);
    341  |       }
    342  |       free(supress_file);
    343  |     }
    344  | }
    345  |
    346  |
    347  |
    348  | /*
    349  |
    350  |   AK_print_ack: Prints out the given file (the ack file) to the standard output
    351  |
    352  | */
    353  | void AK_print_ack( const char * filename )
    354  | {
    355  |     FILE * ack_file;
    356  |     char buf[1024];
    357  |
    358  |     if (( ack_file = fopen(filename, "r")) == NULL)
    359  | 	{
    360  |       fprintf(stderr, "Can't open ack file for reading, %s", filename);
    361  |     }
    362  | 	else
    363  | 	{
    364  |       while (fgets(buf, 1024, ack_file) != NULL)
    365  | 	  {
    366  |         printf("%s", buf);
    367  |       }
    368  |       fclose(ack_file);
    369  |     }
    370  | }
    371  |
    372  |
    373  |
    374  | /*
    375  |
    376  |   AK_delete_ack: deletes the temporary acknowledgement file.
    377  |
    378  | */
    379  |
    380  | void AK_delete_ack( const char * filename )
    381  | {
    382  |    unlink(filename);
    383  | }
    384  |
    385  |
    386  | /*
    387  |
    388  | AK_log_ack: logs the acknowledgements in the "logfilename.date".
    389  |
    390  | */
    391  |
    392  | void AK_log_ack(const char * filename, const char * logfilename)
    393  | {
    394  |   FILE * ack_file, * log_file;
    395  |   char   buf[1024];
    396  |   time_t cur_time;
    397  |   char * time_str;
    398  |   char * logfile_date;
    399  |   char * date;
    400  |
    401  |   if (( ack_file = fopen(filename, "r")) == NULL)
    402  |   {
    403  |     fprintf(stderr, "Can't open ack file for reading, %s\n", filename);
    404  |     return;
    405  |   }
    406  |
    407  |
    408  |   /* construct the "logfilename.date" string */
    409  |   logfile_date = (char *)malloc(strlen(logfilename) + 10);
    410  |   date = UP_get_current_date();
    411  |   snprintf(logfile_date, strlen(logfilename) + 10, "%s.%s", logfilename, date);
    412  |   free(date);
    413  |
    414  |   if (( log_file = fopen(logfile_date, "a")) == NULL)
    415  |   {
    416  |     fprintf(stderr, "Can't open log file for appending, %s\n", logfile_date);
    417  | 	free(logfile_date);
    418  |     return;
    419  |   }
    420  |   free(logfile_date);
    421  |
    422  |   /* get time */
    423  |   cur_time = time(NULL);
    424  |   time_str = strdup(ctime(&cur_time));
    425  |   /* cut the '\n' at the end */
    426  |   time_str[strlen(time_str) - 1] = '\0';
    427  |
    428  |   if (reading_from_mail)
    429  |   {
    430  |     fprintf(log_file, ">>> time: %s MAIL ACK <<<\n\n", time_str);
    431  |   }
    432  |   else if (networkupdate)
    433  |   {
    434  |     fprintf(log_file, ">>> time: %s NETWORKUPDATE ACK <<<\n\n", time_str);
    435  |   }
    436  |   else
    437  |   {
    438  |     fprintf(log_file, ">>> time: %s ACK <<<\n\n", time_str);
    439  |   }
    440  |
    441  |   while (fgets(buf, 1023, ack_file) != NULL)
    442  |   {
    443  |     fprintf(log_file, "%s", buf);
    444  |   }
    445  |
    446  |   free(time_str);
    447  |   fclose(ack_file);
    448  |   fclose(log_file);
    449  | }
    450  |
    451  |
    452  |
    453  |
    454  |
    455  |
    456  |
    457  |