/* * 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); }