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