## 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] */