sbbsecho.c 149 KB
Newer Older
1
/* sbbsecho.c */
2

3
/* Synchronet FidoNet EchoMail Scanning/Tossing and NetMail Tossing Utility */
4

5
6
7
8
9
10
/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 *																			*
 * 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.	*
 ****************************************************************************/
37

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

#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
48
#include <sys/stat.h>
49

rswindell's avatar
rswindell committed
50
#include "conwrap.h"		/* getch() */
51
52
53
54
55
56
#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
57
#include "genwrap.h"		/* PLATFORM_DESC */
rswindell's avatar
rswindell committed
58
59
60
#include "xpendian.h"

#define MAX_OPEN_SMBS	10
61
62

smb_t *smb,*email;
rswindell's avatar
rswindell committed
63
64
65
66
67
68
69
70
71
72
73
74
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;

rswindell's avatar
rswindell committed
75
76
77
78
79
80
81
/* 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
82
83
char tmp[256];
int cur_smb=0;
84
FILE *fidologfile=NULL;
rswindell's avatar
rswindell committed
85
bool twit_list;
86

rswindell's avatar
rswindell committed
87
88
89
90
91
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];
92

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

98
99
str_list_t	locked_bso_nodes;

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

103
104
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
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;
}

133
134
135
136
137
138
139
140
141
142
143
/* 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
144
145
/* for *.bsy file contents: */
const char* program_id(void)
146
{
rswindell's avatar
rswindell committed
147
148
149
	static char str[256];
	
	SAFEPRINTF2(str, "%u %s", getpid(), sbbsecho_pid());
150

rswindell's avatar
rswindell committed
151
	return str;
152
153
}

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

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

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

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

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

206
207
208
209
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
	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);
237
238
						strcat(cmd,str); 
					}
239
240
241
242
243
244
245
246
247
248
249
250
					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);
251
252
						strcat(cmd,str); 
					}
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
					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 */
269
					strcat(cmd,cfg->exec_dir);
270
					break;
271
272
273
274
275
                case '@':   /* EXEC Directory for DOS/OS2/Win32, blank for Unix */
#ifndef __unix__
                    strcat(cmd,cfg->exec_dir);
#endif
                    break;
276
277
278
279
280
281
282
283
284
285
286
				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;
287
288
289
290
291
292
293
294
295
296
				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;
297
				default:    /* unknown specification */
298
					lprintf(LOG_ERR,"ERROR Checking Command Line '%s'",instr);
299
					bail(1);
300
301
302
303
					break; 
			}
			j=strlen(cmd); 
		}
304
		else
305
306
			cmd[j++]=instr[i]; 
}
307
	cmd[j]=0;
308

309
	return(cmd);
310
311
312
}

/****************************************************************************/
rswindell's avatar
rswindell committed
313
/* Runs an external program directly using system()							*/
314
315
316
/****************************************************************************/
int execute(char *cmdline)
{
rswindell's avatar
rswindell committed
317
318
319
320
321
322
	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));
323

rswindell's avatar
rswindell committed
324
	return retval;
325
}
326

327
328
329
/******************************************************************************
 Returns the system address with the same zone as the address passed
******************************************************************************/
rswindell's avatar
rswindell committed
330
fidoaddr_t getsysfaddr(short zone)
331
332
{
	int i;
333

334
335
336
	for(i=0;i<scfg.total_faddrs;i++)
		if(scfg.faddr[i].zone==zone)
			return(scfg.faddr[i]);
337
	return(sys_faddr);
338
}
339

rswindell's avatar
rswindell committed
340
int get_outbound(fidoaddr_t dest, char* outbound, size_t maxlen, bool fileboxes)
341
{
rswindell's avatar
rswindell committed
342
343
	nodecfg_t*	nodecfg;

344
	strncpy(outbound,zone_root_outbound(dest.zone),maxlen);
rswindell's avatar
rswindell committed
345
346
347
348
349
350
351
352
353
354
355
356
357
	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/" */
			*lastchar(outbound) = 0;
			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);
		}
358
359
	}
	backslash(outbound);
rswindell's avatar
rswindell committed
360
361
	if(!isdir(outbound))
		lprintf(LOG_DEBUG, "Creating outbound directory for %s: %s", smb_faddrtoa(&dest, NULL), outbound);
362
363
364
	return mkpath(outbound);
}

rswindell's avatar
rswindell committed
365
366
367
368
369
370
371
372
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)
373
{
rswindell's avatar
rswindell committed
374
	const char* outbound;
375
376
	char fname[MAX_PATH+1];

rswindell's avatar
rswindell committed
377
378
	if(!cfg.flo_mailer)
		return true;
379

rswindell's avatar
rswindell committed
380
	outbound = get_current_outbound(dest, /* fileboxes: */false);
381
382
383
384
385
386

	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
387
388
389
390
391
	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;
392
		lprintf(LOG_NOTICE, "Node (%s) externally locked via: %s", smb_faddrtoa(&dest, NULL), fname);
rswindell's avatar
rswindell committed
393
394
395
396
397
398
399
		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);
400
401
402
	}
	strListPush(&locked_bso_nodes, fname);
	lprintf(LOG_DEBUG, "Node (%s) successfully locked via: %s", smb_faddrtoa(&dest, NULL), fname);
rswindell's avatar
rswindell committed
403
404
405
406
407
408
409
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
	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));
437
438
}

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

rswindell's avatar
rswindell committed
452
453
454
455
	if(use_outbox && (nodecfg=findnodecfg(&cfg, dest, /* exact: */false)) != NULL) {
		if(nodecfg->outbox[0])
			return 0;
	}
456
457
458
459

	if(!bso_lock_node(dest))
		return 1;

rswindell's avatar
rswindell committed
460
461
462
463
464
	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;
465
	}
rswindell's avatar
rswindell committed
466
467
468
469
470
471
472
473
474
475
476
477
	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;
478
479
}

480
/* Writes text buffer to file, expanding sole LFs to CRLFs */
rswindell's avatar
rswindell committed
481
size_t fwrite_crlf(const char* buf, size_t len, FILE* fp)
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
{
	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
503
bool fidoctrl_line_exists(const smbmsg_t* msg, const char* prefix)
504
{
505
	if(msg==NULL || prefix==NULL)
rswindell's avatar
rswindell committed
506
		return false;
507
508
509
	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
510
			return true;
511
	}
rswindell's avatar
rswindell committed
512
	return false;
513
514
}

rswindell's avatar
rswindell committed
515
fidoaddr_t fmsghdr_srcaddr(const fmsghdr_t* hdr)
516
517
518
519
520
521
522
523
524
525
526
{
	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
527
const char* fmsghdr_srcaddr_str(const fmsghdr_t* hdr)
528
529
530
531
532
533
534
{
	static char buf[64];
	fidoaddr_t addr = fmsghdr_srcaddr(hdr);

	return smb_faddrtoa(&addr, buf);
}

rswindell's avatar
rswindell committed
535
fidoaddr_t fmsghdr_destaddr(const fmsghdr_t* hdr)
536
537
538
539
540
541
542
543
544
545
546
{
	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
547
const char* fmsghdr_destaddr_str(const fmsghdr_t* hdr)
548
549
550
551
552
553
554
{
	static char buf[64];
	fidoaddr_t addr = fmsghdr_destaddr(hdr);

	return smb_faddrtoa(&addr, buf);
}

rswindell's avatar
rswindell committed
555
556
557
558
559
560
561
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
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
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;
	enum pkt_type type = PKT_TYPE_2_0;

	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! */

	if(hdr->type2plus.cword == BYTE_SWAP_16(hdr->type2plus.cwcopy)  /* 2+ Packet Header (FSC-39) */
		&& (hdr->type2plus.cword&1)) {
		type = PKT_TYPE_2_PLUS;
		dest.point = hdr->type2plus.destpoint;
		if(hdr->type2plus.origpoint!=0 && orig.net == 0xffff) {	/* see FSC-0048 for details */
			orig.net = hdr->type2plus.auxnet;
			orig.point = hdr->type2plus.origpoint;
		}
	} 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)
{
	enum pkt_type pkt_type = PKT_TYPE_2_0;
	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)
630
		strncpy((char*)hdr->type2.password, nodecfg->pktpwd, sizeof(hdr->type2.password));
rswindell's avatar
rswindell committed
631
632
633
634
635
636

	if(pkt_type == PKT_TYPE_2_0)
		return true;

	if(pkt_type == PKT_TYPE_2_2) {
		hdr->type2_2.subversion = 2;	/* 2.2 */
637
638
		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
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
		return true;
	}
	
	/* 2+ */
	if(pkt_type != PKT_TYPE_2_PLUS) {
		lprintf(LOG_ERR, "UNSUPPORTED PACKET TYPE: %u", pkt_type);
		return false;
	}

	if(orig.point != 0) {
		hdr->type2plus.orignet	= 0xffff;
		hdr->type2plus.auxnet	= orig.net; 
	}
	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;
}

664
665
666
667
668
/******************************************************************************
 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
669
670
int create_netmail(const char *to, const smbmsg_t* msg, const char *subject, const char *body, fidoaddr_t dest
					,bool file_attached)
671
{
672
673
	FILE *fp;
	char fname[MAX_PATH+1];
674
	char* from=NULL;
675
676
	uint i;
	static uint startmsg;
rswindell's avatar
rswindell committed
677
	fidoaddr_t	faddr;
678
	fmsghdr_t hdr;
679
	time_t t;
680
	struct tm *tm;
681
	when_t when_written;
rswindell's avatar
rswindell committed
682
683
	nodecfg_t* nodecfg;
	bool	direct=false;
684

685
	if(msg==NULL) {
rswindell's avatar
rswindell committed
686
		when_written.time = time32(NULL);
687
688
689
690
691
		when_written.zone = sys_timezone(&scfg);
	} else {
		from = msg->from;
		when_written = msg->hdr.when_written;
	}
692
693
694
695
	if(from==NULL)
		from="SBBSecho";
	if(to==NULL)
		to="Sysop";
696
	if(!startmsg) startmsg=1;
rswindell's avatar
rswindell committed
697
698
699
	if((nodecfg=findnodecfg(&cfg, dest, 0)) != NULL) {
		if(nodecfg->status == MAIL_STATUS_NORMAL && !nodecfg->direct)
			nodecfg=findnodecfg(&cfg, dest, /* skip exact match: */2);
700
	}
701

702
	MKDIR(scfg.netmail_dir);
703
704
705
706
707
708
709
710
711
712
	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;
713
	if((fp=fnopen(NULL,fname,O_RDWR|O_CREAT))==NULL) {
714
715
716
		lprintf(LOG_ERR,"ERROR %u (%s) line %d opening %s",errno,strerror(errno),__LINE__,fname);
		return(-1); 
	}
717

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
	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
733
734
735
736
	if(nodecfg != NULL) {
		switch(nodecfg->status) {
			case MAIL_STATUS_HOLD:	hdr.attr|=FIDO_HOLD;	break;
			case MAIL_STATUS_CRASH:	hdr.attr|=FIDO_CRASH;	break;
737
			case MAIL_STATUS_NORMAL:						break;
rswindell's avatar
rswindell committed
738
739
740
		}
		direct = nodecfg->direct;
	}
741

742
	t = when_written.time;
rswindell's avatar
rswindell committed
743
	tm = localtime(&t);
744
745
746
747
748
749
750
751
752
753
754
755
756
	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);

757
758
759
760
761
762
763
764
765
	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);
766
	}
767
768
	/* Add FSC-53 FLAGS kludge */
	fprintf(fp,"\1FLAGS");
rswindell's avatar
rswindell committed
769
	if(direct)
770
771
		fprintf(fp," DIR");
	if(file_attached) {
rswindell's avatar
rswindell committed
772
		if(cfg.trunc_bundles)
773
			fprintf(fp," TFS");
774
		else
775
776
777
			fprintf(fp," KFS");
	}
	fprintf(fp,"\r");
778

779
780
781
782
	if(hdr.destpoint)
		fprintf(fp,"\1TOPT %hu\r",hdr.destpoint);
	if(hdr.origpoint)
		fprintf(fp,"\1FMPT %hu\r",hdr.origpoint);
783
784
785
786
787
788
789
	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
790
	if(!file_attached || (!direct && file_attached))
791
792
793
		fwrite_crlf(body,strlen(body)+1,fp);	/* Write additional NULL */
	else
		fwrite("\0",1,1,fp);               /* Write NULL */
rswindell's avatar
rswindell committed
794
795
796
	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);
797
	return fclose(fp);
798
799
800
801
802
803
}

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

809
810
811
812
	l=len=ftell(infile);
	if(len>8192L)
		len=8192L;
	rewind(infile);
deuce's avatar
deuce committed
813
	if((buf=(char *)malloc(len+1))==NULL) {
814
		lprintf(LOG_ERR,"ERROR line %d allocating %lu for file to netmail buf",__LINE__,len);
815
816
		return; 
	}
817
818
819
	while((m=fread(buf,1,(len>8064L) ? 8064L:len,infile))>0) {
		buf[m]=0;
		if(l>8064L && (p=strrchr(buf,'\n'))!=NULL) {
820
			p++;
821
822
			if(*p) {
				*p=0;
823
				p++;
824
825
826
				fseek(infile,-1L,SEEK_CUR);
				while(*p) { 			/* Seek back to end of last line */
					p++;
827
828
829
830
					fseek(infile,-1L,SEEK_CUR); 
				} 
			} 
		}
831
832
		if(ftell(infile)<l)
			strcat(buf,"\r\nContinued in next message...\r\n");
rswindell's avatar
rswindell committed
833
		create_netmail(to, /* msg: */NULL, title, buf, dest, /* attachment: */false); 
834
	}
deuce's avatar
deuce committed
835
	free(buf);
836
}
837

rswindell's avatar
rswindell committed
838
839
/* Returns true if area is linked with specified node address */
bool area_is_linked(unsigned area_num, const fidoaddr_t* addr)
840
{
841
	unsigned i;
rswindell's avatar
rswindell committed
842
843
844
845
	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;
846
847
}

848
849
850
851
852
/******************************************************************************
 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
853
void gen_notify_list(void)
854
855
856
{
	FILE *	tmpf;
	char	str[256];
deuce's avatar
deuce committed
857
	uint	i,k;
858

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

rswindell's avatar
rswindell committed
861
		if(!cfg.nodecfg[k].send_notify)
862
863
864
			continue;

		if((tmpf=tmpfile())==NULL) {
865
			lprintf(LOG_ERR,"ERROR line %d couldn't open tmpfile",__LINE__);
866
867
			return; 
		}
868
869
870
871

		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
872
		fprintf(tmpf,"Packet Type       %s\r\n", pktTypeStringList[cfg.nodecfg[k].pkt_type]);
873
		fprintf(tmpf,"Archive Type      %s\r\n"
rswindell's avatar
rswindell committed
874
875
876
877
			,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");
878
879
880
881
882
883
884
885
		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
886
			if(area_is_linked(i,&cfg.nodecfg[k].addr))
887
888
				fprintf(tmpf,"%s",str); 
		}
889
890

		if(ftell(tmpf))
rswindell's avatar
rswindell committed
891
			file_to_netmail(tmpf,"SBBSecho Notify List",cfg.nodecfg[k].addr, /* To: */NULL);
892
893
		fclose(tmpf); 
	}
894
}
895

896
897
898
899
/******************************************************************************
 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).
******************************************************************************/
900
901
902
903
904
enum arealist_type {
	 AREALIST_ALL			// %LIST
	,AREALIST_CONNECTED		// %QUERY
	,AREALIST_UNLINKED		// %UNLINKED
};
rswindell's avatar
rswindell committed
905
void netmail_arealist(enum arealist_type type, fidoaddr_t addr, const char* to)
906
{
907
	char str[256],title[128],match,*p,*tp;
908
909
	unsigned k,x,y;
	unsigned u;
910
	str_list_t	area_list;
911

912
	if(type == AREALIST_ALL)
913
		strcpy(title,"List of Available Areas");
914
	else if(type == AREALIST_CONNECTED)
915
916
917
918
		strcpy(title,"List of Connected Areas");
	else
		strcpy(title,"List of Unlinked Areas");

919
920
	if((area_list=strListInit()) == NULL) {
		lprintf(LOG_ERR,"ERROR line %d couldn't allocate string list",__LINE__);
921
922
		return; 
	}
923

924
	/* Include relevant areas from the area file (e.g. areas.bbs): */
925
926
	for(u=0;u<cfg.areas;u++) {
		if((type == AREALIST_CONNECTED || cfg.add_from_echolists_only) && !area_is_linked(u,&addr))
927
			continue;
928
		if(type == AREALIST_UNLINKED && area_is_linked(u,&addr))
929
			continue;
930
		strListPush(&area_list, cfg.area[u].name); 
931
	} 
932

933
	if(type != AREALIST_CONNECTED) {
rswindell's avatar
rswindell committed
934
935
		nodecfg_t* nodecfg=findnodecfg(&cfg, addr,0);
		if(nodecfg != NULL) {
936
			for(u=0;u<cfg.listcfgs;u++) {
937
				match=0;
938
				for(k=0; cfg.listcfg[u].keys[k]; k++) {
939
					if(match) break;
rswindell's avatar
rswindell committed
940
					for(x=0; nodecfg->keys[x]; x++) {
941
						if(!stricmp(cfg.listcfg[u].keys[k]
rswindell's avatar
rswindell committed
942
							,nodecfg->keys[x])) {
943
							FILE* fp;
944
							if((fp=fopen(cfg.listcfg[u].listpath,"r"))==NULL) {
945
								lprintf(LOG_ERR,"ERROR %u (%s) line %d opening %s"
946
									,errno,strerror(errno),__LINE__,cfg.listcfg[u].listpath);
947
								match=1;
948
949
								break; 
							}
950
							while(!feof(fp)) {
951
								memset(str,0,sizeof(str));
952
								if(!fgets(str,sizeof(str),fp))
953
									break;
954
								truncsp(str);
955
								p=str;
956
								SKIP_WHITESPACE(p);
957
								if(*p==0 || *p==';')     /* Ignore Blank and Comment Lines */
958
									continue;
959
960
961
								tp=p;
								FIND_WHITESPACE(tp);
								*tp=0;
962
963
964
								for(y=0;y<cfg.areas;y++)
									if(!stricmp(cfg.area[y].name,p))
										break;
965
966
967
968
								if(y>=cfg.areas || !area_is_linked(y,&addr)) {
									if(strListFind(area_list, p, /* case_sensitive */false) < 0)
										strListPush(&area_list, p);
								}
969
							}
970
							fclose(fp);
971
							match=1;
972
							break; 
973
974
						}
					}
975
976
977
978
				} 
			} 
		} 
	}
979
980
	strListSortAlpha(area_list);
	if(!strListCount(area_list))
rswindell's avatar
rswindell committed
981
		create_netmail(to,/* msg: */NULL,title,"None.",addr,/* attachment: */false);
982
983
984
985
986
987
988
989
990
991
992
993
	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);
994
}
995

rswindell's avatar
rswindell committed
996
int check_elists(const char *areatag, fidoaddr_t addr)
997
998
{
	FILE *stream;
999
	char str[1025],quit=0,*p,*tp;
1000
1001
	unsigned k,x,match=0;
	unsigned u;
1002

rswindell's avatar
rswindell committed
1003
1004
	nodecfg_t* nodecfg=findnodecfg(&cfg, addr,0);
	if(nodecfg!=NULL) {
1005
		for(u=0;u<cfg.listcfgs;u++) {
rswindell's avatar
rswindell committed
1006
			quit=0;
1007
			for(k=0; cfg.listcfg[u].keys[k]; k++) {
rswindell's avatar
rswindell committed
1008
				if(quit) break;
rswindell's avatar
rswindell committed
1009
				for(x=0; nodecfg->keys[x] ;x++)
1010
					if(!stricmp(cfg.listcfg[u].keys[k]
rswindell's avatar
rswindell committed
1011
						,nodecfg->keys[x])) {
1012
						if((stream=fopen(cfg.listcfg[u].listpath,"r"))==NULL) {
1013
							lprintf(LOG_ERR,"ERROR %u (%s) line %d opening %s"
1014
								,errno,strerror(errno),__LINE__,cfg.listcfg[u].listpath);
rswindell's avatar
rswindell committed
1015
							quit=1;
1016
1017
							break; 
						}
rswindell's avatar
rswindell committed
1018
						while(!feof(stream)) {
1019
							if(!fgets(str,sizeof(str),stream))
rswindell's avatar
rswindell committed
1020
1021
								break;
							p=str;
1022
							SKIP_WHITESPACE(p);
rswindell's avatar
rswindell committed
1023
1024
							if(*p==';')     /* Ignore Comment Lines */
								continue;
1025
1026
1027
1028
							tp=p;
							FIND_WHITESPACE(tp);
							*tp=0;
							if(!stricmp(areatag,p)) {
rswindell's avatar
rswindell committed
1029
								match=1;
1030
1031
1032
								break; 
							} 
						}
rswindell's avatar
rswindell committed
1033
						fclose(stream);
1034
						quit=1;
rswindell's avatar
rswindell committed
1035
1036
						if(match)
							return(match);
1037
1038
1039
1040
1041
						break; 
					} 
			} 
		} 
	}
rswindell's avatar
rswindell committed
1042
	return(match);
1043
1044
1045
1046
}
/******************************************************************************
 Used by AREAFIX to add/remove/change areas in the areas file
******************************************************************************/
rswindell's avatar
rswindell committed
1047
void alter_areas(str_list_t add_area, str_list_t del_area, fidoaddr_t addr, const char* to)
1048
1049
{
	FILE *nmfile,*afilein,*afileout,*fwdfile;
1050
1051
	char str[1024],fields[1024],field1[256],field2[256],field3[256]
		,outpath[MAX_PATH+1]
1052
		,*outname,*p,*tp,nomatch=0,match=0;
1053
1054
	unsigned j,k,x,y;
	unsigned u;
1055
1056
	ulong tagcrc;

1057
1058
	SAFECOPY(outpath,cfg.areafile);
	*getfname(outpath)=0;
1059
	if((outname=tempnam(outpath,"AREAS"))==NULL) {
1060
		lprintf(LOG_ERR,"ERROR tempnam(%s,AREAS)",outpath);
1061
1062
		return; 
	}
1063
	if((nmfile=tmpfile())==NULL) {
1064
		lprintf(LOG_ERR,"ERROR in tmpfile()");
1065
		free(outname);
1066
1067
		return; 
	}
1068
	if((afileout=fopen(outname,"w+"))==NULL) {
1069
		lprintf(LOG_ERR,"ERROR %u (%s) line %d opening %s",errno,strerror(errno),__LINE__,outname);
1070
1071
		fclose(nmfile);
		free(outname);
1072
1073
		return; 
	}
1074
	if((afilein=fopen(cfg.areafile,"r"))==NULL) {
1075
		lprintf(LOG_ERR,"ERROR %u (%s) line %d opening %s",errno,strerror(errno),__LINE__,cfg.areafile);
1076
1077
1078
		fclose(afileout);
		fclose(nmfile);
		free(outname);
1079
1080
		return; 
	}
1081
	while(!feof(afilein)) {
1082
		if(!fgets(fields,sizeof(fields),afilein))
1083
1084
1085
			break;
		truncsp(fields);
		p=fields;
1086
		SKIP_WHITESPACE(p);
1087
		if(*p==';') {    /* Skip Comment Lines */
1088
			fprintf(afileout,"%s\n",fields);
1089
1090
			continue; 
		}
1091
		SAFECOPY(field1,p);         /* Internal Code Field */
1092
		truncstr(field1," \t\r\n");
1093
1094
1095
		FIND_WHITESPACE(p);
		SKIP_WHITESPACE(p);
		SAFECOPY(field2,p);         /* Areatag Field */
1096
		truncstr(field2," \t\r\n");
1097
1098
		FIND_WHITESPACE(p);
		SKIP_WHITESPACE(p);
1099
		if((tp=strchr(p,';'))!=NULL) {
1100
1101
			SAFECOPY(field3,p);     /* Comment Field (if any) */
			FIND_WHITESPACE(tp);
1102
1103
			*tp=0; 
		}
1104
1105
		else
			field3[0]=0;
1106
		if(strListCount(del_area)) { 				/* Check for areas to remove */
1107
			lprintf(LOG_DEBUG,"Removing areas for %s from %s", smb_faddrtoa(&addr,NULL), cfg.areafile);
1108
1109
			for(u=0;del_area[u]!=NULL;u++) {
				if(!stricmp(del_area[u],field2) ||
1110
1111
1112
					!stricmp(del_area[0],"-ALL"))     /* Match Found */
					break; 
			}
1113
1114
1115
			if(del_area[u]!=NULL) {
				for(u=0;u<cfg.areas;u++) {
					if(!stricmp(field2,cfg.area[u].name)) {
1116
						lprintf(LOG_DEBUG,"Unlinking area (%s) for %s in %s", field2, smb_faddrtoa(&addr,NULL), cfg.areafile);
1117
						if(!area_is_linked(u,&addr)) {
1118
1119
							fprintf(afileout,"%s\n",fields);
							/* bugfix here Mar-25-2004 (wasn't breaking for "-ALL") */
1120
							if(stricmp(del_area[0],"-ALL"))
1121
1122
1123
								fprintf(nmfile,"%s not connected.\r\n",field2);
							break; 
						}
1124

rswindell's avatar
rswindell committed