/* Areafix improvement by Max Chernogor 2:464/108 */
/*****************************************************************************
* $Id: query.c,v 1.88.2.10 2005/04/09 12:21:36 d_sergienko Exp $
*/
/* libc */
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
/* compiler.h */
#include <smapi/compiler.h>
#ifdef HAS_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAS_DOS_H
#include <dos.h>
#endif
/* smapi */
#include <smapi/progprot.h>
/* fidoconf */
#include <fidoconf/fidoconf.h>
#include <fidoconf/common.h>
#include <fidoconf/xstr.h>
#include <fidoconf/areatree.h>
#include <fidoconf/afixcmd.h>
/* hpt */
#include <global.h>
#include <toss.h>
#include <areafix.h>
#include <query.h>
static time_t tnow;
const long secInDay = 3600*24;
const char czFreqArea[] = "freq";
const char czIdleArea[] = "idle";
const char czKillArea[] = "kill";
const char czChangFlg[] = "changed.qfl";
extern s_query_areas *queryAreasHead;
extern s_message **msgToSysop;
extern char *versionStr;
int checkRefuse(char *areaName)
{
FILE *fp;
char *line;
if (config->newAreaRefuseFile == NULL)
return 0;
fp = fopen(config->newAreaRefuseFile, "r+b");
if (fp == NULL) {
w_log(LL_ERR, "Can't open newAreaRefuseFile \"%s\" : %s\n",
config->newAreaRefuseFile, strerror(errno));
return 0;
}
while((line = readLine(fp)) != NULL)
{
line = trimLine(line);
if (patimat(areaName, line)) {
fclose(fp);
return 1;
}
}
fclose(fp);
return 0;
}
void del_tok(char **ac, char *tok) {
char *p, *q;
q = fc_stristr(*ac,tok);
if (q) {
p = q+strlen(tok);
while (*p && !isspace(*p)) p++;
if (*p) memmove(q, p+1, strlen(p+1)+1); /* begin or middle */
else {
if (q > *ac) *(q-1)='\0'; /* end */
else *q='\0'; /* "-token" defaults */
}
}
}
char* makeAreaParam(s_link *creatingLink, char* c_area, char* msgbDir)
{
char *msgbFileName=NULL, *acDef;
char *msgbtype, *newAC=NULL, *desc, *quote_areaname;
char *cp, *buff=NULL; /* temp. usage */
msgbFileName = makeMsgbFileName(config, c_area);
/* translating name of the area to lowercase/uppercase */
if (config->createAreasCase == eUpper) strUpper(c_area);
else strLower(c_area);
/* translating filename of the area to lowercase/uppercase */
if (config->areasFileNameCase == eUpper) strUpper(msgbFileName);
else strLower(msgbFileName);
acDef = creatingLink->autoAreaCreateDefaults;
xscatprintf(&newAC, "%s%s", (acDef) ? " " : "", (acDef) ? acDef : "");
msgbtype = fc_stristr(newAC, "-b ");
if(!msgbDir)
msgbDir=(creatingLink->msgBaseDir) ?
creatingLink->msgBaseDir : config->msgBaseDir;
quote_areaname = strchr(TRUE_COMMENT "\"", *c_area) ? "\"" : "";
if (stricmp(msgbDir, "passthrough")!=0 && NULL==fc_stristr(newAC,"passthrough"))
{
/* we have to find a file name */
int need_dos_file;
#ifndef MSDOS
need_dos_file = fc_stristr(newAC, "-dosfile")!=NULL;
#else
need_dos_file = 1;
#endif
if (creatingLink->autoAreaCreateSubdirs && !need_dos_file)
{
/* "subdirify" the message base path if the */
/* user wants this. this currently does not */
/* work with the -dosfile option */
for (cp = msgbFileName; *cp; cp++)
{
if (*cp == '.')
{
*cp = PATH_DELIM;
}
}
}
if (!need_dos_file)
xscatprintf(&buff, "EchoArea %s%s%s %s%s%s",
quote_areaname, c_area, quote_areaname,
msgbDir, msgbFileName,
(msgbtype) ? "" : " -b Squish");
else {
sleep(1); /* to prevent time from creating equal numbers */
xscatprintf(&buff,"EchoArea %s%s%s %s%8lx%s",
quote_areaname, c_area, quote_areaname,
msgbDir, (long)time(NULL),
(msgbtype) ? "" : " -b Squish");
}
} else {
/* passthrough */
xscatprintf(&buff, "EchoArea %s%s%s passthrough",
quote_areaname, c_area, quote_areaname);
del_tok(&newAC, "passthrough");
del_tok(&newAC, "-b "); /* del "-b msgbtype" from autocreate defaults */
del_tok(&newAC, "-$m "); /* del "-$m xxx" from autocreate defaults */
del_tok(&newAC, "-p "); /* del "-p xxx" from autocreate defaults */
del_tok(&newAC, "-killsb");
del_tok(&newAC, "-nokillsb");
del_tok(&newAC, "-tinysb");
del_tok(&newAC, "-notinysb");
del_tok(&newAC, "-pack");
del_tok(&newAC, "-nopack");
del_tok(&newAC, "-link");
del_tok(&newAC, "-nolink");
del_tok(&newAC, "-killread");
del_tok(&newAC, "-nokillread");
del_tok(&newAC, "-keepunread");
del_tok(&newAC, "-nokeepunread");
}
nfree(msgbFileName);
if (creatingLink->LinkGrp) {
if (fc_stristr(newAC, " -g ")==NULL)
xscatprintf(&buff, " -g %s", creatingLink->LinkGrp);
}
if (IsAreaAvailable(c_area,creatingLink->forwardRequestFile,&desc,1)==1) {
if (desc) {
if (fc_stristr(newAC, " -d ")==NULL)
xscatprintf(&buff, " -d \"%s\"", desc);
nfree(desc);
}
}
if (*newAC) xstrcat(&buff, newAC);
nfree(newAC);
return buff;
}
int autoCreate(char *c_area, hs_addr pktOrigAddr, ps_addr forwardAddr)
{
FILE *f;
char *fileName;
char *buff=NULL, *hisaddr=NULL;
char *msgbDir=NULL;
s_link *creatingLink;
s_area *area;
s_query_areas* areaNode=NULL;
size_t i=0;
unsigned int j;
char pass[] = "passthrough";
char CR;
w_log( LL_FUNC, "%s::autoCreate() begin", __FILE__ );
if (strlen(c_area)>60){
w_log( LL_FUNC, "%s::autoCreate() rc=11", __FILE__ );
return 11;
}
if (!isValidConference(c_area) || isPatternLine(c_area)){
w_log( LL_FUNC, "%s::autoCreate() rc=7", __FILE__ );
return 7;
}
if (checkRefuse(c_area))
{
w_log(LL_WARN, "Can't create area %s : refused by NewAreaRefuseFile\n", c_area);
return 13;
}
creatingLink = getLinkFromAddr(config, pktOrigAddr);
if (creatingLink == NULL) {
w_log(LL_ERR, "creatingLink == NULL !!!");
w_log( LL_FUNC, "%s::autoCreate() rc=8", __FILE__ );
return 8;
}
fileName = creatingLink->autoAreaCreateFile;
if (fileName == NULL) fileName = cfgFile ? cfgFile : getConfigFileName();
f = fopen(fileName, "a+b");
if (f == NULL) {
fprintf(stderr,"autocreate: cannot open config file\n");
w_log( LL_FUNC, "%s::autoCreate() rc=9", __FILE__ );
return 9;
}
/* setting up msgbase dir */
if (config->createFwdNonPass == 0 && forwardAddr)
msgbDir = pass;
else
msgbDir = creatingLink->msgBaseDir;
if(config->areafixQueueFile)
{
areaNode = af_CheckAreaInQuery(c_area, &pktOrigAddr, NULL, FIND);
if( areaNode ) /* if area in query */
{
if( stricmp(areaNode->type,czKillArea) == 0 ){
w_log( LL_FUNC, "%s::autoCreate() rc=4", __FILE__ );
return 12; /* area already unsubscribed */
}
if( stricmp(areaNode->type,czFreqArea) == 0 &&
addrComp(pktOrigAddr, areaNode->downlinks[0])!=0)
{
w_log( LL_FUNC, "%s::autoCreate() rc=4", __FILE__ );
return 4; /* wrong link to autocreate from */
}
if( stricmp(areaNode->type,czFreqArea) == 0 )
{
/* removinq area from query. it is autocreated now */
queryAreasHead->nFlag = 1; /* query was changed */
areaNode->type[0] = '\0'; /* mark as deleted */
}
if (config->createFwdNonPass == 0)
msgbDir = pass;
/* try to find our aka in links of queried area */
/* if not foun area will be passthrough */
for (i = 1; i < areaNode->linksCount; i++)
for(j = 0; j < config->addrCount; j++)
if (addrComp(areaNode->downlinks[i],config->addr[j])==0)
{
msgbDir = creatingLink->msgBaseDir; break;
}
}
}
/* making address of uplink */
xstrcat(&hisaddr, aka2str(pktOrigAddr));
buff = makeAreaParam(creatingLink , c_area, msgbDir);
/* add new created echo to config in memory */
parseLine(buff, config);
RebuildEchoAreaTree(config);
/* subscribe uplink if he is not subscribed */
area = &(config->echoAreas[config->echoAreaCount-1]);
if ( !isLinkOfArea(creatingLink,area) ) {
xscatprintf(&buff, " %s", hisaddr);
Addlink(creatingLink, area, NULL);
}
/* subscribe downlinks if present */
if(areaNode) { /* areaNode == NULL if areafixQueueFile isn't used */
/* prevent subscribing of defuault links */
/* or not existing links */
for(i = 1; i < areaNode->linksCount; i++) {
if( ( isAreaLink( areaNode->downlinks[i],area ) == -1 ) &&
( getLinkFromAddr(config,areaNode->downlinks[i])) &&
( !isOurAka(config,areaNode->downlinks[i]) )
) {
xstrcat( &buff, " " );
xstrcat( &buff, aka2str(areaNode->downlinks[i]) );
Addlink(getLinkFromAddr(config,areaNode->downlinks[i]), area, NULL);
}
}
}
/* fix if dummys del \n from the end of file */
if( fseek (f, -2L, SEEK_END) == 0)
{
CR = getc (f); /* may be it is CR aka '\r' */
if (getc(f) != '\n') {
fseek (f, 0L, SEEK_END); /* not neccesary, but looks better ;) */
fputs (cfgEol(), f);
} else {
fseek (f, 0L, SEEK_END);
}
i = ftell(f); /* config length */
/* correct EOL in memory */
if(CR == '\r')
xstrcat(&buff,"\r\n"); /* DOS EOL */
else
xstrcat(&buff,"\n"); /* UNIX EOL */
}
else
{
xstrcat(&buff,cfgEol()); /* config depended EOL */
}
/* add line to config */
if ( fprintf(f, "%s", buff) != (int)(strlen(buff)) || fflush(f) != 0)
{
w_log(LL_ERR, "Error creating area %s, config write failed: %s!",
c_area, strerror(errno));
fseek(f, i, SEEK_SET);
setfsize(fileno(f), i);
}
fclose(f);
nfree(buff);
/* echoarea addresses changed by safe_reallocating of config->echoAreas[] */
carbonNames2Addr(config);
w_log(LL_AUTOCREATE, "Area %s autocreated by %s", c_area, hisaddr);
if (forwardAddr == NULL) makeMsgToSysop(c_area, pktOrigAddr, NULL);
else makeMsgToSysop(c_area, *forwardAddr, &pktOrigAddr);
nfree(hisaddr);
/* create flag */
if (config->aacFlag) {
if (NULL == (f = fopen(config->aacFlag,"a")))
w_log(LL_ERR, "Could not open autoAreaCreate flag: %s", config->aacFlag);
else {
w_log(LL_FLAG, "Created autoAreaCreate flag: %s", config->aacFlag);
fclose(f);
}
}
w_log( LL_FUNC, "%s::autoCreate() end", __FILE__ );
return 0;
}
s_query_areas* af_AddAreaListNode(char *areatag, const char *type);
void af_DelAreaListNode(s_query_areas* node);
void af_AddLink(s_query_areas* node, ps_addr link);
s_query_areas* af_CheckAreaInQuery(char *areatag, ps_addr uplink, ps_addr dwlink, e_query_action act)
{
size_t i = 0;
int bFind = 0;
s_query_areas *areaNode = NULL;
s_query_areas *tmpNode = NULL;
if( !queryAreasHead ) af_OpenQuery();
tmpNode = queryAreasHead;
while(tmpNode->next && !bFind)
{
if( tmpNode->next->name && !stricmp(areatag, tmpNode->next->name) )
bFind = 1;
tmpNode = tmpNode->next;
}
switch( act )
{
case FIND:
if( !bFind || tmpNode == queryAreasHead )
tmpNode = NULL;
break;
case ADDFREQ:
if( bFind ) {
if( stricmp(tmpNode->type,czFreqArea) == 0 )
{
i = 1;
while( i < tmpNode->linksCount && addrComp(*dwlink, tmpNode->downlinks[i])!=0)
i++;
if(i == tmpNode->linksCount) {
af_AddLink( tmpNode, dwlink ); /* add link to queried area */
tmpNode->eTime = tnow + config->forwardRequestTimeout*secInDay;
} else {
tmpNode = NULL; /* link already in query */
}
} else {
strcpy(tmpNode->type,czFreqArea); /* change state to @freq" */
af_AddLink( tmpNode, dwlink );
tmpNode->eTime = tnow + config->forwardRequestTimeout*secInDay;
}
} else { /* area not found, so add it */
areaNode = af_AddAreaListNode( areatag, czFreqArea );
if(strlen( areatag ) > queryAreasHead->linksCount) /* max areanane lenght */
queryAreasHead->linksCount = strlen( areatag );
af_AddLink( areaNode, uplink );
af_AddLink( areaNode, dwlink );
areaNode->eTime = tnow + config->forwardRequestTimeout*secInDay;
tmpNode =areaNode;
}
break;
case ADDIDLE:
if( bFind ) {
} else {
areaNode = af_AddAreaListNode( areatag, czIdleArea );
if(strlen( areatag ) > queryAreasHead->linksCount)
queryAreasHead->linksCount = strlen( areatag );
af_AddLink( areaNode, uplink );
areaNode->eTime = tnow + config->idlePassthruTimeout*secInDay;
w_log(LL_AREAFIX, "areafix: make request idle for area: %s", areaNode->name);
tmpNode =areaNode;
}
break;
case DELIDLE:
if( bFind && stricmp(tmpNode->type,czIdleArea) == 0 )
{
queryAreasHead->nFlag = 1;
tmpNode->type[0] = '\0';
w_log( LL_AREAFIX, "areafix: idle request for %s removed from queue file",tmpNode->name);
}
break;
}
return tmpNode;
}
char* af_Req2Idle(char *areatag, char* report, hs_addr linkAddr)
{
size_t i;
s_query_areas *tmpNode = NULL;
s_query_areas *areaNode = NULL;
if( !queryAreasHead ) af_OpenQuery();
tmpNode = queryAreasHead;
while(tmpNode->next)
{
areaNode = tmpNode->next;
if( ( areaNode->name ) &&
( stricmp(areaNode->type,czFreqArea) == 0 ) &&
( patimat(areaNode->name,areatag)==1) )
{
i = 1;
while( i < areaNode->linksCount)
{
if( addrComp(areaNode->downlinks[i],linkAddr) == 0)
break;
i++;
}
if( i < areaNode->linksCount )
{
if( i != areaNode->linksCount-1 )
memmove(&(areaNode->downlinks[i]),&(areaNode->downlinks[i+1]),
sizeof(hs_addr)*(areaNode->linksCount-i));
areaNode->linksCount--;
queryAreasHead->nFlag = 1; /* query was changed */
if(areaNode->linksCount == 1)
{
strcpy(areaNode->type,czIdleArea);
areaNode->bTime = tnow;
areaNode->eTime = tnow + config->idlePassthruTimeout*secInDay;
w_log(LL_AREAFIX, "areafix: make request idle for area: %s", areaNode->name);
}
xscatprintf(&report, " %s %s request cancelled\r",
areaNode->name,
print_ch(49-strlen(areaNode->name), '.'));
w_log(LL_AREAFIX, "areafix: request cancelled for [%s] area: %s",aka2str(linkAddr),
areaNode->name);
}
}
tmpNode = tmpNode->next;
}
return report;
}
char* af_GetQFlagName()
{
char *chanagedflag = NULL;
char *logdir = NULL;
#ifdef DEBUG_HPT
w_log(LL_FUNC, "af_GetQFlagName(): begin");
#endif
if (config->lockfile)
{
logdir = dirname(config->lockfile); /* slash-trailed */
xstrscat(&chanagedflag,logdir,(char*)czChangFlg,NULL);
nfree(logdir);
}
else if (config->echotosslog)
{
logdir = dirname(config->echotosslog); /* slash-trailed */
xstrscat(&chanagedflag,logdir,(char*)czChangFlg,NULL);
nfree(logdir);
}
else if (config->semaDir)
{
logdir = dirname(config->echotosslog); /* slash-trailed */
xstrscat(&chanagedflag,logdir,(char*)czChangFlg,NULL);
nfree(logdir);
}
else
{
chanagedflag = safe_strdup(czChangFlg);
}
w_log(LL_FUNC, "af_GetQFlagName(): end");
return chanagedflag;
}
void af_QueueReport()
{
s_query_areas *tmpNode = NULL;
const char rmask[]="%-37.37s %-4.4s %11.11s %-16.16s %-7.7s\r";
char type[5]="\0\0\0\0";
char state[8]= "\0\0\0\0\0\0\0";
char link1[17]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char link2[17]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char* report = NULL;
char* header = NULL;
int netmail=0;
char *reportFlg = NULL;
w_log(LL_FUNC, "af_QueueReport(): begin");
if( !config->areafixQueueFile ){
w_log(LL_WARN, "areafixQueueFile not defined in config");
w_log(LL_FUNC, "af_QueueReport(): end");
return;
}
w_log(LL_DEBUGU, __FILE__ ":%u:af_QueueReport()", __LINE__);
reportFlg = af_GetQFlagName();
w_log(LL_DEBUGU, __FILE__ ":%u:af_QueueReport()", __LINE__);
if(!fexist(reportFlg))
{
w_log(LL_STOP, "Queue file hasn't been changed. Exiting...");
nfree(reportFlg);
return;
}
w_log(LL_DEBUGU, __FILE__":%u:af_QueueReport()", __LINE__);
if( !queryAreasHead ) af_OpenQuery();
tmpNode = queryAreasHead;
w_log(LL_DEBUGU, __FILE__":%u:af_QueueReport() tmpNode=%X", __LINE__, tmpNode);
while(tmpNode->next)
{
w_log(LL_DEBUGU, __FILE__":%u:af_QueueReport() tmpNode=%X", __LINE__, tmpNode);
tmpNode = tmpNode->next;
strcpy(link1,aka2str(tmpNode->downlinks[0]));
strcpy(type,tmpNode->type);
if( stricmp(tmpNode->type,czFreqArea) == 0 )
{
strcpy(link2,aka2str(tmpNode->downlinks[1]));
if( strcmp(tmpNode->type,czFreqArea) == 0 )
{
queryAreasHead->nFlag = 1;
strUpper(tmpNode->type);
xscatprintf(&report,rmask, tmpNode->name, tmpNode->type,
link1,link2,
"request");
continue;
}
if(tmpNode->eTime < tnow )
{
strcpy(state,"rr_or_d");
}
else
{
int days = (tnow - tmpNode->bTime)/secInDay;
sprintf(state,"%2d days",days);
}
xscatprintf(&report,rmask, tmpNode->name, type,
link1,link2,
state);
}
if( stricmp(tmpNode->type,czKillArea) == 0 )
{
if( strcmp(tmpNode->type,czKillArea) == 0 )
{
queryAreasHead->nFlag = 1;
strUpper(tmpNode->type);
xscatprintf(&report,rmask, tmpNode->name, tmpNode->type,
link1,"",
"timeout");
continue;
}
if(tmpNode->eTime < tnow )
{
strcpy(state,"to_kill");
}
else
{
int days = (tnow - tmpNode->bTime)/secInDay;
sprintf(state,"%2d days",days);
}
xscatprintf(&report,rmask, tmpNode->name, type,
link1,"",
state);
}
if( stricmp(tmpNode->type,czIdleArea) == 0 )
{
if( strcmp(tmpNode->type,czIdleArea) == 0 )
{
queryAreasHead->nFlag = 1;
strUpper(tmpNode->type);
xscatprintf(&report,rmask, tmpNode->name, tmpNode->type,
link1,"",
"timeout");
continue;
}
if(tmpNode->eTime < tnow )
{
strcpy(state,"to_kill");
}
else
{
int days = (tnow - tmpNode->bTime)/secInDay;
sprintf(state,"%2d days",days);
}
xscatprintf(&report,rmask, tmpNode->name, type,
link1,"",
state);
}
}
if(!report) {
remove(reportFlg);
nfree(reportFlg);
return;
}
w_log(LL_START, "Start generating queue report");
xscatprintf(&header,rmask,"Area","Act","From","By","Details");
xscatprintf(&header,"%s\r", print_ch(79,'-'));
xstrcat(&header, report);
report = header;
if (config->ReportTo) {
if (stricmp(config->ReportTo,"netmail")==0) netmail=1;
else if (getNetMailArea(config, config->ReportTo) != NULL) netmail=1;
} else netmail=1;
msgToSysop[0] = makeMessage(&(config->addr[0]),&(config->addr[0]),
config->areafixFromName ? config->areafixFromName : versionStr,
netmail ? (config->sysop ? config->sysop : "sysop"): "All", "Requests report",
netmail,
config->areafixReportsAttr);
msgToSysop[0]->text = createKludges(config,
netmail ? NULL : config->ReportTo,
&(config->addr[0]), &(config->addr[0]),
versionStr);
msgToSysop[0]->recode |= (REC_HDR|REC_TXT);
if (config->areafixReportsFlags)
xstrscat( &(msgToSysop[0]->text), "\001FLAGS ", config->areafixReportsFlags, "\r", NULL);
xstrcat( &(msgToSysop[0]->text), report );
w_log(LL_STOP, "End generating queue report");
writeMsgToSysop();
freeMsgBuffers(msgToSysop[0]);
nfree(msgToSysop[0]);
remove(reportFlg);
nfree(reportFlg);
w_log(LL_FUNC, "af_QueueReport(): end");
}
void af_QueueUpdate()
{
s_query_areas *tmpNode = NULL;
s_link *lastRlink;
s_link *dwlink;
w_log(LL_START, "Start updating queue file");
if( !queryAreasHead ) af_OpenQuery();
tmpNode = queryAreasHead;
while(tmpNode->next)
{
tmpNode = tmpNode->next;
if( tmpNode->eTime > tnow )
continue;
if( stricmp(tmpNode->type,czFreqArea) == 0 )
{
lastRlink = getLinkFromAddr(config,tmpNode->downlinks[0]);
dwlink = getLinkFromAddr(config,tmpNode->downlinks[1]);
forwardRequestToLink(tmpNode->name, lastRlink, NULL, 1);
w_log( LL_AREAFIX, "areafix: request for %s is cancelled for node %s",
tmpNode->name, aka2str(lastRlink->hisAka));
if(dwlink && !forwardRequest(tmpNode->name, dwlink, &lastRlink))
{
tmpNode->downlinks[0] = lastRlink->hisAka;
tmpNode->bTime = tnow;
tmpNode->eTime = tnow + config->forwardRequestTimeout*secInDay;
w_log( LL_AREAFIX, "areafix: request for %s is going to node %s",
tmpNode->name, aka2str(lastRlink->hisAka));
}
else
{
strcpy(tmpNode->type, czKillArea);
tmpNode->bTime = tnow;
tmpNode->eTime = tnow + config->killedRequestTimeout*secInDay;
tmpNode->linksCount = 1;
w_log( LL_AREAFIX, "areafix: request for %s is going to be killed",tmpNode->name);
}
queryAreasHead->nFlag = 1; /* query was changed */
continue;
}
if( stricmp(tmpNode->type,czKillArea) == 0 )
{
queryAreasHead->nFlag = 1;
tmpNode->type[0] = '\0';
w_log( LL_AREAFIX, "areafix: request for %s removed from queue file",tmpNode->name);
continue;
}
if( stricmp(tmpNode->type,czIdleArea) == 0 )
{
ps_area delarea;
queryAreasHead->nFlag = 1; /* query was changed */
strcpy(tmpNode->type, czKillArea);
tmpNode->bTime = tnow;
tmpNode->eTime = tnow + config->killedRequestTimeout*secInDay;
tmpNode->linksCount = 1;
w_log( LL_AREAFIX, "areafix: request for %s is going to be killed",tmpNode->name);
delarea = getArea(config, tmpNode->name);
if (delarea != &(config->badArea))
{
do_delete(NULL, delarea);
} else {
/* send unsubscribe message to uplink when moving from idle to kill */
lastRlink = getLinkFromAddr(config,tmpNode->downlinks[0]);
if (lastRlink) forwardRequestToLink(tmpNode->name, lastRlink, NULL, 1);
}
}
}
/* send msg to the links (forward requests to areafix) */
sendAreafixMessages();
w_log(LL_STOP, "End updating queue file");
}
int af_OpenQuery()
{
FILE *queryFile;
char *line = NULL;
char *token = NULL;
struct tm tr;
char seps[] = " \t\n";
if( queryAreasHead ) /* list already exists */
return 0;
time( &tnow );
queryAreasHead = af_AddAreaListNode("\0","\0");
if( !config->areafixQueueFile ) /* Queue File not defined in config */
{
w_log(LL_ERR, "areafixQueueFile not defined in config");
return 0;
}
if ( !(queryFile = fopen(config->areafixQueueFile,"r")) ) /* can't open query file */
{
w_log(LL_ERR, "Can't open areafixQueueFile %s: %s", config->areafixQueueFile, strerror(errno) );
return 0;
}
while ((line = readLine(queryFile)) != NULL)
{
s_query_areas *areaNode = NULL;
token = strtok( line, seps );
if( token != NULL )
{
areaNode = af_AddAreaListNode(token, "");
if(strlen( areaNode->name ) > queryAreasHead->linksCount)
queryAreasHead->linksCount = strlen( areaNode->name );
token = strtok( NULL, seps );
strncpy( areaNode->type ,token, 4);
token = strtok( NULL, seps );
memset(&tr, '\0', sizeof(tr));
if(sscanf(token, "%d-%d-%d@%d:%d",
&tr.tm_year,
&tr.tm_mon,
&tr.tm_mday,
&tr.tm_hour,
&tr.tm_min
) != 5)
{
af_DelAreaListNode(areaNode);
continue;
} else {
tr.tm_year -= 1900;
tr.tm_mon--;
tr.tm_isdst =- 1;
areaNode->bTime = mktime(&tr);
}
token = strtok( NULL, seps );
memset(&tr, '\0', sizeof(tr));
if(sscanf(token, "%d-%d-%d@%d:%d",
&tr.tm_year,
&tr.tm_mon,
&tr.tm_mday,
&tr.tm_hour,
&tr.tm_min
) != 5)
{
af_DelAreaListNode(areaNode);
continue;
} else {
tr.tm_year -= 1900;
tr.tm_mon--;
tr.tm_isdst =- 1;
areaNode->eTime = mktime(&tr);
}
token = strtok( NULL, seps );
while( token != NULL )
{
areaNode->linksCount++;
areaNode->downlinks =
safe_realloc( areaNode->downlinks,
sizeof(hs_addr)*areaNode->linksCount );
string2addr(token ,
&(areaNode->downlinks[areaNode->linksCount-1]));
token = strtok( NULL, seps );
}
}
nfree(line);
}
fclose(queryFile);
return 0;
}
int af_CloseQuery()
{
char buf[2*1024] = "";
char *p;
int nSpace = 0;
size_t i = 0;
struct tm t1,t2;
int writeChanges = 0;
FILE *queryFile=NULL;
s_query_areas *delNode = NULL;
s_query_areas *tmpNode = NULL;
char *chanagedflag = NULL;
FILE *QFlag = NULL;
w_log(LL_FUNC, __FILE__ ":%u:af_CloseQuery() begin", __LINE__);
if( !queryAreasHead ) { /* list does not exist */
w_log(LL_FUNC, __FILE__ ":%u:af_CloseQuery() end", __LINE__);
return 0;
}
if(queryAreasHead->nFlag == 1) {
writeChanges = 1;
}
if (writeChanges)
{
if ((queryFile = fopen(config->areafixQueueFile,"w")) == NULL)
{
w_log(LL_ERR,"areafix: areafixQueueFile not saved");
writeChanges = 0;
}
else
{
if( (chanagedflag = af_GetQFlagName()) )
{
if( (QFlag = fopen(chanagedflag,"w")) )
fclose(QFlag);
nfree(chanagedflag);
}
}
}
tmpNode = queryAreasHead->next;
nSpace = queryAreasHead->linksCount+1;
p = buf+nSpace;
while(tmpNode) {
if(writeChanges && tmpNode->type[0] != '\0') {
memset(buf, ' ' ,nSpace);
memcpy(buf, tmpNode->name, strlen(tmpNode->name));
t1 = *localtime( &tmpNode->bTime );
t2 = *localtime( &tmpNode->eTime );
sprintf( p , "%s %d-%02d-%02d@%02d:%02d\t%d-%02d-%02d@%02d:%02d" ,
tmpNode->type,
t1.tm_year + 1900,
t1.tm_mon + 1,
t1.tm_mday,
t1.tm_hour,
t1.tm_min,
t2.tm_year + 1900,
t2.tm_mon + 1,
t2.tm_mday,
t2.tm_hour,
t2.tm_min );
p = p + strlen(p);
for(i = 0; i < tmpNode->linksCount; i++) {
strcat(p," ");
strcat(p,aka2str(tmpNode->downlinks[i]));
}
strcat(buf, "\n");
fputs( buf , queryFile );
p = buf+nSpace;
}
delNode = tmpNode;
tmpNode = tmpNode->next;
af_DelAreaListNode(delNode);
}
nfree(queryAreasHead->name);
nfree(queryAreasHead->downlinks);
nfree(queryAreasHead->report);
nfree(queryAreasHead);
if(queryFile) fclose(queryFile);
w_log(LL_FUNC, __FILE__ ":%u:af_CloseQuery() end", __LINE__);
return 0;
}
s_query_areas* af_MakeAreaListNode()
{
s_query_areas *areaNode =NULL;
areaNode = (s_query_areas*)safe_malloc( sizeof(s_query_areas) );
memset( areaNode ,'\0', sizeof(s_query_areas) );
return areaNode;
}
s_query_areas* af_AddAreaListNode(char *areatag, const char *type)
{
s_query_areas *tmpNode = NULL;
s_query_areas *tmpPrevNode = NULL;
s_query_areas *newNode = af_MakeAreaListNode();
newNode->name = sstrlen(areatag) > 0 ? safe_strdup(areatag) : NULL;
strcpy( newNode->type ,type);
tmpPrevNode = tmpNode = queryAreasHead;
while(tmpNode)
{
if( tmpNode->name && strlen(tmpNode->name) > 0 )
if( stricmp(areatag,tmpNode->name) < 0 )
break;
tmpPrevNode = tmpNode;
tmpNode = tmpNode->next;
}
if(tmpPrevNode)
{
tmpPrevNode->next = newNode;
newNode->next = tmpNode;
}
return newNode;
}
void af_DelAreaListNode(s_query_areas* node)
{
s_query_areas* tmpNode = queryAreasHead;
while(tmpNode->next && tmpNode->next != node)
{
tmpNode = tmpNode->next;
}
if(tmpNode->next)
{
tmpNode->next = node->next;
nfree(node->name);
nfree(node->downlinks);
nfree(node->report);
nfree(node);
}
}
void af_AddLink(s_query_areas* node, ps_addr link)
{
node->linksCount++;
node->downlinks =
safe_realloc( node->downlinks, sizeof(hs_addr)*node->linksCount );
memcpy( &(node->downlinks[node->linksCount-1]) ,link, sizeof(hs_addr) );
node->bTime = tnow;
queryAreasHead->nFlag = 1; /* query was changed */
}
syntax highlighted by Code2HTML, v. 0.9.1