1 /*:ts=8*/
2 /*****************************************************************************
3 * FIDOGATE --- Gateway UNIX Mail/News <-> FIDO NetMail/EchoMail
4 *
5 * $Id: ftnafpkt.c,v 1.17 2004/08/22 20:19:10 n0ll Exp $
6 *
7 * Areafix processing FTN packets
8 *
9 *****************************************************************************
10 * Copyright (C) 1990-2004
11 * _____ _____
12 * | |___ | Martin Junius <mj.at.n0ll.dot.net>
13 * | | | | | | Radiumstr. 18
14 * |_|_|_|@home| D-51069 Koeln, Germany
15 *
16 * This file is part of FIDOGATE.
17 *
18 * FIDOGATE is free software; you can redistribute it and/or modify it
19 * under the terms of the GNU General Public License as published by the
20 * Free Software Foundation; either version 2, or (at your option) any
21 * later version.
22 *
23 * FIDOGATE is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with FIDOGATE; see the file COPYING. If not, write to the Free
30 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31 *****************************************************************************/
32
33 #include <signal.h>
34
35 #include "fidogate.h"
36 #include "getopt.h"
37
38
39 #define PROGRAM "ftnafpkt"
40 #define VERSION "$Revision: 1.17 $"
41 #define CONFIG DEFAULT_CONFIG_MAIN
42
43
44
45 /* Prototypes */
46
47 /* areafix.c */
48 int areafix_init (int);
49 void areafix_auth_cmd (void);
50 char *areafix_areasbbs (void);
51 void areafix_set_areasbbs (char *name);
52 char *areafix_name (void);
53 Node *areafix_auth_node (void);
54 int areafix_do (Node *node, char *subj, Textlist*, Textlist*);
55 int rewrite_areas_bbs (void);
56 int areafix_do_cmd (Node *, char *, Textlist *);
57
58
59 int do_netmail (Message *, MsgBody *);
60 int do_echomail (Message *, MsgBody *);
61 int do_packet (FILE *, Packet *);
62 int rename_bad (char *);
63 int do_file (char *);
64 void prog_signal (int);
65 void short_usage (void);
66 void usage (void);
67
68
69
70 /* Global vars */
71 static char in_dir[MAXPATH]; /* Input directory */
72 static int must_exit = FALSE; /* Flag for -x operation */
73 static int severe_error = OK; /* ERROR: exit after error */
74 static int signal_exit = FALSE; /* Flag: TRUE if signal received */
75 static int r_flag = FALSE; /* -r --no-reply */
76
77
78
79 /*
80 * Process one NetMail message
81 */
do_netmail(Message * msg,MsgBody * body)82 int do_netmail(Message *msg, MsgBody *body)
83 {
84 Textlist outbody;
85 Message outmsg;
86
87 tl_init(&outbody);
88
89 /* Run Areafix */
90 if(areafix_do(&msg->node_from, msg->subject, &body->body,
91 (r_flag ? NULL : &outbody) ) == ERROR)
92 return ERROR;
93
94 if(r_flag)
95 return OK;
96
97 /* Send reply */
98 node_clear(&outmsg.node_from);
99 node_clear(&outmsg.node_orig);
100 outmsg.node_to = msg->node_from;
101 outmsg.attr = 0;
102 outmsg.cost = 0;
103 outmsg.date = time(NULL);
104 BUF_COPY (outmsg.name_from, areafix_name());
105 BUF_APPEND(outmsg.name_from, " Daemon" );
106 BUF_COPY (outmsg.name_to , msg->name_from);
107 BUF_COPY (outmsg.subject , "Your " );
108 BUF_APPEND(outmsg.subject , areafix_name());
109 BUF_APPEND(outmsg.subject , " Request" );
110 outmsg.area = NULL;
111
112 return outpkt_netmail(&outmsg, &outbody, PROGRAM);
113 }
114
115
116
117 /*
118 * Process one EchoMail message
119 */
do_echomail(Message * msg,MsgBody * body)120 int do_echomail(Message *msg, MsgBody *body)
121 {
122 logit("echomail message from %s not processed", znfp1(&msg->node_orig));
123
124 return OK;
125 }
126
127
128
129 /*
130 * Read and process FTN packets
131 */
do_packet(FILE * pkt_file,Packet * pkt)132 int do_packet(FILE *pkt_file, Packet *pkt)
133 {
134 Message msg; /* Message header */
135 Textlist tl; /* Textlist for message body */
136 MsgBody body; /* Message body of FTN message */
137 int type;
138
139 /* Initialize */
140 tl_init(&tl);
141 msg_body_init(&body);
142
143
144 /* Read packet */
145 type = pkt_get_int16(pkt_file);
146 if(type == ERROR)
147 {
148 if(feof(pkt_file))
149 {
150 logit("WARNING: premature EOF reading input packet");
151 TMPS_RETURN(OK);
152 }
153
154 logit("ERROR: reading input packet");
155 TMPS_RETURN(ERROR);
156 }
157
158 while(type == MSG_TYPE)
159 {
160 /* Read message header */
161 msg.node_from = pkt->from;
162 msg.node_to = pkt->to;
163 if(pkt_get_msg_hdr(pkt_file, &msg) == ERROR)
164 {
165 logit("ERROR: reading input packet");
166 TMPS_RETURN(ERROR);
167 }
168
169 /* Read message body */
170 type = pkt_get_body(pkt_file, &tl);
171 if(type == ERROR)
172 {
173 if(feof(pkt_file))
174 {
175 logit("WARNING: premature EOF reading input packet");
176 }
177 else
178 {
179 logit("ERROR: reading input packet");
180 TMPS_RETURN(ERROR);
181 }
182 }
183
184 /* Parse message body */
185 if( msg_body_parse(&tl, &body) == -2 )
186 logit("ERROR: parsing message body");
187 /* Retrieve address information from kludges for NetMail */
188 if(body.area == NULL)
189 {
190 /* Retrieve complete address from kludges */
191 kludge_pt_intl(&body, &msg, TRUE);
192 msg.node_orig = msg.node_from;
193
194 debug(5, "NetMail: %s -> %s",
195 znfp1(&msg.node_from), znfp2(&msg.node_to) );
196 if(do_netmail(&msg, &body) == ERROR)
197 TMPS_RETURN(ERROR);
198 }
199 else
200 {
201 /* Retrieve address information from * Origin line */
202 if(msg_parse_origin(body.origin, &msg.node_orig) == ERROR)
203 /* No * Origin line address, use header */
204 msg.node_orig = msg.node_from;
205
206 debug(5, "EchoMail: %s -> %s",
207 znfp1(&msg.node_from), znfp2(&msg.node_to) );
208 if(do_echomail(&msg, &body) == ERROR)
209 TMPS_RETURN(ERROR);
210 }
211
212 /*
213 * Exit if signal received
214 */
215 if(signal_exit)
216 {
217 TMPS_RETURN(severe_error=ERROR);
218 }
219 } /**while(type == MSG_TYPE)**/
220
221 TMPS_RETURN(OK);
222 }
223
224
225
226 /*
227 * Process one packet file
228 */
do_file(char * pkt_name)229 int do_file(char *pkt_name)
230 {
231 Packet pkt;
232 FILE *pkt_file;
233 long pkt_size;
234
235 /* Open packet and read header */
236 pkt_file = fopen(pkt_name, R_MODE);
237 if(!pkt_file) {
238 logit("$ERROR: can't open packet %s", pkt_name);
239 rename_bad(pkt_name);
240 TMPS_RETURN(OK);
241 }
242 if(pkt_get_hdr(pkt_file, &pkt) == ERROR)
243 {
244 logit("ERROR: reading header from %s", pkt_name);
245 fclose(pkt_file);
246 rename_bad(pkt_name);
247 TMPS_RETURN(OK);
248 }
249
250 /* Process it */
251 pkt_size = check_size(pkt_name);
252 logit("packet %s (%ldb) from %s to %s", pkt_name, pkt_size,
253 znfp1(&pkt.from), znfp2(&pkt.to) );
254
255 if(do_packet(pkt_file, &pkt) == ERROR)
256 {
257 logit("ERROR: processing %s", pkt_name);
258 fclose(pkt_file);
259 rename_bad(pkt_name);
260 TMPS_RETURN(severe_error);
261 }
262
263 fclose(pkt_file);
264
265 if (unlink(pkt_name)) {
266 logit("$ERROR: can't unlink %s", pkt_name);
267 rename_bad(pkt_name);
268 TMPS_RETURN(ERROR);
269 }
270
271 TMPS_RETURN(OK);
272 }
273
274
275
276 /*
277 * Signal handler
278 */
prog_signal(int signum)279 void prog_signal(int signum)
280 {
281 char *name = "";
282
283 signal_exit = TRUE;
284
285 switch(signum)
286 {
287 case SIGHUP:
288 name = " by SIGHUP"; break;
289 case SIGINT:
290 name = " by SIGINT"; break;
291 case SIGQUIT:
292 name = " by SIGQUIT"; break;
293 default:
294 name = ""; break;
295 }
296
297 logit("KILLED%s: exit forced", name);
298 }
299
300
301
302 /*
303 * Usage messages
304 */
short_usage(void)305 void short_usage(void)
306 {
307 fprintf(stderr, "usage: %s [-options] [packet ...]\n", PROGRAM);
308 fprintf(stderr, " %s --help for more information\n", PROGRAM);
309 }
310
311
usage(void)312 void usage(void)
313 {
314 fprintf(stderr, "FIDOGATE %s %s %s\n\n",
315 version_global(), PROGRAM, version_local(VERSION) );
316
317 fprintf(stderr, "usage: %s [-options] [packet ...]\n\n", PROGRAM);
318 fprintf(stderr, "\
319 options: -I --in-dir DIR set input packet directory\n\
320 -O --out-dir DIR set output packet directory\n\
321 -l --lock-file create lock file while processing\n\
322 -r --no-reply don't send reply via NetMail\n\
323 -n --no-rewrite don't rewrite AREAS.BBS\n\
324 -b --areas-bbs NAME use alternate AREAS.BBS\n\
325 -F --filefix run as Filefix program (FAREAS.BBS)\n\
326 \n\
327 -v --verbose more verbose\n\
328 -h --help this help\n\
329 -c --config NAME read config file (\"\" = none)\n\
330 -a --addr Z:N/F.P set FTN address\n\
331 -u --uplink-addr Z:N/F.P set FTN uplink address\n");
332
333 exit(0);
334 }
335
336
337
338 /***** main() ****************************************************************/
339
main(int argc,char ** argv)340 int main(int argc, char **argv)
341 {
342 int c, ret;
343 int l_flag = FALSE, n_flag=FALSE;
344 char *I_flag=NULL, *O_flag=NULL;
345 char *c_flag=NULL;
346 char *a_flag=NULL, *u_flag=NULL;
347 char *pkt_name;
348 int areafix=TRUE;
349
350 int option_index;
351 static struct option long_options[] =
352 {
353 { "in-dir", 1, 0, 'I'}, /* Set inbound packets directory */
354 { "lock-file", 0, 0, 'l'}, /* Create lock file while processing */
355 { "out-dir", 1, 0, 'O'}, /* Set packet directory */
356 { "no-reply", 0, 0, 'r'},
357 { "no-rewrite", 0, 0, 'n'},
358 { "areas-bbs", 1, 0, 'b'},
359 { "filefix", 0, 0, 'F'},
360
361 { "verbose", 0, 0, 'v'}, /* More verbose */
362 { "help", 0, 0, 'h'}, /* Help */
363 { "config", 1, 0, 'c'}, /* Config file */
364 { "addr", 1, 0, 'a'}, /* Set FIDO address */
365 { "uplink-addr", 1, 0, 'u'}, /* Set FIDO uplink address */
366 { 0, 0, 0, 0 }
367 };
368
369 /* Log name */
370 log_program(PROGRAM);
371
372 /* Init configuration */
373 cf_initialize();
374
375 /* Parse options */
376 while ((c = getopt_long(argc, argv, "O:I:lrnb:Fvhc:a:u:",
377 long_options, &option_index )) != EOF)
378 switch (c) {
379 /***** program options *****/
380 case 'I':
381 I_flag = optarg;
382 break;
383 case 'l':
384 l_flag = TRUE;
385 break;
386 case 'O':
387 O_flag = optarg;
388 break;
389 case 'r':
390 r_flag = TRUE;
391 break;
392 case 'n':
393 n_flag = TRUE;
394 break;
395 case 'b':
396 areafix_set_areasbbs(optarg);
397 break;
398 case 'F':
399 areafix = FALSE;
400 break;
401
402 /***** Common options *****/
403 case 'v':
404 verbose++;
405 break;
406 case 'h':
407 usage();
408 exit(0);
409 break;
410 case 'c':
411 c_flag = optarg;
412 break;
413 case 'a':
414 a_flag = optarg;
415 break;
416 case 'u':
417 u_flag = optarg;
418 break;
419 default:
420 short_usage();
421 exit(EX_USAGE);
422 break;
423 }
424
425 /* Read config file */
426 cf_read_config_file(c_flag ? c_flag : CONFIG);
427 /* Process config option */
428 if(a_flag)
429 cf_set_addr(a_flag);
430 if(u_flag)
431 cf_set_uplink(u_flag);
432 cf_debug();
433
434 /* Process local options */
435 BUF_EXPAND(in_dir, I_flag ? I_flag : cf_p_pinbound());
436 pkt_outdir(O_flag ? O_flag : DEFAULT_OUTPKT, NULL);
437
438 /* Install signal/exit handlers */
439 signal(SIGHUP, prog_signal);
440 signal(SIGINT, prog_signal);
441 signal(SIGQUIT, prog_signal);
442
443 /* Common init */
444 areafix_init(areafix);
445 /* Read PASSWD */
446 passwd_init();
447
448
449 /***** Main processing loop *****/
450 ret = EXIT_OK;
451
452 if(optind >= argc)
453 {
454 /* process packet files in directory */
455 dir_sortmode(DIR_SORTMTIME);
456 if(dir_open(in_dir, "*.pkt", TRUE) == ERROR)
457 {
458 logit("$ERROR: can't open directory %s", in_dir);
459 exit(EXIT_ERROR);
460 }
461
462 /* Lock file */
463 if(l_flag)
464 if(lock_program(PROGRAM, FALSE) == ERROR)
465 /* Already busy */
466 exit(EXIT_BUSY);
467
468 /* Read areas.bbs */
469 if(areasbbs_init(areafix_areasbbs()) == ERROR)
470 {
471 if(l_flag)
472 unlock_program(PROGRAM);
473 exit(EXIT_ERROR);
474 }
475
476 for(pkt_name=dir_get(TRUE); pkt_name; pkt_name=dir_get(FALSE))
477 {
478 if(do_file(pkt_name) == ERROR)
479 {
480 ret = EXIT_ERROR;
481 break;
482 }
483 if(must_exit)
484 {
485 ret = EXIT_CONTINUE;
486 break;
487 }
488 }
489
490 dir_close();
491
492 /* Rewrite areas.bbs */
493 if(ret==EXIT_OK && !n_flag)
494 if(rewrite_areas_bbs() == ERROR)
495 ret = EXIT_ERROR;
496
497 /* Lock file */
498 if(l_flag)
499 unlock_program(PROGRAM);
500 }
501 else
502 {
503 /* Lock file */
504 if(l_flag)
505 if(lock_program(PROGRAM, FALSE) == ERROR)
506 /* Already busy */
507 exit(EXIT_BUSY);
508
509 /* Read areas.bbs */
510 if(areasbbs_init(areafix_areasbbs()) == ERROR)
511 {
512 if(l_flag)
513 unlock_program(PROGRAM);
514 exit(EXIT_ERROR);
515 }
516
517 /* Process packet files on command line */
518 for(; optind<argc; optind++)
519 {
520 if(do_file(argv[optind]) == ERROR)
521 {
522 ret = EXIT_ERROR;
523 break;
524 }
525 if(must_exit)
526 {
527 ret = EXIT_CONTINUE;
528 break;
529 }
530 }
531
532 /* Rewrite areas.bbs */
533 if(ret==EXIT_OK && !n_flag)
534 if(rewrite_areas_bbs() == ERROR)
535 ret = EXIT_ERROR;
536
537 /* Lock file */
538 if(l_flag)
539 unlock_program(PROGRAM);
540 }
541
542
543 exit(ret);
544 }
545