/********************************************************
* File: config.c
* Created at Sun Jan 28 22:10:29 MSK 2001 by raorn // raorn@binec.ru
* Configuration
* $Id: cfg.c,v 1.15 2002/07/07 12:56:10 raorn Exp $
*******************************************************/
#include "crashecho.h"
bool CorrectFlags(uchar * flags)
{
ulong c;
for (c = 0; c < strlen(flags); c++) {
flags[c] = toupper(flags[c]);
if (flags[c] < 'A' || flags[c] > 'Z')
return (FALSE);
}
return (TRUE);
}
uchar *cfgbuf;
bool ReadConfig(uchar * filename, struct Config * cfg, short *seconderr, ulong * cfgline, uchar * cfgerr, size_t errlen)
{
uchar buf2[200], cfgword[30];
ulong jbcpos;
FILE *cfgfh;
struct Aka *tmpaka, *LastAka = NULL;
struct ConfigNode *tmpnode, *LastCNode = NULL;
struct Packer *tmppacker, *LastPacker = NULL;
struct Carbon *tmpcarbon;
struct AreaFixName *tmpareafixname;
struct Arealist *tmparealist;
struct AddNode *tmpaddnode;
struct RemNode *tmpremnode;
struct Node4D tmp4d;
cfg->changed = FALSE;
mystrncpy(cfg->filename, filename, 100);
*cfgline = 0;
if (!(cfgbuf = malloc(4000))) {
*seconderr = READCONFIG_NO_MEM;
return (FALSE);
}
if (!(cfgfh = fopen(filename, "rt"))) {
*seconderr = READCONFIG_NOT_FOUND;
free(cfgbuf);
return (FALSE);
}
*seconderr = READCONFIG_INVALID;
while (fgets(cfgbuf, 4000, cfgfh)) {
jbcpos = 0;
(*cfgline)++;
jbstrcpy(cfgword, cfgbuf, 30, &jbcpos);
if (cfgword[0] == 0 || strchr(";#", cfgword[0]))
continue;
if (stricmp(cfgword, "AKA") == 0) {
if (!(tmpaka = (struct Aka *) calloc(1, sizeof(struct Aka)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&cfg->AkaList, (struct jbNode *) tmpaka);
LastAka = tmpaka;
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(Parse4D(buf2, &LastAka->Node))) {
snprintf(cfgerr, errlen, "Invalid node number \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbNewList(&LastAka->AddList);
jbNewList(&LastAka->RemList);
} else if (stricmp(cfgword, "ADDNODE") == 0) {
if (!LastAka) {
mystrncpy(cfgerr, "No previous AKA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
while (jbstrcpy(buf2, cfgbuf, 100, &jbcpos)) {
if (!(tmpaddnode = (struct AddNode *) calloc(1, sizeof(struct AddNode)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&LastAka->AddList, (struct jbNode *) tmpaddnode);
if (!(Parse4D(buf2, &tmpaddnode->Node))) {
snprintf(cfgerr, errlen, "Invalid node number \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
} else if (stricmp(cfgword, "REMNODE") == 0) {
if (!LastAka) {
mystrncpy(cfgerr, "No previous AKA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
while (jbstrcpy(buf2, cfgbuf, 100, &jbcpos)) {
if (!(tmpremnode = (struct RemNode *) calloc(1, sizeof(struct RemNode)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&LastAka->RemList, (struct jbNode *) tmpremnode);
if (!Parse2DPat(buf2, &tmpremnode->NodePat)) {
snprintf(cfgerr, errlen, "Invalid node pattern \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
} else if (stricmp(cfgword, "DOMAIN") == 0) {
if (!LastAka) {
mystrncpy(cfgerr, "No previous AKA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastAka->Domain, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "GROUPNAME") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 2, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!CorrectFlags(buf2)) {
snprintf(cfgerr, errlen, "Invalid group \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(cfg->cfg_GroupNames[buf2[0] - 'A'], cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "NODE") == 0) {
if (!(tmpnode = (struct ConfigNode *) calloc(1, sizeof(struct ConfigNode)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbNewList(&tmpnode->RemoteAFList);
jbAddNode(&cfg->CNodeList, (struct jbNode *) tmpnode);
LastCNode = tmpnode;
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(Parse4D(buf2, &LastCNode->Node))) {
snprintf(cfgerr, errlen, "Invalid node number \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
/* Aka */
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(Parse4D(buf2, &tmp4d))) {
snprintf(cfgerr, errlen, "Invalid node number \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
for (tmpaka = (struct Aka *) cfg->AkaList.First; tmpaka; tmpaka = tmpaka->Next)
if (Compare4D(&tmp4d, &tmpaka->Node) == 0)
break;
if (!tmpaka) {
snprintf(cfgerr, errlen, "Unconfigured AKA \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastCNode->Aka = tmpaka;
/* Packer */
if (!(jbstrcpy(buf2, cfgbuf, 10, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
tmppacker = NULL;
if (buf2[0] != 0 || stricmp(buf2, "NONE")) {
for (tmppacker = (struct Packer *) cfg->PackerList.First; tmppacker; tmppacker = tmppacker->Next)
if (stricmp(buf2, tmppacker->Name) == 0)
break;
if (!tmppacker) {
snprintf(cfgerr, errlen, "Unknown packer \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
LastCNode->Packer = tmppacker;
if (!(jbstrcpy(LastCNode->PacketPW, cfgbuf, 9, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastCNode->EchomailPri = PKTS_NORMAL;
while (jbstrcpy(buf2, cfgbuf, 200, &jbcpos)) {
if (stricmp(buf2, "NOTIFY") == 0)
LastCNode->Flags |= NODE_NOTIFY;
else if (stricmp(buf2, "PASSIVE") == 0)
LastCNode->Flags |= NODE_PASSIVE;
else if (stricmp(buf2, "NOSEENBY") == 0)
LastCNode->Flags |= NODE_NOSEENBY;
else if (stricmp(buf2, "TINYSEENBY") == 0)
LastCNode->Flags |= NODE_TINYSEENBY;
else if (stricmp(buf2, "FORWARDREQ") == 0)
LastCNode->Flags |= NODE_FORWARDREQ;
else if (stricmp(buf2, "SENDAREAFIX") == 0)
LastCNode->Flags |= NODE_SENDAREAFIX;
else if (stricmp(buf2, "SENDTEXT") == 0)
LastCNode->Flags |= NODE_SENDTEXT;
else if (stricmp(buf2, "AUTOADD") == 0)
LastCNode->Flags |= NODE_AUTOADD;
else if (stricmp(buf2, "CRASH") == 0)
LastCNode->EchomailPri = PKTS_CRASH;
else if (stricmp(buf2, "DIRECT") == 0)
LastCNode->EchomailPri = PKTS_DIRECT;
else if (stricmp(buf2, "HOLD") == 0)
LastCNode->EchomailPri = PKTS_HOLD;
else {
snprintf(cfgerr, errlen, "Unknown switch \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
} else if (stricmp(cfgword, "AREAFIXINFO") == 0) {
if (!LastCNode) {
mystrncpy(cfgerr, "No previous NODE line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastCNode->AreafixPW, cfgbuf, 40, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (jbstrcpy(LastCNode->Groups, cfgbuf, 70, &jbcpos)) {
if (!CorrectFlags(LastCNode->Groups)) {
snprintf(cfgerr, errlen, "Invalid groups \"%s\"", LastCNode->Groups);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
if (jbstrcpy(LastCNode->ReadOnlyGroups, cfgbuf, 70, &jbcpos)) {
if (!CorrectFlags(LastCNode->ReadOnlyGroups)) {
snprintf(cfgerr, errlen, "Invalid groups \"%s\"", LastCNode->ReadOnlyGroups);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
if (jbstrcpy(LastCNode->AddGroups, cfgbuf, 70, &jbcpos)) {
if (!CorrectFlags(LastCNode->AddGroups)) {
snprintf(cfgerr, errlen, "Invalid groups \"%s\"", LastCNode->AddGroups);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
} else if (stricmp(cfgword, "DEFAULTGROUP") == 0) {
if (!LastCNode) {
mystrncpy(cfgerr, "No previous NODE line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 2, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!CorrectFlags(buf2)) {
snprintf(cfgerr, errlen, "Invalid group \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastCNode->DefaultGroup = buf2[0];
} else if (stricmp(cfgword, "AREAFIXNAME") == 0) {
if (!(tmpareafixname = (struct AreaFixName *) calloc(1, sizeof(struct AreaFixName)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&cfg->AreaFixList, (struct jbNode *) tmpareafixname);
if (!(jbstrcpy(tmpareafixname->Name, cfgbuf, 36, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "AFTERUNPACK") == 0) {
if (!(jbstrcpy(cfg->cfg_AfterUnpack, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "BEFOREPACK") == 0) {
if (!(jbstrcpy(cfg->cfg_BeforePack, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "INBOUND") == 0) {
if (!(jbstrcpy(cfg->cfg_Inbound, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "PROTINBOUND") == 0) {
if (!(jbstrcpy(cfg->cfg_ProtInbound, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "TEMPINBOUND") == 0) {
if (!(jbstrcpy(cfg->cfg_TempInbound, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "LOCALINBOUND") == 0) {
if (!(jbstrcpy(cfg->cfg_LocalInbound, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "OUTBOUND") == 0) {
if (!(jbstrcpy(cfg->cfg_Outbound, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "SYSOP") == 0) {
if (!(jbstrcpy(cfg->cfg_Sysop, cfgbuf, 35, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "AREAFIXHELP") == 0) {
if (!(jbstrcpy(cfg->cfg_AreaFixHelp, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "LOGFILE") == 0) {
if (!(jbstrcpy(cfg->cfg_LogFile, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "LOGLEVEL") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (atoi(buf2) < 1 || atoi(buf2) > 6) {
mystrncpy(cfgerr, "Loglevel out of range", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_LogLevel = atoi(buf2);
} else if (stricmp(cfgword, "STATSFILE") == 0) {
if (!(jbstrcpy(cfg->cfg_StatsFile, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "DUPEFILE") == 0) {
if (!(jbstrcpy(cfg->cfg_DupeFile, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_DupeSize = atoi(buf2) * 1024;
} else if (stricmp(cfgword, "DUPEMODE") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (stricmp(buf2, "IGNORE") == 0)
cfg->cfg_DupeMode = DUPE_IGNORE;
else if (stricmp(buf2, "KILL") == 0)
cfg->cfg_DupeMode = DUPE_KILL;
else if (stricmp(buf2, "BAD") == 0)
cfg->cfg_DupeMode = DUPE_BAD;
else {
snprintf(cfgerr, errlen, "Unknown dupemode \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "CREATEPKTDIR") == 0) {
if (!(jbstrcpy(cfg->cfg_PacketCreate, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "PACKETDIR") == 0) {
if (!(jbstrcpy(cfg->cfg_PacketDir, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "PACKER") == 0) {
if (!(tmppacker = (struct Packer *) calloc(1, sizeof(struct Packer)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&cfg->PackerList, (struct jbNode *) tmppacker);
LastPacker = tmppacker;
if (!(jbstrcpy(LastPacker->Name, cfgbuf, 10, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!stricmp(LastPacker->Name, "NONE")) {
mystrncpy(cfgerr, "\"NONE\" packer is reserved", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastPacker->Packer, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastPacker->Unpacker, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastPacker->Recog, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "CARBON") == 0) {
if (!(tmpcarbon = (struct Carbon *) calloc(1, sizeof(struct Carbon)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&cfg->CarbonList, (struct jbNode *) tmpcarbon);
if (!(jbstrcpy(tmpcarbon->FromArea, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!CheckPattern(tmpcarbon->FromArea)) {
snprintf(cfgerr, errlen, "Invalid area pattern \"%s\"", tmpcarbon->FromArea);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (stricmp(buf2, "TO") == 0)
tmpcarbon->CCType = CC_TO;
else if (stricmp(buf2, "FROM") == 0)
tmpcarbon->CCType = CC_FROM;
else if (stricmp(buf2, "SUBJ") == 0)
tmpcarbon->CCType = CC_SUBJ;
else {
mystrncpy(cfgerr, "Invalid carbon type", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(tmpcarbon->Pattern, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!CheckPattern(tmpcarbon->Pattern)) {
snprintf(cfgerr, errlen, "Invalid pattern \"%s\"", tmpcarbon->Pattern);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(tmpcarbon->ToArea, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing areatag", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "AREAFILE") == 0) {
if (!(jbstrcpy(cfg->areafile, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "AREALIST") == 0) {
if (!(tmparealist = (struct Arealist *) calloc(1, sizeof(struct Arealist)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&cfg->ArealistList, (struct jbNode *) tmparealist);
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(Parse4D(buf2, &tmp4d))) {
snprintf(cfgerr, errlen, "Invalid node number \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
for (tmpnode = (struct ConfigNode *) cfg->CNodeList.First; tmpnode; tmpnode = tmpnode->Next)
if (Compare4D(&tmp4d, &tmpnode->Node) == 0)
break;
if (!tmpnode) {
snprintf(cfgerr, errlen, "Unconfigured node \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
tmparealist->Node = tmpnode;
if (!(jbstrcpy(tmparealist->AreaFile, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
while (jbstrcpy(buf2, cfgbuf, 200, &jbcpos)) {
if (stricmp(buf2, "FORWARD") == 0) {
tmparealist->Flags |= AREALIST_FORWARD;
} else if (stricmp(buf2, "DESC") == 0) {
tmparealist->Flags |= AREALIST_DESC;
} else if (stricmp(buf2, "GROUP") == 0) {
if (!jbstrcpy(buf2, cfgbuf, 200, &jbcpos)) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!CorrectFlags(buf2)) {
snprintf(cfgerr, errlen, "Invalid group \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
tmparealist->Group = buf2[0];
} else {
snprintf(cfgerr, errlen, "Unknown switch \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
} else if (stricmp(cfgword, "REMOTEAF") == 0) {
if (!LastCNode) {
mystrncpy(cfgerr, "No previous NODE line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastCNode->RemoteAFName, cfgbuf, 36, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastCNode->RemoteAFPw, cfgbuf, 72, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "REMOTESYSOP") == 0) {
if (!LastCNode) {
mystrncpy(cfgerr, "No previous NODE line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastCNode->SysopName, cfgbuf, 36, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "STRIPRE") == 0) {
cfg->cfg_Flags |= CFG_STRIPRE;
} else if(stricmp(cfgword,"FORCEINTL")==0) {
cfg->cfg_Flags|=CFG_FORCEINTL;
} else if (stricmp(cfgword, "REMOVEWHENFEED") == 0) {
cfg->cfg_Flags |= CFG_REMOVEWHENFEED;
} else if (stricmp(cfgword, "INCLUDEFORWARD") == 0) {
cfg->cfg_Flags |= CFG_INCLUDEFORWARD;
} else if (stricmp(cfgword, "NOMAXOUTBOUNDZONE") == 0) {
cfg->cfg_Flags |= CFG_NOMAXOUTBOUNDZONE;
} else if (stricmp(cfgword, "USEASO") == 0) {
cfg->cfg_Flags |= CFG_USEASO;
} else if (stricmp(cfgword, "ALLOWKILLSENT") == 0) {
cfg->cfg_Flags |= CFG_ALLOWKILLSENT;
} else if (stricmp(cfgword, "CHECKSEENBY") == 0) {
cfg->cfg_Flags |= CFG_CHECKSEENBY;
} else if (stricmp(cfgword, "CHECKPKTDEST") == 0) {
cfg->cfg_Flags |= CFG_CHECKPKTDEST;
} else if (stricmp(cfgword, "ALLOWNULLPASSWORDS") == 0) {
cfg->cfg_Flags |= CFG_ALLOWNULLPASSWORDS;
} else if (stricmp(cfgword, "KEEPAREAFIX") == 0) {
cfg->cfg_Flags |= CFG_KEEPAREAFIX;
} else if (stricmp(cfgword, "KEEPRECEIPT") == 0) {
cfg->cfg_Flags |= CFG_KEEPRECEIPT;
} else if (stricmp(cfgword, "AREAFIXREMOVE") == 0) {
cfg->cfg_Flags |= CFG_AREAFIXREMOVE;
} else if (stricmp(cfgword, "WEEKDAYNAMING") == 0) {
cfg->cfg_Flags |= CFG_WEEKDAYNAMING;
} else if (stricmp(cfgword, "ADDTID") == 0) {
cfg->cfg_Flags |= CFG_ADDTID;
} else if (stricmp(cfgword, "ALLOWRESCAN") == 0) {
cfg->cfg_Flags |= CFG_ALLOWRESCAN;
} else if (stricmp(cfgword, "FORWARDPASSTHRU") == 0) {
cfg->cfg_Flags |= CFG_FORWARDPASSTHRU;
} else if (stricmp(cfgword, "LOCKBYLINK") == 0) {
cfg->cfg_Flags |= CFG_LOCKBYLINK;
} else if (stricmp(cfgword, "CCONSCAN") == 0) {
cfg->cfg_Flags |= CFG_CCONSCAN;
} else if (stricmp(cfgword, "FORWARDTIMEOUT") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_FwdTimeout = atoi(buf2);
} else if (stricmp(cfgword, "REMOVETIMEOUT") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_RemoveTimeout = atoi(buf2);
} else if (stricmp(cfgword, "MSGBASEUMASK") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (sscanf(buf2, "%o", &cfg->cfg_MsgbaseUmask) != 1) {
mystrncpy(cfgerr, "Invalid umask value", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "MAXPKTSIZE") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_MaxPktSize = atoi(buf2) * 1024;
} else if (stricmp(cfgword, "MAXBUNDLESIZE") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_MaxBundleSize = atoi(buf2) * 1024;
} else if (stricmp(cfgword, "DEFAULTZONE") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_DefaultZone = atoi(buf2);
} else if (stricmp(cfgword, "AREAFIXMAXLINES") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_AreaFixMaxLines = atoi(buf2);
}
/*************************** MSG ******************************/
else if (stricmp(cfgword, "MSG_HIGHWATER") == 0) {
cfg->cfg_msg_Flags |= CFG_MSG_HIGHWATER;
/* } else if (stricmp(cfgword, "MSG_WRITEBACK") == 0) {*/
/* cfg->cfg_msg_Flags |= CFG_MSG_WRITEBACK;*/
}
/*************************** JAM ******************************/
#ifdef MSGBASE_JAM
else if (stricmp(cfgword, "JAM_FLAGSDIR") == 0) {
if (!(jbstrcpy(cfg->cfg_jam_FlagsDir, cfgbuf, 100, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "JAM_HIGHWATER") == 0) {
cfg->cfg_jam_Flags |= CFG_JAM_HIGHWATER;
} else if (stricmp(cfgword, "JAM_HARDDELETE") == 0) {
cfg->cfg_jam_Flags |= CFG_JAM_HARDDELETE;
} else if (stricmp(cfgword, "JAM_QUICKLINK") == 0) {
/* Do nothing - checked in CrashMaint */
} else if (stricmp(cfgword, "JAM_MAXOPEN") == 0) {
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->cfg_jam_MaxOpen = atoi(buf2);
}
#endif
/*************************** Unknown *****************************/
else {
snprintf(cfgerr, errlen, "Unknown keyword \"%s\"", cfgword);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
fclose(cfgfh);
free(cfgbuf);
return (TRUE);
}
bool ReadAreas(uchar * filename, struct Config * cfg, short *seconderr, ulong * cfgline, uchar * cfgerr, size_t errlen)
{
uchar buf2[200], cfgword[30];
ulong c, jbcpos;
FILE *cfgfh;
struct Aka *tmpaka;
struct ConfigNode *tmpnode;
struct Area *tmparea, *LastArea = NULL;
struct TossNode *tmptnode;
struct BannedNode *tmpbnode;
struct Node4D tmp4d;
ushort flags;
*cfgline = 0;
if (!(cfgbuf = malloc(4000))) {
*seconderr = READCONFIG_NO_MEM;
return (FALSE);
}
if (!(cfgfh = fopen(filename, "rt"))) {
*seconderr = READCONFIG_NOT_FOUND;
free(cfgbuf);
return (FALSE);
}
*seconderr = READCONFIG_INVALID;
while (fgets(cfgbuf, 4000, cfgfh)) {
jbcpos = 0;
(*cfgline)++;
jbstrcpy(cfgword, cfgbuf, 30, &jbcpos);
if (cfgword[0] == 0 || strchr(";#", cfgword[0]))
continue;
if (stricmp(cfgword, "NETMAILDIR") == 0) {
strcpy(cfg->Netmail.Tagname, "NETMAIL");
strcpy(cfg->Netmail.Description, "Primary netmail area");
cfg->Netmail.Aka = (struct Aka *) cfg->AkaList.First;
for (c = 0; AvailMessagebases[c].name; c++)
if (stricmp(AvailMessagebases[c].name, "MSG") == 0)
break;
if (AvailMessagebases[c].name) {
cfg->Netmail.Messagebase = &AvailMessagebases[c];
} else {
snprintf(cfgerr, errlen, "*.MSG format not supported");
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(cfg->Netmail.Path, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
cfg->Netmail.AreaType = AREATYPE_NETMAIL;
} else if (stricmp(cfgword, "AREA") == 0 ||
stricmp(cfgword, "NETMAIL") == 0 ||
stricmp(cfgword, "LOCALAREA") == 0) {
if (!(tmparea = (struct Area *) calloc(1, sizeof(struct Area)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbNewList(&tmparea->TossNodes);
jbNewList(&tmparea->BannedNodes);
jbAddNode(&cfg->AreaList, (struct jbNode *) tmparea);
LastArea = tmparea;
if (!(jbstrcpy(LastArea->Tagname, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!stricmp(LastArea->Tagname, "NETMAIL")) {
mystrncpy(cfgerr, "NETMAIL areatag reserved for NETMAILDIR", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(Parse4D(buf2, &tmp4d))) {
snprintf(cfgerr, errlen, "Invalid node number \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
for (tmpaka = (struct Aka *) cfg->AkaList.First; tmpaka;
tmpaka = tmpaka->Next)
if (Compare4D(&tmp4d, &tmpaka->Node) == 0)
break;
if (!tmpaka) {
snprintf(cfgerr, errlen, "Unknown AKA \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Aka = tmpaka;
if (jbstrcpy(buf2, cfgbuf, 200, &jbcpos)) {
int c;
for (c = 0; AvailMessagebases[c].name; c++)
if (stricmp(buf2, AvailMessagebases[c].name) == 0)
break;
if (AvailMessagebases[c].name) {
LastArea->Messagebase = &AvailMessagebases[c];
} else {
snprintf(cfgerr, errlen, "Unknown messagebase format \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastArea->Path, cfgbuf, 200, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
if (stricmp(cfgword, "NETMAIL") == 0) {
if (!LastArea->Messagebase) {
snprintf(cfgerr, errlen, "Netmail area cannot be pass-through");
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->AreaType = AREATYPE_NETMAIL;
} else if (stricmp(cfgword, "LOCALAREA") == 0) {
if (!LastArea->Messagebase) {
snprintf(cfgerr, errlen, "Local area cannot be pass-through");
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->AreaType = AREATYPE_LOCAL;
} else if (stricmp(LastArea->Tagname, "BAD") == 0) {
if (LastArea->Path[0] == 0) {
snprintf(cfgerr, errlen, "BAD area cannot be pass-through");
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->AreaType = AREATYPE_BAD;
} else if (stricmp(LastArea->Tagname, "DEFAULT") == 0 ||
strnicmp(LastArea->Tagname, "DEFAULT_", 8) == 0) {
LastArea->AreaType = AREATYPE_DEFAULT;
} else {
LastArea->AreaType = AREATYPE_ECHOMAIL;
}
} else if (stricmp(cfgword, "UNCONFIRMED") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Flags |= AREA_UNCONFIRMED;
} else if (stricmp(cfgword, "MANDATORY") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Flags |= AREA_MANDATORY;
} else if (stricmp(cfgword, "DEFREADONLY") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Flags |= AREA_DEFREADONLY;
} else if (stricmp(cfgword, "IGNOREDUPES") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Flags |= AREA_IGNOREDUPES;
} else if (stricmp(cfgword, "IGNORESEENBY") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Flags |= AREA_IGNORESEENBY;
} else if (stricmp(cfgword, "IMPORTSEENBY") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Flags |= AREA_IMPORTSEENBY;
} else if (stricmp(cfgword, "EXPORT") == 0) {
struct Node4D tpl4d;
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (LastArea->AreaType != AREATYPE_ECHOMAIL &&
LastArea->AreaType != AREATYPE_DEFAULT) {
mystrncpy(cfgerr, "Not an echomail or default area", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
tpl4d.Zone = 0;
tpl4d.Net = 0;
tpl4d.Node = 0;
tpl4d.Point = 0;
while (jbstrcpy(buf2, cfgbuf, 100, &jbcpos)) {
flags = 0;
if (buf2[0] == '!') {
flags = TOSSNODE_READONLY;
strcpy(buf2, &buf2[1]);
}
if (buf2[0] == '@') {
flags = TOSSNODE_WRITEONLY;
strcpy(buf2, &buf2[1]);
}
if (buf2[0] == '%') {
flags = TOSSNODE_FEED;
strcpy(buf2, &buf2[1]);
}
if (!(Parse4DTemplate(buf2, &tmp4d, &tpl4d))) {
snprintf(cfgerr, errlen, "Invalid node number \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
Copy4D(&tpl4d, &tmp4d);
tpl4d.Point = 0;
for (tmpnode = (struct ConfigNode *) cfg->CNodeList.First; tmpnode;
tmpnode = tmpnode->Next)
if (Compare4D(&tmp4d, &tmpnode->Node) == 0)
break;
if (!tmpnode) {
snprintf(cfgerr, errlen, "Unconfigured node \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(tmptnode = (struct TossNode *) calloc(1, sizeof(struct TossNode)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&LastArea->TossNodes, (struct jbNode *) tmptnode);
tmptnode->ConfigNode = tmpnode;
tmptnode->Flags = flags;
}
} else if (stricmp(cfgword, "BANNED") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
while (jbstrcpy(buf2, cfgbuf, 100, &jbcpos)) {
if (!(Parse4D(buf2, &tmp4d))) {
snprintf(cfgerr, errlen, "Invalid node number \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
for (tmpnode = (struct ConfigNode *) cfg->CNodeList.First; tmpnode;
tmpnode = tmpnode->Next)
if (Compare4D(&tmp4d, &tmpnode->Node) == 0)
break;
if (!tmpnode) {
snprintf(cfgerr, errlen, "Unconfigured node \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(tmpbnode = (struct BannedNode *) calloc(1, sizeof(struct BannedNode)))) {
*seconderr = READCONFIG_NO_MEM;
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
jbAddNode(&LastArea->BannedNodes, (struct jbNode *) tmpbnode);
tmpbnode->ConfigNode = tmpnode;
}
} else if (stricmp(cfgword, "DESCRIPTION") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(LastArea->Description, cfgbuf, 80, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
} else if (stricmp(cfgword, "GROUP") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 30, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!CorrectFlags(buf2)) {
snprintf(cfgerr, errlen, "Invalid group \"%s\"", buf2);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Group = buf2[0];
} else if (stricmp(cfgword, "KEEPNUM") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 30, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->KeepNum = atol(buf2);
} else if (stricmp(cfgword, "KEEPDAYS") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 30, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->KeepDays = atol(buf2);
} else if (stricmp(cfgword, "EXPIRES") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 30, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Expires = atol(buf2);
} else if (stricmp(cfgword, "REMOVED") == 0) {
if (!LastArea) {
mystrncpy(cfgerr, "No previous AREA line", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
if (!(jbstrcpy(buf2, cfgbuf, 30, &jbcpos))) {
mystrncpy(cfgerr, "Missing argument", errlen);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
LastArea->Removed = atol(buf2);
LastArea->AreaType = AREATYPE_DELETED;
} else {
snprintf(cfgerr, errlen, "Unknown keyword \"%s\"", cfgword);
fclose(cfgfh);
free(cfgbuf);
return (FALSE);
}
}
fclose(cfgfh);
free(cfgbuf);
return (TRUE);
}
bool CheckConfig(struct Config * cfg, uchar * cfgerr, size_t errlen)
{
struct Area *a1, *a2;
if (cfg->cfg_ProtInbound[0] == 0) {
snprintf(cfgerr, errlen, "Protected inbound directory not defined");
return (FALSE);
} else if (cfg->cfg_Inbound[0] == 0) {
snprintf(cfgerr, errlen, "Unprotected inbound directory not defined");
return (FALSE);
} else if (cfg->cfg_LocalInbound[0] == 0) {
snprintf(cfgerr, errlen, "Local inbound directory not defined");
return (FALSE);
} else if (cfg->cfg_TempInbound[0] == 0) {
snprintf(cfgerr, errlen, "Temporary inbound directory not defined");
return (FALSE);
} else if (cfg->cfg_LogFile[0] == 0) {
snprintf(cfgerr, errlen, "No logfile defined");
return (FALSE);
}
if (cfg->cfg_PacketCreate[0] == 0)
strcpy(cfg->cfg_PacketCreate, cfg->cfg_Outbound);
if (cfg->cfg_PacketDir[0] == 0)
strcpy(cfg->cfg_PacketDir, cfg->cfg_Outbound);
if (!cfg->AkaList.First) {
snprintf(cfgerr, errlen, "No AKAs configured");
return (FALSE);
}
if (cfg->Netmail.Path[0] == 0) {
snprintf(cfgerr, errlen, "Primary netmail area not defined");
return (FALSE);
}
if (cfg->cfg_DefaultZone == 0) {
snprintf(cfgerr, errlen, "No default zone configured");
return (FALSE);
}
/* Check for areas with same path */
for (a1 = (struct Area *) cfg->AreaList.First; a1; a1 = a1->Next) {
if (a1->AreaType != AREATYPE_DEFAULT) {
for (a2 = a1->Next; a2; a2 = a2->Next)
if (stricmp(a1->Path, a2->Path) == 0 && a1->Messagebase && a2->Messagebase) {
snprintf(cfgerr, errlen, "The areas %s and %s both have the same path", a1->Tagname, a2->Tagname);
return (FALSE);
}
}
}
return (TRUE);
}
void InitConfig(struct Config *cfg)
{
memset(cfg, 0, sizeof(struct Config));
strcpy(cfg->cfg_Sysop, "Sysop");
cfg->cfg_LogLevel = 3;
cfg->cfg_DupeSize = 200;
cfg->Netmail.Path[0] = 0;
cfg->cfg_MsgbaseUmask = umask(0777);
umask(cfg->cfg_MsgbaseUmask);
jbNewList(&cfg->AkaList);
jbNewList(&cfg->AreaList);
jbNewList(&cfg->CNodeList);
jbNewList(&cfg->PackerList);
jbNewList(&cfg->CarbonList);
jbNewList(&cfg->AreaFixList);
jbNewList(&cfg->ArealistList);
}
void WriteSafely(FILE *fh, uchar * str)
{
uchar buf[300];
ushort c, d;
d = 0;
for (c = 0; str[c]; c++) {
if (str[c] == '"' || str[c] == '\\')
buf[d++] = '\\';
buf[d++] = str[c];
}
buf[d] = 0;
fprintf(fh, "\"%s\"", buf);
}
void WriteNode4D(FILE *fh, struct Node4D *n4d)
{
fprintf(fh, "%u:%u/%u.%u", n4d->Zone, n4d->Net, n4d->Node, n4d->Point);
}
uchar *nodekeywords[] = { "DEFAULTGROUP", "REMOTESYSOP", "REMOTEAF",
"AREAFIXINFO", "NODE", NULL
};
uchar *areakeywords[] = { "IGNORESEENBY", "IMPORTSEENBY", "IGNOREDUPES",
"DEFREADONLY", "MANDATORY", "UNCONFIRMED", "KEEPNUM", "KEEPDAYS",
"GROUP", "DESCRIPTION", "BANNED", "EXPORT", "IMPORT", "EXPIRES",
"REMOVED", "AREA", "NETMAIL", NULL
};
void WriteNode(struct ConfigNode *tmpnode, FILE *osfh)
{
fprintf(osfh, "NODE ");
WriteNode4D(osfh, &tmpnode->Node);
fprintf(osfh, " ");
WriteNode4D(osfh, &tmpnode->Aka->Node);
fprintf(osfh, " ");
if (tmpnode->Packer)
WriteSafely(osfh, tmpnode->Packer->Name);
else
WriteSafely(osfh, "NONE");
fprintf(osfh, " ");
WriteSafely(osfh, tmpnode->PacketPW);
if (tmpnode->Flags & NODE_PASSIVE)
fprintf(osfh, " PASSIVE");
if (tmpnode->Flags & NODE_NOTIFY)
fprintf(osfh, " NOTIFY");
if (tmpnode->Flags & NODE_NOSEENBY)
fprintf(osfh, " NOSEENBY");
if (tmpnode->Flags & NODE_TINYSEENBY)
fprintf(osfh, " TINYSEENBY");
if (tmpnode->Flags & NODE_FORWARDREQ)
fprintf(osfh, " FORWARDREQ");
if (tmpnode->Flags & NODE_SENDAREAFIX)
fprintf(osfh, " SENDAREAFIX");
if (tmpnode->Flags & NODE_SENDTEXT)
fprintf(osfh, " SENDTEXT");
if (tmpnode->Flags & NODE_AUTOADD)
fprintf(osfh, " AUTOADD");
if (tmpnode->EchomailPri == PKTS_CRASH)
fprintf(osfh, " CRASH");
if (tmpnode->EchomailPri == PKTS_DIRECT)
fprintf(osfh, " DIRECT");
if (tmpnode->EchomailPri == PKTS_HOLD)
fprintf(osfh, " HOLD");
fprintf(osfh, "\n");
if (tmpnode->AreafixPW[0] || tmpnode->Groups[0] || tmpnode->ReadOnlyGroups[0] || tmpnode->AddGroups[0]) {
fprintf(osfh, "AREAFIXINFO ");
WriteSafely(osfh, tmpnode->AreafixPW);
fprintf(osfh, " ");
WriteSafely(osfh, tmpnode->Groups);
fprintf(osfh, " ");
WriteSafely(osfh, tmpnode->ReadOnlyGroups);
fprintf(osfh, " ");
WriteSafely(osfh, tmpnode->AddGroups);
fprintf(osfh, " ");
fprintf(osfh, "\n");
}
if (tmpnode->RemoteAFName[0]) {
fprintf(osfh, "REMOTEAF ");
WriteSafely(osfh, tmpnode->RemoteAFName);
fprintf(osfh, " ");
WriteSafely(osfh, tmpnode->RemoteAFPw);
fprintf(osfh, "\n");
}
if (tmpnode->SysopName[0]) {
fprintf(osfh, "REMOTESYSOP ");
WriteSafely(osfh, tmpnode->SysopName);
fprintf(osfh, "\n");
}
if (tmpnode->DefaultGroup)
fprintf(osfh, "DEFAULTGROUP %c\n", tmpnode->DefaultGroup);
}
void WriteArea(struct Area *tmparea, FILE *osfh)
{
struct ImportNode *tmpinode;
struct TossNode *tmptnode;
struct BannedNode *tmpbnode;
ulong c;
if (tmparea->AreaType == AREATYPE_NETMAIL)
fprintf(osfh, "NETMAIL ");
if (tmparea->AreaType == AREATYPE_LOCAL)
fprintf(osfh, "LOCALAREA ");
else
fprintf(osfh, "AREA ");
WriteSafely(osfh, tmparea->Tagname);
fprintf(osfh, " ");
WriteNode4D(osfh, &tmparea->Aka->Node);
if (tmparea->Messagebase) {
fprintf(osfh, " %s ", tmparea->Messagebase->name);
WriteSafely(osfh, tmparea->Path);
fprintf(osfh, "\n");
} else {
fprintf(osfh, "\n");
}
if (tmparea->AreaType == AREATYPE_NETMAIL) {
c = 0;
for (tmpinode = (struct ImportNode *) tmparea->TossNodes.First; tmpinode; tmpinode = tmpinode->Next) {
if (c % 10 == 0) {
if (c != 0)
fprintf(osfh, "\n");
fprintf(osfh, "IMPORT");
}
fprintf(osfh, " ");
WriteNode4D(osfh, &tmpinode->Node);
c++;
}
if (c != 0)
fprintf(osfh, "\n");
} else if (tmparea->AreaType == AREATYPE_ECHOMAIL || tmparea->AreaType == AREATYPE_DEFAULT) {
c = 0;
for (tmptnode = (struct TossNode *) tmparea->TossNodes.First; tmptnode; tmptnode = tmptnode->Next) {
if (c % 10 == 0) {
if (c != 0)
fprintf(osfh, "\n");
fprintf(osfh, "EXPORT");
}
fprintf(osfh, " ");
if (tmptnode->Flags & TOSSNODE_READONLY)
fprintf(osfh, "!");
if (tmptnode->Flags & TOSSNODE_WRITEONLY)
fprintf(osfh, "@");
if (tmptnode->Flags & TOSSNODE_FEED)
fprintf(osfh, "%%");
WriteNode4D(osfh, &tmptnode->ConfigNode->Node);
c++;
}
if (c != 0)
fprintf(osfh, "\n");
}
c = 0;
for (tmpbnode = (struct BannedNode *) tmparea->BannedNodes.First; tmpbnode; tmpbnode = tmpbnode->Next) {
if (c % 10 == 0) {
if (c != 0)
fprintf(osfh, "\n");
fprintf(osfh, "BANNED");
}
fprintf(osfh, " ");
WriteNode4D(osfh, &tmpbnode->ConfigNode->Node);
c++;
}
if (c != 0)
fprintf(osfh, "\n");
if (tmparea->Description[0] != 0) {
fprintf(osfh, "DESCRIPTION ");
WriteSafely(osfh, tmparea->Description);
fprintf(osfh, "\n");
}
if (tmparea->Group)
fprintf(osfh, "GROUP %c\n", tmparea->Group);
if (tmparea->KeepNum)
fprintf(osfh, "KEEPNUM %lu\n", tmparea->KeepNum);
if (tmparea->KeepDays)
fprintf(osfh, "KEEPDAYS %lu\n", tmparea->KeepDays);
if (tmparea->Expires)
fprintf(osfh, "EXPIRES %lu\n", tmparea->Expires);
if (tmparea->Removed)
fprintf(osfh, "REMOVED %lu\n", tmparea->Removed);
if (tmparea->Flags & AREA_UNCONFIRMED)
fprintf(osfh, "UNCONFIRMED\n");
if (tmparea->Flags & AREA_MANDATORY)
fprintf(osfh, "MANDATORY\n");
if (tmparea->Flags & AREA_DEFREADONLY)
fprintf(osfh, "DEFREADONLY\n");
if (tmparea->Flags & AREA_IGNOREDUPES)
fprintf(osfh, "IGNOREDUPES\n");
if (tmparea->Flags & AREA_IGNORESEENBY)
fprintf(osfh, "IGNORESEENBY\n");
if (tmparea->Flags & AREA_IMPORTSEENBY)
fprintf(osfh, "IMPORTSEENBY\n");
}
bool UpdateConfig(struct Config *cfg, uchar * cfgerr, size_t errlen)
{
uchar cfgtemp[110], cfgbak[110];
uchar cfgword[30], buf[100];
FILE *oldfh, *newfh;
bool skipnode, dontwrite, copyres;
struct ConfigNode *cnode;
struct Node4D n4d;
ulong jbcpos, c;
struct stat cfgstat;
snprintf(cfgtemp, 110, "%s.tmp", cfg->filename);
snprintf(cfgbak, 110, "%s.bak", cfg->filename);
if (stat(cfg->filename, &cfgstat) != 0) {
snprintf(cfgerr, errlen, "Can't stat file %s (error: %s)", cfg->filename, strerror(errno));
return (FALSE);
}
if (!(cfgbuf = malloc(4000))) {
snprintf(cfgerr, errlen, "Out of memory");
return (FALSE);
}
if (!(oldfh = fopen(cfg->filename, "rt"))) {
snprintf(cfgerr, errlen, "Unable to read file %s (error: %s)", cfg->filename, strerror(errno));
free(cfgbuf);
return (FALSE);
}
if (!(newfh = fopen(cfgtemp, "wt"))) {
snprintf(cfgerr, errlen, "Unable to write to config file %s (error: %s)", cfgtemp, strerror(errno));
fclose(oldfh);
free(cfgbuf);
return (FALSE);
}
skipnode = FALSE;
while (fgets(cfgbuf, 4000, oldfh)) {
jbcpos = 0;
copyres = jbstrcpy(cfgword, cfgbuf, 30, &jbcpos);
if (stricmp(cfgword, "NODE") == 0) {
skipnode = FALSE;
if (jbstrcpy(buf, cfgbuf, 100, &jbcpos)) {
if (Parse4D(buf, &n4d)) {
for (cnode = (struct ConfigNode *) cfg->CNodeList.First; cnode; cnode = cnode->Next)
if (Compare4D(&n4d, &cnode->Node) == 0)
break;
if (cnode && cnode->changed) {
skipnode = TRUE;
WriteNode(cnode, newfh);
fprintf(newfh, "\n");
cnode->changed = FALSE;
}
}
}
}
dontwrite = FALSE;
if (skipnode) {
for (c = 0; nodekeywords[c]; c++)
if (stricmp(cfgword, nodekeywords[c]) == 0)
dontwrite = TRUE;
if (!copyres)
dontwrite = TRUE;
}
if (!dontwrite)
fputs(cfgbuf, newfh);
}
fclose(oldfh);
fclose(newfh);
free(cfgbuf);
unlink(cfgbak);
rename(cfg->filename, cfgbak);
rename(cfgtemp, cfg->filename);
/* Restore attributes */
/* chown(cfg->filename, cfgstat.st_uid, cfgstat.st_gid);*/
chmod(cfg->filename, cfgstat.st_mode);
cfg->changed = FALSE;
return (TRUE);
}
bool UpdateAreas(struct Config *cfg, uchar * cfgerr, size_t errlen)
{
uchar cfgtemp[110], cfgbak[110];
uchar cfgword[30], buf[100];
FILE *oldfh, *newfh;
bool skiparea, dontwrite, copyres;
struct Area *area;
ulong jbcpos, c;
struct stat cfgstat;
snprintf(cfgtemp, 110, "%s.tmp", cfg->areafile);
snprintf(cfgbak, 110, "%s.bak", cfg->areafile);
if (stat(cfg->areafile, &cfgstat) != 0) {
snprintf(cfgerr, errlen, "Can't stat file %s (error: %s)", cfg->areafile, strerror(errno));
return (FALSE);
}
if (!(cfgbuf = malloc(4000))) {
snprintf(cfgerr, errlen, "Out of memory");
return (FALSE);
}
if (!(oldfh = fopen(cfg->areafile, "rt"))) {
snprintf(cfgerr, errlen, "Unable to read file %s (error: %s)", cfg->areafile, strerror(errno));
free(cfgbuf);
return (FALSE);
}
if (!(newfh = fopen(cfgtemp, "wt"))) {
snprintf(cfgerr, errlen, "Unable to write to config file %s (error: %s)", cfgtemp, strerror(errno));
fclose(oldfh);
free(cfgbuf);
return (FALSE);
}
skiparea = FALSE;
while (fgets(cfgbuf, 4000, oldfh)) {
jbcpos = 0;
copyres = jbstrcpy(cfgword, cfgbuf, 30, &jbcpos);
if (stricmp(cfgword, "AREA") == 0 || stricmp(cfgword, "NETMAIL") == 0) {
skiparea = FALSE;
if (jbstrcpy(buf, cfgbuf, 100, &jbcpos)) {
for (area = (struct Area *) cfg->AreaList.First; area; area = area->Next)
if (stricmp(buf, area->Tagname) == 0)
break;
/* Area has been changed */
if (area && area->changed) {
skiparea = TRUE;
WriteArea(area, newfh);
fprintf(newfh, "\n");
area->changed = FALSE;
}
/* Area has been removed */
if (!area) {
skiparea = TRUE;
}
}
}
dontwrite = FALSE;
if (skiparea) {
for (c = 0; areakeywords[c]; c++)
if (stricmp(cfgword, areakeywords[c]) == 0)
dontwrite = TRUE;
if (!copyres)
dontwrite = TRUE;
}
if (!dontwrite)
fputs(cfgbuf, newfh);
}
for (area = (struct Area *) cfg->AreaList.First; area; area = area->Next)
if (area->changed) {
fprintf(newfh, "\n");
WriteArea(area, newfh);
area->changed = FALSE;
}
fclose(oldfh);
fclose(newfh);
free(cfgbuf);
unlink(cfgbak);
rename(cfg->areafile, cfgbak);
rename(cfgtemp, cfg->areafile);
/* Restore attributes */
/* chown(cfg->areafile, cfgstat.st_uid, cfgstat.st_gid);*/
chmod(cfg->areafile, cfgstat.st_mode);
cfg->changed = FALSE;
return (TRUE);
}
void FreeConfig(struct Config *cfg)
{
struct Area *area;
struct Aka *aka;
struct ConfigNode *cnode;
/* Config */
for (area = (struct Area *) cfg->AreaList.First; area; area = area->Next) {
jbFreeList(&area->TossNodes);
jbFreeList(&area->BannedNodes);
}
for (aka = (struct Aka *) cfg->AkaList.First; aka; aka = aka->Next) {
jbFreeList(&aka->AddList);
jbFreeList(&aka->RemList);
}
for (cnode = (struct ConfigNode *) cfg->CNodeList.First; cnode;
cnode = cnode->Next)
jbFreeList(&cnode->RemoteAFList);
jbFreeList(&cfg->AkaList);
jbFreeList(&cfg->AreaList);
jbFreeList(&cfg->CNodeList);
jbFreeList(&cfg->CarbonList);
jbFreeList(&cfg->PackerList);
jbFreeList(&cfg->AreaFixList);
jbFreeList(&cfg->ArealistList);
}
syntax highlighted by Code2HTML, v. 0.9.1