Skip to content
Snippets Groups Projects
sbbsecho.c 149 KiB
Newer Older
/* Synchronet FidoNet EchoMail Scanning/Tossing and NetMail Tossing Utility */
/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
 *																			*
 * 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.	*
 ****************************************************************************/
/* Portions written by Allen Christiansen 1994-1996 						*/

#ifdef _WIN32
	#include <windows.h>
#endif

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

#ifdef __WATCOMC__
	#include <mem.h>
#endif

rswindell's avatar
rswindell committed
#include "conwrap.h"		/* getch() */
#include "sbbs.h"			/* load_cfg() */
#include "sbbsdefs.h"
#include "smblib.h"
#include "scfglib.h"
#include "lzh.h"
#include "sbbsecho.h"

smb_t *smb,*email;
long misc=(IMPORT_PACKETS|IMPORT_NETMAIL|IMPORT_ECHOMAIL|EXPORT_ECHOMAIL
			|DELETE_NETMAIL|DELETE_PACKETS);
ulong netmail=0;
char tmp[256],pkt_type=0;
int secure,cur_smb=0;
FILE *fidologfile=NULL;
two_two_t two_two;
two_plus_t two_plus;
BOOL twit_list;

faddr_t		sys_faddr;
config_t	cfg;
scfg_t		scfg;
char		compiler[32];
BOOL pause_on_exit=FALSE;

#ifdef __WATCOMC__
/******************************************************************************
 A DOS to Unix function - because WATCOM doesn't have one
******************************************************************************/
time_t dostounix(struct date *d,struct time *t)
{
	struct tm tm;

	tm.tm_sec=t->ti_sec;
	tm.tm_min=t->ti_min;
	tm.tm_hour=t->ti_hour;
	tm.tm_mday=d->da_day;
	tm.tm_mon=(d->da_mon-1);
	tm.tm_year=d->da_year-1900;
	tm.tm_isdst=0;

	return(mktime(&tm));
}
#endif

#ifndef __NT__
#define delfile(x) remove(x)
#else
int delfile(char *filename)
{
	int i=0;

	while(remove(filename) && i++<120)	/* Wait up to 60 seconds to delete file */
		delay(500); 					/* for Win95 bug fix */
	return(i);
#if defined(__unix__)	/* borrowed from MSVC */
rswindell's avatar
rswindell committed
unsigned _rotr (
        unsigned val,
        int shift
        )
{
    register unsigned lobit;        /* non-zero means lo bit set */
    register unsigned num = val;    /* number to rotate */

    shift &= 0x1f;                  /* modulo 32 -- this will also make
                                       negative shifts work */
    while (shift--) {
	    lobit = num & 1;        /* get high bit */
        num >>= 1;              /* shift right one bit */
        if (lobit)
			num |= 0x80000000;  /* set hi bit if lo bit was set */
	}
/******************************************************************************
 Displays characters locally
******************************************************************************/
long lputs(char *str)
{
    char tmp[256];
    int i,j,k;


	j=strlen(str);
	for(i=k=0;i<j;i++)      /* remove CRs */
		if(str[i]==CR && str[i+1]==LF)
			continue;
		else
			tmp[k++]=str[i];
	tmp[k]=0;
	return(fputs(tmp,stdout));
}

/****************************************************************************/
/* Performs printf() through local assembly routines                        */
/* Called from everywhere                                                   */
/****************************************************************************/
int lprintf(char *fmat, ...)
{
	va_list argptr;
	char sbuf[256];
	int chcount;

	va_start(argptr,fmat);
	chcount=vsnprintf(sbuf,sizeof(sbuf),fmat,argptr);
	va_end(argptr);
	lputs(sbuf);
	return(chcount);
}

/**********************/
/* Log print function */
/**********************/
void logprintf(char *str, ...)
{
    va_list argptr;
    char buf[256];
    time_t now;
    struct tm *gm;

	if(!(misc&LOGFILE) || fidologfile==NULL)
		return;
	va_start(argptr,str);
	vsnprintf(buf,sizeof(buf),str,argptr);
	buf[sizeof(buf)-1]=0;
	va_end(argptr);
	now=time(NULL);
	gm=localtime(&now);
	fseek(fidologfile,0L,SEEK_END);
	fprintf(fidologfile,"%02u/%02u/%02u %02u:%02u:%02u %s\r\n"
		,gm->tm_mon+1,gm->tm_mday,TM_YEAR(gm->tm_year),gm->tm_hour,gm->tm_min,gm->tm_sec
		,buf);
	fflush(fidologfile);
}

/*****************************************************************************/
/* Returns command line generated from instr with %c replacments             */
/*****************************************************************************/
char *cmdstr(scfg_t* cfg, char *instr, char *fpath, char *fspec)
{
    static char cmd[128];
    char str[256],str2[128];
    int i,j,len;

	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);
						strcat(cmd,str); }
					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);
						strcat(cmd,str); }
					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 */
					if(cfg->exec_dir[0]!='\\' 
						&& cfg->exec_dir[0]!='/' 
						&& cfg->exec_dir[1]!=':') {
						strcpy(str,cfg->node_dir);
						strcat(str,cfg->exec_dir);
						if(FULLPATH(str2,str,40))
							strcpy(str,str2);
						backslash(str);
						strcat(cmd,str); }
					else
						strcat(cmd,cfg->exec_dir);
					break;
				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;
				default:    /* unknown specification */
					printf("ERROR Checking Command Line '%s'\n",instr);
					logprintf("ERROR line %d Checking Command Line '%s'",__LINE__
						,instr);
					bail(1);
					break; }
			j=strlen(cmd); }
		else
			cmd[j++]=instr[i]; }
	cmd[j]=0;
}

/****************************************************************************/
/* Runs an external program directly using spawnvp							*/
/****************************************************************************/
int execute(char *cmdline)
{
rswindell's avatar
rswindell committed
#if 1
rswindell's avatar
rswindell committed
#else
	char c,d,e,cmdlen,*arg[30],str[256];
	int i;

	strcpy(str,cmdline);
	arg[0]=str;	/* point to the beginning of the string */
	cmdlen=strlen(str);
	for(c=0,d=1,e=0;c<cmdlen;c++,e++)	/* Break up command line */
		if(str[c]==SP) {
			str[c]=0;			/* insert nulls */
			arg[d++]=str+c+1;	/* point to the beginning of the next arg */
			e=0; }
	arg[d]=0;
	i=spawnvp(P_WAIT,arg[0],arg);
	return(i);
rswindell's avatar
rswindell committed
#endif
/******************************************************************************
 Returns the system address with the same zone as the address passed
******************************************************************************/
faddr_t getsysfaddr(short zone)
{
	int i;
	faddr_t sysfaddr;

	sysfaddr.zone=sysfaddr.net=sysfaddr.node=1;
	sysfaddr.point=0;
	if(!scfg.total_faddrs)
		return(sys_faddr);
	sysfaddr=scfg.faddr[0];
	if(scfg.total_faddrs==1)
		return(sysfaddr);
	for(i=0;i<scfg.total_faddrs;i++)
		if(scfg.faddr[i].zone==zone)
			return(scfg.faddr[i]);
	return(sysfaddr);
}
/******************************************************************************
 This function creates or appends on existing Binkley compatible .?LO file
 attach file.
 Returns 0 on success.
******************************************************************************/
int write_flofile(char *attachment, faddr_t dest)
{
	char fname[MAX_PATH+1];
	char outbound[MAX_PATH+1];
	char str[MAX_PATH+1];
	char ch;
	char searchstr[MAX_PATH+1];
	ushort attr=0;
	int i,file;
	FILE *stream;

	i=matchnode(dest,0);
	if(i<(int)cfg.nodecfgs)
		attr=cfg.nodecfg[i].attr;

rswindell's avatar
rswindell committed
	if(attr&ATTR_CRASH) ch='c';
	else if(attr&ATTR_HOLD) ch='h';
	else if(attr&ATTR_DIRECT) ch='d';
	else ch='f';
	if(dest.zone==scfg.faddr[0].zone)		/* Default zone, use default outbound */
		strcpy(outbound,cfg.outbound);
	else {								/* Inter-zone outbound is OUTBOUND.XXX */
		sprintf(outbound,"%.*s.%03x"
			,(int)strlen(cfg.outbound)-1,cfg.outbound,dest.zone);
	if(dest.point) {					/* Point destination is OUTBOUND\*.PNT */
rswindell's avatar
rswindell committed
		sprintf(str,"%04x%04x.pnt"
			,dest.net,dest.node);
		strcat(outbound,str); }
rswindell's avatar
rswindell committed
	if(outbound[strlen(outbound)-1]=='\\'
		|| outbound[strlen(outbound)-1]=='/')
		outbound[strlen(outbound)-1]=0;
	MKDIR(outbound);
	backslash(outbound);
	if(dest.point)
rswindell's avatar
rswindell committed
		sprintf(fname,"%s%08x.%clo",outbound,dest.point,ch);
rswindell's avatar
rswindell committed
		sprintf(fname,"%s%04x%04x.%clo",outbound,dest.net,dest.node,ch);
	sprintf(searchstr,"^%s",attachment);
	if(findstr(searchstr,fname))	/* file already in FLO file */
		return(0);
	if((stream=fnopen(&file,fname,O_WRONLY|O_APPEND|O_CREAT))==NULL) {
		printf("\7ERROR line %d opening %s %s\n",__LINE__,fname,strerror(errno));
		logprintf("ERROR line %d opening %s %s",__LINE__,fname,strerror(errno));
	fprintf(stream,"^%s\r\n",attachment);
	fclose(stream);
	return(0);
}

/* Writes text buffer to file, expanding sole LFs to CRLFs */
size_t fwrite_crlf(char* buf, size_t len, FILE* fp)
{
	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);
}

/******************************************************************************
 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.
******************************************************************************/
int create_netmail(char *to, char *subject, char *body, faddr_t dest, BOOL file_attached)
{
	FILE *fstream;
	char str[256],fname[256];
	ushort attr=0;
	int fmsg;
	uint i;
	static uint startmsg;
	time_t t;
	faddr_t	faddr;
	fmsghdr_t hdr;
	struct tm *tm;

	if(!startmsg) startmsg=1;
	i=matchnode(dest,0);
	if(i<cfg.nodecfgs) {
		attr=cfg.nodecfg[i].attr;
		if(!attr) {
			i=matchnode(dest,2);
			if(i<cfg.nodecfgs)
				attr=cfg.nodecfg[i].attr; } }

	do {
		for(i=startmsg;i;i++) {
			sprintf(fname,"%s%u.msg",scfg.netmail_dir,i);
		if(!i) {
			printf("\7%s directory full!\n",scfg.netmail_dir);
			logprintf("Directory full: %s",scfg.netmail_dir);
			return(-1); }
		startmsg=i+1;
		if((fstream=fnopen(&fmsg,fname,O_RDWR|O_CREAT))==NULL) {
			printf("\7ERROR line %d opening %s %s\n",__LINE__,fname,strerror(errno));
			logprintf("ERROR line %d opening %s %s",__LINE__,fname,strerror(errno));
		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);
			hdr.attr|=FIDO_FILE;
		if(attr&ATTR_HOLD)
			hdr.attr|=FIDO_HOLD;
		if(attr&ATTR_CRASH)
			hdr.attr|=FIDO_CRASH;
		sprintf(hdr.from,"SBBSecho");

		t=time(NULL);
		tm=localtime(&t);
		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);

		if(to)
			sprintf(hdr.to,"%s",to);
			sprintf(hdr.to,"SYSOP");

		sprintf(hdr.subj,"%.71s",subject);

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

		/* Add FSC-53 FLAGS kludge */
		fprintf(fstream,"\1FLAGS");
		if(attr&ATTR_DIRECT)
			fprintf(fstream," DIR");
		if(file_attached) {
			if(misc&TRUNC_BUNDLES)
				fprintf(fstream," TFS");
				fprintf(fstream," KFS");
		}
		fprintf(fstream,"\r");

		if(hdr.destpoint) {
			sprintf(str,"\1TOPT %hu\r",hdr.destpoint);
			fwrite(str,strlen(str),1,fstream); }
		if(hdr.origpoint) {
			sprintf(str,"\1FMPT %hu\r",hdr.origpoint);
			fwrite(str,strlen(str),1,fstream); }
		if(!file_attached || (!(attr&ATTR_DIRECT) && file_attached))
			fwrite_crlf(body,strlen(body)+1,fstream);	/* Write additional NULL */
		else
			fwrite("\0",1,1,fstream);               /* Write NULL */
		fclose(fstream);
	} while(!fexistcase(fname));
}

/******************************************************************************
 This function takes the contents of 'infile' and puts it into a netmail
 message bound for addr.
******************************************************************************/
void file_to_netmail(FILE *infile,char *title,faddr_t addr,char *to)
{
	char *buf,*p;
	long l,m,len;

	l=len=ftell(infile);
	if(len>8192L)
		len=8192L;
	rewind(infile);
	if((buf=(char *)MALLOC(len+1))==NULL) {
		printf("ERROR allocating %lu bytes for file to netmail buffer.\n",len);
		logprintf("ERROR line %d allocating %lu for file to netmail buf",__LINE__
			,len);
		return; }
	while((m=fread(buf,1,(len>8064L) ? 8064L:len,infile))>0) {
		buf[m]=0;
		if(l>8064L && (p=strrchr(buf,'\n'))!=NULL) {
				fseek(infile,-1L,SEEK_CUR);
				while(*p) { 			/* Seek back to end of last line */
					p++;
					fseek(infile,-1L,SEEK_CUR); } } }
		if(ftell(infile)<l)
			strcat(buf,"\r\nContinued in next message...\r\n");
		create_netmail(to,title,buf,addr,FALSE); 
	}
}
/******************************************************************************
 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.
******************************************************************************/
void notify_list(void)
{
	FILE *	tmpf;
	char	str[256];
	uint	i,j,k;

	for(k=0;k<cfg.nodecfgs;k++) {

		if(!(cfg.nodecfg[k].attr&SEND_NOTIFY))
			continue;

		if((tmpf=tmpfile())==NULL) {
			printf("\7ERROR couldn't open tmpfile.\n");
			logprintf("ERROR line %d couldn't open tmpfile",__LINE__);
			return; }

		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");
		fprintf(tmpf,"Packet Type       %s\r\n"
			,cfg.nodecfg[k].pkt_type==PKT_TWO ? "2"
			:cfg.nodecfg[k].pkt_type==PKT_TWO_TWO ? "2.2":"2+");
		fprintf(tmpf,"Archive Type      %s\r\n"
			,(cfg.nodecfg[k].arctype>cfg.arcdefs) ?
			 "None":cfg.arcdef[cfg.nodecfg[k].arctype].name);
		fprintf(tmpf,"Mail Status       %s\r\n"
			,cfg.nodecfg[k].attr&ATTR_CRASH ? "Crash"
			:cfg.nodecfg[k].attr&ATTR_HOLD ? "Hold" : "None");
		fprintf(tmpf,"Direct            %s\r\n"
			,cfg.nodecfg[k].attr&ATTR_DIRECT ? "Yes":"No");
		fprintf(tmpf,"Passive           %s\r\n"
			,cfg.nodecfg[k].attr&ATTR_PASSIVE ? "Yes":"No");
		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;
			for(j=0;j<cfg.area[i].uplinks;j++)
				if(!memcmp(&cfg.nodecfg[k].faddr,&cfg.area[i].uplink[j]
					,sizeof(faddr_t)))
					break;
			if(j<cfg.area[i].uplinks)
				fprintf(tmpf,"%s",str); }

		if(ftell(tmpf))
			file_to_netmail(tmpf,"SBBSecho Notify List",cfg.nodecfg[k].faddr,0);
		fclose(tmpf); }
}
/******************************************************************************
 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).
******************************************************************************/
void netmail_arealist(char type,faddr_t addr)
{
	FILE *stream,*tmpf;
	char str[256],temp[256],title[81],match,*p;
	int file,i,j,k,x,y;

	if(!type)
		strcpy(title,"List of Available Areas");
	else if(type==1)
		strcpy(title,"List of Connected Areas");
	else
		strcpy(title,"List of Unlinked Areas");

	if((tmpf=tmpfile())==NULL) {
		printf("\7ERROR couldn't open tmpfile.\n");
		logprintf("ERROR line %d couldn't open tmpfile",__LINE__);
		return; }

	if(type==1 || (type!=1 && !(misc&ELIST_ONLY))) {
		for(i=0;i<cfg.areas;i++) {
			sprintf(str,"%s\r\n",cfg.area[i].name);
			if(type) {
				for(j=0;j<cfg.area[i].uplinks;j++)
					if(!memcmp(&addr,&cfg.area[i].uplink[j],sizeof(faddr_t)))
						break;
				if((type==1 && j<cfg.area[i].uplinks) ||
					(type==2 && j==cfg.area[i].uplinks))
						fprintf(tmpf,"%s",str); }
			else
				fprintf(tmpf,"%s",str); } }

	if(!type) {
		i=matchnode(addr,0);
		if(i<cfg.nodecfgs) {
			for(j=0;j<cfg.listcfgs;j++) {
				match=0;
				for(k=0;k<cfg.listcfg[j].numflags;k++) {
					if(match) break;
					for(x=0;x<cfg.nodecfg[i].numflags;x++)
						if(!stricmp(cfg.listcfg[j].flag[k].flag
							,cfg.nodecfg[i].flag[x].flag)) {
							if((stream=fnopen(&file
								,cfg.listcfg[j].listpath,O_RDONLY))==NULL) {
								printf("\7ERROR couldn't open %s.\n"
									,cfg.listcfg[j].listpath);
								logprintf("ERROR line %d couldn't open %s %s"
									,__LINE__,cfg.listcfg[j].listpath
								match=1;
								break; }
							while(!feof(stream)) {
								if(!fgets(str,255,stream))
									break;
								truncsp(str);
								strcat(str,"\r\n");
								p=str;
								while(*p && *p<=SP) p++;
								if(*p==';')     /* Ignore Comment Lines */
									continue;
								strcpy(temp,p);
								p=temp;
								while(*p && *p>SP) p++;
								*p=0;
								if(!(misc&ELIST_ONLY)) {
									for(y=0;y<cfg.areas;y++)
										if(!stricmp(cfg.area[y].name,temp))
											break;
									if(y==cfg.areas)
										fprintf(tmpf,"%s",str); }
								else
									fprintf(tmpf,"%s",str); }
							fclose(stream);
							match=1;
							break; } } } } }

	if(!ftell(tmpf))
		create_netmail(NULL,title,"None.",addr,FALSE);
	else
		file_to_netmail(tmpf,title,addr,0);
	fclose(tmpf);
}
/******************************************************************************
 Imitation of Borland's tempnam function because Watcom doesn't have it
******************************************************************************/
char *tempname(char *dir, char *prefix)
{
	char str[256],*p;
	int i;

	for(i=0;i<1000;i++) {
		sprintf(str,"%s%s%03u.$$$",dir,prefix,i);
		if(!fexist(str))
			break; }
	if(i>=1000) {
		logprintf("tempnam: too many files");
		return(NULL); }
	p=malloc(strlen(str)+1);
	if(!p) {
		logprintf("tempnam: couldn't malloc %u",strlen(str)+1);
		return(NULL); }
	strcpy(p,str);
	return(p);
rswindell's avatar
rswindell committed
int check_elists(char *areatag,faddr_t addr)
{
	FILE *stream;
rswindell's avatar
rswindell committed
	char str[1025],quit=0,*p;
	int i,j,k,x,file,match=0;
rswindell's avatar
rswindell committed
	i=matchnode(addr,0);
	if(i<cfg.nodecfgs) {
		for(j=0;j<cfg.listcfgs;j++) {
			quit=0;
			for(k=0;k<cfg.listcfg[j].numflags;k++) {
				if(quit) break;
				for(x=0;x<cfg.nodecfg[i].numflags;x++)
					if(!stricmp(cfg.listcfg[j].flag[k].flag
						,cfg.nodecfg[i].flag[x].flag)) {
						if((stream=fnopen(&file
							,cfg.listcfg[j].listpath,O_RDONLY))==NULL) {
							printf("\7ERROR couldn't open %s.\n"
								,cfg.listcfg[j].listpath);
							logprintf("ERROR line %d opening %s"
								,__LINE__,cfg.listcfg[j].listpath);
							quit=1;
							break; }
						while(!feof(stream)) {
							if(!fgets(str,255,stream))
								break;
							truncsp(str);
							strcat(str,"\r\n");
							p=str;
							while(*p && *p<=SP) p++;
							if(*p==';')     /* Ignore Comment Lines */
								continue;
							strcpy(str,p);
							p=str;
							while(*p && *p>SP) p++;
							*p=0;
							if(!stricmp(areatag,str)) {
								match=1;
								break; } }
						fclose(stream);
rswindell's avatar
rswindell committed
						if(match)
							return(match);
						break; } } } }
	return(match);
}
/******************************************************************************
 Used by AREAFIX to add/remove/change areas in the areas file
******************************************************************************/
void alter_areas(area_t add_area,area_t del_area,faddr_t addr)
{
	FILE *nmfile,*afilein,*afileout,*fwdfile;
	char str[1025],fields[1025],field1[81],field2[81],field3[81]
		,drive[3],dir[MAX_PATH+1],name[MAX_PATH+1],ext[MAX_PATH+1],outpath[128]
		,*outname,*p,*tp,nomatch=0,match=0;
	int i,j,k,x,y,file;
	ulong tagcrc;

	_splitpath(cfg.areafile,drive,dir,name,ext);
	sprintf(outpath,"%s%s",drive,dir);
	if((outname=tempname(outpath,"AREAS"))==NULL) {
		printf("\7ERROR creating temp file name for %s.\n",outpath);
		logprintf("ERROR tempnam(%s,AREAS)",outpath);
		return; }
	if((nmfile=tmpfile())==NULL) {
		printf("\7ERROR couldn't open NetMail temp file.\n");
		logprintf("ERROR in tmpfile()");
		free(outname);
		return; }
	if((afileout=fopen(outname,"w+b"))==NULL) {
		printf("\7ERROR couldn't open %s.\n",outname);
		logprintf("ERROR line %d opening %s %s",__LINE__,outname
		fclose(nmfile);
		free(outname);
		return; }
	if((afilein=fnopen(&file,cfg.areafile,O_RDONLY))==NULL) {
		printf("\7ERROR couldn't open %s.\n",cfg.areafile);
		logprintf("ERROR line %d opening %s %s",__LINE__,cfg.areafile
		fclose(afileout);
		fclose(nmfile);
		free(outname);
		return; }
	while(!feof(afilein)) {
		if(!fgets(fields,1024,afilein))
			break;
		truncsp(fields);
		strcat(fields,"\r\n");
		p=fields;
		while(*p && *p<=SP) p++;
		if(*p==';') {    /* Skip Comment Lines */
			fprintf(afileout,"%s",fields);
			continue; }
		sprintf(field1,"%-.81s",p);         /* Internal Code Field */
		tp=field1;
		while(*tp && *tp>SP) tp++;
		*tp=0;
		while(*p && *p>SP) p++;
		while(*p && *p<=SP) p++;
		sprintf(field2,"%-.81s",p);         /* Areatag Field */
		tp=field2;
		while(*tp && *tp>SP) tp++;
		*tp=0;
		while(*p && *p>SP) p++;
		while(*p && *p<=SP) p++;
		if((tp=strchr(p,';'))!=NULL) {
			sprintf(field3,"%-.81s",p);     /* Comment Field (if any) */
			while(*tp && *tp>SP) tp++;
			*tp=0; }
		else
			field3[0]=0;
		if(del_area.tags) { 				/* Check for areas to remove */
			for(i=0;i<del_area.tags;i++) {
				if(!stricmp(del_area.tag[i],field2) ||
					!stricmp(del_area.tag[0],"-ALL"))     /* Match Found */
					break; }
			if(i<del_area.tags) {
				for(i=0;i<cfg.areas;i++) {
					if(!stricmp(field2,cfg.area[i].name)) {
						for(j=0;j<cfg.area[i].uplinks;j++)
							if(!memcmp(&cfg.area[i].uplink[j],&addr
								,sizeof(faddr_t)))
								break;
						if(j==cfg.area[i].uplinks &&
							stricmp(del_area.tag[0],"-ALL")) {
							fprintf(afileout,"%s",fields);
							fprintf(nmfile,"%s not connected.\r\n",field2);
							break; }
						/* Added 12/4/95 to remove uplink from connected uplinks */

						for(k=j;k<cfg.area[i].uplinks-1;k++)
							memcpy(&cfg.area[i].uplink[k],&cfg.area[i].uplink[k+1]
								,sizeof(faddr_t));
						--cfg.area[i].uplinks;
						if((cfg.area[i].uplink=(faddr_t *)
							REALLOC(cfg.area[i].uplink,sizeof(faddr_t)
							*(cfg.area[i].uplinks)))==NULL) {
							printf("ERROR allocating memory for area #%u "
								"uplinks.\n",i+1);
							logprintf("ERROR line %d allocating memory for area "
								"#%u uplinks.\n",__LINE__,i+1);
							bail(1); }

						fprintf(afileout,"%-16s%-23s ",field1,field2);
						for(j=0;j<cfg.area[i].uplinks;j++) {
							if(!memcmp(&cfg.area[i].uplink[j],&addr
								,sizeof(faddr_t)))
								continue;
							fprintf(afileout,"%s "
								,faddrtoa(&cfg.area[i].uplink[j],NULL)); }
						if(field3[0])
							fprintf(afileout,"%s",field3);
						fprintf(afileout,"\r\n");
						fprintf(nmfile,"%s removed.\r\n",field2);
						break; } }
				if(i==cfg.areas)			/* Something screwy going on */
					fprintf(afileout,"%s",fields);
				continue; } }				/* Area match so continue on */
		if(add_area.tags) { 				/* Check for areas to add */
			for(i=0;i<add_area.tags;i++)
				if(!stricmp(add_area.tag[i],field2) ||
					!stricmp(add_area.tag[0],"+ALL"))      /* Match Found */
					break;
			if(i<add_area.tags) {
				if(stricmp(add_area.tag[i],"+ALL"))
					add_area.tag[i][0]=0;  /* So we can check other lists */
				for(i=0;i<cfg.areas;i++) {
					if(!stricmp(field2,cfg.area[i].name)) {
						for(j=0;j<cfg.area[i].uplinks;j++)
							if(!memcmp(&cfg.area[i].uplink[j],&addr
								,sizeof(faddr_t)))
								break;
						if(j<cfg.area[i].uplinks) {
							fprintf(afileout,"%s",fields);
							fprintf(nmfile,"%s already connected.\r\n",field2);
						if(misc&ELIST_ONLY && !check_elists(field2,addr)) {
							fprintf(afileout,"%s",fields);

						/* Added 12/4/95 to add uplink to connected uplinks */

						++cfg.area[i].uplinks;
						if((cfg.area[i].uplink=(faddr_t *)
							REALLOC(cfg.area[i].uplink,sizeof(faddr_t)
							*(cfg.area[i].uplinks)))==NULL) {
							printf("ERROR allocating memory for area #%u "
								"uplinks.\n",i+1);
							logprintf("ERROR line %d allocating memory for area "
								"#%u uplinks.\n",__LINE__,i+1);
							bail(1); }
						memcpy(&cfg.area[i].uplink[j],&addr,sizeof(faddr_t));

						fprintf(afileout,"%-16s%-23s ",field1,field2);
						for(j=0;j<cfg.area[i].uplinks;j++)
							fprintf(afileout,"%s "
								,faddrtoa(&cfg.area[i].uplink[j],NULL));
						if(field3[0])
							fprintf(afileout,"%s",field3);
						fprintf(afileout,"\r\n");
						fprintf(nmfile,"%s added.\r\n",field2);
						break; } }
				if(i==cfg.areas)			/* Something screwy going on */
					fprintf(afileout,"%s",fields);
				continue; } 				/* Area match so continue on */
			nomatch=1; }					/* This area wasn't in there */
		fprintf(afileout,"%s",fields); }    /* No match so write back line */
	fclose(afilein);
	if(nomatch || (add_area.tags && !stricmp(add_area.tag[0],"+ALL"))) {
		i=matchnode(addr,0);
		if(i<cfg.nodecfgs) {
			for(j=0;j<cfg.listcfgs;j++) {
				match=0;
				for(k=0;k<cfg.listcfg[j].numflags;k++) {
					if(match) break;
					for(x=0;x<cfg.nodecfg[i].numflags;x++)
						if(!stricmp(cfg.listcfg[j].flag[k].flag
							,cfg.nodecfg[i].flag[x].flag)) {
							if((fwdfile=tmpfile())==NULL) {
								printf("\7ERROR couldn't open forwarding temp "
									"file.\n");
								logprintf("ERROR line %d opening forward temp "
									"file",__LINE__);
								match=1;
								break; }
							if((afilein=fnopen(&file
								,cfg.listcfg[j].listpath,O_RDONLY))==NULL) {
								printf("\7ERROR couldn't open %s.\n"
									,cfg.listcfg[j].listpath);
								logprintf("ERROR line %d opening %s"
									,__LINE__,cfg.listcfg[j].listpath);
								fclose(fwdfile);
								match=1;
								break; }
							while(!feof(afilein)) {
								if(!fgets(str,255,afilein))
								truncsp(str);
								strcat(str,"\r\n");
								p=str;
								while(*p && *p<=SP) p++;
								if(*p==';')     /* Ignore Comment Lines */
									continue;
								strcpy(str,p);
								p=str;
								while(*p && *p>SP) p++;
								*p=0;
								if(!stricmp(add_area.tag[0],"+ALL")) {
									sprintf(fields,"%.1024s",str);
									tagcrc=crc32(strupr(fields),0);