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