1 /*:ts=8*/
2 /*****************************************************************************
3 * FIDOGATE --- Gateway UNIX Mail/News <-> FTN NetMail/EchoMail
4 *
5 * $Id: ftnafutil.c,v 1.16 2004/08/22 20:19:10 n0ll Exp $
6 *
7 * Utility program for Areafix.
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 "fidogate.h"
34 #include "getopt.h"
35
36
37
38 #define PROGRAM "ftnafutil"
39 #define VERSION "$Revision: 1.16 $"
40 #define CONFIG DEFAULT_CONFIG_MAIN
41
42
43
44 /*
45 * Prototypes
46 */
47 int areafix_init (int);
48 void areafix_auth_cmd (void);
49 char *areafix_areasbbs (void);
50 void areafix_set_areasbbs (char *name);
51 char *areafix_name (void);
52 Node *areafix_auth_node (void);
53 int areafix_do (Node *node, char *subj, Textlist*, Textlist*);
54 int rewrite_areas_bbs (void);
55 int areafix_do_cmd (Node *, char *, Textlist *);
56 void areafix_set_changed (void);
57
58 int do_mail (Node *, char *, char *, Passwd *);
59 int do_areasbbs (int);
60 int do_cmd (char **);
61 void short_usage (void);
62 void usage (void);
63
64
65
66 /*
67 * Global vars
68 */
69 static int n_flag = FALSE;
70
71
72
73 /*
74 * Subscribe to an area
75 */
do_mail(Node * node,char * area,char * s,Passwd * pwd)76 int do_mail(Node *node, char *area, char *s, Passwd *pwd)
77 {
78 Textlist outbody;
79 Message outmsg;
80 char *to;
81
82 if(!pwd || !pwd->passwd)
83 {
84 logit("ERROR: no uplink password for %s, can't send request",
85 znfp1(node));
86 return ERROR;
87 }
88 to = pwd->args && *pwd->args ? pwd->args : areafix_name();
89
90 /* Send Areafix message */
91 tl_init(&outbody);
92 cf_set_zone(node->zone);
93
94 outmsg.node_from = cf_n_addr();
95 outmsg.node_to = *node;
96 outmsg.attr = 0;
97 outmsg.cost = 0;
98 outmsg.date = time(NULL);
99 BUF_COPY (outmsg.name_from, areafix_name());
100 BUF_APPEND(outmsg.name_from, " Daemon" );
101 BUF_COPY (outmsg.name_to , to );
102 BUF_COPY (outmsg.subject , pwd->passwd );
103 outmsg.area = NULL;
104
105 tl_appendf(&outbody, "%s%s", s, area);
106
107 return outpkt_netmail(&outmsg, &outbody, PROGRAM);
108 }
109
110
111
112 /*
113 * Process areas.bbs
114 */
115 #define DO_DELETE 0
116 #define DO_SUBSCRIBE 1
117 #define DO_UNSUBSCRIBE 2
118 #define DO_LISTGWLINKS 3
119
do_areasbbs(int cmd)120 int do_areasbbs(int cmd)
121 {
122 AreasBBS *p, *pl;
123 LON *lon;
124 Node *uplink;
125 int n;
126 char *state;
127 Passwd *pwd;
128
129 pl = NULL;
130 p = areasbbs_first();
131 while(p)
132 {
133 lon = &p->nodes;
134 uplink = lon->first ? &lon->first->node : NULL;
135 n = lon->size - 1;
136 state = p->state ? p->state : "";
137
138 debug(3, "processing area %s: state=%s uplink=%s #dl=%d",
139 p->area, state, uplink ? znfp1(uplink) : "(none)", n );
140
141 switch(cmd)
142 {
143 case DO_DELETE:
144 if(!uplink)
145 {
146 logit("area %s: no uplink, deleting", p->area);
147 if(!n_flag)
148 {
149 areasbbs_remove(p, pl);
150 areafix_set_changed();
151 p = p->next;
152 continue;
153 }
154 }
155 break;
156
157 case DO_SUBSCRIBE:
158 if(uplink && n>0 && strchr(state, 'U'))
159 {
160 if(! (pwd = passwd_lookup("uplink", uplink)) )
161 break;
162 logit("area %s: #dl=%d state=%s, subscribing at uplink %s",
163 p->area, n, state, znfp1(uplink));
164 if(!n_flag && do_mail(uplink, p->area, "+", pwd) != ERROR)
165 {
166 /**FIXME: remove "U", add "S"**/
167 p->state = strsave("S");
168 areafix_set_changed();
169 }
170 }
171 break;
172
173 case DO_UNSUBSCRIBE:
174 if(uplink && n<=0 && strchr(state, 'S'))
175 {
176 if(! (pwd = passwd_lookup("uplink", uplink)) )
177 break;
178 logit("area %s: #dl=%d state=%s, unsubscribing at uplink %s",
179 p->area, n, state, znfp1(uplink));
180 if(!n_flag && do_mail(uplink, p->area, "-", pwd) != ERROR)
181 {
182 /**FIXME: add "U", remove "S"**/
183 p->state = strsave("U");
184 areafix_set_changed();
185 }
186 }
187 break;
188
189 case DO_LISTGWLINKS:
190 n = lon->size;
191 cf_set_zone(p->zone);
192 debug(5, "area %s, LON size %d, zone %d", p->area, n, p->zone);
193 if(uplink && node_eq(uplink, cf_addr())) {
194 /* 1st downlink is gateway, don't include in # of downlinks */
195 n--;
196 debug(5, " # downlinks is %d", n);
197 }
198 printf("%s %s %d\n",
199 p->area, uplink ? znfp1(uplink) : "-", n);
200 break;
201
202 default:
203 return ERROR;
204 /**NOT REACHED**/
205 break;
206 }
207
208 /* Next */
209 pl = p;
210 p = p->next;
211
212 tmps_freeall();
213 }
214
215 return OK;
216 }
217
218
219
220 /*
221 * Do command
222 */
do_cmd(char * cmd[])223 int do_cmd(char *cmd[])
224 {
225 if(cmd[0])
226 {
227 if (strieq(cmd[0], "delete"))
228 do_areasbbs(DO_DELETE);
229 else if(strieq(cmd[0], "subscribe"))
230 do_areasbbs(DO_SUBSCRIBE);
231 else if(strieq(cmd[0], "unsubscribe"))
232 do_areasbbs(DO_UNSUBSCRIBE);
233 else if(strieq(cmd[0], "listgwlinks"))
234 {
235 cf_i_am_a_gateway_prog();
236 cf_debug();
237 do_areasbbs(DO_LISTGWLINKS);
238 }
239 else
240 {
241 fprintf(stderr, "%s: illegal command %s\n", PROGRAM, cmd[0]);
242 return ERROR;
243 }
244 }
245
246 return OK;
247 }
248
249
250
251 /*
252 * Usage messages
253 */
short_usage(void)254 void short_usage(void)
255 {
256 fprintf(stderr, "usage: %s [-options] command ...\n", PROGRAM);
257 fprintf(stderr, " %s --help for more information\n", PROGRAM);
258 exit(EX_USAGE);
259 }
260
261
usage(void)262 void usage(void)
263 {
264 fprintf(stderr, "FIDOGATE %s %s %s\n\n",
265 version_global(), PROGRAM, version_local(VERSION) );
266
267 fprintf(stderr, "usage: %s [-options] command ...\n\n", PROGRAM);
268 fprintf(stderr, "\
269 options: -n --noaction don't really do anything ;-)\n\
270 -b --areas-bbs NAME use alternate AREAS.BBS\n\
271 -F --filefix run as Filefix program (FAREAS.BBS)\n\
272 -O --out-dir DIR set output packet directory\n\
273 \n\
274 -v --verbose more verbose\n\
275 -h --help this help\n\
276 -c --config name read config file (\"\" = none)\n\
277 -a --addr Z:N/F.P set FTN address\n\
278 -u --uplink-addr Z:N/F.P set FTN uplink address\n\
279 \n\
280 command: delete delete dead areas (no uplink or downlink)\n\
281 subscribe subscribe to areas with new downlinks\n\
282 unsubscribe unsubscribe from areas with no more downlinks\n\
283 listgwlinks list areas with number of ext. links (excl. gateway)\n\
284 ");
285
286 exit(0);
287 }
288
289
290
291 /***** main() ****************************************************************/
292
main(int argc,char ** argv)293 int main(int argc, char **argv)
294 {
295 int c;
296 char *c_flag=NULL;
297 char *a_flag=NULL, *u_flag=NULL;
298 char *O_flag=NULL;
299 int areafix=TRUE;
300 int ret;
301
302 int option_index;
303 static struct option long_options[] =
304 {
305 { "no-rewrite", 0, 0, 'n'},
306 { "areas-bbs", 1, 0, 'b'},
307 { "filefix", 0, 0, 'F'},
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_program(PROGRAM);
319
320 /* Init configuration */
321 cf_initialize();
322
323
324 while ((c = getopt_long(argc, argv, "nb:FO:vhc:a:u:",
325 long_options, &option_index )) != EOF)
326 switch (c) {
327 /***** ftnaf options *****/
328 case 'n':
329 n_flag = TRUE;
330 break;
331 case 'b':
332 areafix_set_areasbbs(optarg);
333 break;
334 case 'F':
335 areafix = FALSE;
336 break;
337 case 'O':
338 O_flag = optarg;
339 break;
340
341 /***** Common options *****/
342 case 'v':
343 verbose++;
344 break;
345 case 'h':
346 usage();
347 exit(0);
348 break;
349 case 'c':
350 c_flag = optarg;
351 break;
352 case 'a':
353 a_flag = optarg;
354 break;
355 case 'u':
356 u_flag = optarg;
357 break;
358 default:
359 short_usage();
360 exit(EX_USAGE);
361 break;
362 }
363
364 /* Read config file */
365 cf_read_config_file(c_flag ? c_flag : CONFIG);
366
367 /* Process config options */
368 if(a_flag)
369 cf_set_addr(a_flag);
370 if(u_flag)
371 cf_set_uplink(u_flag);
372 cf_debug();
373
374 /* Process local options */
375 pkt_outdir(O_flag ? O_flag : DEFAULT_OUTPKT, NULL);
376
377 /* Common init */
378 areafix_init(areafix);
379 /* Read PASSWD */
380 passwd_init();
381
382 ret = 0;
383
384 /*
385 * Process command on command line
386 */
387 if(optind >= argc)
388 {
389 fprintf(stderr, "%s: expecting command\n", PROGRAM);
390 short_usage();
391 }
392
393 if(areasbbs_init(areafix_areasbbs()) == ERROR)
394 exit(EX_OSFILE);
395
396 if(do_cmd(argv+optind) == ERROR)
397 ret = EX_DATAERR;
398 if(ret==0 && !n_flag)
399 if( rewrite_areas_bbs() == ERROR )
400 ret = EX_CANTCREAT;
401
402 exit(ret);
403 }
404