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