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