sbbsecho.c 154 KB
Newer Older
1
/* Synchronet FidoNet EchoMail Scanning/Tossing and NetMail Tossing Utility */
2

3
/* $Id$ */
4
// vi: tabstop=4
5
6
7
8
9

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
10
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/
36

37
/* Portions written by Allen Christiansen 1994-1996 						*/
38
39
40
41
42
43
44
45
46

#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
47
#include <sys/stat.h>
48
49
50
#if defined(__unix__)
	#include <signal.h>
#endif
51

rswindell's avatar
rswindell committed
52
#include "conwrap.h"		/* getch() */
53
54
55
56
57
58
#include "sbbs.h"			/* load_cfg() */
#include "sbbsdefs.h"
#include "smblib.h"
#include "scfglib.h"
#include "lzh.h"
#include "sbbsecho.h"
deuce's avatar
deuce committed
59
#include "genwrap.h"		/* PLATFORM_DESC */
rswindell's avatar
rswindell committed
60
61
62
#include "xpendian.h"

#define MAX_OPEN_SMBS	10
63
64

smb_t *smb,*email;
rswindell's avatar
rswindell committed
65
66
67
68
69
70
71
72
73
74
75
bool opt_import_packets		= true;
bool opt_import_netmail		= true;
bool opt_import_echomail	= true;
bool opt_export_echomail	= true;
bool opt_export_netmail		= true;
bool opt_pack_netmail		= true;
bool opt_gen_notify_list	= false;
bool opt_export_ftn_echomail= false;	/* Export msgs previously imported from FidoNet */
bool opt_update_msgptrs		= false;
bool opt_ignore_msgptrs		= false;
bool opt_leave_msgptrs		= false;
76
bool opt_dump_area_file		= false;
rswindell's avatar
rswindell committed
77

rswindell's avatar
rswindell committed
78
79
80
81
82
83
84
/* statistics */
ulong netmail=0;	/* imported */
ulong echomail=0;	/* imported */
ulong exported_netmail=0;
ulong exported_echomail=0;
ulong packed_netmail=0;

rswindell's avatar
rswindell committed
85
int cur_smb=0;
86
FILE *fidologfile=NULL;
rswindell's avatar
rswindell committed
87
bool twit_list;
88

rswindell's avatar
rswindell committed
89
90
91
92
93
fidoaddr_t		sys_faddr = {1,1,1,0};		/* Default system address: 1:1/1.0 */
sbbsecho_cfg_t	cfg;
scfg_t			scfg;
char			revision[16];
char			compiler[32];
94

rswindell's avatar
rswindell committed
95
96
97
98
bool pause_on_exit=false;
bool pause_on_abend=false;
bool mtxfile_locked=false;
bool terminated=false;
99

100
101
str_list_t	locked_bso_nodes;

rswindell's avatar
rswindell committed
102
103
104
int mv(const char *insrc, const char *indest, bool copy);
void export_echomail(const char *sub_code, const nodecfg_t*, bool rescan);

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const char default_domain[] = "fidonet";

const char* zone_domain(uint16_t zone)
{
	struct zone_mapping *i;

	if (!cfg.use_ftn_domains)
		return default_domain;

	for (i=cfg.zone_map; i; i=i->next)
		if (i->zone == zone)
			return i->domain;

	return default_domain;
}

const char* zone_root_outbound(uint16_t zone)
{
	struct zone_mapping *i;

	if (!cfg.use_ftn_domains)
		return cfg.outbound;

	for (i=cfg.zone_map; i; i=i->next)
		if (i->zone == zone)
			return i->root;

	return cfg.outbound;
}

135
136
137
138
139
140
141
142
143
144
145
/* FTN-compliant "Program Identifier"/PID (also used as a "Tosser Identifier"/TID) */
const char* sbbsecho_pid(void)
{
	static char str[256];
	
	sprintf(str, "SBBSecho %u.%02u-%s r%s %s %s"
		,SBBSECHO_VERSION_MAJOR,SBBSECHO_VERSION_MINOR,PLATFORM_DESC,revision,__DATE__,compiler);

	return str;
}

rswindell's avatar
rswindell committed
146
147
/* for *.bsy file contents: */
const char* program_id(void)
148
{
rswindell's avatar
rswindell committed
149
150
151
	static char str[256];
	
	SAFEPRINTF2(str, "%u %s", getpid(), sbbsecho_pid());
152

rswindell's avatar
rswindell committed
153
	return str;
154
155
}

rswindell's avatar
rswindell committed
156
157
158
159
/**********************/
/* Log print function */
/**********************/
int lprintf(int level, char *fmt, ...)
rswindell's avatar
rswindell committed
160
161
{
	va_list argptr;
rswindell's avatar
rswindell committed
162
	char sbuf[1024];
rswindell's avatar
rswindell committed
163
164
	int chcount;

rswindell's avatar
rswindell committed
165
166
	va_start(argptr,fmt);
	chcount=vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
167
	sbuf[sizeof(sbuf)-1]=0;
rswindell's avatar
rswindell committed
168
	va_end(argptr);
169
170
	truncsp(sbuf);
	printf("%s\n",sbuf);
171

rswindell's avatar
rswindell committed
172
173
174
175
	if(fidologfile!=NULL && level<=cfg.log_level) {
	    time_t now = time(NULL);
		struct tm *tm;
		struct tm tmbuf = {0};
176
		char timestamp[128];
rswindell's avatar
rswindell committed
177
178
179
		strip_ctrl(sbuf, sbuf);
		if((tm = localtime(&now)) == NULL)
			tm = &tmbuf;
180
181
182
183
184
		if(strftime(timestamp, sizeof(timestamp), cfg.logtime, tm) <= 0)
			snprintf(timestamp, sizeof(timestamp)-1, "%u-%02u-%02u %02u:%02u:%02u"
				,1900+tm->tm_year, tm->tm_mon+1, tm->tm_mday
				,tm->tm_hour, tm->tm_min, tm->tm_sec);
		fprintf(fidologfile, "%s %s\n", timestamp, sbuf);
rswindell's avatar
rswindell committed
185
186
		fflush(fidologfile);
	}
rswindell's avatar
rswindell committed
187
188
189
	return(chcount);
}

rswindell's avatar
rswindell committed
190
bool delfile(const char *filename, int line)
191
{
rswindell's avatar
rswindell committed
192
	lprintf(LOG_DEBUG, "Deleting %s (from line %u)", filename, line);
193
	if(remove(filename) != 0) {
194
195
		lprintf(LOG_ERR, "ERROR %u (%s) line %u removing file %s"
			,errno, strerror(errno), line, filename);
rswindell's avatar
rswindell committed
196
		return false;
197
	}
rswindell's avatar
rswindell committed
198
	return true;
199
200
}

201
202
203
/*****************************************************************************/
/* Returns command line generated from instr with %c replacments             */
/*****************************************************************************/
rswindell's avatar
rswindell committed
204
char *mycmdstr(scfg_t* cfg, const char *instr, const char *fpath, const char *fspec)
205
{
206
    static char cmd[MAX_PATH+1];
207
208
209
    char str[256],str2[128];
    int i,j,len;

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
	len=strlen(instr);
	for(i=j=0;i<len && j<128;i++) {
		if(instr[i]=='%') {
			i++;
			cmd[j]=0;
			switch(toupper(instr[i])) {
				case 'F':   /* File path */
					strcat(cmd,fpath);
					break;
				case 'G':   /* Temp directory */
					if(cfg->temp_dir[0]!='\\' 
						&& cfg->temp_dir[0]!='/' 
						&& cfg->temp_dir[1]!=':') {
						strcpy(str,cfg->node_dir);
						strcat(str,cfg->temp_dir);
						if(FULLPATH(str2,str,40))
							strcpy(str,str2);
						backslash(str);
						strcat(cmd,str);}
					else
						strcat(cmd,cfg->temp_dir);
					break;
				case 'J':
					if(cfg->data_dir[0]!='\\' 
						&& cfg->data_dir[0]!='/' 
						&& cfg->data_dir[1]!=':') {
						strcpy(str,cfg->node_dir);
						strcat(str,cfg->data_dir);
						if(FULLPATH(str2,str,40))
							strcpy(str,str2);
						backslash(str);
241
242
						strcat(cmd,str); 
					}
243
244
245
246
247
248
249
250
251
252
253
254
					else
						strcat(cmd,cfg->data_dir);
					break;
				case 'K':
					if(cfg->ctrl_dir[0]!='\\' 
						&& cfg->ctrl_dir[0]!='/' 
						&& cfg->ctrl_dir[1]!=':') {
						strcpy(str,cfg->node_dir);
						strcat(str,cfg->ctrl_dir);
						if(FULLPATH(str2,str,40))
							strcpy(str,str2);
						backslash(str);
255
256
						strcat(cmd,str); 
					}
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
					else
						strcat(cmd,cfg->ctrl_dir);
					break;
				case 'N':   /* Node Directory (same as SBBSNODE environment var) */
					strcat(cmd,cfg->node_dir);
					break;
				case 'O':   /* SysOp */
					strcat(cmd,cfg->sys_op);
					break;
				case 'Q':   /* QWK ID */
					strcat(cmd,cfg->sys_id);
					break;
				case 'S':   /* File Spec */
					strcat(cmd,fspec);
					break;
				case '!':   /* EXEC Directory */
273
					strcat(cmd,cfg->exec_dir);
274
					break;
275
276
277
278
279
                case '@':   /* EXEC Directory for DOS/OS2/Win32, blank for Unix */
#ifndef __unix__
                    strcat(cmd,cfg->exec_dir);
#endif
                    break;
280
281
282
283
284
285
286
287
288
289
290
				case '#':   /* Node number (same as SBBSNNUM environment var) */
					sprintf(str,"%d",cfg->node_num);
					strcat(cmd,str);
					break;
				case '*':
					sprintf(str,"%03d",cfg->node_num);
					strcat(cmd,str);
					break;
				case '%':   /* %% for percent sign */
					strcat(cmd,"%");
					break;
291
292
293
294
295
296
297
298
299
300
				case '.':	/* .exe for DOS/OS2/Win32, blank for Unix */
#ifndef __unix__
					strcat(cmd,".exe");
#endif
					break;
				case '?':	/* Platform */
					strcpy(str,PLATFORM_DESC);
					strlwr(str);
					strcat(cmd,str);
					break;
301
				default:    /* unknown specification */
302
					lprintf(LOG_ERR,"ERROR Checking Command Line '%s'",instr);
303
					bail(1);
304
305
306
307
					break; 
			}
			j=strlen(cmd); 
		}
308
		else
309
310
			cmd[j++]=instr[i]; 
}
311
	cmd[j]=0;
312

313
	return(cmd);
314
315
316
}

/****************************************************************************/
rswindell's avatar
rswindell committed
317
/* Runs an external program directly using system()							*/
318
319
320
/****************************************************************************/
int execute(char *cmdline)
{
rswindell's avatar
rswindell committed
321
322
323
324
325
326
	int retval;
	
	lprintf(LOG_DEBUG, "Executing: %s", cmdline);
	if((retval = system(cmdline)) != 0)
		lprintf(LOG_ERR,"ERROR executing '%s' system returned: %d, errno: %d (%s)"
			,cmdline, retval, errno, strerror(errno));
327

rswindell's avatar
rswindell committed
328
	return retval;
329
}
330

331
332
333
/******************************************************************************
 Returns the system address with the same zone as the address passed
******************************************************************************/
rswindell's avatar
rswindell committed
334
fidoaddr_t getsysfaddr(short zone)
335
336
{
	int i;
337

338
339
340
	for(i=0;i<scfg.total_faddrs;i++)
		if(scfg.faddr[i].zone==zone)
			return(scfg.faddr[i]);
341
	return(sys_faddr);
342
}
343

rswindell's avatar
rswindell committed
344
int get_outbound(fidoaddr_t dest, char* outbound, size_t maxlen, bool fileboxes)
345
{
rswindell's avatar
rswindell committed
346
347
	nodecfg_t*	nodecfg;

348
	strncpy(outbound,zone_root_outbound(dest.zone),maxlen);
rswindell's avatar
rswindell committed
349
350
351
352
353
354
	if(fileboxes &&
		(nodecfg = findnodecfg(&cfg, dest, /* exact */true)) != NULL
		&& nodecfg->outbox[0])
		strncpy(outbound, nodecfg->outbox, maxlen);
	else if(cfg.flo_mailer) {
		if(dest.zone != sys_faddr.zone)	{ /* Inter-zone outbound is "OUTBOUND.ZZZ/" */
355
356
357
			char* p = lastchar(outbound);
			if(IS_PATH_DELIM(*p))
				*p = 0;
rswindell's avatar
rswindell committed
358
359
360
361
362
363
			safe_snprintf(outbound+strlen(outbound), maxlen,".%03x", dest.zone);
		}
		if(dest.point != 0) {			/* Point destination is "OUTBOUND[.ZZZ]/NNNNnnnn.pnt/" */
			backslash(outbound);
			safe_snprintf(outbound+strlen(outbound), maxlen, "%04x%04x.pnt", dest.net, dest.node);
		}
364
365
	}
	backslash(outbound);
366
367
368
	if(isdir(outbound))
		return 0;
	lprintf(LOG_DEBUG, "Creating outbound directory for %s: %s", smb_faddrtoa(&dest, NULL), outbound);
369
370
371
	return mkpath(outbound);
}

rswindell's avatar
rswindell committed
372
373
374
375
376
377
378
379
const char* get_current_outbound(fidoaddr_t dest, bool fileboxes)
{
	static char outbound[MAX_PATH+1];
	get_outbound(dest, outbound, sizeof(outbound)-1, fileboxes);
	return outbound;
}

bool bso_lock_node(fidoaddr_t dest)
380
{
rswindell's avatar
rswindell committed
381
	const char* outbound;
382
383
	char fname[MAX_PATH+1];

rswindell's avatar
rswindell committed
384
385
	if(!cfg.flo_mailer)
		return true;
386

rswindell's avatar
rswindell committed
387
	outbound = get_current_outbound(dest, /* fileboxes: */false);
388
389
390
391
392
393

	if(dest.point)
		SAFEPRINTF2(fname,"%s%08x.bsy",outbound,dest.point);
	else
		SAFEPRINTF3(fname,"%s%04x%04x.bsy",outbound,dest.net,dest.node);

rswindell's avatar
rswindell committed
394
395
396
397
398
	if(strListFind(locked_bso_nodes, fname, /* case_sensitive: */true) >= 0)
		return true;
	for(unsigned attempt=0;;) {
		if(fmutex(fname, program_id(), cfg.bsy_timeout))
			break;
399
		lprintf(LOG_NOTICE, "Node (%s) externally locked via: %s", smb_faddrtoa(&dest, NULL), fname);
rswindell's avatar
rswindell committed
400
401
402
403
404
405
406
		if(++attempt >= cfg.bso_lock_attempts) {
			lprintf(LOG_WARNING, "Giving up after %u attempts to lock node %s", attempt, smb_faddrtoa(&dest, NULL));
			return false;
		}
		if(terminated)
			return false;
		SLEEP(cfg.bso_lock_delay*1000);
407
408
409
	}
	strListPush(&locked_bso_nodes, fname);
	lprintf(LOG_DEBUG, "Node (%s) successfully locked via: %s", smb_faddrtoa(&dest, NULL), fname);
rswindell's avatar
rswindell committed
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
	return true;
}

const char* bso_flo_filename(fidoaddr_t dest)
{
	nodecfg_t* nodecfg;
	char ch='f';
	const char* outbound;
	static char filename[MAX_PATH+1];

	if((nodecfg=findnodecfg(&cfg, dest, /* exact: */false)) != NULL) {
		switch(nodecfg->status) {
			case MAIL_STATUS_CRASH:	ch='c';	break;
			case MAIL_STATUS_HOLD:	ch='h';	break;
			default:
				if(nodecfg->direct)
					ch='d';
				break;
		}
	}
	outbound = get_current_outbound(dest, /* fileboxes: */false);

	if(dest.point)
		SAFEPRINTF3(filename,"%s%08x.%clo",outbound,dest.point,ch);
	else
		SAFEPRINTF4(filename,"%s%04x%04x.%clo",outbound,dest.net,dest.node,ch);
	return filename;
}

bool bso_file_attached_to_flo(const char* attachment, fidoaddr_t dest, bool bundle)
{
	char searchstr[MAX_PATH+1];
	SAFEPRINTF2(searchstr,"%c%s",(bundle && cfg.trunc_bundles) ? '#':'^', attachment);
	return findstr(searchstr, bso_flo_filename(dest));
444
445
}

446
447
448
449
450
/******************************************************************************
 This function creates or appends on existing Binkley compatible .?LO file
 attach file.
 Returns 0 on success.
******************************************************************************/
rswindell's avatar
rswindell committed
451
int write_flofile(const char *infile, fidoaddr_t dest, bool bundle, bool use_outbox)
452
{
rswindell's avatar
rswindell committed
453
454
	const char* flo_filename;
	char attachment[MAX_PATH+1];
455
	char searchstr[MAX_PATH+1];
rswindell's avatar
rswindell committed
456
457
	FILE *fp;
	nodecfg_t* nodecfg;
458

rswindell's avatar
rswindell committed
459
460
461
462
	if(use_outbox && (nodecfg=findnodecfg(&cfg, dest, /* exact: */false)) != NULL) {
		if(nodecfg->outbox[0])
			return 0;
	}
463
464
465
466

	if(!bso_lock_node(dest))
		return 1;

rswindell's avatar
rswindell committed
467
468
469
470
471
	flo_filename = bso_flo_filename(dest);
	SAFECOPY(attachment, infile);
	if(!fexistcase(attachment))	{ /* just in-case it's the wrong case for a Unix file system */
		lprintf(LOG_ERR, "ERROR line %u, attachment file not found: %s", __LINE__, attachment);
		return -1;
472
	}
rswindell's avatar
rswindell committed
473
474
475
476
477
478
479
480
481
482
483
484
	SAFEPRINTF2(searchstr,"%c%s",bundle && (cfg.trunc_bundles) ? '#':'^', attachment);
	if(findstr(searchstr,flo_filename))	/* file already in FLO file */
		return 0;
	if((fp=fopen(flo_filename,"a"))==NULL) {
		lprintf(LOG_ERR,"ERROR %u (%s) opening %s",errno, strerror(errno), flo_filename);
		return -1; 
	}
	fprintf(fp,"%s\n",searchstr);
	fclose(fp);
	lprintf(LOG_INFO, "File (%s, %1.1fKB) for %s added to BSO/FLO file: %s"
		,attachment, flength(attachment)/1024.0, smb_faddrtoa(&dest,NULL), flo_filename);
	return 0;
485
486
}

487
/* Writes text buffer to file, expanding sole LFs to CRLFs */
rswindell's avatar
rswindell committed
488
size_t fwrite_crlf(const char* buf, size_t len, FILE* fp)
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
{
	char	ch,last_ch=0;
	size_t	i;
	size_t	wr=0;	/* total chars written (may be > len) */

	for(i=0;i<len;i++) {
		ch=*buf++;
		if(ch=='\n' && last_ch!='\r') {
			if(fputc('\r',fp)==EOF)
				return(wr);
			wr++;
		}
		if(fputc(ch,fp)==EOF)
			return(wr);
		wr++;
		last_ch=ch;
	}

	return(wr);
}

rswindell's avatar
rswindell committed
510
bool fidoctrl_line_exists(const smbmsg_t* msg, const char* prefix)
511
{
512
	if(msg==NULL || prefix==NULL)
rswindell's avatar
rswindell committed
513
		return false;
514
515
516
	for(int i=0; i<msg->total_hfields; i++) {
		if(msg->hfield[i].type == FIDOCTRL
			&& strncmp((char*)msg->hfield_dat[i], prefix, strlen(prefix)) == 0)
rswindell's avatar
rswindell committed
517
			return true;
518
	}
rswindell's avatar
rswindell committed
519
	return false;
520
521
}

rswindell's avatar
rswindell committed
522
fidoaddr_t fmsghdr_srcaddr(const fmsghdr_t* hdr)
523
524
525
526
527
528
529
530
531
532
533
{
	fidoaddr_t addr;

	addr.zone	= hdr->origzone;
	addr.net	= hdr->orignet;
	addr.node	= hdr->orignode;
	addr.point	= hdr->origpoint;

	return addr;
}

rswindell's avatar
rswindell committed
534
const char* fmsghdr_srcaddr_str(const fmsghdr_t* hdr)
535
536
537
538
539
540
541
{
	static char buf[64];
	fidoaddr_t addr = fmsghdr_srcaddr(hdr);

	return smb_faddrtoa(&addr, buf);
}

rswindell's avatar
rswindell committed
542
fidoaddr_t fmsghdr_destaddr(const fmsghdr_t* hdr)
543
544
545
546
547
548
549
550
551
552
553
{
	fidoaddr_t addr;

	addr.zone	= hdr->destzone;
	addr.net	= hdr->destnet;
	addr.node	= hdr->destnode;
	addr.point	= hdr->destpoint;

	return addr;
}

rswindell's avatar
rswindell committed
554
const char* fmsghdr_destaddr_str(const fmsghdr_t* hdr)
555
556
557
558
559
560
561
{
	static char buf[64];
	fidoaddr_t addr = fmsghdr_destaddr(hdr);

	return smb_faddrtoa(&addr, buf);
}

562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
bool parse_origin(const char* fmsgbuf, fmsghdr_t* hdr)
{
	char* p;
	fidoaddr_t origaddr;
	
	if((p = strstr(fmsgbuf, FIDO_ORIGIN_PREFIX_FORM_1)) == NULL)
		p = strstr(fmsgbuf, FIDO_ORIGIN_PREFIX_FORM_2);
	if(p == NULL)
		return false;

	p += FIDO_ORIGIN_PREFIX_LEN;
	p = strrchr(p, '(');
	if(p == NULL)
		return false;
	p++;
	origaddr = atofaddr(p);
	if(origaddr.zone == 0 
		|| origaddr.zone == 0xffff
		|| origaddr.net == 0xffff
		|| origaddr.node == 0xffff
		|| origaddr.point == 0xffff)
		return false;
	hdr->origzone	= origaddr.zone;
	hdr->orignet	= origaddr.net;
	hdr->orignode	= origaddr.node;
	hdr->origpoint	= origaddr.point;
	return true;
}

rswindell's avatar
rswindell committed
591
592
593
594
bool parse_pkthdr(const fpkthdr_t* hdr, fidoaddr_t* orig_addr, fidoaddr_t* dest_addr, enum pkt_type* pkt_type)
{
	fidoaddr_t	orig;
	fidoaddr_t	dest;
rswindell's avatar
rswindell committed
595
	enum pkt_type type = PKT_TYPE_2;
rswindell's avatar
rswindell committed
596
597
598
599
600
601
602
603
604
605
606
607
608
609

	if(hdr->type2.pkttype != 2)
		return false;

	orig.zone	= hdr->type2.origzone;
	orig.net	= hdr->type2.orignet;
	orig.node	= hdr->type2.orignode;
	orig.point	= 0;

	dest.zone	= hdr->type2.destzone;
	dest.net	= hdr->type2.destnet;
	dest.node	= hdr->type2.destnode;
	dest.point	= 0;				/* No point info in the 2.0 hdr! */

rswindell's avatar
rswindell committed
610
611
612
613
	if(hdr->type2plus.cword == BYTE_SWAP_16(hdr->type2plus.cwcopy)  /* 2e Packet Header (FSC-39) */
		&& (hdr->type2plus.cword&1)) {	/* Some call this a Type-2+ packet, but it's not (yet) FSC-48 conforming */
		type = PKT_TYPE_2_EXT;
		orig.point = hdr->type2plus.origpoint;
rswindell's avatar
rswindell committed
614
		dest.point = hdr->type2plus.destpoint;
rswindell's avatar
rswindell committed
615
616
617
618
619
620
		if(orig.zone == 0) orig.zone = hdr->type2plus.origzone;
		if(dest.zone == 0) dest.zone = hdr->type2plus.destzone;
		if(hdr->type2plus.auxnet != 0) {	/* strictly speaking, auxnet may be 0 and a valid 2+ packet */
			type = PKT_TYPE_2_PLUS;
			if(orig.point != 0 && orig.net == 0xffff) 	/* see FSC-0048 for details */
				orig.net = hdr->type2plus.auxnet;
rswindell's avatar
rswindell committed
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
		}
	} else if(hdr->type2_2.subversion==2) {					/* Type 2.2 Packet Header (FSC-45) */
		type = PKT_TYPE_2_2;
		orig.point = hdr->type2_2.origpoint;
		dest.point = hdr->type2_2.destpoint; 
	}

	if(pkt_type != NULL)
		*pkt_type = type;
	if(dest_addr != NULL)
		*dest_addr = dest;
	if(orig_addr != NULL)
		*orig_addr = orig;
	
	return true;
}

bool new_pkthdr(fpkthdr_t* hdr, fidoaddr_t orig, fidoaddr_t dest, const nodecfg_t* nodecfg)
{
rswindell's avatar
rswindell committed
640
	enum pkt_type pkt_type = PKT_TYPE_2;
rswindell's avatar
rswindell committed
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
	struct tm* tm;
	time_t now = time(NULL);

	if(nodecfg != NULL)
		pkt_type = nodecfg->pkt_type;

	memset(hdr, 0, sizeof(fpkthdr_t));

	if((tm = localtime(&now)) != NULL) {
		hdr->type2.year	= tm->tm_year+1900;
		hdr->type2.month= tm->tm_mon;
		hdr->type2.day	= tm->tm_mday;
		hdr->type2.hour	= tm->tm_hour;
		hdr->type2.min	= tm->tm_min;
		hdr->type2.sec	= tm->tm_sec;
	}

	hdr->type2.origzone = orig.zone;
	hdr->type2.orignet	= orig.net;
	hdr->type2.orignode	= orig.node;
	hdr->type2.destzone	= dest.zone;
	hdr->type2.destnet	= dest.net;
	hdr->type2.destnode	= dest.node;
	
	hdr->type2.pkttype	= 2;
	hdr->type2.prodcode	= SBBSECHO_PRODUCT_CODE&0xff;
	hdr->type2.sernum	= SBBSECHO_VERSION_MAJOR;

	if(nodecfg != NULL && nodecfg->pktpwd[0] != 0)
670
		strncpy((char*)hdr->type2.password, nodecfg->pktpwd, sizeof(hdr->type2.password));
rswindell's avatar
rswindell committed
671

rswindell's avatar
rswindell committed
672
	if(pkt_type == PKT_TYPE_2)
rswindell's avatar
rswindell committed
673
674
675
676
		return true;

	if(pkt_type == PKT_TYPE_2_2) {
		hdr->type2_2.subversion = 2;	/* 2.2 */
677
678
		strncpy((char*)hdr->type2_2.origdomn,zone_domain(orig.zone),sizeof(hdr->type2_2.origdomn));
		strncpy((char*)hdr->type2_2.destdomn,zone_domain(dest.zone),sizeof(hdr->type2_2.destdomn));
rswindell's avatar
rswindell committed
679
680
681
		return true;
	}
	
rswindell's avatar
rswindell committed
682
683
	/* 2e and 2+ */
	if(pkt_type != PKT_TYPE_2_EXT && pkt_type != PKT_TYPE_2_PLUS) {
rswindell's avatar
rswindell committed
684
685
686
687
		lprintf(LOG_ERR, "UNSUPPORTED PACKET TYPE: %u", pkt_type);
		return false;
	}

rswindell's avatar
rswindell committed
688
689
690
691
	if(pkt_type == PKT_TYPE_2_PLUS) {
		if(orig.point != 0)
			hdr->type2plus.orignet	= 0xffff;
		hdr->type2plus.auxnet	= orig.net; /* Squish always copies the orignet here */
rswindell's avatar
rswindell committed
692
693
694
695
696
697
698
699
700
701
702
703
704
	}
	hdr->type2plus.cword		= 0x0001;
	hdr->type2plus.cwcopy		= 0x0100;
	hdr->type2plus.prodcodeHi	= SBBSECHO_PRODUCT_CODE>>8;
	hdr->type2plus.prodrevMinor	= SBBSECHO_VERSION_MINOR;
	hdr->type2plus.origzone		= orig.zone;
	hdr->type2plus.destzone		= dest.zone;
	hdr->type2plus.origpoint	= orig.point;
	hdr->type2plus.destpoint	= dest.point;

	return true;
}

705
706
707
708
709
/******************************************************************************
 This function will create a netmail message (.MSG format).
 If file is non-zero, will set file attachment bit (for bundles).
 Returns 0 on success.
******************************************************************************/
rswindell's avatar
rswindell committed
710
711
int create_netmail(const char *to, const smbmsg_t* msg, const char *subject, const char *body, fidoaddr_t dest
					,bool file_attached)
712
{
713
	FILE *fp;
714
	char tmp[256];
715
	char fname[MAX_PATH+1];
716
	char* from=NULL;
717
718
	uint i;
	static uint startmsg;
rswindell's avatar
rswindell committed
719
	fidoaddr_t	faddr;
720
	fmsghdr_t hdr;
721
	time_t t;
722
	struct tm *tm;
723
	when_t when_written;
rswindell's avatar
rswindell committed
724
725
	nodecfg_t* nodecfg;
	bool	direct=false;
726

727
	if(msg==NULL) {
rswindell's avatar
rswindell committed
728
		when_written.time = time32(NULL);
729
730
731
732
733
		when_written.zone = sys_timezone(&scfg);
	} else {
		from = msg->from;
		when_written = msg->hdr.when_written;
	}
734
735
736
737
	if(from==NULL)
		from="SBBSecho";
	if(to==NULL)
		to="Sysop";
738
	if(!startmsg) startmsg=1;
rswindell's avatar
rswindell committed
739
740
741
	if((nodecfg=findnodecfg(&cfg, dest, 0)) != NULL) {
		if(nodecfg->status == MAIL_STATUS_NORMAL && !nodecfg->direct)
			nodecfg=findnodecfg(&cfg, dest, /* skip exact match: */2);
742
	}
743

744
	MKDIR(scfg.netmail_dir);
745
746
747
748
749
750
751
752
753
754
	for(i=startmsg;i;i++) {
		sprintf(fname,"%s%u.msg",scfg.netmail_dir,i);
		if(!fexistcase(fname))
			break; 
	}
	if(!i) {
		lprintf(LOG_WARNING,"Directory full: %s",scfg.netmail_dir);
		return(-1); 
	}
	startmsg=i+1;
755
	if((fp=fnopen(NULL,fname,O_RDWR|O_CREAT))==NULL) {
756
757
758
		lprintf(LOG_ERR,"ERROR %u (%s) line %d opening %s",errno,strerror(errno),__LINE__,fname);
		return(-1); 
	}
759

760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
	faddr=getsysfaddr(dest.zone);
	memset(&hdr,0,sizeof(fmsghdr_t));
	hdr.origzone=faddr.zone;
	hdr.orignet=faddr.net;
	hdr.orignode=faddr.node;
	hdr.origpoint=faddr.point;
	hdr.destzone=dest.zone;
	hdr.destnet=dest.net;
	hdr.destnode=dest.node;
	hdr.destpoint=dest.point;

	hdr.attr=(FIDO_PRIVATE|FIDO_KILLSENT|FIDO_LOCAL);
	if(file_attached)
		hdr.attr|=FIDO_FILE;

rswindell's avatar
rswindell committed
775
776
777
778
	if(nodecfg != NULL) {
		switch(nodecfg->status) {
			case MAIL_STATUS_HOLD:	hdr.attr|=FIDO_HOLD;	break;
			case MAIL_STATUS_CRASH:	hdr.attr|=FIDO_CRASH;	break;
779
			case MAIL_STATUS_NORMAL:						break;
rswindell's avatar
rswindell committed
780
781
782
		}
		direct = nodecfg->direct;
	}
783

784
	t = when_written.time;
rswindell's avatar
rswindell committed
785
	tm = localtime(&t);
786
787
788
789
790
791
792
793
794
795
796
797
798
	sprintf(hdr.time,"%02u %3.3s %02u  %02u:%02u:%02u"
		,tm->tm_mday,mon[tm->tm_mon],TM_YEAR(tm->tm_year)
		,tm->tm_hour,tm->tm_min,tm->tm_sec);

	SAFECOPY(hdr.to,to);
	SAFECOPY(hdr.from,from);
	SAFECOPY(hdr.subj,subject);

	fwrite(&hdr,sizeof(fmsghdr_t),1,fp);
	fprintf(fp,"\1INTL %hu:%hu/%hu %hu:%hu/%hu\r"
		,hdr.destzone,hdr.destnet,hdr.destnode
		,hdr.origzone,hdr.orignet,hdr.orignode);

799
800
801
802
803
804
805
806
807
	if(!fidoctrl_line_exists(msg, "TZUTC:")) {
		/* TZUTC (FSP-1001) */
		int tzone=smb_tzutc(when_written.zone);
		char* minus="";
		if(tzone<0) {
			minus="-";
			tzone=-tzone;
		}
		fprintf(fp,"\1TZUTC: %s%02d%02u\r", minus, tzone/60, tzone%60);
808
	}
809
810
	/* Add FSC-53 FLAGS kludge */
	fprintf(fp,"\1FLAGS");
rswindell's avatar
rswindell committed
811
	if(direct)
812
813
		fprintf(fp," DIR");
	if(file_attached) {
rswindell's avatar
rswindell committed
814
		if(cfg.trunc_bundles)
815
			fprintf(fp," TFS");
816
		else
817
818
819
			fprintf(fp," KFS");
	}
	fprintf(fp,"\r");
820

821
822
823
824
	if(hdr.destpoint)
		fprintf(fp,"\1TOPT %hu\r",hdr.destpoint);
	if(hdr.origpoint)
		fprintf(fp,"\1FMPT %hu\r",hdr.origpoint);
825
826
827
828
829
830
831
	fprintf(fp,"\1PID: %s\r", (msg==NULL || msg->ftn_pid==NULL) ? sbbsecho_pid() : msg->ftn_pid);
	if(msg != NULL) {
		/* Unknown kludge lines are added here */
		for(int i=0; i<msg->total_hfields; i++)
			if(msg->hfield[i].type == FIDOCTRL)
				fprintf(fp,"\1%.512s\r",(char*)msg->hfield_dat[i]);
	}
rswindell's avatar
rswindell committed
832
	if(!file_attached || (!direct && file_attached))
833
834
835
		fwrite_crlf(body,strlen(body)+1,fp);	/* Write additional NULL */
	else
		fwrite("\0",1,1,fp);               /* Write NULL */
rswindell's avatar
rswindell committed
836
837
838
	lprintf(LOG_INFO, "Created NetMail (%s)%s from %s (%s) to %s (%s), attr: %04hX, subject: %s"
		,getfname(fname), file_attached ? " with attachment" : ""
		,from, smb_faddrtoa(&faddr, tmp), to, smb_faddrtoa(&dest, NULL), hdr.attr, subject);
839
	return fclose(fp);
840
841
842
843
844
845
}

/******************************************************************************
 This function takes the contents of 'infile' and puts it into a netmail
 message bound for addr.
******************************************************************************/
rswindell's avatar
rswindell committed
846
void file_to_netmail(FILE* infile, const char* title, fidoaddr_t dest, const char* to)
847
848
849
850
{
	char *buf,*p;
	long l,m,len;

851
852
853
854
	l=len=ftell(infile);
	if(len>8192L)
		len=8192L;
	rewind(infile);
deuce's avatar
deuce committed
855
	if((buf=(char *)malloc(len+1))==NULL) {
856
		lprintf(LOG_ERR,"ERROR line %d allocating %lu for file to netmail buf",__LINE__,len);
857
858
		return; 
	}
859
860
861
	while((m=fread(buf,1,(len>8064L) ? 8064L:len,infile))>0) {
		buf[m]=0;
		if(l>8064L && (p=strrchr(buf,'\n'))!=NULL) {
862
			p++;
863
864
			if(*p) {
				*p=0;
865
				p++;
866
867
868
				fseek(infile,-1L,SEEK_CUR);
				while(*p) { 			/* Seek back to end of last line */
					p++;
869
870
871
872
					fseek(infile,-1L,SEEK_CUR); 
				} 
			} 
		}
873
874
		if(ftell(infile)<l)
			strcat(buf,"\r\nContinued in next message...\r\n");
rswindell's avatar
rswindell committed
875
		create_netmail(to, /* msg: */NULL, title, buf, dest, /* attachment: */false); 
876
	}
deuce's avatar
deuce committed
877
	free(buf);
878
}
879

rswindell's avatar
rswindell committed
880
881
/* Returns true if area is linked with specified node address */
bool area_is_linked(unsigned area_num, const fidoaddr_t* addr)
882
{
883
	unsigned i;
rswindell's avatar
rswindell committed
884
885
886
887
	for(i=0;i<cfg.area[area_num].links;i++)
		if(!memcmp(addr,&cfg.area[area_num].link[i],sizeof(fidoaddr_t)))
			return true;
	return false;
888
889
}

890
891
/* Returns area index */
uint find_area(const char* echotag)
rswindell's avatar
rswindell committed
892
{
893
894
895
896
897
898
899
900
901
902
903
904
905
906
	unsigned u;

	for(u=0; u < cfg.areas; u++)
		if(stricmp(cfg.area[u].name, echotag) == 0)
			break;

	return u;
}

bool area_is_valid(uint areanum)
{
	return areanum < cfg.areas;
}

907
908
/* Returns subnum (INVALID_SUB if pass-through) or SUB_NOT_FOUND */
#define SUB_NOT_FOUND ((uint)-2)
909
910
911
912
913
uint find_linked_area(const char* echotag, fidoaddr_t addr)
{
	unsigned area;

	if(area_is_valid(area = find_area(echotag)) && area_is_linked(area, &addr))
914
		return cfg.area[area].sub;
rswindell's avatar
rswindell committed
915

916
	return SUB_NOT_FOUND;
rswindell's avatar
rswindell committed
917
918
}

919
920
921
922
923
/******************************************************************************
 This function sends a notify list to applicable nodes, this list includes the
 settings configured for the node, as well as a list of areas the node is
 connected to.
******************************************************************************/
rswindell's avatar
rswindell committed
924
void gen_notify_list(void)
925
926
927
{
	FILE *	tmpf;
	char	str[256];
deuce's avatar
deuce committed
928
	uint	i,k;
929

rswindell's avatar
rswindell committed
930
	for(k=0;k<cfg.nodecfgs && !terminated;k++) {
931

rswindell's avatar
rswindell committed
932
		if(!cfg.nodecfg[k].send_notify)
933
934
935
			continue;

		if((tmpf=tmpfile())==NULL) {
936
			lprintf(LOG_ERR,"ERROR line %d couldn't open tmpfile",__LINE__);
937
938
			return; 
		}
939
940
941
942

		fprintf(tmpf,"Following are the options set for your system and a list "
			"of areas\r\nyou are connected to.  Please make sure everything "
			"is correct.\r\n\r\n");
rswindell's avatar
rswindell committed
943
		fprintf(tmpf,"Packet Type       %s\r\n", pktTypeStringList[cfg.nodecfg[k].pkt_type]);
944
		fprintf(tmpf,"Archive Type      %s\r\n"
rswindell's avatar
rswindell committed
945
946
947
948
			,cfg.nodecfg[k].archive == SBBSECHO_ARCHIVE_NONE ? "None" : cfg.nodecfg[k].archive->name);
		fprintf(tmpf,"Mail Status       %s\r\n", mailStatusStringList[cfg.nodecfg[k].status]);
		fprintf(tmpf,"Direct            %s\r\n", cfg.nodecfg[k].direct ? "Yes":"No");
		fprintf(tmpf,"Passive           %s\r\n", cfg.nodecfg[k].passive ? "Yes":"No");
949
950
951
952
953
954
955
956
		fprintf(tmpf,"Remote AreaMgr    %s\r\n\r\n"
			,cfg.nodecfg[k].password[0] ? "Yes" : "No");

		fprintf(tmpf,"Connected Areas\r\n---------------\r\n");
		for(i=0;i<cfg.areas;i++) {
			sprintf(str,"%s\r\n",cfg.area[i].name);
			if(str[0]=='*')
				continue;
rswindell's avatar
rswindell committed
957
			if(area_is_linked(i,&cfg.nodecfg[k].addr))
958
959
				fprintf(tmpf,"%s",str); 
		}
960
961

		if(ftell(tmpf))
rswindell's avatar
rswindell committed
962
			file_to_netmail(tmpf,"SBBSecho Notify List",cfg.nodecfg[k].addr, /* To: */NULL);
963
964
		fclose(tmpf); 
	}
965
}
966

967
968
969
970
/******************************************************************************
 This function creates a netmail to addr showing a list of available areas (0),
 a list of connected areas (1), or a list of removed areas (2).
******************************************************************************/
971
972
973
974
975
enum arealist_type {
	 AREALIST_ALL			// %LIST
	,AREALIST_CONNECTED		// %QUERY
	,AREALIST_UNLINKED		// %UNLINKED
};
rswindell's avatar
rswindell committed
976
void netmail_arealist(enum arealist_type type, fidoaddr_t addr, const char* to)
977
{
978
	char str[256],title[128],match,*p,*tp;
979
	unsigned k,x;
980
	unsigned u;
981
	str_list_t	area_list;
982

983
	if(type == AREALIST_ALL)
984
		strcpy(title,"List of Available Areas");
985
	else if(type == AREALIST_CONNECTED)
986
987
988
989
		strcpy(title,"List of Connected Areas");
	else
		strcpy(title,"List of Unlinked Areas");

990
991
	if((area_list=strListInit()) == NULL) {
		lprintf(LOG_ERR,"ERROR line %d couldn't allocate string list",__LINE__);
992
993
		return; 
	}
994

995
	/* Include relevant areas from the area file (e.g. areas.bbs): */
996
997
	for(u=0;u<cfg.areas;u++) {
		if((type == AREALIST_CONNECTED || cfg.add_from_echolists_only) && !area_is_linked(u,&addr))
998
			continue;
999
		if(type == AREALIST_UNLINKED && area_is_linked(u,&addr))
1000
			continue;
1001
		strListPush(&area_list, cfg.area[u].name); 
1002
	} 
1003

1004
	if(type != AREALIST_CONNECTED) {
rswindell's avatar
rswindell committed
1005
1006
		nodecfg_t* nodecfg=findnodecfg(&cfg, addr,0);
		if(nodecfg != NULL) {
1007
			for(u=0;u<cfg.listcfgs;u++) {
1008
				match=0;
1009
				for(k=0; cfg.listcfg[u].keys[k]; k++) {
1010
					if(match) break;
rswindell's avatar
rswindell committed
1011
					for(x=0; nodecfg->keys[x]; x++) {
1012
						if(!stricmp(cfg.listcfg[u].keys[k]
rswindell's avatar
rswindell committed
1013
							,nodecfg->keys[x])) {
1014
							FILE* fp;
1015
							if((fp=fopen(cfg.listcfg[u].listpath,"r"))==NULL) {
1016
								lprintf(LOG_ERR,"ERROR %u (%s) line %d opening %s"
1017
									,errno,strerror(errno),__LINE__,cfg.listcfg[u].listpath);
1018
								match=1;
1019
1020
								break; 
							}
1021
							while(!feof(fp)) {
1022
								memset(str,0,sizeof(str));
1023
								if(!fgets(str,sizeof(str),fp))
1024
									break;
1025
								truncsp(str);
1026
								p=str;
1027
								SKIP_WHITESPACE(p);
1028
								if(*p==0 || *p==';')     /* Ignore Blank and Comment Lines */
1029
									continue;
1030
1031
1032
								tp=p;
								FIND_WHITESPACE(tp);
								*tp=0;
1033
								if(find_linked_area(p, addr) == SUB_NOT_FOUND) {
1034
1035
1036
									if(strListFind(area_list, p, /* case_sensitive */false) < 0)
										strListPush(&area_list, p);
								}
1037
							}
1038
							fclose(fp);
1039
							match=1;
1040
							break; 
1041
1042
						}
					}
1043
1044
1045
1046
				} 
			} 
		} 
	}
1047
1048
	strListSortAlpha(area_list);
	if(!strListCount(area_list))
rswindell's avatar
rswindell committed
1049
		create_netmail(to,/* msg: */NULL,title,"None.",addr,/* attachment: */false);
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
	else {
		FILE* fp;
		if((fp=tmpfile())==NULL) {
			lprintf(LOG_ERR,"ERROR line %d couldn't open tmpfile",__LINE__);
		} else {
			strListWriteFile(fp, area_list, "\r\n");
			file_to_netmail(fp,title,addr,to);
			fclose(fp);
		}
	}
	lprintf(LOG_INFO,"Created AreaFix response netmail with %s (%u areas)", title, strListCount(area_list));
	strListFree(&area_list);
1062
}
1063

rswindell's avatar
rswindell committed
1064
int check_elists(const char *areatag, fidoaddr_t addr)
1065
1066
{
	FILE *stream;
1067
	char str[1025],quit=0,*p,*tp;
1068
1069
	unsigned k,x,match=0;
	unsigned u;
1070

rswindell's avatar
rswindell committed
1071
1072
	nodecfg_t* nodecfg=findnodecfg(&cfg, addr,0);
	if(nodecfg!=NULL) {
1073
		for(u=0;u<cfg.listcfgs;u++) {
rswindell's avatar
rswindell committed
1074
			quit=0;
1075
			for(k=0; cfg.listcfg[u].keys[k]; k++) {
rswindell's avatar
rswindell committed
1076
				if(quit) break;
rswindell's avatar
rswindell committed
1077
				for(x=0; nodecfg->keys[x] ;x++)
1078
					if(!stricmp(cfg.listcfg[u].keys[k]
rswindell's avatar
rswindell committed
1079
						,nodecfg->keys[x])) {
1080
						if((stream=fopen(cfg.listcfg[u].listpath,"r"))==NULL) {
1081
							lprintf(LOG_ERR,"ERROR %u (%s) line %d opening %s"
1082
								,errno,strerror(errno),__LINE__,cfg.listcfg[u].listpath);
rswindell's avatar
rswindell committed
1083
							quit=1;
1084
1085
							break; 
						}
rswindell's avatar
rswindell committed
1086
						while(!feof(stream)) {
1087
							if(!fgets(str,sizeof(str),stream))
rswindell's avatar
rswindell committed
1088
1089
								break;
							p=str;
1090
							SKIP_WHITESPACE(p);
rswindell's avatar
rswindell committed
1091
1092
							if(*p==';')     /* Ignore Comment Lines */
								continue;
1093
1094
1095
1096
							tp=p;
							FIND_WHITESPACE(tp);
							*tp=0;
							if(!stricmp(areatag,p)) {
rswindell's avatar
rswindell committed
1097
								match=1;
1098
1099
1100
								break; 
							} 
						}
rswindell's avatar
rswindell committed
1101
						fclose(stream);
1102
						quit=1;
rswindell's avatar
rswindell committed
1103
1104
						if(match)
							return(match);
1105
1106
1107
1108
1109
						break; 
					} 
			} 
		} 
	}
rswindell's avatar
rswindell committed
1110
	return(match);
1111
1112
1113
1114
}
/******************************************************************************
 Used by AREAFIX to add/remove/change areas in the areas file
******************************************************************************/
rswindell's avatar
rswindell committed
1115
void alter_areas(str_list_t add_area, str_list_t del_area, fidoaddr_t addr, const char* to)
1116
1117
{
	FILE *nmfile,*afilein,*afileout,*fwdfile;
1118
1119
	char str[1024],fields[1024],field1[256],field2[256],field3[256]
		,outpath[MAX_PATH+1]
1120
		,*outname,*p,*tp,nomatch=0,match=0;
1121
1122
	unsigned j,k,x,y;
	unsigned u;
rswindell's avatar
rswindell committed
1123
1124
	size_t add_count;
	size_t del_count;
1125

rswindell's avatar
rswindell committed
1126
1127
1128
1129
1130
1131
1132
1133
	if((add_count = strListCount(add_area)) !=0 )
		lprintf(LOG_DEBUG,"Adding %u areas for %s to %s"
			,add_count, smb_faddrtoa(&addr,NULL), cfg.areafile);

	if((del_count = strListCount(del_area)) != 0)
		lprintf(LOG_DEBUG,"Removing %u areas for %s from %s"
			,del_count, smb_faddrtoa(&addr,NULL), cfg.areafile);

1134
1135
	SAFECOPY(outpath,cfg.areafile);
	*getfname(outpath)=0;
1136
	if((outname=tempnam(outpath,"AREAS"))==NULL) {
1137
		lprintf(LOG_ERR,"ERROR tempnam(%s,AREAS)",outpath);
1138
1139
		return; 
	}