modules/ak/ack.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
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.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