modules/ak/ack.cc

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

FUNCTIONS

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

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

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