1 /*:ts=8*/
2 /*****************************************************************************
3  * FIDOGATE --- Gateway UNIX Mail/News <-> FIDO NetMail/EchoMail
4  *
5  * $Id: pkttmpl.c,v 1.15 2004/08/22 20:19:10 n0ll Exp $
6  *
7  * Template for utility 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 	"ftnxxx"
40 #define VERSION 	"$Revision: 1.15 $"
41 #define CONFIG		DEFAULT_CONFIG_MAIN
42 
43 
44 
45 /* Prototypes */
46 int	do_netmail		(Message *, MsgBody *);
47 int	do_echomail		(Message *, MsgBody *);
48 int	do_packet		(FILE *, Packet *);
49 int	rename_bad		(char *);
50 int	do_file			(char *);
51 void	prog_signal		(int);
52 void	short_usage		(void);
53 void	usage			(void);
54 
55 
56 
57 /* Global vars */
58 static char in_dir[MAXPATH];		/* Input directory */
59 static int must_exit    = FALSE;	/* Flag for -x operation */
60 static int severe_error = OK;		/* ERROR: exit after error */
61 static int signal_exit  = FALSE;	/* Flag: TRUE if signal received */
62 
63 
64 
65 /*
66  * Process one NetMail message
67  */
do_netmail(Message * msg,MsgBody * body)68 int do_netmail(Message *msg, MsgBody *body)
69 {
70 
71     return OK;
72 }
73 
74 
75 
76 /*
77  * Process one EchoMail message
78  */
do_echomail(Message * msg,MsgBody * body)79 int do_echomail(Message *msg, MsgBody *body)
80 {
81 
82     return OK;
83 }
84 
85 
86 
87 /*
88  * Read and process FTN packets
89  */
do_packet(FILE * pkt_file,Packet * pkt)90 int do_packet(FILE *pkt_file, Packet *pkt)
91 {
92     Message msg;			/* Message header */
93     Textlist tl;			/* Textlist for message body */
94     MsgBody body;			/* Message body of FTN message */
95     int type;
96 
97     /* Initialize */
98     tl_init(&tl);
99     msg_body_init(&body);
100 
101 
102     /* Read packet */
103     type = pkt_get_int16(pkt_file);
104     if(type == ERROR)
105     {
106 	if(feof(pkt_file))
107 	{
108 	    logit("WARNING: premature EOF reading input packet");
109 	    TMPS_RETURN(OK);
110 	}
111 
112 	logit("ERROR: reading input packet");
113 	TMPS_RETURN(ERROR);
114     }
115 
116     while(type == MSG_TYPE)
117     {
118 	/* Read message header */
119 	msg.node_from = pkt->from;
120 	msg.node_to   = pkt->to;
121 	if(pkt_get_msg_hdr(pkt_file, &msg) == ERROR)
122 	{
123 	    logit("ERROR: reading input packet");
124 	    TMPS_RETURN(ERROR);
125 	}
126 
127 	/* Read message body */
128 	type = pkt_get_body(pkt_file, &tl);
129 	if(type == ERROR)
130 	{
131 	    if(feof(pkt_file))
132 	    {
133 		logit("WARNING: premature EOF reading input packet");
134 	    }
135 	    else
136 	    {
137 		logit("ERROR: reading input packet");
138 		TMPS_RETURN(ERROR);
139 	    }
140 	}
141 
142 	/* Parse message body */
143 	if( msg_body_parse(&tl, &body) == -2 )
144 	    logit("ERROR: parsing message body");
145 	/* Retrieve address information from kludges for NetMail */
146 	if(body.area == NULL)
147 	{
148 	    /* Retrieve complete address from kludges */
149 	    kludge_pt_intl(&body, &msg, TRUE);
150 	    msg.node_orig = msg.node_from;
151 
152 	    debug(5, "NetMail: %s -> %s",
153 		  znfp1(&msg.node_from), znfp2(&msg.node_to) );
154 	    if(do_netmail(&msg, &body) == ERROR)
155 		TMPS_RETURN(ERROR);
156 	}
157 	else
158 	{
159 	    /* Retrieve address information from * Origin line */
160 	    if(msg_parse_origin(body.origin, &msg.node_orig) == ERROR)
161 		/* No * Origin line address, use header */
162 		msg.node_orig = msg.node_from;
163 
164 	    debug(5, "EchoMail: %s -> %s",
165 		  znfp1(&msg.node_from), znfp2(&msg.node_to) );
166 	    if(do_echomail(&msg, &body) == ERROR)
167 		TMPS_RETURN(ERROR);
168 	}
169 
170 	/*
171 	 * Exit if signal received
172 	 */
173 	if(signal_exit)
174 	{
175 	    TMPS_RETURN(severe_error=ERROR);
176 	}
177     } /**while(type == MSG_TYPE)**/
178 
179     TMPS_RETURN(OK);
180 }
181 
182 
183 
184 /*
185  * Process one packet file
186  */
do_file(char * pkt_name)187 int do_file(char *pkt_name)
188 {
189     Packet pkt;
190     FILE *pkt_file;
191     long pkt_size;
192 
193     /* Open packet and read header */
194     pkt_file = fopen(pkt_name, R_MODE);
195     if(!pkt_file) {
196 	logit("$ERROR: can't open packet %s", pkt_name);
197 	rename_bad(pkt_name);
198 	TMPS_RETURN(OK);
199     }
200     if(pkt_get_hdr(pkt_file, &pkt) == ERROR)
201     {
202 	logit("ERROR: reading header from %s", pkt_name);
203 	fclose(pkt_file);
204 	rename_bad(pkt_name);
205 	TMPS_RETURN(OK);
206     }
207 
208     /* Process it */
209     pkt_size = check_size(pkt_name);
210     logit("packet %s (%ldb) from %s to %s", pkt_name, pkt_size,
211 	znfp1(&pkt.from), znfp2(&pkt.to) );
212 
213     if(do_packet(pkt_file, &pkt) == ERROR)
214     {
215 	logit("ERROR: processing %s", pkt_name);
216 	fclose(pkt_file);
217 	rename_bad(pkt_name);
218 	TMPS_RETURN(severe_error);
219     }
220 
221     fclose(pkt_file);
222 
223     if (unlink(pkt_name)) {
224 	logit("$ERROR: can't unlink %s", pkt_name);
225 	rename_bad(pkt_name);
226 	TMPS_RETURN(ERROR);
227     }
228 
229     TMPS_RETURN(OK);
230 }
231 
232 
233 
234 /*
235  * Signal handler
236  */
prog_signal(int signum)237 void prog_signal(int signum)
238 {
239     char *name = "";
240 
241     signal_exit = TRUE;
242 
243     switch(signum)
244     {
245     case SIGHUP:
246 	name = " by SIGHUP";  break;
247     case SIGINT:
248 	name = " by SIGINT";  break;
249     case SIGQUIT:
250 	name = " by SIGQUIT"; break;
251     default:
252 	name = "";            break;
253     }
254 
255     logit("KILLED%s: exit forced", name);
256 }
257 
258 
259 
260 /*
261  * Usage messages
262  */
short_usage(void)263 void short_usage(void)
264 {
265     fprintf(stderr, "usage: %s [-options] [packet ...]\n", PROGRAM);
266     fprintf(stderr, "       %s --help  for more information\n", PROGRAM);
267 }
268 
269 
usage(void)270 void usage(void)
271 {
272     fprintf(stderr, "FIDOGATE %s  %s %s\n\n",
273 	    version_global(), PROGRAM, version_local(VERSION) );
274 
275     fprintf(stderr, "usage:   %s [-options] [packet ...]\n\n", PROGRAM);
276     fprintf(stderr, "\
277 options: -I --in-dir DIR              set input packet directory\n\
278          -O --out-dir DIR             set output packet directory\n\
279          -l --lock-file               create lock file while processing\n\
280 \n\
281 	 -v --verbose                 more verbose\n\
282 	 -h --help                    this help\n\
283          -c --config NAME             read config file (\"\" = none)\n\
284 	 -a --addr Z:N/F.P            set FTN address\n\
285 	 -u --uplink-addr Z:N/F.P     set FTN uplink address\n");
286 
287     exit(0);
288 }
289 
290 
291 
292 /***** main() ****************************************************************/
293 
main(int argc,char ** argv)294 int main(int argc, char **argv)
295 {
296     int c, ret;
297     int l_flag = FALSE;
298     char *I_flag=NULL, *O_flag=NULL;
299     char *c_flag=NULL;
300     char *a_flag=NULL, *u_flag=NULL;
301     char *pkt_name;
302 
303     int option_index;
304     static struct option long_options[] =
305     {
306 	{ "in-dir",       1, 0, 'I'},	/* Set inbound packets directory */
307 	{ "lock-file",    0, 0, 'l'},	/* Create lock file while processing */
308 	{ "out-dir",      1, 0, 'O'},	/* Set packet directory */
309 
310 	{ "verbose",      0, 0, 'v'},	/* More verbose */
311 	{ "help",         0, 0, 'h'},	/* Help */
312 	{ "config",       1, 0, 'c'},	/* Config file */
313 	{ "addr",         1, 0, 'a'},	/* Set FIDO address */
314 	{ "uplink-addr",  1, 0, 'u'},	/* Set FIDO uplink address */
315 	{ 0,              0, 0, 0  }
316     };
317 
318     /* Log name */
319     log_program(PROGRAM);
320 
321     /* Init configuration */
322     cf_initialize();
323 
324     /* Parse options */
325     while ((c = getopt_long(argc, argv, "O:I:lvhc:a:u:",
326 			    long_options, &option_index     )) != EOF)
327 	switch (c) {
328 	/***** program options *****/
329 	case 'I':
330 	    I_flag = optarg;
331 	    break;
332         case 'l':
333 	    l_flag = TRUE;
334             break;
335 	case 'O':
336 	    O_flag = optarg;
337 	    break;
338 
339 	/***** Common options *****/
340 	case 'v':
341 	    verbose++;
342 	    break;
343 	case 'h':
344 	    usage();
345 	    exit(0);
346 	    break;
347 	case 'c':
348 	    c_flag = optarg;
349 	    break;
350 	case 'a':
351 	    a_flag = optarg;
352 	    break;
353 	case 'u':
354 	    u_flag = optarg;
355 	    break;
356 	default:
357 	    short_usage();
358 	    exit(EX_USAGE);
359 	    break;
360 	}
361 
362     /* Read config file */
363     cf_read_config_file(c_flag ? c_flag : CONFIG);
364 
365     /* Process config option */
366     if(a_flag)
367 	cf_set_addr(a_flag);
368     if(u_flag)
369 	cf_set_uplink(u_flag);
370 
371     cf_debug();
372 
373     /* Process optional config statements */
374     if(cf_get_string("XXX", TRUE))
375     {
376 	debug(8, "config: XXX");
377 
378     }
379 
380     /* Process local options */
381     BUF_EXPAND(in_dir, I_flag ? I_flag : cf_p_pinbound());
382     pkt_outdir(O_flag ? O_flag : DEFAULT_OUTPKT, NULL);
383 
384     /* Install signal/exit handlers */
385     signal(SIGHUP,  prog_signal);
386     signal(SIGINT,  prog_signal);
387     signal(SIGQUIT, prog_signal);
388 
389 
390     /***** Main processing loop *****/
391     ret = EXIT_OK;
392 
393     if(optind >= argc)
394     {
395 	/* process packet files in directory */
396 	dir_sortmode(DIR_SORTMTIME);
397 	if(dir_open(in_dir, "*.pkt", TRUE) == ERROR)
398 	{
399 	    logit("$ERROR: can't open directory %s", in_dir);
400 	    exit(EX_OSERR);
401 	}
402 
403 	/* Lock file */
404 	if(l_flag)
405 	    if(lock_program(PROGRAM, FALSE) == ERROR)
406 		/* Already busy */
407 		exit(EXIT_BUSY);
408 
409 	for(pkt_name=dir_get(TRUE); pkt_name; pkt_name=dir_get(FALSE))
410 	{
411 	    if(do_file(pkt_name) == ERROR)
412 	    {
413 		ret = EXIT_ERROR;
414 		break;
415 	    }
416 	    if(must_exit)
417 	    {
418 		ret = EXIT_CONTINUE;
419 		break;
420 	    }
421 	}
422 
423 	dir_close();
424 
425 	/* Lock file */
426 	if(l_flag)
427 	    unlock_program(PROGRAM);
428     }
429     else
430     {
431 	/* Lock file */
432 	if(l_flag)
433 	    if(lock_program(PROGRAM, FALSE) == ERROR)
434 		/* Already busy */
435 		exit(EXIT_BUSY);
436 
437 	/* Process packet files on command line */
438 	for(; optind<argc; optind++)
439 	{
440 	    if(do_file(argv[optind]) == ERROR)
441 	    {
442 		ret = EXIT_ERROR;
443 		break;
444 	    }
445 	    if(must_exit)
446 	    {
447 		ret = EXIT_CONTINUE;
448 		break;
449 	    }
450 	}
451 
452 	/* Lock file */
453 	if(l_flag)
454 	    unlock_program(PROGRAM);
455     }
456 
457 
458     exit(ret);
459 }
460