/*
* LIB/CONFIG.C - Scan configuration file
*
* (c)Copyright 1998, Matthew Dillon, All Rights Reserved. Refer to
* the COPYRIGHT file in the base directory of this distribution
* for specific rights granted.
*
*/
#include "defs.h"
Prototype void LoadDiabloConfig(int ac, char **av);
Prototype void PrintVersion(void);
Prototype void SetMyHostName(char **hostname);
Prototype void SetNewsAdmin(char **admin, char *host);
Prototype void AddBindList(BindList **blist, char *interface, char *port, int append);
Prototype int SetGroupHashMethod(const char *opt, GroupHashType *pmethod);
Prototype int SetCommand(FILE *fo, char *cmd, char *opt, int *cmdErr);
Prototype int CheckConfigOptions(int which);
Prototype void DumpConfigOptions(FILE *fo, char *cmd, int which);
Prototype struct DiabloOpts DOpts;
int SetHashMethod(const char *opt, int *pmethod);
int SetCacheDirs(const char *opt, CacheDirType *cachedir);
struct DiabloOpts DOpts;
void
PrintVersion(void)
{
printf("DIABLO Version %s - %s\n", VERS, SUBREV);
exit(0);
}
void
SetMyHostName(char **hostname)
{
char buf[1024];
buf[sizeof(buf)-1] = 0;
if (gethostname(buf, sizeof(buf) - 1) == -1)
strcpy(buf, "localhost");
*hostname = strdup(buf);
}
void
SetNewsAdmin(char **admin, char *host)
{
char buf[1024];
snprintf(buf, sizeof(buf), "news@%s", host);
*admin = strdup(buf);
}
void
AddBindList(BindList **blist, char *interface, char *port, int append)
{
BindList *bl;
bl = (BindList *)malloc(sizeof(BindList));
bl->bl_Host = strdup(interface);
bl->bl_Port = strdup(port);
bl->bl_Next = NULL;
if (*blist == NULL) {
*blist = bl;
return;
}
if (!append && *blist != NULL) {
BindList *tbl;
while (*blist != NULL) {
tbl = *blist;
*blist = (*blist)->bl_Next;
if (tbl->bl_Host != NULL)
free(tbl->bl_Host);
if (tbl->bl_Port != NULL)
free(tbl->bl_Port);
free(tbl);
}
*blist = bl;
} else {
BindList *tbl = *blist;
while (tbl->bl_Next != NULL)
tbl = tbl->bl_Next;
tbl->bl_Next = bl;
}
}
void
initDOpts(void)
{
int i;
/*
* Set all the default options for the global config
*/
memset(&DOpts, 0, sizeof(DOpts));
DOpts.HashMethod = HASH_CRC;
DOpts.CompatHashMethod = HASH_CRC;
DOpts.ReaderGroupHashMethod.gh_type = HASHGRP_CRC;
DOpts.ReaderGroupHashMethod.gh_sigbytes = 20;
DOpts.ReaderGroupHashMethod.gh_dirtype = HASHGRP_DIR_BIT;
DOpts.ReaderGroupHashMethod.gh_dirlvl = 1;
DOpts.ReaderGroupHashMethod.gh_dirinfo[0] = 2;
DOpts.HashSize = 16 * 1024 * 1024;
DOpts.FeederBufferSize = 1;
DOpts.FeederMaxArtSize = 10000000;
DOpts.FeederArtTypes = 1;
DOpts.FeederPreloadArt = 1;
DOpts.SpoolPreloadArt = 1;
DOpts.ReaderMaxArtSize = 10000000;
DOpts.ReaderForks = 10;
DOpts.ReaderThreads = 40;
DOpts.ReaderFeedForks = 2;
DOpts.ReaderDns = 5;
DOpts.ReaderCacheMode = 1;
DOpts.ReaderCacheHashSize = 4096;
DOpts.ReaderXOverMode = 1;
DOpts.ReaderAutoAddToActive = 0;
DOpts.FeederAutoAddToActive = 0;
DOpts.ReaderDetailLog = 1;
DOpts.RememberSecs = 14 * 24 * 60 * 60;
DOpts.FeederMaxAcceptAge = DOpts.RememberSecs;
DOpts.HostCacheRebuildTime = 60 * 60;
DOpts.DisplayAdminVersion = 1;
DOpts.FeederRTStats = RTSTATS_NONE;
DOpts.SpamFilterOpt = NULL;
DOpts.FeederXRefHost = NULL;
DOpts.ReaderXRefHost = NULL;
DOpts.ReaderXRefSlaveHost = NULL;
DOpts.FeederPathHost = NULL;
DOpts.FeederFilter = NULL;
DOpts.ReaderPathHost = NULL;
DOpts.NewsAdmin = NULL;
DOpts.FeederHostName = NULL;
DOpts.ReaderHostName = NULL;
DOpts.NewsMaster = NULL;
DOpts.ReaderCrashHandler = strdup("none");
DOpts.PathList = NULL;
DOpts.ReaderBan = NULL;
DOpts.FeederBindHost = NULL;
DOpts.FeederPort = strdup("nntp");
DOpts.ReaderBindHost = NULL;
DOpts.ReaderPort = strdup("nntp");
DOpts.ReaderCacheDirs.dt_dirlvl = 1;
DOpts.ReaderCacheDirs.dt_dirinfo[0] = 512;
for (i = 0; i < 10; i++)
DOpts.PgpVerifyArgs[i] = NULL;
}
void
LoadDiabloConfig(int ac, char **av)
{
FILE *fi;
char buf[256];
int versOk = 0;
int exitMe = 0;
int i;
const char *diabloConfig;
/*
* Figure out path to diablo.config. Check environment first, then
* look for -C option to override it. If neither is given, use the
* default.
*/
if ((diabloConfig = getenv("DIABLO_CONFIG_PATH")) == NULL) {
diabloConfig = "%s/diablo.config";
}
for (i = 1; i < ac; ++i) {
char *ptr = av[i];
if (ptr[0] == '-' && ptr[1] == 'C') {
diabloConfig = ptr[2] ? ptr + 2 : av[++i];
}
}
if (diabloConfig == NULL) {
fprintf(stderr, "Expected argument to -C option\n");
exit(1);
}
initDOpts();
if ((fi = xfopen("r", diabloConfig, NewsHome)) != NULL) {
while (fgets(buf, sizeof(buf), fi) != NULL) {
char *cmd;
char *opt = buf;
int cmdErr = 1;
int i;
if (buf[0] == '\n' || buf[0] == '#')
continue;
if ((cmd = strchr(buf, '#')) != NULL)
*cmd = 0;
while (isspace((int)*opt))
opt++;
while ((i = strlen(opt) - 1) >= 0 && isspace((int)opt[i]))
opt[i] = 0;
if (strlen(opt) == 0)
continue;
if ((cmd = strsep(&opt, " \t\n")) != NULL && (opt != NULL)) {
int optErr = 1;
while (isspace((int)*opt))
opt++;
cmdErr = 0;
if (strcasecmp(cmd, "version") == 0) {
optErr = 0;
if (strtod(opt, NULL) > strtod(VERS, NULL))
versOk = 0;
else
versOk = 1;
} else if (versOk == 0) {
optErr = 0;
} else if (strcasecmp(cmd, "expire") == 0) {
/* Now unused */
optErr = 0;
} else if (strcasecmp(cmd, "hash") == 0) {
if (opt) {
char *p2;
if ((p2 = strchr(opt, '/')) != NULL)
*p2++ = 0;
optErr = SetHashMethod(opt, &DOpts.HashMethod);
if (p2)
optErr = SetHashMethod(p2, &DOpts.CompatHashMethod);
}
} else if (strcasecmp(cmd, "readergrouphash") == 0) {
if (opt) {
optErr = SetGroupHashMethod(opt, &DOpts.ReaderGroupHashMethod);
if (optErr != 0)
logit(LOG_CRIT, "Illegal reader group hash: %s", opt);
}
} else if (strcasecmp(cmd, "hsize") == 0) {
if (opt) {
int n = bsizetol(opt);
optErr = 0;
if (n < 256 * 1024 || n > 128 * 1024 * 1024) {
optErr = 1;
fprintf(stderr, "Illegal Hash size: %d\n", n);
logit(LOG_CRIT, "Illegal Hash size: %d", n);
}
if ((n ^ (n - 1)) != (n << 1) - 1) {
optErr = 1;
fprintf(stderr, "Hash size not a power of 2: %d\n", n);
logit(LOG_CRIT, "Hash size not a power of 2: %d", n);
}
if (optErr == 0)
DOpts.HashSize = n;
}
} else if (strcasecmp(cmd, "active") == 0) {
if (opt) {
if (strcasecmp(opt, "on") == 0) {
optErr = 0;
DOpts.FeederActiveEnabled = 1;
} else if (strcasecmp(opt, "off") == 0) {
optErr = 0;
DOpts.FeederActiveEnabled = 0;
} else if (opt[0] == '/') {
optErr = 0;
DOpts.FeederActiveEnabled = 1;
ServerDActivePat = strdup(opt);
}
}
} else if (strcasecmp(cmd, "maxspool") == 0) {
/* No longer used */
} else if (strcasecmp(cmd, "hiscachesize") == 0) {
if (opt) {
SetPCommitExpire(-1, -1, atoi(opt));
optErr = 0;
}
} else if (strcasecmp(cmd, "wireformat") == 0) {
if (opt) {
if (strcasecmp(opt, "on") == 0) {
optErr = 0;
DOpts.WireFormat = 1;
} else if (strcasecmp(opt, "off") == 0) {
optErr = 0;
DOpts.WireFormat = 0;
}
}
} else if (strcasecmp(cmd, "readerdns") == 0) {
if (opt) {
DOpts.ReaderDns = strtol(opt, NULL, 0);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerforks") == 0) {
if (opt) {
DOpts.ReaderForks = strtol(opt, NULL, 0);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerfeedforks") == 0) {
if (opt) {
DOpts.ReaderFeedForks = strtol(opt, NULL, 0);
optErr = 0;
}
} else if (strncasecmp(cmd, "path_", 5) == 0) {
/*
* Paths (defaults already preset in globals)
*/
const char **pptr = NULL;
char *p = cmd;
/*
* path_ entries can only have one value, so be backward
* compatable with old diablo.config files that didn't
* have a '#' before a comment.
*/
cmd = strsep(&p, " \t\n");
if (strcasecmp(cmd + 5, "home") == 0)
pptr = &NewsHome;
else if (strcasecmp(cmd + 5, "spool") == 0)
pptr = &SpoolHomePat;
else if (strcasecmp(cmd + 5, "dqueue") == 0)
pptr = &DQueueHomePat;
else if (strcasecmp(cmd + 5, "group") == 0)
pptr = &GroupHomePat;
else if (strcasecmp(cmd + 5, "cache") == 0)
pptr = &CacheHomePat;
else if (strcasecmp(cmd + 5, "log") == 0)
pptr = &LogHomePat;
else if (strcasecmp(cmd + 5, "feeds") == 0)
pptr = &FeedsHomePat;
else if (strcasecmp(cmd + 5, "run") == 0)
pptr = &RunHomePat;
else if (strcasecmp(cmd + 5, "lib") == 0)
pptr = &LibHomePat;
else if (strcasecmp(cmd + 5, "db") == 0)
pptr = &DbHomePat;
else if (strcasecmp(cmd + 5, "server_dactive") == 0)
pptr = &ServerDActivePat;
else if (strcasecmp(cmd + 5, "reader_dactive") == 0)
pptr = &ReaderDActivePat;
else if (strcasecmp(cmd + 5, "diablo_socket") == 0)
pptr = &DiabloSocketPat;
else if (strcasecmp(cmd + 5, "dreader_socket") == 0)
pptr = &DReaderSocketPat;
else if (strcasecmp(cmd + 5, "feednotify_socket") == 0)
pptr = &DFeedNotifySocketPat;
else if (strcasecmp(cmd + 5, "feednotify_lock") == 0)
pptr = &DFeedNotifyLockPat;
else if (strcasecmp(cmd + 5, "dexpire") == 0)
pptr = &DExpireCtlPat;
else if (strcasecmp(cmd + 5, "dcontrol") == 0)
pptr = &DControlCtlPat;
else if (strcasecmp(cmd + 5, "dhistory") == 0)
pptr = &DHistoryPat;
else if (strcasecmp(cmd + 5, "dumphist") == 0)
pptr = &DumpHistPat;
else if (strcasecmp(cmd + 5, "diablo_hosts") == 0)
pptr = &DiabloHostsPat;
else if (strcasecmp(cmd + 5, "dserver_hosts") == 0)
pptr = &DServerHostsPat;
else if (strcasecmp(cmd + 5, "moderators") == 0)
pptr = &ModeratorsPat;
else if (strcasecmp(cmd + 5, "spam_body_cache") == 0)
pptr = &SpamBodyCachePat;
else if (strcasecmp(cmd + 5, "spam_nph_cache") == 0)
pptr = &SpamNphCachePat;
else if (strcasecmp(cmd + 5, "pcommit_cache") == 0)
pptr = &PCommitCachePat;
else if (strcasecmp(cmd + 5, "dexpover_list") == 0)
pptr = &DExpireOverListPat;
else if (strcasecmp(cmd + 5, "dhosts_cache") == 0)
pptr = &DHostsCachePat;
else if (strcasecmp(cmd + 5, "dnewsfeeds") == 0)
pptr = &DNewsfeedsPat;
else if (strcasecmp(cmd + 5, "dnntpspool") == 0)
pptr = &DNNTPSpoolCtlPat;
else if (strcasecmp(cmd + 5, "distrib_pats") == 0)
pptr = &DistribDotPatsPat;
else if (strcasecmp(cmd + 5, "distributions") == 0)
pptr = &DistributionsPat;
else if (strcasecmp(cmd + 5, "dspoolctl") == 0)
pptr = &DSpoolCtlPat;
else if (strcasecmp(cmd + 5, "generallog") == 0)
pptr = &GeneralLogPat;
else if (strcasecmp(cmd + 5, "incominglog") == 0)
pptr = &IncomingLogPat;
else if (strcasecmp(cmd + 5, "drincominglog") == 0)
pptr = &DRIncomingLogPat;
else if (strcasecmp(cmd + 5, "feedstats") == 0)
pptr = &DFeedStatsPat;
else if (strcasecmp(cmd + 5, "pathlog") == 0)
pptr = &FPathLogPat;
else if (strcasecmp(cmd + 5, "artlog") == 0)
pptr = &FArtLogPat;
else if (strcasecmp(cmd + 5, "shutdown_cleanup") == 0)
pptr = &ShutdownCleanup;
else if (strcasecmp(cmd + 5, "cachehits") == 0)
pptr = &CacheHitsPat;
else
cmdErr = 1;
/*
* XXX check for zero or one '%s' in opt.
*/
if (cmdErr == 0 && opt != NULL) {
*pptr = strdup(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "spooldirs") == 0) {
/* No longer used */
} else if (strcasecmp(cmd, "port") == 0) {
if (opt) {
strdupfree(&DOpts.FeederPort, opt, "nntp");
strdupfree(&DOpts.ReaderPort, opt, "nntp");
optErr = 0;
}
} else if (strcasecmp(cmd, "feederbindport") == 0) {
if (opt) {
strdupfree(&DOpts.FeederPort, opt, "nntp");
optErr = 0;
}
} else if (strcasecmp(cmd, "feederbindhost") == 0) {
if (opt) {
strdupfree(&DOpts.FeederBindHost, SanitiseAddr(opt), NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerbindport") == 0) {
if (opt) {
strdupfree(&DOpts.ReaderPort, opt, "nntp");
optErr = 0;
}
} else if (strcasecmp(cmd, "readerbindhost") == 0) {
if (opt) {
strdupfree(&DOpts.ReaderBindHost, SanitiseAddr(opt), NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerpath") == 0) {
if (opt) {
strdupfree(&DOpts.ReaderPathHost, opt, "");
optErr = 0;
}
} else if (strcasecmp(cmd, "path") == 0) {
if (opt) {
PathListType *pl = NULL;
strdupfree(&DOpts.FeederPathHost, opt, "");
strdupfree(&DOpts.ReaderPathHost, opt, "");
pl = zalloc(&SysMemPool, sizeof(PathListType));
pl->pathent = strdup(DOpts.FeederPathHost);
pl->pathtype = 1;
pl->next = DOpts.PathList;
DOpts.PathList = pl;
optErr = 0;
}
} else if (strcasecmp(cmd, "feederpath") == 0) {
if (opt) {
PathListType *pl = NULL;
strdupfree(&DOpts.FeederPathHost, opt, "");
pl = zalloc(&SysMemPool, sizeof(PathListType));
pl->pathent = strdup(DOpts.FeederPathHost);
pl->pathtype = 1;
pl->next = DOpts.PathList;
DOpts.PathList = pl;
optErr = 0;
}
} else if (strcasecmp(cmd, "commonpath") == 0) {
if (opt) {
PathListType *pl = NULL;
pl = zalloc(&SysMemPool, sizeof(PathListType));
pl->pathent = strdup(opt);
pl->pathtype = 2;
pl->next = DOpts.PathList;
DOpts.PathList = pl;
optErr = 0;
}
} else {
optErr = SetCommand(stderr, cmd, opt, &cmdErr);
}
if (optErr) {
exitMe = 1;
fprintf(stderr, "Unknown diablo.config command: %s %s\n",
cmd, ((opt) ? opt : ""));
logit(LOG_CRIT, "Unknown diablo.config command: %s %s",
cmd, ((opt) ? opt : ""));
}
}
if (cmdErr && cmd) {
exitMe = 1;
fprintf(stderr, "Unknown diablo.config command: %s %s\n",
cmd, ((opt) ? opt : ""));
logit(LOG_CRIT, "Unknown diablo.config command: %s %s",
cmd, ((opt) ? opt : ""));
}
}
fclose(fi);
CheckConfigOptions(0);
} else {
fprintf(stderr, "Unable to open diablo.config using pattern %s\n",
diabloConfig);
logit(LOG_CRIT, "Unable to open diablo.config using pattern %s",
diabloConfig);
exitMe = 1;
}
if (exitMe) {
fprintf(stderr, "critical error parsing diablo.config, exiting.\n");
exit(1);
}
}
/*
*
* Set various options that can also be set via dicmd/drcmd (runtime)
*
*/
int
SetCommand(FILE *fo, char *cmd, char *opt, int *cmdErr)
{
int optErr = 1;
if (strcasecmp(cmd, "remember") == 0) {
if (opt) {
DOpts.RememberSecs = TimeSpec(opt, "d");
DOpts.FeederMaxAcceptAge = DOpts.RememberSecs;
optErr = 0;
}
} else if (strcasecmp(cmd, "feedermaxacceptage") == 0) {
if (opt) {
DOpts.FeederMaxAcceptAge = TimeSpec(opt, "d");
optErr = 0;
}
} else if (strcasecmp(cmd, "maxconnect") == 0) {
if (opt) {
DOpts.MaxPerRemote = strtol(opt, NULL, 0);
optErr = 0;
}
} else if (strcasecmp(cmd, "hostcacherebuildtime") == 0) {
if (opt) {
DOpts.HostCacheRebuildTime = strtol(opt, NULL, 0);
optErr = 0;
}
} else if (strcasecmp(cmd, "activedrop") == 0) {
if (opt) {
DOpts.FeederActiveDrop = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "precommittime") == 0) {
if (opt) {
SetPCommitExpire(atoi(opt), -1, -1);
optErr = 0;
}
} else if (strcasecmp(cmd, "postcommittime") == 0) {
if (opt) {
SetPCommitExpire(-1, atoi(opt), -1);
optErr = 0;
}
} else if (strcasecmp(cmd, "slave") == 0 ||
strcasecmp(cmd, "feederxrefslave") == 0) {
if (opt) {
DOpts.FeederXRefSlave = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "feederxrefsync") == 0) {
if (opt) {
DOpts.FeederXRefSync = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "displayadminversion") == 0) {
if (opt) {
DOpts.DisplayAdminVersion = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "autoaddtoactive") == 0) {
if (opt) {
DOpts.FeederAutoAddToActive = enabled(opt);
DOpts.ReaderAutoAddToActive = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "feederautoaddtoactive") == 0) {
if (opt) {
DOpts.FeederAutoAddToActive = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerautoaddtoactive") == 0) {
if (opt) {
DOpts.ReaderAutoAddToActive = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerdetaillog") == 0) {
if (opt) {
DOpts.ReaderDetailLog = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerthreads") == 0) {
if (opt) {
DOpts.ReaderThreads = strtol(opt, NULL, 0);
optErr = 0;
}
} else if (strcasecmp(cmd, "readercache") == 0) {
if (opt) {
DOpts.ReaderCacheMode = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "readercachehashsize") == 0) {
if (opt) {
int n = bsizetol(opt);
if (n<=0) {
fprintf(stderr, "Hash size should be greater than 0 (%d)\n", n);
logit(LOG_CRIT, "Hash size should be greater than 0 (%d)", n);
} else {
DOpts.ReaderCacheHashSize = n;
optErr = 0;
}
}
} else if (strcasecmp(cmd, "readerxover") == 0) {
if (opt) {
if (strcasecmp(opt, "trackonly") == 0) {
DOpts.ReaderXOverMode = 2;
optErr = 0;
} else {
/* OTHER OPTIONS NOT YET SUPPORTED */
DOpts.ReaderXOverMode = 1;
optErr = 0;
}
}
} else if (strcasecmp(cmd, "feederrtstats") == 0) {
if (opt) {
if (strcasecmp(opt, "none") == 0)
DOpts.FeederRTStats = RTSTATS_NONE;
else if (strcasecmp(opt, "label") == 0)
DOpts.FeederRTStats = RTSTATS_LABEL;
else if (strcasecmp(opt, "hostname") == 0)
DOpts.FeederRTStats = RTSTATS_HOST;
else {
fprintf(fo, "Unknown feedertstats option: '%s'\n", opt);
logit(LOG_CRIT, "Unknown feederrtstats option: '%s'\n",
opt);
}
optErr = 0;
}
} else if (strcasecmp(cmd, "internalfilter") == 0) {
if (opt) {
strdupfree(&DOpts.SpamFilterOpt, opt, NULL);
SetSpamFilterOpt();
optErr = 0;
}
} else if (strcasecmp(cmd, "rejectartswithnul") == 0) {
if (opt) {
DOpts.RejectArtsWithNul = strtol(opt, NULL, 0);
optErr = 0;
}
} else if (strcasecmp(cmd, "newsmaster") == 0) {
if (opt) {
strdupfree(&DOpts.NewsMaster, opt, NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "readercrash") == 0) {
if (opt) {
strdupfree(&DOpts.ReaderCrashHandler, opt, "none");
optErr = 0;
}
} else if (strcasecmp(cmd, "readerban") == 0) {
if (opt) {
strdupfree(&DOpts.ReaderBan, opt, NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "xrefhost") == 0) {
if (opt) {
strdupfree(&DOpts.FeederXRefHost, opt, NULL);
strdupfree(&DOpts.ReaderXRefHost, opt, NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "feederxrefhost") == 0) {
if (opt) {
strdupfree(&DOpts.FeederXRefHost, opt, NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerxrefhost") == 0) {
if (opt) {
strdupfree(&DOpts.ReaderXRefHost, opt, NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "readerxrefslavehost") == 0) {
if (opt) {
strdupfree(&DOpts.ReaderXRefSlaveHost, opt, NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "feederfilter") == 0) {
if (opt) {
strdupfree(&DOpts.FeederFilter, opt, NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "readercachedirs") == 0) {
if (opt) {
optErr = SetCacheDirs(opt, &DOpts.ReaderCacheDirs);
if (optErr != 0) {
fprintf(fo, "Illegal reader cache dir format\n");
logit(LOG_CRIT, "Illegal reader cache dir format");
}
}
} else if (strcasecmp(cmd, "newsadmin") == 0) {
if (opt) {
strdupfree(&DOpts.NewsAdmin, opt, "");
optErr = 0;
}
} else if (strcasecmp(cmd, "newsmaster") == 0) {
if (opt) {
strdupfree(&DOpts.NewsMaster, opt, NULL);
optErr = 0;
}
} else if (strcasecmp(cmd, "hostname") == 0) {
if (opt) {
strdupfree(&DOpts.FeederHostName, opt, "");
strdupfree(&DOpts.ReaderHostName, opt, "");
optErr = 0;
}
} else if (strcasecmp(cmd, "feederhostname") == 0) {
if (opt) {
strdupfree(&DOpts.FeederHostName, opt, "");
optErr = 0;
}
} else if (strcasecmp(cmd, "readerhostname") == 0) {
if (opt) {
strdupfree(&DOpts.ReaderHostName, opt, "");
optErr = 0;
}
} else if (strcasecmp(cmd, "feederbuffersize") == 0) {
if (opt) {
int n = bsizetol(opt);
optErr = 0;
if ((n ^ (n - 1)) != (n << 1) - 1) {
fprintf(stderr, "Buffer size not a power of 2: %d\n", n);
logit(LOG_CRIT, "Buffer size not a power of 2: %d", n);
optErr = 1;
}
if (optErr == 0)
DOpts.FeederBufferSize = n;
}
} else if (strcasecmp(cmd, "feedermaxartsize") == 0) {
if (opt) {
DOpts.FeederMaxArtSize = bsizetol(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "readermaxartsize") == 0) {
if (opt) {
DOpts.ReaderMaxArtSize = bsizetol(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "feederarttypes") == 0) {
if (opt) {
DOpts.FeederArtTypes = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "feederpreloadart") == 0) {
if (opt) {
DOpts.FeederPreloadArt = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "spoolpreloadart") == 0) {
if (opt) {
DOpts.SpoolPreloadArt = enabled(opt);
optErr = 0;
}
} else if (strcasecmp(cmd, "pgpverifyargs") == 0) {
if (opt) {
char *p = opt;
int i = 0;
char path[PATH_MAX];
snprintf(path, sizeof(path), PGP_VERIFY_PATH, NewsHome);
strdupfree(&DOpts.PgpVerifyArgs[i++], path, NULL);
strdupfree(&DOpts.PgpVerifyArgs[i++], PGP_VERIFY_ARG0, NULL);
for (p = strtok(p, " \t"); p != NULL; p = strtok(NULL, " \t")) {
if (i < 6)
strdupfree(&DOpts.PgpVerifyArgs[i++], p, NULL);
}
DOpts.PgpVerifyArgs[i] = NULL;
optErr = 0;
}
} else {
optErr = 0;
if (cmdErr != NULL)
*cmdErr = 1;
}
return(optErr);
}
void
dumpConfigFeeder(FILE *fo, char *cmd)
{
if (cmd == NULL || strcasecmp(cmd, "hash") == 0) {
fprintf(fo, "*hash: ");
switch (DOpts.HashMethod) {
case HASH_PRIME: fprintf(fo, "prime");
break;
case HASH_CRC: fprintf(fo, "crc");
break;
case HASH_OCRC: fprintf(fo, "ocrc");
break;
default: fprintf(fo, "UNKNOWN");
break;
}
fprintf(fo, "\n");
}
if (cmd == NULL || strcasecmp(cmd, "hsize") == 0)
fprintf(fo, "*hsize: %d\n", DOpts.HashSize);
if (cmd == NULL || strcasecmp(cmd, "feederactive") == 0)
fprintf(fo, "*feederactive: %d\n", DOpts.FeederActiveEnabled);
if (cmd == NULL || strcasecmp(cmd, "hiscachesize") == 0)
fprintf(fo, "*hiscachesize: %d\n", GetPCommit(3));
if (cmd == NULL || strcasecmp(cmd, "feederbindhost") == 0)
fprintf(fo, "*feederbindhost: %s\n",
safestr(DOpts.FeederBindHost, "ANY"));
if (cmd == NULL || strcasecmp(cmd, "feederbindport") == 0)
fprintf(fo, "*feederbindport: %s\n", safestr(DOpts.FeederPort, NULL));
if (cmd == NULL || strcasecmp(cmd, "feederpath") == 0)
fprintf(fo, "*feederpath: %s\n", safestr(DOpts.FeederPathHost, NULL));
if (cmd == NULL || strcasecmp(cmd, "feederpathlist") == 0) {
PathListType *pl = NULL;
fprintf(fo, "*pathlist: ");
for (pl = DOpts.PathList; pl != NULL; pl = pl->next)
fprintf(fo, "%s%s", pl->pathent, (pl->next != NULL) ? "!" : "");
fprintf(fo, "\n");
}
if (cmd == NULL || strcasecmp(cmd, "feederhostname") == 0)
fprintf(fo, "feederhostname: %s\n",
safestr(DOpts.FeederHostName, NULL));
if (cmd == NULL || strcasecmp(cmd, "feederxrefhost") == 0)
fprintf(fo, "feederxrefhost: %s\n",
safestr(DOpts.FeederXRefHost, NULL));
if (cmd == NULL || strcasecmp(cmd, "internalfilter") == 0)
fprintf(fo, "*internalfilter: %s\n",
safestr(DOpts.SpamFilterOpt, NULL));
if (cmd == NULL || strcasecmp(cmd, "feederfilter") == 0)
fprintf(fo, "feederfilter: %s\n", safestr(DOpts.FeederFilter, NULL));
if (cmd == NULL || strcasecmp(cmd, "rejectartswithnul") == 0)
fprintf(fo, "rejectartswithnul: %d\n", DOpts.RejectArtsWithNul);
if (cmd == NULL || strcasecmp(cmd, "remember") == 0)
fprintf(fo, "remember: %d\n", DOpts.RememberSecs / 24 / 60 / 60);
if (cmd == NULL || strcasecmp(cmd, "feedermaxacceptage") == 0)
fprintf(fo, "feedermaxacceptage: %d\n", DOpts.FeederMaxAcceptAge);
if (cmd == NULL || strcasecmp(cmd, "maxconnect") == 0)
fprintf(fo, "maxconnect: %d\n", DOpts.MaxPerRemote);
if (cmd == NULL || strcasecmp(cmd, "hostcacherebuildtime") == 0)
fprintf(fo, "hostcacherebuildtime: %d\n", DOpts.HostCacheRebuildTime);
if (cmd == NULL || strcasecmp(cmd, "activedrop") == 0)
fprintf(fo, "activedrop: %d\n", DOpts.FeederActiveDrop);
if (cmd == NULL || strcasecmp(cmd, "precommittime") == 0)
fprintf(fo, "precommittime: %d\n", GetPCommit(1));
if (cmd == NULL || strcasecmp(cmd, "postcommittime") == 0)
fprintf(fo, "postcommittime: %d\n", GetPCommit(2));
if (cmd == NULL || strcasecmp(cmd, "pcommithsize") == 0)
fprintf(fo, "pcommithsize: %d\n", GetPCommit(3));
if (cmd == NULL || strcasecmp(cmd, "feederxrefslave") == 0)
fprintf(fo, "feederxrefslave: %d\n", DOpts.FeederXRefSlave);
if (cmd == NULL || strcasecmp(cmd, "feederxrefsync") == 0)
fprintf(fo, "feederxrefsync: %d\n", DOpts.FeederXRefSync);
if (cmd == NULL || strcasecmp(cmd, "feederautoaddtoactive") == 0)
fprintf(fo, "feederautoaddtoactive: %d\n", DOpts.FeederAutoAddToActive);
if (cmd == NULL || strcasecmp(cmd, "feederrtstats") == 0) {
switch (DOpts.FeederRTStats) {
case RTSTATS_NONE: fprintf(fo, "feederrtstats: none\n");
break;
case RTSTATS_LABEL: fprintf(fo, "feederrtstats: label\n");
break;
case RTSTATS_HOST: fprintf(fo, "feederrtstats: host\n");
break;
}
}
if (cmd == NULL || strcasecmp(cmd, "feederbuffersize") == 0)
fprintf(fo, "feederbuffersize: %d\n", DOpts.FeederBufferSize);
if (cmd == NULL || strcasecmp(cmd, "feedermaxartsize") == 0)
fprintf(fo, "feedermaxartsize: %d\n", DOpts.FeederMaxArtSize);
if (cmd == NULL || strcasecmp(cmd, "feederarttypes") == 0)
fprintf(fo, "feederarttypes: %d\n", DOpts.FeederArtTypes);
}
void
dumpConfigReader(FILE *fo, char *cmd)
{
char st[PATH_MAX];
if (cmd == NULL || strcasecmp(cmd, "readergrouphash") == 0)
fprintf(fo, "*readergrouphash: %s\n",
GetHash(&DOpts.ReaderGroupHashMethod, st));
if (cmd == NULL || strcasecmp(cmd, "readerdns") == 0)
fprintf(fo, "*readerdns: %d\n", DOpts.ReaderDns);
if (cmd == NULL || strcasecmp(cmd, "readerforks") == 0)
fprintf(fo, "*readerforks: %d\n", DOpts.ReaderForks);
if (cmd == NULL || strcasecmp(cmd, "readerfeedforks") == 0)
fprintf(fo, "*readerfeedforks: %d\n", DOpts.ReaderFeedForks);
if (cmd == NULL || strcasecmp(cmd, "readerbindhost") == 0)
fprintf(fo, "*readerbindhost: %s\n",
safestr(DOpts.ReaderBindHost, "ANY"));
if (cmd == NULL || strcasecmp(cmd, "readerbindport") == 0)
fprintf(fo, "*readerbindport: %s\n", safestr(DOpts.ReaderPort, NULL));
if (cmd == NULL || strcasecmp(cmd, "readerpath") == 0)
fprintf(fo, "*readerpath: %s\n", safestr(DOpts.ReaderPathHost, NULL));
if (cmd == NULL || strcasecmp(cmd, "readerhostname") == 0)
fprintf(fo, "readerhostname: %s\n",
safestr(DOpts.ReaderHostName, NULL));
if (cmd == NULL || strcasecmp(cmd, "readerxrefhost") == 0)
fprintf(fo, "readerxrefhost: %s\n",
safestr(DOpts.ReaderXRefHost, NULL));
if (cmd == NULL || strcasecmp(cmd, "readerxrefslavehost") == 0)
fprintf(fo, "readerxrefslavehost: %s\n",
safestr(DOpts.ReaderXRefSlaveHost, NULL));
if (cmd == NULL || strcasecmp(cmd, "readercachedirs") == 0) {
int i;
fprintf(fo, "readercachedirs: ");
for (i = 1; i <= DOpts.ReaderCacheDirs.dt_dirlvl; i++)
fprintf(fo, "%d%s", DOpts.ReaderCacheDirs.dt_dirinfo[i - 1],
(i == DOpts.ReaderCacheDirs.dt_dirlvl) ? "" : "/");
fprintf(fo, "\n");
}
if (cmd == NULL || strcasecmp(cmd, "readerautoaddtoactive") == 0)
fprintf(fo, "readerautoaddtoactive: %d\n", DOpts.ReaderAutoAddToActive);
if (cmd == NULL || strcasecmp(cmd, "readerdetaillog") == 0)
fprintf(fo, "readerdetaillog: %d\n", DOpts.ReaderDetailLog);
if (cmd == NULL || strcasecmp(cmd, "readerthreads") == 0)
fprintf(fo, "readerthreads: %d\n", DOpts.ReaderThreads);
if (cmd == NULL || strcasecmp(cmd, "readercache") == 0)
fprintf(fo, "readercache: %d\n", DOpts.ReaderCacheMode);
if (cmd == NULL || strcasecmp(cmd, "readercachehashsize") == 0) {
fprintf(fo, "readercachehashsize: %d\n", DOpts.ReaderCacheHashSize);
}
if (cmd == NULL || strcasecmp(cmd, "readerxover") == 0) {
switch (DOpts.ReaderXOverMode) {
case 0: fprintf(fo, "readerxover: off\n");
break;
case 1: fprintf(fo, "readerxover: on\n");
break;
case 2: fprintf(fo, "readerxover: trackonly\n");
break;
}
}
if (cmd == NULL || strcasecmp(cmd, "readercrash") == 0)
fprintf(fo, "readercrash: %s\n",
safestr(DOpts.ReaderCrashHandler, NULL));
if (cmd == NULL || strcasecmp(cmd, "readermaxartsize") == 0)
fprintf(fo, "readermaxartsize: %d\n", DOpts.ReaderMaxArtSize);
#ifdef READER_BAN_LISTS
if (cmd == NULL || strcasecmp(cmd, "readerban") == 0)
fprintf(fo, "readerban: %s\n",
safestr(DOpts.ReaderBan, NULL));
#endif
}
/*
*
* Dump options that can also be set via dicmd/drcmd (runtime)
*
*/
void
DumpConfigOptions(FILE *fo, char *cmd, int which)
{
fprintf(fo, "Options with '*' cannot be changed while server is running\n");
if (cmd == NULL || strcasecmp(cmd, "displayadminversion") == 0)
fprintf(fo, "displayadminversion: %d\n", DOpts.DisplayAdminVersion);
if (cmd == NULL || strcasecmp(cmd, "newsadmin") == 0)
fprintf(fo, "newsadmin: %s\n", safestr(DOpts.NewsAdmin, NULL));
if (cmd == NULL || strcasecmp(cmd, "newsmaster") == 0)
fprintf(fo, "newsmaster: %s\n", safestr(DOpts.NewsMaster, NULL));
if (which & CONF_FEEDER)
dumpConfigFeeder(fo, cmd);
if (which & CONF_READER)
dumpConfigReader(fo, cmd);
}
/*
* Check some configuration options that are required and set some
* default values if they are wrong.
*/
int
CheckConfigOptions(int which)
{
switch (which) {
case CONF_FEEDER:
if (DOpts.FeederHostName == NULL)
SetMyHostName(&DOpts.FeederHostName);
break;
case CONF_READER:
if (DOpts.ReaderHostName == NULL)
SetMyHostName(&DOpts.ReaderHostName);
break;
}
if (DOpts.PgpVerifyArgs[0] == NULL) {
char path[PATH_MAX];
snprintf(path, sizeof(path), PGP_VERIFY_PATH, NewsHome);
strdupfree(&DOpts.PgpVerifyArgs[0], path, NULL);
strdupfree(&DOpts.PgpVerifyArgs[1], PGP_VERIFY_ARG0, NULL);
DOpts.PgpVerifyArgs[2] = NULL;
}
return(0);
}
int
SetHashMethod(const char *opt, int *pmethod)
{
int optErr = 0;
if (strcasecmp(opt, "prime") == 0) {
*pmethod = HASH_PRIME;
} else if (strcasecmp(opt, "crc") == 0) {
*pmethod = HASH_CRC;
} else if (strcasecmp(opt, "ocrc") == 0) {
*pmethod = HASH_OCRC;
} else {
optErr = 1;
}
return(optErr);
}
/*
* SetGroupHashMethod - Set the newsgroup hashing method used to create
* header db files.
*
* Returns: 0 = success
* 1 = error
*/
int
SetGroupHashMethod(const char *opt, GroupHashType *pmethod)
{
bzero(pmethod, sizeof(*pmethod));
if (strcasecmp(opt, "crc") == 0) {
pmethod->gh_type = HASHGRP_CRC;
pmethod->gh_sigbytes = 20;
pmethod->gh_dirtype = HASHGRP_DIR_BIT;
pmethod->gh_dirlvl = 1;
pmethod->gh_dirinfo[0] = 2;
} else if (strcasecmp(opt, "hierarchy") == 0) {
pmethod->gh_type = HASHGRP_HIER;
pmethod->gh_sigbytes = 1024;
pmethod->gh_dirtype = HASHGRP_DIR_BIT;
pmethod->gh_dirlvl = 1;
pmethod->gh_dirinfo[0] = 0;
} else if (strncasecmp(opt, "md5", 3) == 0) {
char *p;
int v;
pmethod->gh_type = HASHGRP_32MD5;
pmethod->gh_sigbytes = 22;
pmethod->gh_dirtype = HASHGRP_DIR_BIT;
pmethod->gh_dirlvl = 1;
pmethod->gh_dirinfo[0] = 2;
opt += 3;
if (*opt == '-') {
opt++;
switch (atoi(opt)) {
case 32:
pmethod->gh_type = HASHGRP_32MD5;
break;
case 64:
pmethod->gh_type = HASHGRP_64MD5;
break;
default:
return(1);
}
}
if ((p = strchr(opt, ':')) != NULL) {
p++;
opt = p;
v = atoi(p);
if (v < 1 || v > 200)
return(1);
pmethod->gh_sigbytes = v;
}
if ((p = strchr(opt, '\\')) != NULL) {
pmethod->gh_dirtype = HASHGRP_DIR_BIT;
pmethod->gh_dirlvl = 0;
pmethod->gh_dirinfo[0] = 0;
while ((p = strchr(opt, '\\')) != NULL) {
p++;
opt = p;
v = atoi(p);
if (v < 1 || v > 9)
return(1);
pmethod->gh_dirinfo[pmethod->gh_dirlvl] = v;
pmethod->gh_dirlvl++;
if (pmethod->gh_dirlvl > 9)
break;
}
} else if ((p = strchr(opt, '/')) != NULL) {
pmethod->gh_dirtype = HASHGRP_DIR_NUM;
pmethod->gh_dirlvl = 0;
pmethod->gh_dirinfo[0] = 0;
while ((p = strchr(opt, '/')) != NULL) {
p++;
opt = p;
v = atoi(p);
if (v < 1)
return(1);
pmethod->gh_dirinfo[pmethod->gh_dirlvl] = v;
pmethod->gh_dirlvl++;
if (pmethod->gh_dirlvl > 9)
break;
}
} else
return(1);
return(0);
} else {
return(1);
}
return(0);
}
int
SetCacheDirs(const char *opt, CacheDirType *cachedir)
{
int v;
char *p;
cachedir->dt_dirlvl = 0;
v = atoi(opt);
if (v < 1)
return(1);
cachedir->dt_dirinfo[cachedir->dt_dirlvl] = v;
cachedir->dt_dirlvl++;
while ((p = strchr(opt, '/')) != NULL) {
p++;
opt = p;
v = atoi(p);
if (v < 1)
return(1);
cachedir->dt_dirinfo[cachedir->dt_dirlvl] = v;
cachedir->dt_dirlvl++;
if (cachedir->dt_dirlvl > 9)
break;
}
return(0);
}
syntax highlighted by Code2HTML, v. 0.9.1