modules/ak/ack.c

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

FUNCTIONS

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.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, ...){
     /* [<][>][^][v][top][bottom][index][help] */
  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){
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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 )
     /* [<][>][^][v][top][bottom][index][help] */
 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 )
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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 

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