modules/ak/ack.c

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

DEFINITIONS

This source file includes following functions.
  1. AK_add_to_ack
  2. AK_add_file_to_ack
  3. AK_ack_file_name_generate
  4. AK_send_ack
  5. AK_print_ack
  6. AK_delete_ack
  7. AK_log_ack

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

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