/*****************************************************************************
* HPT --- FTN NetMail/EchoMail Tosser
*****************************************************************************
* Copyright (C) 1997-1999
*
* Matthias Tichy
*
* Fido: 2:2433/1245 2:2433/1247 2:2432/605.14
* Internet: mtt@tichy.de
*
* Grimmestr. 12 Buchholzer Weg 4
* 33098 Paderborn 40472 Duesseldorf
* Germany Germany
*
* Copyright (c) 1999-2001
* Max Levenkov, sackett@mail.ru
*
* This file is part of HPT.
*
* HPT 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, or (at your option) any
* later version.
*
* HPT is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HPT; see the file COPYING. If not, write to the Free
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************
* $Id: scan.c,v 1.166.2.4 2003/05/11 00:29:25 d_sergienko Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#if defined (UNIX)
#include <unistd.h>
#endif
#if defined (__WATCOMC__) || defined(__TURBOC__) || defined(__DJGPP__) || defined (__EMX__) || (defined (_MSC_VER) && (_MSC_VER >= 1200))
#include <process.h>
#include <io.h>
#endif
#include <fidoconf/fidoconf.h>
#include <fidoconf/common.h>
#include <fidoconf/xstr.h>
#include <fidoconf/afixcmd.h>
#include <fcommon.h>
#include <pkt.h>
#include <scan.h>
#include <fidoconf/log.h>
#include <global.h>
#include <version.h>
#include <fidoconf/recode.h>
#include <toss.h>
#include <smapi/msgapi.h>
#include <smapi/progprot.h>
#include <smapi/patmat.h>
#ifdef DO_PERL
#include <hptperl.h>
#endif
s_statScan statScan;
void cvtAddr(const NETADDR aka1, s_addr *aka2)
{
aka2->zone = aka1.zone;
aka2->net = aka1.net;
aka2->node = aka1.node;
aka2->point = aka1.point;
}
void convertMsgHeader(XMSG xmsg, s_message *msg)
{
// convert header
msg->attributes = xmsg.attr;
msg->origAddr.zone = xmsg.orig.zone;
msg->origAddr.net = xmsg.orig.net;
msg->origAddr.node = xmsg.orig.node;
msg->origAddr.point = xmsg.orig.point;
msg->destAddr.zone = xmsg.dest.zone;
msg->destAddr.net = xmsg.dest.net;
msg->destAddr.node = xmsg.dest.node;
msg->destAddr.point = xmsg.dest.point;
strcpy((char *)msg->datetime, (char *) xmsg.__ftsc_date);
xstrcat(&(msg->subjectLine), (char *) xmsg.subj);
xstrcat(&(msg->toUserName), (char *) xmsg.to);
xstrcat(&(msg->fromUserName), (char *) xmsg.from);
// recoding subjectLine to TransportCharset
if (config->outtab != NULL) {
recodeToTransportCharset((CHAR*)msg->subjectLine);
recodeToTransportCharset((CHAR*)msg->fromUserName);
recodeToTransportCharset((CHAR*)msg->toUserName);
}
// set netmail flag
msg->netMail = 1;
}
void convertMsgText(HMSG SQmsg, s_message *msg)
{
UCHAR *ctrlBuff;
UINT32 ctrlLen;
// get kludge lines
ctrlLen = MsgGetCtrlLen(SQmsg);
ctrlBuff = (unsigned char *) safe_malloc(ctrlLen+1);
MsgReadMsg(SQmsg, NULL, 0, 0, NULL, ctrlLen, ctrlBuff);
/* MsgReadMsg does not do zero termination! */
ctrlBuff[ctrlLen] = '\0';
msg->text = (char *) CvtCtrlToKludge(ctrlBuff);
nfree(ctrlBuff);
// make text
msg->textLength = MsgGetTextLen(SQmsg); // including zero termination???
ctrlLen = strlen(msg->text);
xstralloc(&(msg->text), msg->textLength + ctrlLen);
MsgReadMsg(SQmsg, NULL, 0, msg->textLength, (UCHAR *) msg->text+ctrlLen, 0, NULL);
/* MsgReadMsg doesn't do zero termination! */
msg->text[msg->textLength+ctrlLen] = '\0';
msg->textLength += ctrlLen-1;
// recoding text to TransportCharSet
if (config->outtab != NULL) recodeToTransportCharset((CHAR*)msg->text);
}
void addViaToMsg(s_message *msg, s_addr ourAka) {
time_t tm;
struct tm *dt;
char buf[2];
time(&tm);
dt = gmtime(&tm);
/*
* OG: If the last char of the message isn't a \r, so it is a good
* idea to add the \r.
*/
buf[0] = buf[1] = 0;
if (msg->text && msg->text[0])
{
if (msg->text[strlen(msg->text)-1] != '\r')
buf[0] = '\r';
}
if (ourAka.point==0)
xscatprintf(&(msg->text),"%s\001Via %u:%u/%u @%04u%02u%02u.%02u%02u%02u.UTC %s\r",
buf, ourAka.zone, ourAka.net, ourAka.node,
dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday,
dt->tm_hour, dt->tm_min, dt->tm_sec, versionStr);
else
xscatprintf(&(msg->text),"%s\001Via %u:%u/%u.%u @%04u%02u%02u.%02u%02u%02u.UTC %s\r",
buf, ourAka.zone, ourAka.net, ourAka.node, ourAka.point,
dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday,
dt->tm_hour, dt->tm_min, dt->tm_sec, versionStr);
}
void makePktHeader(s_link *link, s_pktHeader *header)
{
if (link != NULL) {
header->origAddr = *(link->ourAka);
header->destAddr = link->hisAka;
}
header->minorProductRev = (UCHAR)VER_MINOR;
header->majorProductRev = (UCHAR)VER_MAJOR;
header->hiProductCode = 0;
header->loProductCode = 0xfe;
memset(header->pktPassword, '\0', sizeof(header->pktPassword)); // no password
if (link != NULL && link->pktPwd != NULL) {
if (strlen(link->pktPwd) > 8)
strncpy(header->pktPassword, link->pktPwd, 8);
else
strcpy(header->pktPassword, link->pktPwd);
}
time(&(header->pktCreated));
header->capabilityWord = 1;
header->prodData = 0;
}
static s_route *findSelfRouteForNetmail(s_message msg)
{
char *addrStr=NULL;
UINT i;
xscatprintf(&addrStr, "%u:%u/%u.%u",
msg.destAddr.zone, msg.destAddr.net,
msg.destAddr.node, msg.destAddr.point);
for (i=0; i < config->routeCount; i++) {
if ((msg.attributes & MSGFILE) == MSGFILE) { // routeFile
if (config->route[i].id == id_routeFile)
if (patmat(addrStr, config->route[i].pattern))
break;
} else {
if (config->route[i].id != id_routeFile) // route & routeMail
if (patmat(addrStr, config->route[i].pattern))
break;
}
}
nfree(addrStr);
return (i==config->routeCount) ? NULL : &(config->route[i]);
}
s_route *findRouteForNetmail(s_message msg)
{
s_route *route;
route = findSelfRouteForNetmail(msg);
#ifdef DO_PERL
{ s_route *sroute;
if ((sroute = perlroute(&msg, route)) != NULL)
return sroute;
}
#endif
return route;
}
s_link *getLinkForRoute(s_route *route, s_message *msg) {
static s_link tempLink;
s_link *getLink = NULL;
if (route==NULL) return NULL;
if (route->target == NULL) {
memset(&tempLink, '\0', sizeof(s_link));
tempLink.hisAka = msg->destAddr;
tempLink.ourAka = &(config->addr[0]);
switch (route->routeVia) {
case route_zero:
break;
case host:
tempLink.hisAka.node = 0;
tempLink.hisAka.point = 0;
break;
case boss:
tempLink.hisAka.point = 0;
break;
case noroute:
break;
case nopack:
break;
case hub:
tempLink.hisAka.node -= (tempLink.hisAka.node % 100);
tempLink.hisAka.point = 0;
break;
case route_extern:
string2addr(route->viaStr, &tempLink.hisAka);
break;
}
getLink = getLinkFromAddr(config, tempLink.hisAka);
if (getLink != NULL) return getLink;
else return &tempLink;
} else return route->target;
}
void processAttachs(s_link *link, s_message *msg, unsigned int attr)
{
FILE *flo = NULL;
char *p = NULL, *running = NULL, *token = NULL, *flags = NULL;
char *newSubjectLine = NULL;
flo = fopen(link->floFile, "a");
running = msg->subjectLine;
token = strseparate(&running, " \t");
while (token != NULL) {
#if defined(UNIX) || defined(__linux__)
if (!fexist(token)) strLower(token);
#endif
if (flo != NULL) {
if (msg->text) flags =
(char *) GetCtrlToken((byte *)msg->text,(byte *)"FLAGS");
if ((flags && strstr(flags, "KFS")) ||
(config->keepTrsFiles==0 && (attr & MSGFWD)==MSGFWD))
fprintf(flo, "^%s\n", token);
else if (flags && strstr(flags, "TFS"))
fprintf(flo, "#%s\n", token);
else
fprintf(flo, "%s\n", token);
nfree(flags);
}
if (newSubjectLine!=NULL) xstrcat(&newSubjectLine, " ");
if (NULL != (p=strrchr(token, PATH_DELIM))) xstrcat(&newSubjectLine, p+1);
else xstrcat(&newSubjectLine, token);
token = strseparate(&running, " \t");
}
if (flo!= NULL) {
fclose(flo);
} else w_log(LL_ERR, "Could not open FloFile");
// replace subjectLine
nfree(msg->subjectLine);
msg->subjectLine = newSubjectLine;
}
void processRequests(s_link *link, s_message *msg)
{
FILE *flo = NULL;
char *running = NULL;
char *token = NULL;
flo = fopen(link->floFile, "ab");
running = msg->subjectLine;
token = strseparate(&running, " \t");
while (token != NULL) {
if (flo != NULL) fprintf(flo, "%s\015\012", token); // #13#10 to create dos LFCR which ends a line
token = strseparate(&running, " \t");
}
if (flo!= NULL) {
fclose(flo);
} else w_log(LL_ERR, "Could not open FloFile");
}
int packMsg(HMSG SQmsg, XMSG *xmsg, s_area *area)
{
FILE *pkt = NULL;
e_flavour prio = normal;
s_message msg;
s_pktHeader header;
s_route *route = NULL;
s_link *link = NULL, *virtualLink = NULL;
char freeVirtualLink = 0;
char *flags=NULL;
int r, arcNetmail;
memset(&msg,'\0',sizeof(s_message));
convertMsgHeader(*xmsg, &msg);
convertMsgText(SQmsg, &msg);
#ifdef DO_PERL
if (perlscanmsg(area->areaName, &msg)) {
xmsg->attr |= MSGSENT;
freeMsgBuffers(&msg);
return 0;
}
#endif
// clear trs, local & k/s flags
msg.attributes &= ~(MSGFWD|MSGLOCAL|MSGKILL);
// prepare virtual link...
virtualLink = getLinkFromAddr(config, msg.destAddr); //maybe the link is in config?
if (virtualLink == NULL) {
virtualLink = safe_malloc(sizeof(s_link)); // if not create new virtualLink link
memset(virtualLink, '\0', sizeof(s_link));
virtualLink->hisAka = msg.destAddr;
virtualLink->ourAka = &(msg.origAddr);
virtualLink->name = (char *) safe_malloc(strlen(msg.toUserName)+1);
strcpy(virtualLink->name, msg.toUserName);
freeVirtualLink = 1; //virtualLink is a temporary link, please free it..
}
// calculate prio
if ((xmsg->attr & MSGCRASH)==MSGCRASH) prio = crash;
if ((xmsg->attr & MSGHOLD)==MSGHOLD) prio = hold;
if ((xmsg->attr & MSGXX2)==MSGXX2 ||
((xmsg->attr & MSGHOLD)==MSGHOLD &&
(xmsg->attr & MSGCRASH)==MSGCRASH)) prio = direct; // XX2 or Crash+Hold
if (msg.text) {
flags = (char *) GetCtrlToken((byte *)msg.text,(byte *)"FLAGS");
if (flags) {
if (strstr(flags,"DIR")!=NULL) prio = direct;
if (strstr(flags,"IMM")!=NULL) prio = immediate; // most priority
nfree(flags);
}
}
if ((xmsg->attr & MSGFILE) == MSGFILE) {
// file attach
// we need route mail
if (prio==normal) {
route = findRouteForNetmail(msg);
link = getLinkForRoute(route, &msg);
if ((route != NULL) && (link != NULL)) {
if (createOutboundFileName(link,route->flavour,
FLOFILE) == 0) {
processAttachs(link, &msg, xmsg->attr);
remove(link->bsyFile);
nfree(link->bsyFile);
// mark Mail as sent
xmsg->attr |= MSGSENT;
MsgWriteMsg(SQmsg, 0, xmsg, NULL, 0, 0, 0, NULL);
nfree(link->floFile);
w_log(LL_FROUTE, "File %s from %u:%u/%u.%u -> %u:%u/%u.%u via %u:%u/%u.%u", msg.subjectLine, msg.origAddr.zone, msg.origAddr.net, msg.origAddr.node, msg.origAddr.point, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point, link->hisAka.zone, link->hisAka.net, link->hisAka.node, link->hisAka.point);
}
}
}
else if (createOutboundFileName(virtualLink, prio, FLOFILE) == 0) {
processAttachs(virtualLink, &msg, xmsg->attr);
remove(virtualLink->bsyFile);
nfree(virtualLink->bsyFile);
// mark Mail as sent
xmsg->attr |= MSGSENT;
MsgWriteMsg(SQmsg, 0, xmsg, NULL, 0, 0, 0, NULL);
nfree(virtualLink->floFile);
w_log(LL_FROUTE, "File %s from %u:%u/%u.%u -> %u:%u/%u.%u", msg.subjectLine, msg.origAddr.zone, msg.origAddr.net, msg.origAddr.node, msg.origAddr.point, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point);
}
} /* endif file attach */
// file requests always direct
if ((xmsg->attr & MSGFRQ) == MSGFRQ) {
// if msg has request flag then put the subjectline into request file.
if (createOutboundFileName(virtualLink, normal, REQUEST) == 0) {
processRequests(virtualLink, &msg);
remove(virtualLink->bsyFile);
nfree(virtualLink->bsyFile);
// mark Mail as sent
xmsg->attr |= MSGSENT;
MsgWriteMsg(SQmsg, 0, xmsg, NULL, 0, 0, 0, NULL);
nfree(virtualLink->floFile);
w_log(LL_FREQ, "Request %s from %u:%u/%u.%u", msg.subjectLine, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point);
}
}
// no route
if (prio!=normal || (xmsg->attr & MSGFRQ)==MSGFRQ) {
// direct, crash, immediate, hold messages
if (virtualLink->arcNetmail &&
prio == virtualLink->echoMailFlavour) {
arcNetmail = 1;
if (virtualLink->pktFile && virtualLink->pktSize)
if (fsize(virtualLink->pktFile) >= (long)(virtualLink->pktSize*1024)) {
nfree(virtualLink->pktFile);
nfree(virtualLink->packFile);
}
if (virtualLink->pktFile == NULL)
r = createTempPktFileName(virtualLink);
else
r = 0;
} else {
arcNetmail = 0;
r = createOutboundFileName(virtualLink, prio, PKT);
}
if (r == 0) {
addViaToMsg(&msg, msg.origAddr);
makePktHeader(virtualLink, &header);
pkt = openPktForAppending(arcNetmail ? virtualLink->pktFile : virtualLink->floFile, &header);
writeMsgToPkt(pkt, msg);
closeCreatedPkt(pkt);
if (prio==crash) w_log(LL_ROUTE, "Crash-Msg packed: %u:%u/%u.%u -> %u:%u/%u.%u", msg.origAddr.zone, msg.origAddr.net, msg.origAddr.node, msg.origAddr.point, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point);
else if (prio==hold) w_log(LL_ROUTE, "Hold-Msg packed: %u:%u/%u.%u -> %u:%u/%u.%u", msg.origAddr.zone, msg.origAddr.net, msg.origAddr.node, msg.origAddr.point, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point);
else if (prio==direct) w_log(LL_ROUTE, "Direct-Msg packed: %u:%u/%u.%u -> %u:%u/%u.%u", msg.origAddr.zone, msg.origAddr.net, msg.origAddr.node, msg.origAddr.point, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point);
else if (prio==immediate) w_log(LL_ROUTE, "Immediate-Msg packed: %u:%u/%u.%u -> %u:%u/%u.%u", msg.origAddr.zone, msg.origAddr.net, msg.origAddr.node, msg.origAddr.point, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point);
else if (prio==normal) w_log(LL_ROUTE, "Normal-Msg packed: %u:%u/%u.%u -> %u:%u/%u.%u", msg.origAddr.zone, msg.origAddr.net, msg.origAddr.node, msg.origAddr.point, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point);
if (!arcNetmail) {
remove(virtualLink->bsyFile);
nfree(virtualLink->bsyFile);
nfree(virtualLink->floFile);
}
// mark Mail as sent
xmsg->attr |= MSGSENT;
MsgWriteMsg(SQmsg, 0, xmsg, NULL, 0, 0, 0, NULL);
}
} else {
// no crash, no hold flag -> route netmail
route = findRouteForNetmail(msg);
link = getLinkForRoute(route, &msg);
if ((route != NULL) && (link != NULL) && (route->routeVia != nopack)) {
prio = route->flavour;
if (link->arcNetmail &&
route->flavour == link->echoMailFlavour) {
arcNetmail = 1;
if (link->pktFile && link->pktSize)
if (fsize(link->pktFile) >= (long)(link->pktSize*1024)) {
nfree(link->pktFile);
nfree(link->packFile);
}
if (link->pktFile == NULL)
r = createTempPktFileName(link);
else
r = 0;
} else {
arcNetmail = 0;
r = createOutboundFileName(link, prio, PKT);
}
if (r == 0) {
addViaToMsg(&msg, *(link->ourAka));
makePktHeader(NULL, &header);
header.destAddr = link->hisAka;
header.origAddr = *(link->ourAka);
if (link->pktPwd != NULL)
strcpy(&(header.pktPassword[0]), link->pktPwd);
pkt = openPktForAppending(arcNetmail ? link->pktFile : link->floFile, &header);
writeMsgToPkt(pkt, msg);
closeCreatedPkt(pkt);
w_log(LL_ROUTE, "Msg from %u:%u/%u.%u -> %u:%u/%u.%u via %u:%u/%u.%u", msg.origAddr.zone, msg.origAddr.net, msg.origAddr.node, msg.origAddr.point, msg.destAddr.zone, msg.destAddr.net, msg.destAddr.node, msg.destAddr.point, link->hisAka.zone, link->hisAka.net, link->hisAka.node, link->hisAka.point);
if (!arcNetmail) {
remove(link->bsyFile);
nfree(link->bsyFile);
nfree(link->floFile);
}
// mark Mail as sent
xmsg->attr |= MSGSENT;
MsgWriteMsg(SQmsg, 0, xmsg, NULL, 0, 0, 0, NULL);
}
} else {
if ((xmsg->attr & MSGFILE) == MSGFILE) w_log(LL_FROUTE, "no routeFile found or no-pack for %s - leave mail untouched", aka2str(msg.destAddr));
else w_log(LL_ROUTE, "no route found or no-pack for %s - leave mail untouched", aka2str(msg.destAddr));
}
}
// process carbon copy
if (config->carbonOut) carbonCopy(&msg, xmsg, area);
freeMsgBuffers(&msg);
if (freeVirtualLink==1) {
nfree(virtualLink->name);
nfree(virtualLink);
}
if ((xmsg->attr & MSGSENT) == MSGSENT) {
return 0;
} else {
return 1;
}
}
void scanNMArea(s_area *area)
{
HAREA netmail;
HMSG msg;
dword highestMsg, i, j;
XMSG xmsg;
s_addr dest, orig;
int for_us, from_us;
FILE *f = NULL;
// do not scan one area twice
if (area->scn) return;
if (config->routeCount == 0) {
w_log(LL_ROUTE, "No routing -> Scanning stop");
// create flag for netmail trackers
if (config->netmailFlag) {
if (NULL == (f = fopen(config->netmailFlag,"a")))
w_log(LL_ERR, "Could not create netmail flag: %s", config->netmailFlag);
else {
w_log(LL_FLAG, "Created netmail flag: %s", config->netmailFlag);
fclose(f);
}
}
return;
}
netmail = MsgOpenArea((unsigned char *) area -> fileName, MSGAREA_NORMAL,
/* config->netMailArea.fperm,
config->netMailArea.uid,
config->netMailArea.gid, */
(word)area -> msgbType);
if (netmail != NULL) {
statScan.areas++;
area->scn++;
w_log(LL_START, "Scanning NetmailArea %s", area -> areaName);
if (area->msgbType == MSGTYPE_SDM) noHighWaters = 1;
i = (noHighWaters) ? 0 : MsgGetHighWater(netmail);
highestMsg = MsgGetNumMsg(netmail);
// scan all Messages and test if they are already sent.
while (i < highestMsg) {
msg = MsgOpenMsg(netmail, MOPEN_RW, ++i);
// msg does not exist
if (msg == NULL) continue;
statScan.msgs++;
MsgReadMsg(msg, &xmsg, 0, 0, NULL, 0, NULL);
cvtAddr(xmsg.dest, &dest);
for_us = 0;
for (j=0; j < config->addrCount; j++)
{
if (addrComp(dest, config->addr[j])==0) {for_us = 1; break;}
}
// if not sent and not for us -> pack it
if (((xmsg.attr & MSGSENT) != MSGSENT) &&
((xmsg.attr & MSGLOCKED) != MSGLOCKED) &&
(for_us==0))
{
if (packMsg(msg, &xmsg, area) == 0) {
statScan.exported++;
area->scn++;
}
}
MsgCloseMsg(msg);
cvtAddr(xmsg.orig, &orig);
from_us = 0;
for (j=0; j < config->addrCount; j++)
if (addrComp(orig, config->addr[j])==0) {from_us = 1; break;}
// non transit messages without k/s flag not killed
if (!(xmsg.attr & MSGKILL) && !(xmsg.attr & MSGFWD)) from_us = 1;
// transit messages from us will be killed
if (from_us && (xmsg.attr & MSGFWD)) from_us = 0;
if ((!config->keepTrsMail) && ((!for_us && !from_us) ||
(xmsg.attr&MSGKILL)) && (xmsg.attr&MSGSENT)) {
MsgKillMsg(netmail, i);
i--;
}
} /* endfor */
if (noHighWaters==0) MsgSetHighWater(netmail, i);
MsgCloseArea(netmail);
closeOpenedPkt();
} else {
w_log(LL_ERR, "Could not open NetmailArea %s", area -> areaName);
} /* endif */
}
void writeScanStatToLog(void) {
unsigned i;
w_log(LL_STAT, "Statistics");
w_log(LL_STAT, " areas: % 4d msgs: % 6d", statScan.areas, statScan.msgs);
w_log(LL_STAT, " exported: % 4d", statScan.exported);
/* Now write areas summary */
w_log(LL_SUMMARY, "Areas summary:");
for (i = 0; i < config->netMailAreaCount; i++)
if (config->netMailAreas[i].scn > 1)
w_log(LL_SUMMARY, "netmail area %s - %d msgs",
config->netMailAreas[i].areaName, config->netMailAreas[i].scn-1);
for (i = 0; i < config->echoAreaCount; i++)
if (config->echoAreas[i].scn > 1)
w_log(LL_SUMMARY, "echo area %s - %d msgs",
config->echoAreas[i].areaName, config->echoAreas[i].scn-1);
}
s_area *getLocalArea(s_fidoconfig *config, char *areaName)
{
UINT i;
for (i=0; i < config->localAreaCount; i++) {
if (stricmp(config->localAreas[i].areaName, areaName)==0)
return &(config->localAreas[i]);
}
return NULL;
}
int scanByName(char *name) {
s_area *area = NULL;
if ((area = getNetMailArea(config, name)) != NULL) {
scanNMArea(area);
return 1;
} else {
// maybe it's echo area
area = getEchoArea(config, name);
if (area != &(config->badArea)) {
if (area && area->msgbType != MSGTYPE_PASSTHROUGH &&
area -> downlinkCount > 0) {
scanEMArea(area);
return 1;
}
} else {
if (NULL != getLocalArea(config,name))
w_log(LL_SCANNING, "Area \'%s\' is local -> Skipped", name);
else
w_log(LL_SCANNING, "Area \'%s\' is not found -> Scanning stop", name);
}
}
return 0;
}
void scanExport(int type, char *str) {
unsigned int i = 0;
FILE *f = NULL;
FILE *ftmp = NULL;
char *tmplogname = NULL, *tmppath = NULL;
char *line = NULL;
struct stat st;
w_log( LL_FUNC, "scanExport() begin" );
// zero statScan
memset(&statScan, '\0', sizeof(s_statScan));
w_log(LL_START, "Start %s%s...",
type & SCN_ECHOMAIL ? "scanning" : "packing",
type & SCN_FILE ? " with -f " :
type & SCN_NAME ? " with -a " : "");
if (config->echotosslog)
{
tmppath = (char *) safe_malloc(strlen(config->echotosslog)+1);
memset(tmppath, 0, strlen(config->echotosslog)+1);
strncpy(tmppath, config->echotosslog,
(strrchr(config->echotosslog, PATH_DELIM) - config->echotosslog));
tmplogname = makeUniqueDosFileName(tmppath, "tmp", config);
nfree(tmppath);
}
w_log( LL_SRCLINE, "%s:%d", __FILE__, __LINE__ );
if (type & SCN_ALL) {
if (config->echotosslog)
{
f = fopen(config->echotosslog, "r");
if (f != NULL && config->packNetMailOnScan == 0) {
ftmp = fopen(tmplogname, "w");
if (ftmp == NULL) {
w_log(LL_ERR, "Can't open file %s for writing : %s", tmplogname, strerror(errno));
// close file so all areas will be scanned instead of panic.
fclose(f);
}
}
}
}
w_log( LL_SRCLINE, "%s:%d", __FILE__, __LINE__ );
if (type & SCN_FILE) {
f = fopen(str, "r");
if (f != NULL) {
ftmp = fopen(tmplogname, "w");
if (ftmp == NULL) {
w_log(LL_ERR, "Can't open file %s for writing : %s", tmplogname, strerror(errno));
// close file so all areas will be scanned instead of panic.
fclose(f);
}
}
}
w_log( LL_SRCLINE, "%s:%d", __FILE__, __LINE__ );
if (type & SCN_NAME) {
scanByName(str);
} else if (f == NULL) {
if (type & SCN_FILE) {
w_log(LL_START, "EchoTossLogFile not found -> Scanning stop");
nfree(tmplogname);
return;
}
if (type & SCN_ECHOMAIL) {
// if echotoss file does not exist scan all areas
w_log(LL_START, "EchoTossLogFile not found -> Scanning all areas.");
for (i = 0; i< config->echoAreaCount; i++) {
if ((config->echoAreas[i].msgbType != MSGTYPE_PASSTHROUGH) && (config->echoAreas[i].downlinkCount > 0)) {
scanEMArea(&(config->echoAreas[i]));
}
}
};
if (type & SCN_NETMAIL) {
for (i = 0; i < config->netMailAreaCount; i++) {
scanNMArea(&(config->netMailAreas[i]));
}
};
} else {
// else scan only those areas which are listed in the file
w_log(LL_START, "EchoTossLogFile found -> Scanning only listed areas");
while (!feof(f)) {
line = readLine(f);
if (line != NULL) {
if (*line && line[strlen(line)-1] == '\r')
line[strlen(line)-1] = '\0'; /* fix for DOSish echotoss.log */
striptwhite(line);
if (!ftmp) { // the same as if(config->packNetMailOnScan) {
scanByName(line);
} else {
/* exclude NetmailAreas in echoTossLogFile */
if (type & SCN_ECHOMAIL) {
if (getNetMailArea(config, line) == NULL)
scanByName(line);
else
fprintf(ftmp, "%s\n", line);
} else {
if (getNetMailArea(config, line) != NULL)
scanByName(line);
else
fprintf(ftmp, "%s\n", line);
}
}
nfree(line);
}
}
}
w_log( LL_SRCLINE, "%s:%d", __FILE__, __LINE__ );
if (f != NULL) {
fclose(f);
if (ftmp != NULL)
{
fclose(ftmp);
memset(&st, 0, sizeof(st));
stat(tmplogname, &st);
if (type & SCN_ALL) {
if (st.st_size == 0) { // all entries was processed
remove(config->echotosslog);
if (remove(tmplogname) != 0)
w_log(LL_ERR, "Couldn't remove temporary file\"%s\"", tmplogname);
} else { // we still have areas
remove(config->echotosslog);
if (rename(tmplogname, config->echotosslog) != 0)
w_log(LL_ERR, "Couldn't rename \"%s\" -> \"%s\"", tmplogname, config->echotosslog);
}
} else {
if (st.st_size == 0) {
remove(str);
if (remove(tmplogname) != 0)
w_log(LL_ERR, "Couldn't remove temporary file\"%s\"", tmplogname);
} else {
remove(str);
if (rename(tmplogname, str) != 0)
w_log(LL_ERR, "Couldn't rename \"%s\" -> \"%s\"", tmplogname, str);
}
}
}
else
{
if (type & SCN_ALL) {
remove(config->echotosslog);
}
else if (type & SCN_FILE) {
remove(str);
}
}
}
nfree (tmplogname);
tossTempOutbound(config->tempOutbound);
writeDupeFiles();
writeScanStatToLog();
w_log( LL_FUNC, "scanExport() end" );
}
syntax highlighted by Code2HTML, v. 0.9.1