modules/ak/ack.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- AK_add_to_ack
- AK_add_to_ack_string
- AK_add_file_to_ack
- AK_ack_file_name_generate
- AK_send_ack
- AK_print_ack
- AK_delete_ack
- 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