/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- AK_add_to_ack
- 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.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