home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
prog
/
c
/
afixsrc.lha
/
areafix.c
next >
Wrap
C/C++ Source or Header
|
1990-05-23
|
38KB
|
1,658 lines
/*======================================================================*/
/* AreaFix 1.00 by Russel Miranda */
/*======================================================================*/
#include <AreaFix.h>
void main(int argc, char *argv[])
{
struct msg *header; /* I found that all the variables I */
char *msgname; /* needed wouldn't fit nicely onto the */
char *line; /* stack, so I made pointers to all of */
short high; /* them, and allocated the space later. */
char *temp;
char *cmds;
char *in;
char *out;
char *pass;
char *message;
char *configname="PARAGON:AreaFix.CFG";
int index,count,processed=0,dots,searchbase=0;
int fwdlvl=0;
char rescan=FALSE,remove=FALSE,firstline=FALSE;
char query=FALSE,listareas=FALSE,change=FALSE;
struct area *found=NULL;
struct address *newadr;
struct address *orignode;
FILE *fptr;
printf( "%-15s v%-5s - by Russel Miranda\n------------------------------------------\n",prgname,version);
if((argc>1)&&(argv[1][0]=='?'))
{
printf(
"Usage:\n"
"\n"
"1.> AreaFix [-c<filename>] [-f]\n\n"
"-c<filename> - specifies an alternate config file.\n"
"-f - forces the generation of a new Areas.CTL file.\n\n"
"ParCon must be active before this can be run.\n\n");
exit(0);
}
for(index=1;index<argc;index++)
{
if(argv[index][0]=='-')
{
switch(toupper(argv[index][1]))
{
case 'C':
configname=&argv[index][2];
break;
case 'F':
change=TRUE;
break;
}
}
}
mytask=FindTask(0L); /* Rename the task for */
oldname=mytask->tc_Node.ln_Name; /* the brief period of */
mytask->tc_Node.ln_Name = prgname; /* time I'm here! */
StartLink(); /* For info on this, see the */
bbspath=bbsconfig->defpath; /* header "ParConLnk.h" */
printf("Working...");
/* This way is much better than putting a 256 character string */
/* onto the stack. */
line=(char *)calloc(256,sizeof(char));
filename=(char *)calloc(256,sizeof(char));
if(!(filename && line))
{
printf("Error allocating memory.\n");
EXit(10);
}
lprintf(" %s v%s by Russel Miranda\n",prgname,version);
TimeStr(line);
lprintf("*-- Session started @ %s\n",line);
newadr=(struct address *)calloc(1,sizeof(struct address));
orignode=(struct address *)calloc(1,sizeof(struct address));
header=(struct msg *)calloc(1,sizeof(struct msg));
msgname=(char *)calloc(256,sizeof(char));
in=(char *)calloc(256,sizeof(char));
out=(char *)calloc(256,sizeof(char));
pass=(char *)calloc(256,sizeof(char));
message=(char *)calloc(256,sizeof(char));
if(!(newadr && orignode && header && msgname && in && out && pass && message))
NoMem();
/* Setup the default input and output files. */
sprintf(in,"%sAreas.CTL",bbspath);
sprintf(out,"%sAreas.CTL",bbspath);
/* Read the config file. */
ReadCfg(configname,in,out,&fwdlvl,&searchbase);
/* Read the highpoint file. */
high=GetHiMk((short)searchbase);
/* Read the AREAS.CTL file, and build a list of areas and the */
/* systems they are connected to. */
InputAreas(&change,in);
/* Check the QUE file to find out if anyone is waiting for an */
/* echo whose request we've forwarded... If so, build the list. */
BuildReqLst();
/* Scan for messages to AreaFix, and if any are found, process */
/* them immediately! */
lprintf("| Scanning messages in area %d...\n",searchbase+1);
for(count=high+1;count<=bbsconfig->himsgno[searchbase];count++)
{
sprintf(msgname,"%s%d.%d",bbsconfig->msgpath[searchbase],count,searchbase+1);
#ifdef DEBUG
printf("Checking message: %s\r",msgname);
#endif
if(fptr=fopen(msgname,"rb"))
{
#ifdef DEBUG
printf("\nOpened, checking...\r");
#endif
fread((char *)header,sizeof(struct msg)-2,1,fptr);
if(AliasMatch(header->touser))
{
#ifdef DEBUG
printf("\nHas my name on it...\n");
printf("Destination Address: (%d/%d)\n",header->desnet,header->desnode);
#endif
/* Process the message. */
if((header->desnet!=bbsconfig->net)||(header->desnode!=bbsconfig->node))
continue;
#ifdef DEBUG
printf("It's for me!\n");
#endif
orignode->zone=0;
orignode->net=header->orignet;
orignode->node=header->orignode;
lprintf("| * Processing message #%d from (%d/%d):\n",count,orignode->net,orignode->node);
replymsg=MessageOpen(orignode,header->fromuser,prgname,searchbase,"Auto Reply",message);
listareas=FALSE;
rescan=FALSE;
query=FALSE;
processed++;
if(cmds=strchr(header->subject,' '))
{
*cmds=0;
cmds++;
cmds=stpblk(cmds);
}
if(!PassMatch(orignode,header->subject))
{
fprintf(replymsg,"Invalid password.\r\n");
MessageClose(replymsg,searchbase,message);
lprintf("| : Invalid password: \"%s\"\n",header->subject);
lprintf("| * Message processing aborted.\n");
continue;
}
while((*cmds)&&(cmds))
{
if(cmds[0]=='-')
{
if(!strnicmp(cmds,"-L",2))
{
lprintf("| | Echo list requested.\n");
listareas=TRUE;
if(cmds=strchr(cmds,' '))
cmds=stpblk(cmds);
continue;
}
if(!strnicmp(cmds,"-R",2))
{
lprintf("| | Requested rescan.\n");
rescan=TRUE;
if(cmds=strchr(cmds,' '))
cmds=stpblk(cmds);
continue;
}
if(!strnicmp(cmds,"-Q",2))
{
lprintf("| | Query list requested.\n");
query=TRUE;
if(cmds=strchr(cmds,' '))
cmds=stpblk(cmds);
continue;
}
}
if(cmds=strchr(cmds,' '))
cmds=stpblk(cmds);
lprintf("| < Invalid subject line command.\r\n");
}
firstline=TRUE;
while(GetLine(fptr,line))
{
if(line[0]==0x01)
continue;
strupr(line);
temp=line;
if(!strncmp(temp,"---",3))
break;
if(firstline)
{
fprintf(replymsg," Changes in EchoMail Topology\r\n\r\n");
fprintf(replymsg,"AREA: STATUS:\r\n");
fprintf(replymsg,"------------------------------- -------------------------------\r\n");
firstline=FALSE;
}
if(temp[0]=='-')
{
temp++;
remove=TRUE;
}
else
remove=FALSE;
fprintf(replymsg,"%s ",line);
for(dots=strlen(line);dots<=29;dots++)
fputc('.',replymsg);
fprintf(replymsg," ");
if(found=FindAreaT(temp))
{
if(remove)
{
lprintf("| | Attempting to disconnect from area \"%s\": ",temp);
if(RemoveNode(found,orignode))
{
fprintf(replymsg,"Deleted.\r\n");
lprintf("Disconnected.\n");
change=TRUE;
}
else
{
fprintf(replymsg,"Not previously connected.\r\n");
lprintf("Not connected.\r\n");
}
}
else
{
lprintf("| | Attempting to add area \"%s\": ",temp);
if(!FindNode(found,orignode))
{
if(GoodLevel(orignode,temp))
{
NodeAdd(found,orignode);
fprintf(replymsg,"Added area");
lprintf("Added");
change=TRUE;
if(rescan)
{
ReScan(found);
fprintf(replymsg," and rescanned");
lprintf(" and rescanned");
}
fprintf(replymsg,".\r\n");
lprintf(".\n");
}
else
{
fprintf(replymsg,"Security too low.\r\n");
lprintf("Insufficient security.\n");
}
}
else
{
fprintf(replymsg,"Previously connected");
lprintf("Previously connected");
if(rescan)
{
fprintf(replymsg,", rescanning\r\n");
lprintf(", rescanning\n");
ReScan(found);
}
fprintf(replymsg,".\r\n");
lprintf(".\n");
}
}
}
else
{
if(!remove)
{
if(AvailFrom(newadr,temp,pass))
{
if(SecLevel(orignode)>=fwdlvl)
{
if(AddReq(temp,newadr,orignode))
AddFwd(line,newadr,pass);
fprintf(replymsg,"Forwarded request.\r\n");
lprintf("| | Attempting to add area \"%s\": Forwarded request to (%d/%d).\n",temp,newadr->net,newadr->node);
}
else
{
fprintf(replymsg,"Not Available.\r\n");
lprintf("| + Attempting to forward request for area \"%s\": Insufficient security.\n",temp);
}
}
else
{
fprintf(replymsg,"Not available.\r\n");
lprintf("| + Attempting to add area \"%s\": Tag not found/available.\n",temp);
}
}
else
{
fprintf(replymsg,"Not connected.\n");
lprintf("| + Attempting to remove \"%s\": Not connected.\n",temp);
}
}
}
ActiveAreas(replymsg,orignode);
if(query)
AvailAreas(replymsg,orignode);
MessageClose(replymsg,searchbase,message);
if(listareas)
{
lprintf("| | Attempting to send AvailAreas.TXT\n");
List(orignode,searchbase);
}
lprintf("| * Processing complete.\n");
}
fclose(fptr);
}
}
/* Save the high marks again. */
SaveHiMk((short)searchbase,bbsconfig->himsgno[searchbase]);
lprintf("| Scanning complete. %d messages processed.\n",processed);
/* If someone sent out a request (or maybe several) that I had */
/* to forward, now is a good time to send them. */
SendFwd(searchbase);
/* Check to see if any of the echos we've been waiting for are */
/* here yet... */
ProcQue(&change,searchbase);
/* Save the ones that aren't in yet... */
SaveQue();
/* We don't need ParCon anymore, sever the link. */
EndLink();
/* If anything changed, save the AREAS.CTL file... */
if(change)
{
OutputAreas(out);
lprintf("| New \"%s\" created.\n",out);
}
TimeStr(line);
lprintf("*-- Session ended @ %s\n",line);
printf("Done.\nTotal messages processed: %d\n",processed);
EXit(0);
}
/*- -*\
* GetLine() - A nice little function I slapped together for reading a *
* line from a config file or a message, it will only return lines *
* that have something in them, and will discard the text after a *
* semicolon. Pass over the file pointer, and the address of a *
* string 256 characters in length, and it will fill it with the *
* line from the file. Returns a 1 if it was sucessful, returns *
\*- a 0 if it hit the end of the file. -*/
int GetLine(FILE *fptr,char *str)
{
char *strptr;
unsigned char count;
unsigned char len;
do
{
if(!fgets(str,255,fptr))
return 0;
if(str[strlen(str)-1]=='\n')
str[strlen(str)-1]=0;
strptr=stpblk(str);
len=strlen(strptr);
for(count=0;count<len;count++)
{
if(strptr[count]==';')
{
strptr[count]=0;
break;
}
}
len=strlen(strptr);
for(count=len-1;((count>=0)&&(isspace(strptr[count])));count--)
strptr[count]=0;
} while(!strlen(strptr));
return 1;
}
/*- -*\
* AreaAdd - adds an area to the area list *
\*- -*/
struct area *AreaAdd(short number)
{
struct area *new;
if(!(new=(struct area *)calloc(1,sizeof(struct area))))
EXit(10);
new->areanum=number;
strcpy(new->areatag,bbsconfig->tagname[number-1]);
if(!first)
first=new;
else
last->next=new;
last=new;
return new;
}
/*- -*\
* NodeAdd() - adds a node to the node list hanging off of an area list *
\*- -*/
void NodeAdd(struct area *to,struct address *add)
{
struct address *new;
if(!(new=(struct address *)calloc(1,sizeof(struct address))))
EXit(10);
new->zone=(add->zone);
new->net=(add->net);
new->node=(add->node);
if(!(to->firstnode))
to->firstnode=new;
else
to->lastnode->nextnode=new;
to->lastnode=new;
}
/*- -*\
* OutputAreas() - writes the Areas.CTL file *
\*- -*/
void OutputAreas(char *outfile)
{
struct address *curadd;
struct area *cur=first;
FILE *fptr;
if(!(fptr=fopen(outfile,"w")))
{
printf("Error writing output file: \"%s\"\n",outfile);
lprintf("| E Error writing output file: \"%s\"\n",outfile);
return;
}
fprintf(fptr,"; Areas.CTL - created by %-15s v%-5s\n",prgname,version);
fprintf(fptr,"; By Russel Miranda\n");
fprintf(fptr,"; Another utilility for Paragon BBS\n");
fprintf(fptr,";\n");
while(cur)
{
fprintf(fptr,";---Tag Name: %s\n",cur->areatag);
fprintf(fptr,"AREA %d\n",cur->areanum);
curadd=cur->firstnode;
while(curadd)
{
fprintf(fptr,"%d/%d\n",curadd->net,curadd->node);
curadd=curadd->nextnode;
}
cur=cur->next;
}
fclose(fptr);
}
/*- -*\
* FindAreaT() - Returns a pointer to the area with tag <match> *
\*- -*/
struct area *FindAreaT(char *match)
{
register struct area *cur=first;
while(cur)
{
if(!stricmp(cur->areatag,match))
return cur;
cur=cur->next;
}
return NULL;
}
/*- -*\
* RemoveNode() - Removes a system's address from the list attached to *
\* the area pointed to by <from>. */
int RemoveNode(struct area *from,struct address *adr)
{
register struct address *prev,*cur;
prev=NULL;
cur=from->firstnode;
while(cur)
{
if(!cmpnode(cur,adr))
{
if(!prev)
from->firstnode=cur->nextnode;
else
prev->nextnode=cur->nextnode;
free(cur);
return 1;
}
prev=cur;
cur=cur->nextnode;
}
return 0;
}
/*- -*\
* FindNode() - Looks for the system pointed to by <match> in the list *
\*- attached to the area pointed to by <where>. -*/
struct address *FindNode(struct area *where,struct address *match)
{
register struct address *curadr=where->firstnode;
while(curadr)
{
if(!cmpnode(curadr,match))
return curadr;
curadr=curadr->nextnode;
}
return NULL;
}
/*- -*\
* cmpnode() - Compares two addresses, returns a 0 if they are the same *
\*- or a 1 if they are different -*/
int cmpnode(struct address *one,struct address *two)
{
if(one->net!=two->net)
return 1;
if(one->node!=two->node)
return 1;
return 0;
}
/*- -*\
* AvailAreas() - Outputs a query list for <adr> into the file <file> *
\*- -*/
void AvailAreas(FILE *file,struct address *adr)
{
struct area *cur=first;
char stat;
fprintf(file,"\r\nAreas available to (%d/%d) from (%d/%d):\r\n",adr->net,adr->node,bbsconfig->net,bbsconfig->node);
while(cur)
{
if(FindNode(cur,adr))
{
stat='*';
}
else
{
if(GoodLevel(adr,cur->areatag))
{
stat=' ';
}
else
{
cur=cur->next;
continue;
}
}
if(strnicmp(bbsconfig->msgname[cur->areanum-1],"NEW_",4))
fprintf(file," %c %-16s - %s\r\n",stat,cur->areatag,bbsconfig->msgname[cur->areanum-1]);
else
fprintf(file," %c %-16s - <New Area>\r\n",stat,cur->areatag);
cur=cur->next;
}
fprintf(file,"\r\nNote: '*' denotes area you are connected to.\r\n");
}
/*- -*\
* ActiveAreas() - Outputs a list of areas that <adr> is connected to *
\*- -*/
void ActiveAreas(FILE *file,struct address *adr)
{
register struct area *cur=first;
int total=0;
char feed;
fprintf(file,"\r\nActive areas on (%d/%d):\r\n",adr->net,adr->node);
while(cur)
{
if(FindNode(cur,adr))
{
if(!cmpnode(cur->firstnode,adr))
feed='*';
else
feed=' ';
fprintf(file," %c %s\r\n",feed,cur->areatag);
total++;
}
cur=cur->next;
}
if(!total)
fprintf(file,"\r\nNone\r\n");
else
fprintf(file,"\r\nTotal: %d\r\n",total);
fprintf(file,"Note: '*' indicates you are the feed for this echo.\r\n");
}
/*- -*\
* MessageOpen() - Opens a private message to <to> on <dest> with the *
* subject <subject>. You must keep track of the name, which is *
\*- placed into the string you point to with <MsgName>. -*/
FILE *MessageOpen(struct address *dest,char *to,char *from,int area,char *subject,char *MsgName)
{
struct msg msgheader={0};
FILE *msgptr;
static char number;
number++;
sprintf(filename,"%s%x%d-Tmp.AFX",bbsconfig->msgpath[area],mytask,number);
strcpy(MsgName,filename);
if(!(msgptr=fopen(filename,"w")))
{
printf("Error opening message.\n");
lprintf("| E Error opening message.\n");
EXit(10);
}
TimeStr(msgheader.datetime);
strcpy(msgheader.fromuser,from);
strcpy(msgheader.touser,to);
strcpy(msgheader.subject,subject);
msgheader.desnode=dest->node;
msgheader.desnet=dest->net;
msgheader.orignode=bbsconfig->node;
msgheader.orignet=bbsconfig->net;
msgheader.private=1;
msgheader.fileupreq=1;
fwrite((char *)&msgheader,sizeof(struct msg)-2,1,msgptr);
return msgptr;
}
/*- -*\
* MessageClose() - closes the message <file> (in <area>) with the *
\*- name <MsgName>. Turns this temp file into a new message. -*/
void MessageClose(FILE *file,int area,char *MsgName)
{
int msgnum;
fprintf(file,"\r\n\r\n--- %s v%s\r\n",prgname,version);
fclose(file);
Own(area);
msgnum=++bbsconfig->himsgno[area];
bbsconfig->lomsgno[area]++;
DisOwn(area);
sprintf(filename,"%s%d.%d",bbsconfig->msgpath[area],msgnum,area+1);
rename(MsgName,filename);
sprintf(filename,"%s%d.%d",bbsconfig->msgpath[area],msgnum-(bbsconfig->msgno[area]+1),area+1);
remove(filename);
}
/*- -*\
* AliasAdd() - Adds an alias to the list of acceptable names *
\*- -*/
void AliasAdd(char *addition)
{
struct alias *new;
if(!(new=calloc(1,sizeof(struct alias))))
NoMem();
strcpy(new->name,addition);
if(!falias)
falias=new;
else
lalias->nextalias=new;
lalias=new;
}
/*- -*\
* PassAdd() - Adds a password to the list of passwords for the system *
\*- pointed to by <add>, and gives this system security <level>. -*/
void PassAdd(struct address *add,char *text,short level)
{
struct pass *new;
if(!(new=calloc(1,sizeof(struct pass))))
NoMem();
strcpy(new->pass,text);
new->level=level;
new->adr=*add;
if(!fpass)
fpass=new;
else
lpass->nextpass=new;
lpass=new;
}
/*- -*\
* PassMatch() - Checks to see if <password> matches the password set *
\*- up for system <where>. -*/
int PassMatch(struct address *where,char *password)
{
register struct pass *cur=fpass;
while(cur)
{
if(!cmpnode(where,&cur->adr))
{
if(!stricmp(cur->pass,password))
return 1;
return 0;
}
cur=cur->nextpass;
}
return 0;
}
/*- -*\
* AliasMatch() - Checks to see if <match> is an acceptable name for *
\*- a message addressed to AreaFix. -*/
int AliasMatch(char *match)
{
register struct alias *cur=falias;
while(cur)
{
if(!stricmp(match,cur->name))
return 1;
cur=cur->nextalias;
}
return 0;
}
/*- -*\
* ProtAdd() - Adds a protection level for the echo <tag> *
\*- -*/
void ProtAdd(char *tag,short level)
{
struct protect *new;
if(!(new=calloc(1,sizeof(struct protect))))
NoMem();
strcpy(new->tag,tag);
new->level=level;
if(!fprot)
fprot=new;
else
lprot->nextprot=new;
lprot=new;
}
/*- -*\
* FindProt - Finds the protection level for the echo area <tag>. *
\*- -*/
int FindProt(char *tag)
{
register struct protect *cur=fprot;
while(cur)
{
if(!stricmp(tag,cur->tag))
return (long)(cur->level);
cur=cur->nextprot;
}
return 0;
}
/*- -*\
* SecLevel() - Returns the security level for the system <where>. *
\*- -*/
int SecLevel(struct address *where)
{
register struct pass *cur=fpass;
while(cur)
{
if(!cmpnode(&cur->adr,where))
return (long)(cur->level);
cur=cur->nextpass;
}
return 0;
}
/*- -*\
* GoodLevel() - Checks to see if <where> has enough security to add *
\*- the echo <tag>. -*/
int GoodLevel(struct address *where,char *tag)
{
short area,node;
node=SecLevel(where);
area=FindProt(tag);
if(node>=area)
return 1;
return 0;
}
/*- -*\
* SyntaxEr() - reports a syntax error in the parsing of a text file. *
\*- -*/
void SyntaxEr(char *err)
{
lprintf("| < Syntax error in AreaFix.CFG: %s\n",err);
printf("Syntax error in AreaFix.CFG:\n\"%s\"\n",err);
printf("Skipping entry.\n");
}
/*- -*\
* lprintf() - prints line out to log file. *
\*- -*/
void lprintf(char *fmt, ...)
{
va_list ap;
char *p,*sval;
int ival;
FILE *log;
sprintf(filename,"%sAreaFix.LOG",bbspath);
if(!(log=fopen(filename,"a")))
{
printf("Error opening logfile!\n");
printf("Aborting!!!\n");
EXit(10);
}
va_start(ap, fmt);
for(p = fmt; *p; p++)
{
if(*p != '%')
{
fputc(*p,log);
continue;
}
switch(*++p)
{
case 'd':
ival=va_arg(ap,int);
fprintf(log,"%d",ival);
break;
case 's':
for(sval=va_arg(ap,char *); *sval; sval++)
fputc(*sval,log);
break;
default:
fputc(*p,log);
break;
}
}
fclose(log);
va_end(ap);
}
/*- -*\
* TimeStr() - places the standard time string for messages into <str> *
\*- -*/
void TimeStr(char *str)
{
unsigned long t;
char work[26];
time(&t);
strcpy(work,ctime(&t));
work[7]=0;
work[10]=0;
work[19]=0;
work[24]=0;
sprintf(str,"%s %s %s %s",&work[8],&work[4],&work[22],&work[11]);
}
/*- -*\
* ReScan() - Forces <Area> to be rescanned. *
\*- -*/
void ReScan(struct area *Area)
{
bbsconfig->himsgsent[Area->areanum-1]=bbsconfig->lomsgno[Area->areanum-1];
}
/*- -*\
* List() - Sends the file AvailAreas.TXT to <dest> in a message. *
\*- -*/
void List(struct address *dest,int area)
{
FILE *listmsg;
FILE *source;
int ret;
char tmpname[256];
if(!(listmsg=MessageOpen(dest,"Sysop",prgname,area,"Available areas list",tmpname)))
{
lprintf("| < No list sent.\n");
return;
}
sprintf(filename,"%sAvailAreas.TXT",bbspath);
if(!(source=fopen(filename,"r")))
{
MessageClose(listmsg,area,tmpname);
lprintf("| < AvailAreas.TXT could not be opened.\n");
return;
}
while((ret=fgetc(source))!=EOF)
{
switch(ret)
{
case '\n':
fputc('\r',listmsg);
default:
fputc(ret,listmsg);
}
}
fclose(source);
MessageClose(listmsg,area,tmpname);
}
/*- -*\
* EXit() - Sets the task name to the old name, and then exits *
\*- -*/
void EXit(int level)
{
mytask->tc_Node.ln_Name = oldname;
exit(level);
}
/*- -*\
* validarea() - checks to see if <number> is an OK echomail base *
\*- -*/
int validarea(int number)
{
if(strlen(bbsconfig->tagname[number-1])<2)
return 0;
if(strlen(bbsconfig->msgname[number-1])<2)
return 0;
if(bbsconfig->msglevel[number-1]>15)
return 0;
return 1;
}
/*- -*\
* NoMem() - When AreaFix can't allocate memory, it notes it in the log *
\*- and exits. -*/
void NoMem(void)
{
printf("Error allocating memory.\n");
lprintf("| E Error allocating memory.\n");
lprintf("*-- Operation aborted.\n");
EXit(10);
}
/*- -*\
* AddFwd() - Adds forward request for sending out later. *
\*- -*/
void AddFwd(char *tag,struct address *from,char *pswd)
{
struct fwdsys *curFS=firstFS;
while(curFS)
{
if(!cmpnode(&curFS->adr,from))
{
AddFwdArea(curFS,tag);
return;
}
curFS=curFS->next;
}
if(curFS=calloc(1,sizeof(struct fwdsys)))
{
if(firstFS)
lastFS->next=curFS;
else
firstFS=curFS;
lastFS=curFS;
lastFS->next=NULL;
curFS->adr=*from;
strcpy(curFS->password,pswd);
AddFwdArea(curFS,tag);
return;
}
NoMem();
}
/*- -*\
* AddFwdArea() - Adds area to list of areas being requested from a *
\*- system. -*/
void AddFwdArea(struct fwdsys *system,char *tag)
{
struct fwdarea *newfwd;
if(newfwd=calloc(1,sizeof(struct fwdarea)))
{
if(system->firstarea)
system->lastarea->next=newfwd;
else
system->firstarea=newfwd;
system->lastarea=newfwd;
system->lastarea->next=NULL;
strcpy(newfwd->tag,tag);
return;
}
NoMem();
}
/*- -*\
* SendFwd() - Sends out all the requests that are to be forwarded. *
\*- -*/
void SendFwd(int area)
{
FILE *file;
char tmpname[256];
struct fwdsys *curFS=firstFS;
struct fwdarea *curFA;
while(curFS)
{
file=MessageOpen(&curFS->adr,"Areafix","(Auto request) Areafix",area,curFS->password,tmpname);
{
curFA=curFS->firstarea;
while(curFA)
{
fprintf(file,"%s\r\n",curFA->tag);
curFA=curFA->next;
}
MessageClose(file,area,tmpname);
}
curFS=curFS->next;
}
}
/*- -*\
* AvailFrom() - finds if area <tag> is available for requesting, and *
\*- if so, from where, and what is the password for that system. -*/
int AvailFrom(struct address *where,char *tag,char *pass)
{
char buffer[256];
char *pswd;
char *node;
char *net;
FILE *file;
sprintf(filename,"%sEchoReq.LST",bbspath);
if(file=fopen(filename,"r"))
{
while(GetLine(file,buffer))
{
if(!strnicmp(buffer,"#SYSTEM",7))
{
net=stpblk(&buffer[7]);
node=strchr(net,'/');
pswd=strchr(node,' ');
pswd++;
if((*net)&&(node))
{
*node=0;
node++;
where->net=atoi(net);
where->node=atoi(node);
}
strcpy(pass,pswd);
continue;
}
if(where->net)
{
if(!stricmp(buffer,tag))
{
fclose(file);
return 1;
}
}
}
}
return 0;
}
/*- -*\
* BuildReqLst() - Reads in the current QUE file, and builds the list *
\*- of requests in memory. -*/
void BuildReqLst(void)
{
char buffer[256];
char *token;
char *endtoken;
char *nodeptr;
FILE *file;
struct request *area;
int net,node;
sprintf(filename,"%sAreaFix.QUE",bbspath);
if(file=fopen(filename,"r"))
{
while(GetLine(file,buffer))
{
endtoken=strchr(buffer,' ');
if(endtoken)
{
*endtoken=0;
token=endtoken;
area=AddQueArea(buffer);
do
{
token++;
token=stpblk(token);
endtoken=strchr(token,' ');
if(endtoken)
*endtoken=0;
nodeptr=strchr(token,'/');
*nodeptr=0;
nodeptr++;
net=atoi(token);
node=atoi(nodeptr);
AddQue(area,net,node);
token=endtoken;
} while(endtoken);
}
}
fclose(file);
}
}
/*- -*\
* AddQue() - Adds a request for the area described by <to> *
\*- -*/
void AddQue(struct request *to, int net, int node)
{
struct address *newadr;
if(newadr=calloc(1,sizeof(struct address)))
{
newadr->net=(short)net;
newadr->node=(short)node;
if(to->firstadr)
to->lastadr->nextnode=newadr;
else
to->firstadr=newadr;
to->lastadr=newadr;
to->lastadr->nextnode=NULL;
return;
}
NoMem();
}
/*- -*\
* AddQueArea() - Adds new que area for <tag>. *
\*- -*/
struct request *AddQueArea(char *tag)
{
struct request *newreq;
if(newreq=calloc(1,sizeof(struct request)))
{
if(firstreq)
lastreq->next=newreq;
else
firstreq=newreq;
lastreq=newreq;
lastreq->next=NULL;
strcpy(newreq->tag,tag);
return newreq;
}
NoMem();
}
/*- -*\
* AddReq() - Handles adding a system to the que, for the echo named *
* <tag>, from the system <source>. Will add address on end if *
\*- previously requested by another, or will create new line. -*/
int AddReq(char *tag, struct address *source, struct address *dest)
{
struct request *curR=firstreq;
struct request *newreq;
while(curR)
{
if(!stricmp(curR->tag,tag))
{
AddQue(curR,dest->net,dest->node);
return 0;
}
curR=curR->next;
}
newreq=AddQueArea(tag);
AddQue(newreq,source->net,source->node);
AddQue(newreq,dest->net,dest->node);
return 1;
}
/*- -*\
* ProcQue() - Processes que, and adds lines to AREAS.CTL if an area *
* that was previously requested is found. (usually because it *
\*- created by MailProc) -*/
void ProcQue(char *change,int search)
{
struct area *cur;
struct request *curR=firstreq;
struct request *prevR=NULL;
int count,cnt;
struct address *curA,*tempA;
FILE *notify;
char tempnme[256];
if(curR)
{
lprintf("| * Processing request que:\n");
while(curR)
{
for(count=0;count<MAXMSGBASE;count++)
{
if(!stricmp(curR->tag,bbsconfig->tagname[count]))
break;
}
if(count!=MAXMSGBASE)
{
*change=TRUE;
if(!(cur=FindAreaT(curR->tag)))
cur=AreaAdd((short)(count+1));
curA=curR->firstadr;
while(curA)
{
if(!FindNode(cur,curA))
{
lprintf("| | Added system (%d/%d) to echo \"%s\"\n",curA->net,curA->node,curR->tag);
NodeAdd(cur,curA);
notify=MessageOpen(curA,"Sysop",prgname,search,"Previously requested areas",tempnme);
fprintf(notify,"The following previously requested area is now available.\r\n");
fprintf(notify,"------------------------------- -------------------------------\r\n");
fprintf(notify,"%s ",curR->tag);
for(cnt=strlen(curR->tag);cnt<=29;cnt++)
fputc('.',notify);
fprintf(notify," Added area.\r\n");
MessageClose(notify,search,tempnme);
}
tempA=curA;
curA=curA->nextnode;
free(tempA);
}
if(prevR)
{
prevR->next=curR->next;
free(curR);
curR=prevR->next;
continue;
}
else
{
firstreq=curR->next;
free(curR);
curR=firstreq;
continue;
}
break;
}
prevR=curR;
curR=curR->next;
}
lprintf("| * Finished processing request que.\n");
}
}
/*- -*\
* SaveQue() - Saves the AreaFix.QUE file, if there are any que entries *
\*- that have not been removed. -*/
void SaveQue(void)
{
struct request *curR=firstreq;
struct address *curA;
FILE *file;
sprintf(filename,"%sAreaFix.QUE",bbspath);
if(firstreq)
{
if(file=fopen(filename,"w"))
{
while(curR)
{
fprintf(file,"%s",curR->tag);
curA=curR->firstadr;
while(curA)
{
fprintf(file," %d/%d",curA->net,curA->node);
curA=curA->nextnode;
}
fprintf(file,"\n");
curR=curR->next;
}
fclose(file);
}
return;
}
remove(filename);
}
/*- -*\
* InputAreas() - Reads the areas.ctl file, and builds the list of echo *
\*- areas & the systems they are connected to. -*/
void InputAreas(char *change,char *in)
{
FILE *fptr;
char buffer[256];
char *temp,*node;
short number;
struct area *cur;
struct address newadr;
if(fptr=fopen(in,"r"))
{
while(GetLine(fptr,buffer))
{
if(!strnicmp(buffer,"AREA",4))
{
temp=stpblk(&buffer[4]);
number=(short)atoi(temp);
if(!validarea(number))
{
cur=NULL;
lprintf("| < Area %d is not a valid EchoMail message base. Skipped.\n",number);
printf("Area %d is not a valid EchoMail message base.\n",number);
*change=TRUE;
continue;
}
cur=AreaAdd(number);
continue;
}
if(!cur)
{
printf("\n");
lprintf("| < No valid area specified for address (%s). Skipped entry.\n",buffer);
printf("No valid area specified for address \"%s\". Skipped.\n",buffer);
*change=TRUE;
continue;
}
node=strchr(buffer,'/');
*node=0;
node++;
newadr.net=atoi(buffer);
newadr.node=atoi(node);
newadr.zone=0;
NodeAdd(cur,&newadr);
}
fclose(fptr);
}
else
{
printf("Error!\n");
lprintf("| E Error opening areas file \"%s\".\n",in);
lprintf("*-- Operation aborted.\n");
EXit(10);
}
}
/*- -*\
* ReadCfg() - Reads the config file, and builds the alias, protection, *
* and password lists - along with setting the search base and *
* protection on forwarding. *
\*- -*/
void ReadCfg(char *cfgname, char *in, char *out, int *forward, int *search)
{
char buffer[256];
char *temp,*level,*net,*node,*passwd;
FILE *fptr;
struct address newadr;
if(fptr=fopen(cfgname,"r"))
{
AliasAdd("Areafix");
while(GetLine(fptr,buffer))
{
if(!strnicmp(buffer,"ALIAS",5))
{
temp=stpblk(&buffer[5]);
if(!strlen(temp))
{
lprintf("| < Missing alias name in AreaFix.CFG: %s\n",buffer);
printf("Missing alias name in AreaFix.CFG:\n\"%s\"\n",buffer);
printf("Skipping entry.\n");
continue;
}
AliasAdd(temp);
continue;
}
if(!strnicmp(buffer,"PROTECT",7))
{
temp=stpblk(&buffer[7]);
if(!strlen(temp))
{
SyntaxEr(buffer);
continue;
}
if(!(level=strchr(temp,' ')))
{
SyntaxEr(buffer);
continue;
}
*level=0;
level++;
level=stpblk(level);
if(!strlen(level))
{
SyntaxEr(buffer);
continue;
}
ProtAdd(temp,(short)atoi(level));
}
if(!strnicmp(buffer,"PASS",4))
{
net=stpblk(&buffer[4]);
if(!(node=strchr(net,'/')))
{
SyntaxEr(buffer);
continue;
}
*node=0;
node++;
if(!(passwd=strchr(node,' ')))
{
SyntaxEr(buffer);
continue;
}
*passwd=0;
passwd++;
if(!(level=strchr(passwd,' ')))
{
SyntaxEr(buffer);
continue;
}
*level=0;
level++;
newadr.net=atoi(net);
newadr.node=atoi(node);
newadr.zone=0;
PassAdd(&newadr,passwd,(short)atoi(level));
continue;
}
if(!strnicmp(buffer,"INPUT",5))
{
temp=stpblk(&buffer[5]);
strcpy(in,temp);
continue;
}
if(!strnicmp(buffer,"OUTPUT",6))
{
temp=stpblk(&buffer[6]);
strcpy(out,temp);
continue;
}
if(!strnicmp(buffer,"FORWARD",7))
{
temp=stpblk(&buffer[7]);
*forward=atoi(temp);
continue;
}
if(!strnicmp(buffer,"SEARCH",6))
{
temp=stpblk(&buffer[6]);
*search=atoi(temp)-1;
if((*search<0)||(*search>=MAXMSGBASE))
{
lprintf("| E Search base is out of range.\n");
lprintf("*-- Operation aborted.\n");
printf("Search base is out of range.\n");
EXit(10);
}
if(bbsconfig->msglevel[*search]>16)
{
lprintf("| E Search base access level out of range.\n");
lprintf("*-- Operation aborted.\n");
printf("Search base access level is out of range.\n");
EXit(10);
}
if(bbsconfig->basetype[*search]!=2)
{
lprintf("| E Search base is not of type NetMail.\n");
lprintf("*-- Operation aborted.\n");
printf("Search base is not of type NetMail.\n");
EXit(10);
}
if(stricmp(bbsconfig->tagname[*search],"MATRIX"))
{
lprintf("| E Search base has incorrect tag name.\n");
lprintf("*-- Operation aborted.\n");
printf("Search base has incorrect tag name.\n");
EXit(10);
}
continue;
}
}
if(!(*search))
{
lprintf("| E Search base not defined.\n");
lprintf("*-- Operation aborted.\n");
printf("Search base not defined.\n");
EXit(10);
}
fclose(fptr);
}
else
{
lprintf("| E Error reading %s\n",cfgname);
lprintf("*-- Operation aborted.\n");
printf("Error reading %s\n",cfgname);
EXit(10);
}
}
/*- -*\
* GetHiMk() - Gets the "High Water Mark" for a certain message base. *
* This is typically the last message AreaFix read from this base, *
* unless the search base area is not the same area as the last *
* time, in which case it returns the lowest message number in *
\*- that base. -*/
short GetHiMk(short search)
{
FILE *fptr;
struct himark hmk;
short highpt;
sprintf(filename,"%sAreaFix.HPT",bbspath);
if(fptr=fopen(filename,"r"))
{
fread((void *)&hmk,sizeof(struct himark),1,fptr);
if(!strncmp(hmk.version,hiptver,strlen(hiptver)))
{
fclose(fptr);
if(hmk.basenumber==search)
{
return hmk.highmsg;
}
else
{
lprintf("| < High-watermark is for area %d - Discarding & scanning from beginning.\n",hmk.basenumber+1);
return bbsconfig->lomsgno[search];
}
}
lprintf("| < Old version HiMark, updating to v%s\n",version);
fseek(fptr,(search*sizeof(short)),0);
fread((void *)&highpt,sizeof(short),1,fptr);
fclose(fptr);
return highpt;
}
else
{
lprintf("| < AreaFix.HPT couldn't be opened. Scanning from beginning.\n");
printf("\nHighpoint file couldn't be opened!\n");
printf("Assuming low message is highpoint of previous scan.\n");
return bbsconfig->lomsgno[search];
}
}
/*- -*\
* SaveHiMk() - Saves the "High Water Mark" for the search base, along *
* with the number of the search base, and the version of the *
\*- mark, just incase I someday decide to store more in there. -*/
void SaveHiMk(short search,short point)
{
struct himark hpt;
FILE *fptr;
sprintf(filename,"%sAreaFix.HPT",bbspath);
if(fptr=fopen(filename,"w"))
{
hpt.basenumber=search;
hpt.highmsg=point;
strcpy(hpt.version,hiptver);
fwrite((char *)&hpt,sizeof(struct himark),1,fptr);
fclose(fptr);
}
else
{
printf("Error saving highpoint info.\n");
lprintf("| < Error saving AreaFix.HPT\n");
}
}
/*----------------------------------------------------------------------*
* The End. This program was fun to write... I had never used lists *
* like I did in this one, and I'd like to once again thank Thomas E. *
* Cotton III for sitting down one day and explaining dynamic QUE's to *
* me... this is an offspring of that hour at work one boring day... *
*----------------------------------------------------------------------*
* If you have any questions about this source, contact me on my BBS *
* The Enterprise BBS (717) 588-7636, or on the Paragon Support BBS, *
* The Inner Circle (508) 393-3875. I'm usually happy to hear from *
* other programmers and to help them out if they need it. On the *
* other hand, if you see something that should definately be fixed, *
* or can suggest something better for some part, I'll gladly hear your *
* suggestions. This source is NOT public domain... but you can use it *
* or any part of it you want in any program you wish, as long as: *
* *
* 1) You give me credit, where it's due. Nothing fancy... *
* 2) You tell me you used it, and (optional) send me a copy of the *
* finished program. *
* *
* I'm just curious as to what it gets used for, and (heheheh) greedy *
* because I want all the latest PD, ShareWare and FreeWare programs *
* that come out... I can't help it! *
*----------------------------------------------------------------------*/